craise
craise
Public release notes

What's new.

Every meaningful update we ship to Pitched, in plain English. Bookmark this page — partners + investors can check back any time to see what's moving.

The Funding Tracker, redesigned around the tape

Where capital is moving, at a glance: sector heat up top, a steady flow of funding news you can tune to your patch, and the full tape underneath.

  • Sector heat, end to end. A full-width band of capital-tinted sector tiles — 30 days of deployment with momentum arrows against the prior 30. Click any sector to filter the tape to it.
  • The flow. A steady stream of the latest funding news on the left, with the India ↔ Global slider right in the header — drag it and both the flow and the tape re-tune to your patch.
  • The shape, on the right. Mega rounds ($50M+), the stage flow, Deploying now — the funds writing the most cheques this quarter, straight from Fund Pulse — and where the capital is going by geography.
  • The tape. Every round as it crossed the wire, behind a live ticker banner showing how many rounds we track and what landed in the last 24 hours — with full search, stage, sector, geography and source filters.
  • Headline totals now count only real venture rounds. The news wire occasionally carries earnings figures, IPO valuations and revenue lines — those stay on the tape but no longer inflate "capital raised this week".
  • Geography split no longer shows the same country three ways (US / USA / United States are one row now).
  • Page typography brought fully onto the Craise type system.

Run your round: a round tracker, warm intros, and live investor pulse

The biggest fundraising upgrade we've shipped: know which funds are actually deploying, find your warm way in, and run the whole round from one page.

the Round Tracker
  • A new Round Tracker in your sidebar runs the live raise end to end: your target, pre-money and instrument at the top, and a progress bar that shows exactly where you stand — secured money (docs signed / wired) in dark, soft-circled in light, against your target.
  • The breakup, as a ledger. Every cheque in the round — funds from your pipeline or the angel who said yes over dinner — with its own status walk: *prospect → soft-circled → verbal → term sheet → docs → wired*. Click anyone to log calls, set the next action, and keep the whole conversation in one place.
  • Your cap table, before and after. Enter today's ownership (founders, ESOP, advisors, earlier investors) and watch what the round does to it — per holder, with a toggle between "at what's committed" and "at target". Post-money is always computed from pre-money + what you've raised, so it can never drift. Optional ESOP top-up modelling included.
  • It talks to the rest of Craise: warm investors from your pipeline are one click to add, marking someone *committed* nudges you to put their cheque in the round, and you're notified the moment your target is fully circled.
warm ways into every firm
  • Investor matches now come with WARM chips: someone at the firm already read your memo, the fund backed a founder who's on Craise, your contacts share the firm's domain, or a fund already in talks with you co-invests with them. When nothing's warm, we point you at the right partner to approach directly.
  • Ask for intro on any warm path — the Craise team works the connection for you and your pipeline updates automatically when the intro goes out.
  • A new Intro network setting lets you choose whether founders raising from your investors can see your company as a path in — off by default, your email is never shared.
Fund Pulse on every investor profile
  • Every investor page now shows what the fund is actually doing: a live deploy status (actively deploying / warming / quiet), their deal cadence over 8 quarters, the sectors they're really writing cheques into — flagged when it differs from their stated focus — and a one-line analyst read of what they're hunting for right now.
  • Recent chatter pulls what communities are saying about the fund from across the social web, scored by real engagement.
  • Sort the investor directory by "Active now" to pitch the funds that are actually deploying this quarter.
  • The numbers at the top of your memo are clickable now — click any headline stat in build mode, type the new value, hit Enter. Works on every memo style.

Two new memo styles: Ledger & Studio

Pick the register your raise deserves — an institutional investment document, or a dark photo-led lookbook. Both are in the Style picker today.

Ledger, the memo as an investment document
  • Annual-report craft on warm ivory paper: ruled key-figure tables with dotted leaders, numbered sections opened by giant serif folio numerals, a real Contents index, and running *Confidential* footers on every page.
  • Your ask, set as a classic IPO tombstone — a solid ink slab with your raise at the centre of the cover, sealed with your monogram. An engraved guilloché rosette (the stock-certificate pattern) marks the masthead.
  • Typeset *in your brand*: headings, the big numbers, and the dark spreads all derive from your brand colour. Market sizing renders as an analyst table, use of funds as an allocation statement — and verified metrics keep their green ticks. It prints beautifully.
Studio, the dark photo-led lookbook
  • Our first dark style: a charcoal studio backdrop with your hero image as a full-bleed cover and your company name at poster scale — and your video and gallery promoted right below the title, where they belong.
  • Numbers as spotlight posters — a swipeable, mobile-first reel of stat cards, each lit from below in your brand colour.
  • Founders appear as magazine portraits — duotone prints that bloom into colour — and your quotes are set as oversized pull-quotes. One clean single-page flow on every device.
  • The top numbers on every memo are now click-to-edit in build mode — click, type, Enter. No more hunting for where a number lives.
  • Every page style is now reachable from every Style picker, whichever layout you're on.

Meet Copilot, your AI co-pilot for building memos

Your AI coach grew up into a real conversation. Ask Copilot for anything while you build — and it works on your memo live, right beside you.

Copilot, the conversational AI co-pilot
  • A new Copilot rail sits alongside your memo. Talk to it like a teammate — ask it to sharpen your traction, tighten the ask, or flag what an investor will question — and it answers in clean, readable formatting with quick-action chips.
  • It acts on your memo, live. Tell it to rewrite a section, rename something everywhere ("call us HYLENR Technologies, not Hylen — fix it across the memo"), or fill in the gaps, and you watch it happen — with clear feedback if something can't be done.
  • It knows your live memo — your sections, numbers and content are in context, so its help is about *your* company, not generic advice.
  • Your conversation persists — reload and pick up right where you left off.

A real data room, built into every memo

Your data room grows up: an investor-ready folder structure, a clean way to manage it, and a home of its own.

the investor-ready data room
  • Open Data Room from the sidebar. If you have one memo it opens straight to its room; if you have several, a new landing lets you pick a live data room to manage — or start one for another memo.
  • Inside, your documents now live in an investor-ready folder structure — Company Summary, Team, Company, Investment, Clients, Legal, Financials, Press — each folder telling you *why* investors look for it. Switch between Folders (click into each folder), a guided Checklist, or a plain Flat list, whatever you prefer.
  • "Pull from my memo" fills the room in one click — your deck and any cap table / financials you've already added drop into the right folders.
  • Drag files between folders, or use the Move to folder menu. Add many files at once.
  • On the memo itself, the data room is now a tidy, scrollable list (no more wall of cards), and in edit mode you can add or remove files right there.
  • A new Data Room box on your dashboard jumps you straight to the right room.
your deck, view-only
  • Decks now open in a clean, view-only viewer — no accidental downloads — and a PowerPoint (.pptx) deck now opens properly instead of showing raw file data.
  • Every email from Craise now comes from Craise (no-reply@craise.ai) with the Craise mark — clean and consistent.

Your deck is now view-only, and you see everyone who opens it

Your pitch deck no longer downloads to anyone who lands on your memo. Visitors give their name and email, then read it in a protected viewer — and you get a lead for every open.

a protected deck, not a free download
  • When someone opens your deck from a memo, it now launches in Craise's own view-only viewer in a new window — clean, full-screen, page-by-page. There's no download or print button, and the raw file link is never exposed on the page. Casual "save the PDF and forward it" is closed off.
  • Anyone who isn't signed in is asked for their name and email first (it used to ask for email only). They read the deck the moment they enter it — and you get a named lead, with their location, every time.
  • Signed-in viewers skip the form, open the same view-only viewer, and their deck open is still captured against your memo — so you can see who looked.
  • You keep full access to your own deck. As the owner, opening your deck in build mode or on your own memo still gives you the original file, with download — it's yours.
  • Every "someone opened your deck" alert now leads with their name, so you know who's reading before you even open the notification.

Preview on any device, payments are live, and a bigger investor universe

See exactly how your memo looks on a phone, upgrade to a paid plan right now, and reach hundreds more investors.

preview your memo on any device
  • While editing a memo, click Preview at the top. Instead of jumping straight to the page, you'll now get a choice: Desktop or Mobile.
  • Pick Mobile and your live memo opens inside a true-to-life phone frame on a clean studio backdrop — the exact view an investor gets on their phone, *before* you ever send it. Flip between Mobile and Desktop with one tap to compare how it reads on each.
  • Hit Scan to open in the preview and a branded QR code lifts the live memo straight onto your own phone in seconds — handy for a final real-device check.
  • Prefer the classic full-page view? Choose Desktop and it opens in a new tab, exactly as before.
payments are live
  • Subscriptions are now live. Upgrade to Plus (₹1,999/mo) or Pro (₹4,999/mo) — each with a 14-day free trial — and pay securely by card through Razorpay, with your plan activating instantly. (This was "coming soon" last week; it's here.) More ways to pay, including UPI AutoPay, are rolling out.
a bigger, richer investor universe
  • The investor directory now lists hundreds more funds with a direct "Pitch them" link — far more investors you can reach in one click, straight from a memo or the directory.
  • Open any investor for live, sourced enrichment: Craise fills in their focus, stage, geography and notable portfolio companies on demand — so every profile stays current, not stale.
  • Memos read better on phones — editorial, showcase and dashy styles now show a larger header image on mobile.
  • The "Why now?" section always tells a timing story now: if your deck didn't spell it out, Craise composes one from your market signals — on every memo style.

Claim your own memo URL, and scan any memo from the homepage

Pick a clean, memorable web address for any memo — and let anyone scan a memo straight from the homepage gallery.

pick your vanity URL
  • Give any memo a clean address — craise.ai/spacex instead of a long auto-generated link. In build mode, open Share → "Customise this URL", type the name you want, and Craise checks availability live as you type (it flags anything already taken or reserved).
  • Your old links never break. Rename as often as you like — every link and QR code you've already shared keeps working and quietly forwards to the new address.
scan any memo from the homepage
  • Every memo in the homepage gallery now has a QR button next to its title. Click it for a branded code anyone can scan with their phone camera to open that memo — perfect for showing the gallery live on a screen.

Share any memo with a scan, smarter financials, and billing on the way

A scannable QR on every memo, sharper number-reading from your deck, and subscription billing fully wired and ready to switch on.

scan-to-share QR codes
  • Every published memo now has a share button, top-right, that opens a beautiful branded QR code — anyone can scan to open your memo on their phone, copy the link, or share straight to WhatsApp. Perfect for showing your pitch live in a meeting or putting it on a slide.
  • The same one-tap QR is built into your Mini-memo share and the build-mode share panel — so whether you're presenting, sending, or printing, there's always a scannable code pointing to your live memo.
  • Download the QR as an image to drop onto a slide, poster, or business card.
smarter financial reading
  • Craise now reads revenue and growth straight from chart bars and fundraise / IPO offering slides — figures that used to hide inside a graphic now make it onto your memo.
  • New "Rescan financials" nudge: if your deck clearly has revenue or a raise that didn't land on the memo, Craise offers to pull it in — one click, straight from your deck, never invented.
subscription billing wired up
  • The full billing flow is built and integrated: Plus (₹1,999/mo) and Pro (₹4,999/mo) with a 14-day free trial, plus Group Pro for venture partners managing portfolios ($2,000/mo, international). It goes live as soon as our payment provider finishes activating subscriptions on the account.
  • A polish pass on the share popup — cleaner card, faster load, and a tasteful grey QR in view mode.
  • The feedback button now sits neatly at the page edge on the Modern and Brutalist memo styles.

Find anyone, verify your numbers

Two big additions: a people-search engine built into Craise, and a way to prove your traction with a green tick investors trust.

Find People
  • A new Find People workspace: search the global people graph by name, company, position, country, industry, skills or keyword — or just paste a LinkedIn URL — and get a clean, paginated list of results.
  • Reveal verified email & phone for anyone, then add them to your lead list with a full mini-profile — experience, education, skills — and a private note.
  • The Craise team is pinned to the top so you're always one click from reaching us, and every founder gets 10 free reveals to start.
Find the people behind any firm
  • See an investor you want to reach? Hit Find people on any firm — in your Potential Investors list, the investor directory, or an investor's profile — and Craise instantly pulls that firm's team into Find People, ready to reveal and save.
Craise Verified
  • Prove your numbers. Connect your real sources — revenue, traffic and more — and earn a green tick investors trust.
  • Everything you connect rolls up into a single source-of-truth dashboard: every metric verified and live — the page you send investors.
  • Distinct, animated hero art across your Dashboard, Memos and Investors pages — a little more momentum every time you land.
  • Search results now paginate, so you can page through hundreds of people at a firm instead of just the first screen.
  • Fixed a rendered-memo glitch where a market's geography figures could repeat (e.g. "Global" listed several times) — each region now shows once, with its headline number.
  • The time a visitor came to your memo is back on both your dashboard and Viewers list.

Link previews that pop, a fresh sign-in, and friendlier viewers

Polish across the parts of Craise the outside world sees — plus a few touches just for you.

your memo links finally look the part
  • Drop a memo link into WhatsApp, LinkedIn, Slack or email and it now unfurls into a rich preview card — your company name, tagline and deck cover — instead of a bare URL. The first impression now lands before anyone even clicks.
a brand-new sign-in & sign-up
  • A faster, cleaner way in — one-tap Google, a show/hide password, and a "keep me signed in" that actually sticks — alongside a live glimpse of a founder's memo being read in real time.
  • Your dashboard now previews your latest memo even while it's a draft, with a *"Draft mode · click to edit"* tag — so the work-in-progress is always one click from where you left off.
  • Anonymous readers on your dashboard now get a friendly avatar (a little astronaut, tiger, eagle…) instead of a faceless "?" — and each person keeps the same face on every visit, so your viewer list is easy to scan.
  • Pitch Interview is now "Virtual Pitch" — same live AI-investor rehearsal, clearer name.

A brand-new look for your whole workspace

Craise just got a head-to-toe redesign. Every page in your workspace now wears the new Sky look — a calm, sky-blue palette, a cleaner sidebar, and a top bar with instant search.

the Sky workspace
  • A refreshed sidebar and top bar across your entire workspace, with ⌘K search to jump to any memo, investor or company in a keystroke and notifications always a click away.
  • Every page now leads with a crisp, colour-coded header so you always know where you are — Pipeline, Analytics, Companies, Coach and the rest each get their own accent.
  • Your dashboard, memos and every other page now share one consistent, modern design — lighter, faster, and easier on the eyes.
  • Cleaner type and spacing throughout, and a mobile experience that finally feels first-class — a slide-out menu with your profile and sign-out always within reach.

Tidier memo cards and full control over company links

A few quality-of-life wins on your memo list and the build experience.

manage a memo's company
  • Click the company chip on any memo card to do more than filter. You can now change the linked company (your current one is ✓-marked), remove the link entirely if it's wrong, or jump to all memos for that company — all in two clicks.
  • Memos without an uploaded deck now show your own header image on the card instead of a blank tile — wizard-built memos look finished at a glance.
  • The mobile build menu is taller, so every tool — Mini-memo, Numbers, Data Room, Share, Publish — is visible without scrolling, and it's now identical across every page style.
  • Fixed a crash that could show a blank page when editing certain memos in the build view.

Sign in with Google, a share-anywhere Mini-memo, and a bigger investor universe

Three new ways to move faster: one-tap Google login, a lightweight memo you can fire to anyone, and a much deeper investor list.

Continue with Google
  • Sign in or sign up with one tap — no more passwords to remember. (We only ever see your name and email — never your inbox.)
the Mini-memo
  • A one-screen teaser — your headline numbers, the ask, and your deck — behind a single link that works over link, email, or WhatsApp. Create it from any memo at *Pitches → Mini*.
  • It tracks engagement: opens, unique viewers, time spent, and how many opened your deck — so you know who's actually interested before you follow up.
grow your investor list
  • A new Grow list tool: paste any list of investors, or just describe who you want ("family offices in India backing consumer brands") and Craise finds matching VCs, micro-VCs, family offices and angels — each enriched and held for your review before it joins matching.

A cleaner plan, and a sync that keeps your whole pitch honest

Follow-on polish to the financial-plan engine: a tidier assumptions view, a "Sync to pitch" that updates the numbers *everywhere* (not just the chart), and a funding figure that comes from your model — not a deck typo.

assumptions ledger
  • Levers that aren't used in the plan now show a quiet "—" instead of a stark "0.00", so the inputs that actually matter stand out.
  • Cleaner number formatting (no more "1.00"), a subtle confidence dot in place of the ✓/△/⚠ symbols, and tidy sensitivity bars that no longer spill into the next column.
Sync to pitch updates everything
  • "Sync to pitch" now refreshes your hero / traction tiles too — Revenue, EBITDA and GMV by year — so your headline KPIs match the financials section instead of contradicting it. It even recomputes the "N×" growth multipliers from the real year-over-year numbers.
  • The funding ask now comes from your model, not the deck. Decks often mis-write the currency ("$5M" becoming "₹5 Cr" — off by 10×); the plan now reads the actual round size from your model and rescales the use-of-funds split to it. If there's no model, the deck's number is still used.

Upload your financial model, get a real interactive plan

Drop in your Excel model and Craise now turns it into a faithful interactive plan — for any business in any category. The biggest change is in what it reads: it finds your actual income statement and leads with the numbers investors look for first.

your numbers, actually understood
  • Craise now reads your real P&L — Revenue, EBITDA, margins, PAT — even when it lives on a separate Dashboard or Summary sheet inside a big operational model. The plan leads with your financial story instead of whatever rows happened to be densest.
  • Every assumption comes back with a clean label and a plain-English rationale — "Aggregator Commission", "Content Creator Salary" — grouped into the right category (unit economics, COGS, marketing, team…).
  • The plan now respects the scale you wrote: if your sheet says "₹ Cr", the plan shows ₹ Cr — no more silent unit mismatches.
  • Proven across every sector — marketplace, SaaS, lending, hotels, D2C, logistics, manufacturing, F&B — against a 22-model test corpus, with no loss on models that already worked.
  • Large models that used to produce a thin or empty plan now fill properly, with named, explained assumptions.
  • Models with a heavy operational build (monthly driver / supply / acquisition grids) no longer drown out the real P&L — the headline shows your revenue and profitability, not your roster.
  • Your stated business category is respected when classifying the model, instead of a misleading auto-guess.

Research Assistant, AI Autopilot, and one tidy place for suggestions

Today the build experience gets a lot smarter. Two new ways to fill your memo with real substance — a Research Assistant that goes to the live web and brings back sourced market data, and AI Autopilot that completes your pitch from your deck in one pass — plus every build-mode nudge consolidated into a single, tidy "For your attention" pill.

Craise Research Assistant
  • A new Research tool in the build toolbar. Click Research my market and Craise reads your memo's context, then goes to the live web and brings back sourced findings — market size (TAM / SAM / SOM / CAGR), named competitors and their funding, comparable valuations, the regulatory landscape, category benchmarks, and recent signals. Every finding carries its source — title, a verbatim snippet, and a link — so you can trust it.
  • You decide what goes in. Each finding is an accept/reject card — click Add to memo and it lands in the right field; nothing is added without your say-so. When sources disagree on a number, you get the single consensus figure rather than the same metric three different ways.
  • Scoped to you. It researches your country and target market specifically, so the competitors and numbers match who you actually sell to — not the whole world. If your memo's geography is vague, set the country right in the panel and re-run.
AI Autopilot: complete your pitch in one pass
  • The Coach can now complete your pitch for you. It reads your uploaded deck plus what's already on the page and fills the gaps in one ~30-second run. Facts it can ground in your deck snap into place; anything it infers comes back as accept / reject suggestions, so you stay in control.
  • It stays anchored to your company — no generic, industry-template filler. Relevant beats complete: it leaves a field empty rather than padding it with something that isn't true for you.
One place for suggestions: "For your attention"
  • All the scattered build-mode nudges are now a single tidy pill in the corner. Click it and one card lists what would make your memo stronger — research your empty sections, fill missing fields, tidy flagged numbers — each with a one-click action.
  • No more pop-ups stacking over your toolbar. The "page changed → Refresh" alert and the Enhance prompt stay on their own, and the pill repositions cleanly on every layout — including the editorial and dashboard styles that have a side rail, where the toolbar now centres over your content too.
Richer memos
  • More of what we capture now actually shows on the page: partnerships, regulatory & compliance (licences, certifications, data residency), comparable rounds & valuations (on Modern too), market headwinds, and more. Memos that had the data but were hiding it now read fuller — and anything you accept from Research lands where it belongs.
Accepted research now renders
  • A handful of accepted research findings — competitors especially — were saving to your memo but not showing up. They now appear correctly across every layout.

Brutalist: a bold new memo style, and Craise for Mac

Today is about a brand-new way your memo can look, building anywhere, and a native app to build it in. The core of the work was a full mobile sweep so building a memo works properly on a phone in *every* style. On top of that: Brutalist, a high-contrast, editorial take on the Modern engine — a dark poster-style cover, hard rules, oversized type, your brand colour driving the page, and a data ledger that reads like a terminal — now a first-class choice in the style picker next to Modern, Showcase, Editorial and Dashy. Plus a Mac desktop app, fixes across the marketing site, and a cleaner build toolbar.

Brutalist, a new memo style
  • A new Brutalist option in the page-style picker (alongside Modern / Showcase / Editorial / Dashy). It runs on the Modern engine, so everything you've written carries straight over — pick it and your memo is instantly re-set as a bold editorial document.
  • A poster-style cover — a dark masthead with a hard-ruled bar, a brand register mark, your company name set huge in uppercase with a brand "kicker" slab beneath it, a hard-ruled stat ledger, corner registration ticks, and a giant ghost initial watermarking the page. Header images get a duotone treatment so any photo reads as an intentional plate.
  • A brand-coloured sidebar — the nav rail picks up your brand colour instead of grey, with a gradient highlight on hover and on the active page.
  • Every block restyled — squared corners, hard 2px rules, heavy type, boxed labels, numbered sections (01 · 02 · 03…) and oversized numbers. Market sizing defaults to a big TAM → SAM → SOM ladder in Brutalist, while Modern keeps the rings.
  • The style picker is now one drawer — page style and the bold skin merged into a single five-tile chooser, on both the Modern and classic toolbars.
Craise for Mac
  • There's now a native Mac app. Download it at craise.ai/craise.zip, unzip, and drag Craise into your Applications folder — it opens straight to sign-in and runs in its own window, separate from your browser tabs.
Build mode
  • The build top bar is cleaner: the left now reads Return to dashboard, and your memo's name sits centred in the bar (every layout).
  • Switching styles or themes now re-renders cleanly instead of leaving a half-updated page.
Autopilot stays on-topic
  • Autopilot stays anchored to *your* company — it no longer invents generic metrics that don't fit your industry or stage. Facts it can ground in your deck snap into place automatically; anything it infers is held as an accept / reject suggestion instead of being written in silently.
Formatting renders properly
  • Bold / italic / underline and headings now render as formatting in every layout, instead of occasionally showing the raw tags as text. Your emphasis shows up exactly the way you set it.
Building a memo works on mobile, in every style
  • A full mobile sweep of the builder. Whatever style you're in — Modern, Brutalist, Showcase, Editorial or Dashy — building a memo now works properly on a phone: the build tools open in a single clean bottom sheet, the toolbar and formatting controls fit the screen, sections no longer overflow their frame, and the navigation collapses to a tidy bottom pill. This was the core of the work.
  • The sign-out button is reachable on mobile from the dashboard.
Marketing site
  • A set of layout and responsiveness fixes across the public pages — including the homepage hero and the showcase carousel, which no longer run long or overflow on phones.
Contrast
  • Labels and values never land white-on-white on dark sections any more.

Playbook: a founder learning library with smart YouTube ingest

A new module landed today. Playbook is a curated video library for founders — talks, teardowns, tactics, and storytelling clips from the people who've done this before. It lives at /app/library under Intelligence in the sidebar, with a dedicated watch page per video that runs on a custom-skinned player. The other half of the story is the back office: a platform-admin surface that lets us add videos three ways — one at a time, in bulk, or by searching YouTube directly inside Craise — and an AI cleanup pass that turns YouTube's noisy descriptions into a tight summary plus concrete takeaways before anything reaches a founder. This is the editorial / educational layer the product was missing.

Playbook for founders
  • Browse at /app/library — a 3-column responsive card grid of every published video, with category filter pills along the top (Fundraising / Pitching / Storytelling / Product / GTM / Finance / Operations / Founder stories). Cards show the thumbnail with a duration badge, category, title, and speaker.
  • Watch at /app/library/{slug} — dedicated page with the embedded player, title, speaker, duration, "Watch on YouTube" link, the AI-cleaned summary, a "Key takeaways" block, and a "More in {category}" rail of related videos at the bottom.
  • Custom player skin via Plyr — the YouTube control bar gets replaced with our own chrome in Craise purple: clean progress line, your own play / volume / captions / settings, playback speed 0.5×–2×, PiP, AirPlay, fullscreen. A soft ambient glow sits under the player. The video autoplays the moment the page loads.
three ways to add videos in the admin
  • Quick parse — paste one YouTube URL, pick an optional category, hit *Parse & add*. Server reads the URL, pulls title + channel + duration + thumbnail + description from YouTube, rewrites the description with AI, saves as a draft. Works on every YouTube URL shape (youtube.com/watch, youtu.be, embed, shorts, watch?v=ID&t=120).
  • Bulk parse — modal with N URL + category rows. Paste a stack of URLs into one box and they auto-split onto separate rows. Set a default category and status once, hit *Parse & add all*, get a per-row summary of what landed and what failed and why.
  • Search YouTube — new page at /platform-admin/playbook/search. Type a query, get a result grid with thumbnails, durations, channels. Click cards to select (purple ring + check chip), set a category for the batch, hit *Add selected* — they all land as drafts with metadata + AI-cleaned descriptions already in place.
AI description cleanup (gpt-4o-mini)
  • Every video added via Quick / Bulk / Search runs through an automatic cleanup pass. The pre-pass strips obvious noise (timestamp lines, bare-URL lines, "Subscribe…" / "Follow me on…" / hashtag dumps / social handle blocks), then gpt-4o-mini rewrites what's left into a 2-3 sentence editorial summary plus 3-5 concrete takeaways (each 6-14 words, no generic filler).
  • The output replaces YouTube's raw description before the row hits the database. Founders never see the marketing fluff.
  • A wand-sparkles button on every admin row triggers a re-clean — re-fetches the freshest raw description from YouTube and runs the refiner again. Useful when the result wasn't quite right or YouTube updated the source.
YouTube Data API v3 wired
  • Full metadata (title + channel + description + duration + best-available thumbnail) now pulls from YouTube Data API v3, with a clean fallback to oEmbed if the key is ever missing. Search uses the Data API directly. The Search page surfaces a friendly setup banner if the key isn't enabled, instead of failing silently.

A new name, a new home: Pitched is now Craise

We've renamed. Pitched is now Craise, and the site has a new home at craise.ai. Same team, same platform, all your work exactly where you left it — your memos, data rooms, investors, analytics and everything else are untouched. What changed is the identity and the public face: a name that fits what this has become — not a pitch-page tool, but the operating system for your entire raise. Along with it: a completely rebuilt homepage, a redesigned sign-in and sign-up, a refreshed about page, and the first public look at the investor side that's coming.

Craise
  • New name, new logo, new look. The product you log into is unchanged — nothing in your account moved or reset. Your existing memo links keep working. The new identity drops the old palette for a cleaner green-and-cyan system on white, with the wordmark and momentum mark you'll now see across the site.
A rebuilt homepage
  • The new homepage tells the whole story in one scroll: drop a deck, get a live page, pitch six AI investors, and track exactly who's reading — all in sixty seconds. It includes a live product walkthrough, the six-investor dress-rehearsal panel, an index of everything the platform does end-to-end, and a gallery of real published memos.
A first look at the investor side
  • There's a new investors page at craise.ai/for-investors. We built the founder side first; now investors can join the waitlist to be notified when investor access opens — thesis-matched dealflow that's current and already structured, live memos, and diligence tools, instead of an inbox of cold decks.
Redesigned sign-in and sign-up
  • Both pages were rebuilt to match the new look, with a clearer picture of what you actually get: turn a deck into a live page, pitch six AI investors, and know which fund is reading. The about page also picked up the new navigation.
Mobile
  • The homepage now has a proper mobile header — logo on the left, a hamburger menu on the right — bigger hero type with a tighter sub-line, and the mobile browser chrome goes black so the page reads as one continuous surface.
Data Room button on the Modern layout toolbar
  • On the Modern layout, the build toolbar was missing its Data Room button because of a naming collision with a leftover element. It's back, alongside the share, numbers and preview controls where it belongs.

Book a time with the founder, your own investors, and a sharper Headshot Studio

A founder-tools day. The headline is scheduling: visitors can now book a slot with the founder straight from a published memo, and founders set their availability in a new Calendly-style Calendar — no third-party tool, no back-and-forth email. Alongside it, founders can bring their *own* investor list into the platform (one at a time or a bulk spreadsheet), Headshot Studio finally works on the Modern layout, and we closed a genuinely nasty bug where restyling one founder's photo could land on a different founder.

Book a time with the founder, right from the memo
  • Every published memo now carries a "Book a time" button next to the feedback button. A visitor picks a day, sees the founder's real open slots, and books in three clicks — name, email, done. They get a confirmation; the meeting drops straight onto the founder's calendar. It only appears once a founder has set up their availability, so an unconfigured memo stays clean.
  • Founders set this up in the new Tools → Calendar: choose your booking link, meeting length, time zone, notice + buffer windows, and tick the days/hours you're free. The public booking page respects all of it — no double-bookings, no slots inside your buffer, nothing before your minimum notice.
  • *Coming next:* connecting your Google or Microsoft calendar so your real busy times are accounted for automatically. The hook is in the UI, flagged as on the way.
Add your own investors — one at a time, or in bulk
  • The Potential Investors page gets an Add my investors button. Add a single investor through a quick form, or download an Excel template, fill it in, and upload the whole list at once. Either way they're added in seconds and flagged "Added by you".
  • These are completely private to you — they never appear for any other founder or team — and they automatically join your match pool, so the next time you run Match they're scored against your memo alongside the global investor universe.
"Find more investors" now picks the right memo
  • If you have more than one memo, the Find more investors button on Potential Investors opens a quick picker — your memos, each tagged Live or Draft — so you choose which one to match against. One memo? It just runs. No more guessing which pitch the matcher is using.
Headshot Studio comes to the Modern layout
  • On the Modern layout, clicking a founder's photo now offers Upload *or* Headshot Studio — the same 7-style AI restyler that's been on the other layouts. Previously Modern could only upload or delete a photo.
Email-gate your pitch deck
  • On any published memo, an anonymous viewer is now asked for their email before the full deck opens at the bottom. It's a polite one-time ask (remembered on their browser), and it turns every deck view into a lead — you get their email, location, and a heads-up that someone's reading. Logged-in viewers skip it entirely.
A nudge to build your data room
  • In build mode there's now a small "Add your key documents to the data room" card with one click to start uploading. Once you've added documents, your memo automatically grows a Data room entry in its navigation and a request-access flow for investors — so the diligence vault is discoverable instead of hidden.
Investor Match shows 15 and sorts the way you want
  • Match now surfaces 15 investors instead of 12, and you can flip the ranking between Fit score (the AI's read on how well they fit) and Relevance (raw sector/stage/geography overlap) with one tap.
Sharper AI headshots
  • Headshot Studio now uses Google's latest image model (Nano Banana 2) when available, with an automatic fall-back to the proven one — better likeness and lighting, same cost, no change to how you use it.
Restyling one founder's photo could overwrite another's
  • On the Modern layout, finishing a headshot for one founder and then clicking a second founder's face could apply the new photo to the *wrong* person. The page was renumbering the team list for display but saving against the original order, so the indexes drifted whenever a teammate had no name yet. Photos (and deletes) are now matched to the founder by name, not by position, so an edit always lands on the person you clicked.
Certifications were invisible on the Dashboard layout
  • On the Dashboard (dashy) layout, the licence/certification chips in the Regulatory section were rendering as light text on a light background — effectively invisible. They now show as a clean dark pill with dark text. The other layouts were already fine and are unchanged.
The "Add a moment" image in Enhance didn't stick
  • In the Enhance walkthrough's final step, dropping in a photo showed "✓ Added" but the image never actually appeared on the memo — it uploaded to storage but was never attached to the page. It now lands at the end of your memo exactly as promised (and you can drag it anywhere from the toolbar afterwards).

2026-05-23 (late) — 14-day sessions, Headshot Studio previews, Legal Room rebuild, analytics chart fixed

Second pass on the day. The big one: founders no longer get kicked back to the login screen mid-afternoon — sessions now last 14 days instead of 2 hours, which matches what every modern SaaS tool defaults to (Linear, GitHub, Notion all sit in the 14-30 day range). On top of that: Headshot Studio gets a thumbnail-led picker so founders see what they'll get before spending compute, Legal Room is restructured around moments in the fundraise instead of a flat 9-template grid, the founder dashboard's activity feed reads like English instead of a log line, and two silent bugs that had been killing the per-pitch analytics chart and the funding-tracker cron get isolated and fixed.

Headshot Studio shows what you'll get before generating
  • The style picker on /app/headshot-studio no longer asks founders to read seven similar-sounding descriptions and guess what'll come out. Each style tile now leads with a 1:1 thumbnail of the same demo founder rendered through that exact style. Studio Natural (cream backdrop, soft natural light — the LinkedIn standard) · Formal (tailored navy suit, Rembrandt key light, exec presence) · Casual (olive linen shirt, warm golden-hour light, friendly smile) · Touched up (the studio shot, professionally retouched — same identity, cleaner skin tone, brighter eyes) · Caricature (New Yorker editorial illustration, ink with watercolour wash on cream paper) · Pop / Comic (Roy Lichtenstein halftone with vivid magenta + cyan + yellow palette) · Pencil sketch (graphite on white drawing paper, soft hatching). Founders see exactly what their portrait will look like in each register before committing to the 15-second generation, and because the same identity carries across all 7 thumbnails — same face, same beard, same hairline — the "we preserve the face, only style changes" guarantee is visible at a glance, not just a claim in the marketing copy.
  • The seven base images were generated through Gemini Nano Banana with character-consistency mode. The Studio Natural shot came first as the identity reference; the other six were generated using that as inputImagePath so the model preserved the founder's face while restyling everything else (clothing, lighting, backdrop, medium). Output lives at /img/headshot-styles/hs-*.jpg (~700KB each, lazy-loaded).
  • Tile interaction: hover lifts the card 2px with a brand-purple shadow, click adds a 3px brand-purple ring + a small check chip in the top-right of the thumbnail, the thumbnail gently scales 1.04× on hover for tactility. Grid is responsive — 4-column on wide desktops, 2-column at 540px and below.
Legal Room rebuilt around clarity, not a template dump
  • New "How it works" strip directly under the page header explains the lifecycle in four numbered steps: Pick a template → Edit in your voice → Sign & send → Push to the data room. Each step is one short sentence — "Company name, date and counterparty fields prefill automatically" · "Click anything to edit. Bold, italic, lists — autosaves every keystroke" · "Sign on a canvas pad. Counterparty signs at a private link; both signatures merge" · "Finalised PDF goes straight into your pitch's data room with full tracking". A founder landing on the page cold now understands the entire flow without clicking anything.
  • The nine templates are now organised into five clusters by moment in the fundraise, not a flat 9-tile grid. *Before sharing* groups the Mutual NDA + One-Way NDA (lock confidentiality before the deck leaves the room). *Investor signals interest* groups the LOI + Side Letter (soft commitment paperwork, non-binding outlines before lawyers get involved). *Investment paperwork* groups the SAFE + Term Sheet (the actual instruments — pick by stage and round structure). *People & partners* groups the MOU + Advisor Agreement (bring on an advisor, lock in a pilot, paper the relationship). *Custom* holds the Blank template for when nothing fits. Each cluster has a one-line editorial lede explaining the grouping so the founder isn't guessing what these documents have in common.
  • Every template tile carries a "When to use" line keyed by stage: *"Before sending your data room to a new investor"* (One-Way NDA) · *"After a soft yes — before drafting definitive agreements"* (LOI) · *"Pre-seed and seed rounds. Fast close, no priced valuation yet"* (SAFE) · *"Series A onwards, once you have a lead investor"* (Term Sheet) · *"When one investor needs terms different from the rest of the round"* (Side Letter) · *"When you bring on an advisor in exchange for equity"* (Advisor Agreement). Founders pick the right document by moment, not by reading legal jargon and hoping.
  • Typography pulled to a strict 4-tier scale — 10px mono caps for eyebrows + meta · 13px Inter Tight for body / ledes / descriptions · 16px Fraunces for tile names + step headings · 18px Fraunces for the hero lede only — across two font families. Was previously eleven distinct sizes across three families. Sans stack switched to the platform-standard 'Inter Tight', system-ui so the page reads the same as funding-tracker / events / pitch-interview rather than falling back to whatever default sans the OS provides (SF on macOS, Segoe on Windows, Roboto on Android — three different visual rhythms).
  • Alignment locked across the whole surface. Cluster eyebrows + ledes share a single flush-left edge (no decorative hairline pushing the lede to a different column). Template tiles use a fixed 36-px icon column with min-height: 92px so every tile in a row hits identical vertical rhythm — no more "this tile is taller because its description wrapped to two lines and the others didn't".
  • Density audit: cut the redundant "Templates" eyebrow row above the clusters (the cluster eyebrows ARE the section headings), the "Prefilled from your pitch" hint (was already said in the page lede AND in the how-it-works strip), the per-tile "Start this document →" CTA (the whole tile is clickable and lifts on hover; the CTA was decoration), and the duplicated what-it-is description on each tile (the "When to use" line is more actionable). Each tile went from five visual layers down to three — icon, name, one editorial line.
Sessions stay alive for 14 days, not 2 hours
  • The auto-logout-on-idle window jumped from 2 hours → 14 days (Config\Session::$expiration 7200 → 1209600). Founders were getting kicked back to /login on any nav click after lunch — if they left a tab open through a meeting and clicked the Investor link when they got back, the AuthFilter saw user_id = null (server-side session was already garbage-collected) and bounced them. 14 days matches what Linear, GitHub, Notion and basically every modern SaaS tool default to. Cookie max-age tracks the same value so the session cookie persists across browser restarts within that window.
  • The "Remember me" toggle on the login form now sends an actual remember: bool value to the server (it was previously sending nothing — the checkbox was purely cosmetic for as long as Pitched has existed). The server reads the flag and retains it for future per-toggle handling — an earlier attempt at per-login cookie-lifetime override conflicted with CI4's own session-cookie write path and broke logins, so for now every login gets the full 14 days regardless of the toggle state.
Funding tracker · Founders Day reinstated as two parallel sources
  • foundersday.co/startup-funding-tracker is back as an active source after sitting dormant since 2026-05-07. The trick: the page is an aggregator, not a publisher. Each card on it links out to the original announcement on Economic Times / Inc42 / Pulse / IAN / TechCircle / Business Standard / PRNewswire — not to internal /news/ pages. The first pass of the parser was looking for internal links and got nothing useful; the rewritten parser extracts external article URLs directly from the static HTML (39KB server-rendered, no JS needed), filters out asset hosts / social / navigation, requires a funding-signal keyword in the URL slug ("raises" / "funding" / "seed" / "series" / "round" / "crore" / "million" etc.), and derives a title from the slug (real URLs like instafix-raises-rs-7-55-crore-in-a-pre-seed-round carry company + amount + stage signal that the gate LLM can read directly).
  • Wired in as two parallel source entries. foundersday_html runs every cron tick (free, costs nothing — just a curl + regex extract). foundersday_fc runs once every 4 hours through Firecrawl (~6 credits per tick) to catch anything that's JS-only and missed by the static scrape. Both feed into the same gate → extract pipeline as every other source, with a pre-dedup on source_url so the same article that comes in through both paths plus our primary RSS feeds doesn't get processed three times.
  • Net effect: foundersday acts as a redundancy layer that catches funding announcements the primary feeds miss. Same-article dedup means it doesn't inflate the count when there's no new signal, but it picks up the niche outlets (PRNewswire press wires, IAN's own blog, smaller D2C-focused publications) that don't have first-class RSS feeds of their own.
Activity feed reads like English, not a log line
  • The founder dashboard's *Recent activity* feed used to render Anonymous viewer viewed Byde as the title, 21s · Bengaluru, IN as a body line, and 2m ago as a separate timestamp — three lines of muted text per row. It now reads as a single sentence: "A viewer from Mumbai viewed Byde on iPhone for 3m" with a small timestamp below in the standard activity-row style. Device label is derived from CI4's User-Agent parser (os + device_type columns on pitch_view_sessions): iOS + mobile → "iPhone", iOS + tablet → "iPad", Android + tablet → "Android tablet", Android + anything → "Android", macOS → "Mac", Windows → "Windows", everything else → "desktop". Location uses the existing IpGeo lib's ip_city (falls back gracefully if city isn't resolvable). When the viewer is identified (they signed in, opened a tracked-share NDA, etc.), "A viewer" becomes the actual name. Honest, scannable, and tells the founder what they actually want to know in one glance — who, where, what device, how long.
Per-pitch analytics "Traffic over time" chart now actually draws
  • The chart on /app/pitches/{id}/analytics was silently failing with Uncaught TypeError: Cannot read properties of null (reading 'save') inside Chart.js's render pipeline. Two stacked bugs, both invisible without DevTools open:
Funding tracker silently bailing after 1-2 items per run
  • A double-quoted PHP string in FundingTrackerService::aiExtract's system prompt contained "X raised $Y" — PHP interpolated $Y as a variable (undefined → empty string + PHP 8 warning), which had two compounding effects. First, the prompt the AI actually saw became "X raised " — less clear about what we were asking it to extract. Second, the Undefined variable $Y warning was being caught by the try/catch around processItem, setting the error column on funding_source_runs AND breaking the per-source loop after the first article. Every cron run was processing 1-2 items, logging the warning, and exiting — items_new had been stuck at 0 across most sources for a week. Escaped to \$Y. Immediately after the fix: techcrunch_rss went from 0 events/run to 1 new + 6 LLM calls, mint_rss to 2 new + 13 LLM calls, inc42_rss to 1 new + 3 LLM calls. Total flow restored.

v1 ⇄ v2 build chrome parity, Enhance wizard shared, visitor feedback unified, smarter nudges

A long quality pass that brings every build-mode surface into sync across both renderers (Modern / Showcase / Editorial / Dashy) so founders get the same UX no matter which layout their memo is on. Plus a marketing-home hero tightening and an editorial activity feed.

Enhance wizard everywhere
  • The full 4-step Enhance wizard — Fraunces + Inter, brand-pink chrome, progress dots, segmented tabs, spring-pop animations, Unsplash search + AI generate + Upload header step → 8 curated brand-palette tiles → single-image upload → Done — now runs on every layout, not just Modern. Extracted from v2's inline copy into a new shared partial at partials/_enhance-wizard.php (~568 CSS / 126 HTML / 496 JS, all self-contained), included by both skeleton-v1.php and (next session) skeleton-v2.php. The wizard's JS binds to both #pbEnhanceBtn (v1's top bar) and #ptEnhanceBtn (v2's top bar) so a single source of truth powers both. window.openEnhanceWizard() exposed for any programmatic caller (thermometer click router, future toolbar tooltips).
Visitor feedback FAB unified
  • The brand-pink floating feedback FAB (Message founder / Section feedback / Overall feedback) used to live as ~760 inline lines in skeleton-v1.php only — Modern had no FAB at all. Extracted into partials/_visitor-feedback.php and included by both renderers. Same hover halo + cookie-based anonymous capture + 5-minute idempotency window + founder inbox notification fanout.
  • Section picker now works on Modern too. The "Feedback on a section" dropdown was empty on Modern because the picker only matched section.sec[data-section="…"] (v1's markup). Modern emits sections as <section class="sec" id="story"> instead — no data-section. Picker now matches both shapes, reads the key from data-section || id, and pulls a friendly label from .sec-eye (v1) or .eye (v2) or the inner h2/h3. Same fix applied to the section-react widget mount.
  • FAB icon + theme color on Modern. v2 was loading no FontAwesome, so <i class="fas fa-message"> rendered as a blank glyph and the FAB looked like an empty pink dot. Added the FA CSS link to v2 + aliased --rail-bg and --primary to v2's --p so the shared partial picks up the pitch's brand color the same way v1 does.
Gallery image delete on v1
  • Per-tile × button on hover (revealed by mouseover, 28px circle, glass-blur with brand-pink border on hover state) + a "Remove gallery" pill in the section header. Both wired through /skeleton-patch with native confirm() before the destructive write. Matches the pattern v2 already had.
Company identity editor
  • New "Company" section in the build-toolbar drawer (Modules chip → Company) lets founders edit company name, tagline, website URL, and logo URL from one panel. Was previously only reachable by clicking the hero in build mode (and the website field had no UI at all). Available on every layout.
  • Website chip in Modern's hero meta row. Sits right after "Raising" in the Founded / Team / Raising / Website / Pre-money strip — clickable underline link, opens in new tab, hides clean if the founder hasn't set a website yet.
Activity feed redesigned
  • Founder dashboard "Recent activity" rows used to read Anonymous viewer viewed Byde / 21s · Bengaluru, IN / 2m ago — three lines of muted text. Now reads as a single bold sentence: "A viewer from Mumbai viewed Byde on iPhone for 3m" with a small timestamp below. Device label derived from CI4's UA parser (iPhone / iPad / Android / Android tablet / Mac / Windows / desktop). When the viewer is identified, "A viewer" becomes the actual name. Honest, scannable, and tells the founder what they actually want to know in one glance.
Completeness thermometer routing
  • Smart click destinations. The thermometer at the bottom of the floating toolbar used to always open the Enhance wizard regardless of what the nudge said — clicking on "Define the problem you solve" would open the gallery wizard step (because the wizard remembered the last step you visited). Now each item in PitchCompleteness carries a target field that tells the click router exactly where to go: a section editor drawer (Story, Market, Team, Ask, Model, Competition…), a toolbar chip popover (Insert / Modules / Numbers), a specific button id (Data Room split / Publish), the recorder modal (45-second elevator pitch), or a wizard step (Header / Theme / Image). Router tries DOM matches first (v1 + v2 selectors), then opens the editor drawer for the matching key, then falls back gracefully. Section flash is now a strong pink wash + outline that lingers 2.6s so the destination is unmissable.
  • Filled-checks read both shapes. Real pitches store problem / solution / why_now as either a plain string OR an object with statement / summary / description / body / text / points keys (the digester stores them as plain strings; the older check missed the string path and kept nagging founders even after they'd filled the field).
  • Thresholds relaxed so partial fills move the needle. One ARR or MRR or customers number tips traction. Any of TAM / SAM / SOM / CAGR / tailwinds tips market. Any founder with bio OR photo (not both on the same row) tips founders. Two competitors instead of three. The bar now actually moves when you make a single edit, instead of staying stuck until you hit some arbitrary list-count threshold.
  • Tooltip is clickable now. The "Click for a guided nudge →" tooltip had pointer-events: none and an 8px gap between the bar and the tooltip that killed :hover when the cursor tried to reach it. Added an invisible hover-bridge + enabled pointer-events: auto when shown + cursor: pointer. Now the whole tooltip is the click target.
Marketing home hero polish
  • The "Deck to live investor page in 60 seconds" hero on /home got a tightening pass. Left column type pulled back (H1 clamp 36-58 → 32-52, "60 seconds." big number 3-5rem → 2.6-4.4rem, step rows from 12px / 52px padding to 8px / 44px, step number 32 → 28px, sub paragraph 540ch / 24px below → 500ch / 18px below). Phone visual on the right nudged ~48px lower so it visually balances the (taller) left column instead of floating at the top. Top padding tuned to 55px on desktop / 104px on mobile so the H1 clears the fixed nav cleanly on first paint — no more "Deck to live" tucked under the nav.
Editorial typography on v1
  • v1 now has the same $rich() helper v2 has — bold / italic / line break / paragraph / heading tags pass through cleanly on problem, solution, why_now fields, with everything else stripped. Previously when Modern saved <b>IRIS</b> provides…, v1 would render the literal <b> text. Now v1 displays the same formatting as v2.
Floating toolbar lift
  • Toolbar moved from bottom: 88px to bottom: 138px so the thermometer tooltip below has full viewport-edge clearance and dropdowns above the bar have room to render without scrolling the page.

2026-05-21 (late) — v1 toolbar parity, completeness thermometer everywhere, smarter nudges

Closes out the day with three quality passes on the build-mode chrome.

  • Premium toolbar chrome ported into the shared partial. The floating build toolbar on Showcase / Editorial / Dashy layouts (v1) now uses the same chrome as Modern (v2): lifted to bottom: 88px so the thermometer tooltip below has clearance, deeper glass (36px blur), 1px outer hairline + inset highlights + 4-layer drop shadow, and data-pt-chip attribute selectors driving the group dividers between Insert · Layout / Theme · Format / Modules · Numbers / AI (survives the dynamically-injected drag grip, which used to break the old nth-child(...) rules). AI chip carries a permanent pink icon + pink halo on hover. Drag grip now uses align-self: stretch so it centres vertically against any chip height.
  • Completeness thermometer on every layout. The pink → purple → blue gradient bar that hangs along the bottom of the toolbar — with tick marks at the 20% Foundation / 45% Investor-ready intro / 70% Memo-worthy milestones, hover tooltip showing percentage + milestone label + the next-best nudge, click jumps into the Enhance flow — now ships through the shared partial. v1 layouts get the same Pitched-signature mark as Modern.
  • Popovers anchor to whichever chip opened them. When the toolbar is dragged across the viewport (or the window resizes), any open popover follows the chip — positionPop() measures the active chip + popover, prefers above-the-toolbar with an 8px gap, flips below when headroom is short, clamps horizontally to viewport edges. No more "modals fixed in place while the toolbar moves underneath."
  • Smarter completeness scoring — stop nagging for things you've already done. The "next nudge" used to recommend Pick a header image even when the deck cover was auto-filling the slot (the renderer falls back to PT_DECK_COVER when display.hero_image_url is empty). Same for Choose your brand colours (the deck/website crawl had already extracted primary_color / accent_color) and Drop in an in-body image (the founder had a gallery, just not single figures). PitchCompleteness now counts: any pitch with a digestion_id or hero_image_source flag as having a header, any pitch with an extracted primary/accent colour as themed, and any of display.figures / display.gallery.items / display.gallery.images / product.screenshots as having imagery. The thermometer now points at the highest-weight thing that's actually missing.
  • Toolbar position no longer persists. Dragging the toolbar mid-session moves it for the session only — switching memos or coming back later resets to default centred. Removes the "where did my toolbar go" disorientation.

Pitch Interview launches; dashboard rebuilt around live preview; funding tracker auto-discovers investors

The biggest single-day platform expansion yet. Founders get a real-feeling AI investor to practice against. The dashboard goes from list-of-rows to a hero live-preview tile of their latest memo. The funding tracker stops treating clickbait headlines as company names and starts compounding every funding event into our investor universe. Events know where you are. Plus a handful of platform-wide polish hits.

Pitch Interview
  • /app/pitch-interview — practice a real call. Founder picks one of six investor personas + one of their memos, confirms the country / sector / stage we auto-extracted from the memo, hits Begin — and inside a second is on a live voice call. The agent has read their memo and opens with a persona-specific first question. 10–15 minutes, full-duplex, interruptible. Ends with a five-dimension score (Clarity / Market sizing / Traction credibility / Founder presence / Question handling) + a punch list of what to tighten + a few quotes worth keeping from the transcript.
  • Six personas across named funds and archetypes. Karan Mehta (Peak XV — India growth, unit-economics-first), Marcus Reeves (a16z — non-consensus thesis, "what does the world look like in 10 years"), Diane Holloway (Accel — moats + pattern matching), David Chen (Sequoia — first-principles, "why now"), The Skeptic (devil's advocate, presses every number), The Visionary (category-defining ambition + 10-year story). Each persona has its own thesis block (loaded into the system prompt), tone descriptor, ~6 signature questions, and a uniform editorial portrait.
  • Per-persona voices. Karan → Ruhaan (Indian English, conversational — added to our voice library via API). Diane → Alice (premade British, Clear/Engaging). The Visionary → Matilda (premade American, Knowledgeable/Professional). Marcus / David / The Skeptic use the default Mark voice for v1. The voice override is plumbed through overrides.tts.voiceId on the SDK session start, so any persona can be swapped to any library voice with a single UPDATE.
  • Voice loop via ElevenLabs Conversational AI (@elevenlabs/client over WebRTC, ~400ms end-to-end latency). Server mints a single-use signed conversation URL — API key never touches the browser. Per-session dynamic variables inject the full persona system prompt + memo digest + country/market/stage context. Owner-embed authentication so drafts can be previewed without publishing first.
  • Live session UI at /app/pitch-interview/{id}/live — full-screen, charcoal background, 320px persona avatar that breathes + glows pink when the investor is speaking, animated 5-bar waveform underneath, 15:00 countdown that turns amber at 2:00 and red at 0:30. Mic indicator + last two caption lines (founder + investor turns) along the bottom.
  • Time-limit banner under the top bar. Default state: "15-minute practice session" in calm grey. At T-2:00 the banner switches to pink-tinted "Wrapping up — 1:42 left · Upgrade for longer calls →" with a gradient-pill CTA pointing at /billing. Visual cue + agent-side prompt instruction reinforce the same wrap timing.
  • Scoring at /app/pitch-interview/{id}/results. Single GPT-4o call after the session ends (fired via register_shutdown_function so the founder gets an immediate redirect and the page polls for completion). Five dimensions 0–100 with one-sentence notes each, overall score with letter grade (A/B/C/D/F) in a color-coded ring, 3–5 "what to tighten" bullets tied to specific moments in the transcript, 2–3 "quotes worth keeping" the AI flagged as strong, full transcript collapsed below.
  • Prompt discipline. The agent is told to be a VC, not a coach: push back on weak numbers, ask one thing at a time, mix easy and hard questions, never recite the memo back, never fawn. Time discipline is explicit — "the system will end the session at 15 minutes; you do NOT call end_conversation early. If you feel you've covered the basics, go DEEPER on a previous answer." Wrap only when the founder themselves signals it.
  • Cost controls. 10 sessions/day per founder (master accounts unlimited). 60 minutes/month per tenant. 15-minute hard cap. ~$2 per session ($1.80 ElevenLabs + ~$0.30 GPT-4o for scoring).
  • 8 API endpoints under /api/pitch-interview/* (investors / preflight / start / transcript-append / end / show / sessions / delete). All TenantModel-scoped + explicit tenant_id guards on session ops.
  • 2 new tablesvirtual_pitch_investors (canonical persona catalogue) + virtual_pitch_sessions (tenant-scoped, with transcript_json + scoring_json + duration_seconds for usage tracking).
Dashboard rebuilt around the live preview
  • Featured live-preview tile for the most-recently-edited memo. Iframes /{slug}?embed=1 so it always uses the actual live template (skeleton-v1 or skeleton-v2 — whichever the founder picked), never the legacy renderer. Browser-like 16:10 aspect, lazy-loaded via IntersectionObserver, auto-scaled to fit the tile. Click anywhere → opens build mode. Hover shows an "Open in build mode" pill at the bottom-right.
  • Live · List toggle in the section header, persists per-founder in localStorage. Live = featured tile + compact rows for older memos. List = all memos as compact rows (for founders with many memos / versions).
  • Compact memo rows — logo, name, status chip (Draft v3 / Published v2), view/unique/conv stats. A menu on each row offers Open in build, Preview (new tab), Numbers, Analytics, Duplicate for another investor, Delete.
  • Duplicate flow — one click → POST /api/pitches/{id}/duplicate → server clones the row + skeleton_json + display_json + all sections → redirects to /app/pitches/{newId}/build ready to edit a new version for a specific investor.
  • First-run empty state. When zero memos, the entire memo block becomes a single hero with a 3-step explainer (Upload deck → AI builds → Share & track), a big pink "Upload your deck" CTA → /app/pitches/studio (the cinematic multi-file uploader), and a "Don't have a deck yet? Start with the guided wizard →" secondary link.
  • Owner-embed mode added to PublicPitchPage::show and ::showV2. When the session owns the pitch and ?embed=1 is set, drafts render the actual live page (no 404, no forced-showcase layout-override) — what powers the dashboard preview tile. Marketing-slider use case (anonymous embed) still forces showcase for backward compat.
Funding tracker auto-discovers investors
  • Every funding event we ingest now enriches our investor universe. After each processItem insert, InvestorAutoDiscovery::processFundingEvent() runs each named investor (lead + participating) through: clean → normalise (strip "Capital", "Ventures", "Partners", "LLC" etc.) → fuzzy match against existing canonical investors rows. Existing rows get mention_count += 1 and last_seen_at = NOW() (no LLM cost). New names get a single gpt-4o-mini enrichment call (~$0.002) returning website / HQ / stage focus / sector focus / 1-line description + per-field confidence, inserted with is_auto_discovered=1, is_verified=0.
  • Curated investor universe untouched. Existing 327 hand-curated rows now carry is_verified=1, is_auto_discovered=0. Matrix matcher's deterministic prefilter still only consumes verified rows — auto-discovered rows pile up for manual review without polluting recommendations.
  • Noise filter rejects "Undisclosed", "Multiple investors", "Angel investors", "TBD", "Existing investors", etc. — keeps the discovery queue clean.
Events know where you are
  • Dashboard events block. Right column now stacks Latest funding (bumped from 6 → 10 rows) + Upcoming events. Events filtered by the founder's IP-resolved country via IpGeo (same library that enriches pitch-view analytics), cached in session for 24h so we hit ip-api once per founder per day. Sort priority: events in their city first → events in their country → online events. Within each tier, soonest-first. Section header reads "Events in {City}".
  • /app/events page also auto-locates. Lands filtered to the founder's country with a city-priority sort. Eyebrow shows a green "· in {City}" tag. Lead paragraph carries a "Showing events in {City}. [Show all globally →]" escape hatch via ?country=all.
  • Funding rows on the dashboard link internally to our own /funding-tracker/c/{company_key} detail page (multi-source coverage, investor pills, KPI tiles) instead of bouncing founders to TechCrunch / Inc42 / etc.
Data Room quick-add from the build-mode top bar
  • The Data Room button in the build-mode top bar (both Modern v2 and Showcase / Editorial / Dashy v1 layouts) is now a split-dropdown. Click it → small menu with Quick add (opens an in-place upload modal — drag/drop a file, pick a doc type from 9 categories, optional name + description, POSTs to the same /data-room/upload endpoint the full page uses, success → toast + modal closes) or Go to data room (navigates to the full page like before).
  • Saves the round-trip when the founder is mid-pitch-edit and wants to attach a financial model / term sheet / cap table without losing their place.
Enhance wizard in the build-mode top bar
  • New Enhance button in the build-mode top bar (pink-tinted, sparkles icon, between Preview and Numbers). Subtle pink pulse on first visit per pitch — cleared once the founder opens it.
  • Three-step guided modal that surfaces the tools founders miss most: header image (Search Unsplash with auto-prefilled query · Generate with AI · Upload) → brand colours (8 curated palettes as swatch tiles, live-recolours the page behind the modal) → add an image (drop zone for a single in-body figure). Each step has a Skip option; Continue is gated until something is applied.
  • Done step animates a green check with discovery tips for the rest of the toolbar (record elevator pitch, click any text to edit, change theme again, add more from Add tab).
  • Every step posts to the same endpoints the existing toolbar uses (/use-image-direct, /enhance-image, /upload, /skeleton-patch) — pure discovery layer, no parallel system. Theme step auto-skipped when skeleton.theme is already set, so returning founders aren't re-asked.
  • Form alignment on the Pitch Interview landing. Memo dropdown, the three context inputs (Country / Sector / Stage), and the notes textarea now share one shape: 46px height, 12/14 padding, 14px font, 10px radius, identical focus state. Labels shortened to single words so they don't wrap unevenly.
  • Avatar consistency. Every persona portrait regenerated with one uniform template — same neutral medium-grey studio backdrop, same three-point lighting, same tight head-and-shoulders crop, same 1:1 aspect, no environmental context. The portraits all look like they're from the same shoot.
  • Page-content top padding tightened from 28px → 10px across the platform (16px → 10px on mobile, 12px → 8px on phones). Prism page headers now sit close to the topbar instead of floating 28px below it — better use of vertical space on every authed page.
  • Funding limit on the dashboard bumped 6 → 10 rows. The right column has the height now.
  • Investor Intel sidebar link hidden. Restored when the exchange feature opens (one-line uncomment in CrmModules.php).
  • Actions Required strip hidden on the founder dashboard. Restored by removing a false && guard.
  • System prompt for the Pitch Interview rewritten to forbid early end — agent uses the full 15 minutes, goes deeper on previous answers when it feels topically done, only calls end_conversation when the founder explicitly signals wrap.
  • Dashboard live-preview was hitting the legacy renderer. First version iframed /app/pitches/{id}/preview which falls through to PitchRenderer + master.php when display.layout isn't 'modern' — that path is dead code (the one with the Light/Dark toggle + "Built with Pitched" footer). Switched to /{slug}?embed=1 which auto-routes to the actual live template per memo. Owner-embed bypass added to both show() and showV2() so drafts render too.
  • Pitch Interview dynamic variables weren't injecting. The live JS was preparing the dynamic-variables blob server-side but never actually passing it to the SDK — the agent was getting raw {{system_prompt}} placeholders instead of substituted text, so it acted as a generic chatbot. Now sends dynamicVariables + overrides.agent.prompt.prompt + overrides.agent.firstMessage + overrides.tts.voiceId on every session start.
  • Avatars landed in the wrong directory on Hostinger. The GeminiImageService::generateBanner path saves to uploads/{tenantId}/headers/ which on Hostinger's split layout resolved to public/ instead of public_html/ — making them invisible on the web. Added a GeminiImageService::generatePortrait() entry point that doesn't carry the banner-style prompt scaffolding (which was contradicting our square-portrait spec). Seeder now uses that + writes a stamped ?v={timestamp} cache-bust on avatar_url so future regens load fresh without manual cache-bumping.
  • Diane and The Visionary had male voices. First pick was Jodi (Indian English female via shared library) — but shared-library voices need to be POST /v1/voices/add-ed to the workspace before agents can override to them, and they weren't. Swapped to premade voices that are always on the account: Alice for Diane, Matilda for Visionary, Ruhaan added via API for Karan.
  • TechFundingNews articles were being saved with the article HEADLINE as the company name ("The missing piece in crypto's financial infrastructure", "The startup that catches malicious code in minutes"). Fixed at two layers: (1) explicit prompt rule that company_name must be the actual company from the BODY, not the title, with editorial outlets called out by name; (2) server-side looksLikeHeadline() guard that rejects sentence-shaped names (6+ words, >60 chars, mid-string lowercase function words like "the/in/for/missing/piece", trailing ?/!) before saving. Existing 2 confirmed bad rows scrubbed; real names like "Wow! Momo" and "House of Chikankari" preserved.
  • Events block on the dashboard said "no events scraped yet" despite 88 future events in the DB. Two bugs stacked: (a) the SELECT included a slug column that doesn't exist (the table uses source_id as the URL handle), causing a silent column error; (b) the empty-state copy used the word "scraped". Both fixed — internal language is now neutral ("no upcoming events right now — browse the directory").
  • Per-persona Pitch Interview voices weren't switching even though voice_id was set on the persona row. The blob passed from /start was missing the voice_id key — the landing page wasn't including it in the sessionStorage handoff. Fixed; voice now switches per persona on every session.
  • Pitch Interview was wrapping early (around minute 10 of 15). Agent's discretion to call end_conversation was triggering once it felt topically complete. Prompt now explicitly forbids early end + gives concrete "go deeper" moves when running out of new topics.

2026-05-20 (morning) — Header system unified on prism, event bookmarks, sidebar auto-hide, data-room fixes

Follow-up pass to the night's work. Walked back the editorial header experiment after seeing both side-by-side — the prism pattern on /app and /app/pitches was preferred, so every other authed page now matches it. Plus event bookmarks, sidebar scrollbar polish, and three data-room bugs.

  • Prism header pattern unified across the authed app. Ten pages reverted from the editorial pink-border headline back to prism-page-header (coloured dot + "Group · Tag" eyebrow + Fraunces headline with accent--{colour} span + lead). Each page picked its own dot + accent colour from the four available variants:
  • Data room was stuck on "Loading documents…" forever. The page's inline IIFE called load() synchronously during HTML parsing, but api-client.js (which defines CrmAPI) sits at the bottom of main.php *after* the page content block. CrmAPI was undefined when CrmAPI.get() ran, throwing synchronously and never reaching the .then() or .catch(). Every other page on Pitched dodges this by initialising inside DOMContentLoaded; data-room was the holdout. Fix: wrap the IIFE's bottom load() call in a readyState === 'loading' ? DOMContentLoaded : load() guard. Also added a visible error message + console.error on the load promise's .catch so any future silent breakage is immediately visible instead of presenting as endless spinners.
  • Approve + Deny buttons on access requests rendered as 32×32 squares clipping their text. The base .dr-act class is sized for icon-only buttons (rename / delete / revoke). The request row reused it with text labels — "Approve + send link" doesn't fit in 32px. Added a .dr-req-actions .dr-act override scoped to the request row only: auto-width pill, 8px × 14px padding, Inter Tight 600. Primary variant is now solid pink with a subtle pink shadow; secondary is outlined and inverts to dark on hover. Icon buttons elsewhere keep their square look.
  • Event card bookmark was overlapping source-chip + price-label on cards with full footers because it was positioned bottom-right over the variable-height foot row. Moved to a fixed top-right corner of the cover image (10px / 10px), shrunk from 36px → 30px, dropped the heavy border for a glass-blur background with a small drop shadow. Always in the same place regardless of card content; doesn't obscure anything.

Events directory, Memos rename, editorial header pass + typography unification

Day-long pass: shipped the events directory, renamed pitches to memos in the UI, refreshed the funding tracker, and unified typography across every public-facing surface.

  • Events directory at /app/events. New pitched_events table + EventScraper library + PitchedEventModel. Pulls upcoming startup events from foundercal.com (which already aggregates Luma + Meetup) plus targeted India city sweeps for Mumbai, Delhi and Bangalore. Filters: city / source / online or in-person / search. Sidebar entry under Intelligence available to every persona.
  • Event detail pages at /app/events/{slug}. Clicking a card stays on Pitched — hero with cover image (or gradient + icon when no cover), full body text, venue + host, RSVP CTA labelled per upstream platform ("RSVP on Meetup" / "RSVP on Luma" / "Get tickets on Eventbrite" / "RSVP on Partiful"), date card with 2px pink stroke, related events from the same city in the sidebar, share-link copy.
  • JSON-LD parser + second-pass image fetch. Scraper reads schema.org Event blocks for structured data, then falls back to the upstream Luma/Meetup page for og:image when foundercal doesn't carry the cover. Result: ~95% of events render with real cover images. Title-case rule converts SHOUTY titles ("STARTUP FOUNDERS MEETUP BY CEDAT NEXUS" → "Startup Founders Meetup by CEDAT Nexus") with a brand-acronym allowlist (CEDAT / VC / AI / IPO / GTM / etc.).
  • CDN deep-linking for trusted hosts. Luma + Meetup + Eventbrite + Partiful images render straight from their CDN. Anything else gets mirrored to public_html/uploads/_events/ so link rot doesn't bite. Missing covers render as a deterministic gradient + Font Awesome icon (9-palette rotation hashed by event id), consistent index → detail.
  • Day-granularity archival. Events show on their date and retire at midnight via DATE(starts_at) >= CURDATE(). New pitched:archive-past-events spark + matching demoter inside pitched:scrape-events. Past-event banner on detail pages.
  • Cron endpoints at /cron/pitched/events-scrape and /cron/pitched/events-archive, token-gated, wired to cron-job.org (foundercal-india every 4h, all sources every 6h, archive daily at 00:15 IST).
  • Pitches → Memos UI rename. Sidebar, headers, CTAs, empty states, modals, page titles across pitch-list.php, pitch-create.php, pitch-studio.php, pitch-wizard.php, founder-dashboard.php, founder-feedback.php, founder-intel.php, billing.php, the founder-app layout, and the build-toolbar publish toast. Plus DashboardSurfaces action-strip ("Draft memos to publish") and DashboardInsights auto-insight copy ("Your memo is heating up"). Internal routes, controllers, DB columns, and asset paths untouched.
  • Wishlist → Potential Investors. Sidebar label + visible headline + empty-state copy on /app/wishlist. Backing table/route stays.
  • Funding tracker editorial rebuild. Same content, cleaner skin. Editorial header (pink left border, Inter Tight eyebrow, Fraunces 500 headline with pink italic em). Single hero stat — one big tabular $X.XB raised this week with delta plus 3 supporting columns (deals, top sector, most active lead). Compact controls bar: pill window-tabs (7d / 30d / 90d), search, four filter selects, "Tune ▾" reveal that collapses the region slider + sector chips by default. Cleaner editorial event rows — Fraunces company name, Fraunces tabular amount on the right, Inter headline, single "Led by X · Sector · Geo · Source" meta line. Three charts moved to a bottom "The shape of the week" strip. Full-width container.
  • Editorial header pattern applied across Intelligence + Origination + Tools. /companies, /companies?sector=…, /feed, /funding-tracker, /app/events, /investors, /app/coach, /app/headshot-studio all share the same chrome now: 2px pink left border, Inter Tight uppercase eyebrow with letter-spacing, Fraunces 500-weight headline with pink italic em, Inter Tight lead. Every page fills the layout's full content area instead of clamping to 980/1240px.
  • Shared build toolbar across every pitch layout. Modern (v2), Showcase, Editorial and Dashy now load the same public-pitch/partials/build-toolbar.php partial — the floating chrome with chip + popover + per-section drawer + AI Coach panel + Modules count badge + share modal that previously only existed on v2. Extracted from skeleton-v2.php lines 6155-10084 (full chrome: pt-tb, pt-pop, pt-sheet, pt-mod, pt-toast, pt-bubble, pt-share, pt-rec, pt-gal, pt-reframe, pt-hdr, pt-fig, pt-studio, pt-coach) plus the per-section drawer block. Tokens are scoped to toolbar surfaces only (.pt-tb, .pt-pop, .pb-drawer-v2) so theme fonts on the page content still differ per layout — that's intentional. Includes the drag-handle CSS+JS, heavier shadow, and a hide-v1-chrome CSS rule that suppresses the old #pbBar / .pb-drawer while build mode is active.
  • v1 per-section editor schema upgraded to v2's full 235-line registry. v1's slim path+label $sectionEditors replaced with v2's full schema including kind, placeholder, item_fields — so every section in every theme now opens the same rich drawer (text / longtext / tags / list / bespoke kinds) when you tap edit. Defensive CSS token fallbacks scoped to toolbar elements only so theme fonts don't bleed into the toolbar chrome.
  • Typography unification — one source of truth. New partials/typography-tokens.php emits the canonical font load (Fraunces + Inter Tight + JetBrains Mono) and the three CSS vars: --serif, --sans, --mono. Wired into layouts/main.php, layouts/founder-app.php, the auth surfaces (login / signup / verify / verify-error), every marketing page (home / about / privacy / terms), the public data-room flow, the public legal-sign flow, and the public invoice template. Instrument Serif and IBM Plex Mono retired everywhere. crm.css + editor.css body fonts now resolve through var(--sans).
  • Body text on every authed page. crm.css body font went from literal 'Inter' to var(--sans) resolving to Inter Tight — small but visible improvement: tighter letter-shapes, better at small sizes.
  • One Google Fonts request per page. Was 1–3 overlapping family loads across login / signup / marketing / data-room / invoice. Now every public surface hits the same single URL — cache-friendly.
  • Memo rename copy. Action-strip "Draft memos to publish", auto-insight "Your memo is heating up", "Refresh memo", "Open memos" — wherever the dashboard surfaced pitch-language, it now reads memo-language.
  • Sidebar drift. Founder-app shell had its own hardcoded "Pitches" label separate from the CrmModules-driven sidebar. Both now say "Memos".
  • Browser tab titles. My Memos — {tenant}, New memo — Pitched, Build a memo — Wizard — pulled into rendering via the same renderPage path.
  • Funding tracker event row. Sources column shows max 3 chips with a +N for overflow. Source labels show the real upstream ("Meetup" / "Luma" / "Partiful" / "Eventbrite"), never "Foundercal" — that's our scraper origin, not the destination a founder cares about.
  • Date card on event detail pages was rendering translucent over the hero image. .ed-hero__inner had no explicit z-index, so the .ed-hero__veil (z-index 3) rendered on top of the date card. Bumped the inner to z-index 4, replaced the translucent white border with a solid 2px pink stroke, deeper drop shadow. Reads as opaque now.
  • Auto-insight cache stale on prod. DashboardInsights writes to writable/cache/dashinsight_* and TTLs through tomorrow. After the memo-rename deploy, founders still saw "Your pitch is heating up" because the cached blob predated the code change. Cleared once on prod.
  • Generated image fallback path on Hostinger. Initial scraper run wrote _gen.jpg fallback images to public/uploads/_events/ (CI4 FCPATH) which isn't web-served on Hostinger's split layout — actual web root is public_html/. Fixed the upload-dir picker to prefer public_html when present, relocated 76 existing files, and replaced the entire GD-based header generator with CSS gradient + icon (lighter, responsive, no baked text).

2026-05-16 → 2026-05-18 — Interactive Financial Plan: native xlsx ingest, formula DAG, founder-confirmable plan view

The biggest single feature shipped to Pitched. Founders can now upload their actual financial model (xlsx / xlsm / xlsb / csv), and we parse it natively — every cell, every formula, every sheet — into a normalized, interactive plan that lives at /v2/{slug}/plan. Investors play with the levers (sliders, drag-scrub inputs, scenario tabs); founders confirm in 90 seconds; both round-trip through the same plan_json source of truth. Nobody else does this: Causal / Cube / Pigment all force founders to rebuild their model in a proprietary DSL. We preserve the original formulas and DAG and let the founder confirm what we read.

  • /v2/{slug}/plan — interactive plan view. Editorial layout in Modern's design tokens (Fraunces + Inter Tight + JetBrains Mono numbers). Scenario pills swap snapshots. Growth-at-a-glance KPI strip. Sticky use-of-funds donut + slider grid. Year-tab rollout timeline with city tiles. Macro service-category cards with Y1/Y2/Y3 toggles. Dark P&L grid with click-to-expand "show the working" formula reveal — chips for each input lever, source citation (Sheet 'Assumptions' · B12), scroll-flash to the upstream lever. Currency picker (₹ Cr / ₹ M / ₹ Lakh / $ M / $ K / $ B / € M / £ M). Magnitude-aware drag scrubber on every numeric value (1px = 1% of value; Shift = 10×; Alt = 0.1×) with live "from → to (±%)" delta badge. Investor what-if scrubs never persist — only build-mode edits save back.
  • Native xlsx ingest, no DSL rewrite. Founders drop their actual model. XlsxStructureReader (PhpSpreadsheet 4.x) captures every cell: value (prefers getOldCalculatedValue() — Excel's last-saved cache), formula, address, number-format, currency-from-format-code, unit-from-format-code. Classifies sheets by name + cell signature: assumption / pnl / scenario / presentation / data / mixed. Detects year axis from text headers ("FY26") AND integer headers (2026 as a number). .xlsb falls through to LlamaParse fallback (PhpSpreadsheet 4.x doesn't ship .xlsb).
  • XlsxDependencyGraph — formula DAG over the whole workbook. Tokenises every formula (sheet-qualified refs, same-sheet refs, range expansion with 2k-cell cap, named ranges), builds precedents[address] + dependents[address] maps with topo-sort. Powers the show-the-working chips, the diff verification gate, and per-assumption sensitivity scoring (precedent walk → how many P&L rows depend on this lever).
  • SectorClassifier — 9 sectors auto-detected. lending / saas / hotels / restaurants / d2c / ev / marketplace / manufacturing / logistics / generic — picked from sheet names + label patterns (e.g. RevPAR/ADR/occupancy → hotels; AUM/NIM/yield → lending; AOV/CAC/LTV → d2c). Sector label-boost map threads into the candidate picker scoring AND the AI naming prompt's sector conventions so terminology stays correct ("Loan Book" stays "Loan Book" for lending, not generic "Revenue").
  • FinancialPlanDigester::fromXlsx() — narrow AI naming pass with full pitch context. Picks candidate assumption cells (leaf numeric with adjacent label) + P&L rows (numeric across year columns with year-coverage + variance + magnitude score), runs ~3k-token gpt-4o pass that only proposes labels + section grouping — no extraction, no math (those come from the xlsx itself). Prompt includes a structured pitch-context block (buildPitchContext()): company name, tagline, sector (founder-stated + auto-detected), stage, geography, problem + solution, business model, revenue streams, TAM/SAM/SOM, existing pitch traction metrics, declared unit economics, funding ask + use-of-funds, milestones, competitors. AI matches founder's existing terminology from the pitch instead of inventing new labels.
  • Founder confirmation drawer. Review button in build chrome opens a side panel listing every captured assumption + P&L row with checkbox + confidence badge + source citation. Founder un-checks the noise; un-checked items are excluded from the rendered plan but remain in plan_json._review.excluded so the choice survives re-ingest.
  • Sync-to-pitch. One-click pushes plan back into the main skeleton (use_of_funds, asking_amount, unit_economics, financials.projections, summary.elevator). One-way, confirmation-gated. Closes the loop: the plan's numbers become the pitch's numbers.
  • Sensitivity bars per assumption. Each lever shows a precedent-count-driven importance bar — "this assumption drives 12 P&L rows downstream" → high-importance treatment. Plus top_dependents[] array so the show-the-working panel can name the rows that move when you pull the lever.
  • Diff verification gate. After AI naming, plan_json's computed values get checked against the xlsx's getCalculatedValue() cell-by-cell. Anything off by >0.5% lands in _diff_warnings[] so the founder sees mismatches before publishing.
  • Magnitude override for INR formats. If ,, (millions-scale) detected in number formats but median P&L revenue is <500, override to Cr. Indian convention; covers 95% of the test corpus.
  • 22-file regression harness. fin_models/fixture_report.php re-runnable any time the digester changes. 16/22 parse cleanly with 4 growth metrics each. 3 .xlsb files trigger the LlamaParse fallback. 3 files >20MB skipped by the harness's memory guard (prod accepts up to 50MB).
  • Density on early-stage decks. The plan view backfills growth_metrics from funding.asking_amount, valuation.*, market.{tam/sam/som/cagr}, unit_economics.*, and financials.projections[last].revenue when the xlsx is thin or skeleton-only. The KPI strip stays full whether the founder has a 100-tab model or just summary.financials_callouts.
  • Mobile pass on the plan view. Donut stacks above sliders. P&L grid collapses to 1-col with sticky year header. Show-the-working opens as a bottom sheet on phones. Sliders fill width with 44px touch targets.
  • Plausible-but-fabricated values. Native parsing means every number on the plan page is a real cell in the founder's actual workbook. The AI proposes labels for cells that EXIST; it never invents the values. (vs. the v2 page's source-anchoring approach, which catches hallucinated values *after* extraction — here we never let them happen in the first place.)
  • Excel auto-calc unreliability on complex models. Re-computing formulas server-side via PhpSpreadsheet is fragile on large models. getOldCalculatedValue() reads Excel's last-saved cache instead — the value the founder actually saw when they closed the file, which is what the deck quotes too.
  • Stale plans after pitch edits. Sync-to-pitch is one-way (plan → skeleton). The plan doesn't auto-rebuild from skeleton edits — that would silently overwrite the founder's xlsx-anchored numbers. Founder triggers re-ingest explicitly if they want to re-pull from the model.

2026-05-18 (late) — Companies directory: Phase 4 + 5 — heatmap, country chips, UK seed, 2026 trending names

Extending the Companies directory two more cuts the same evening.

  • UK seed (Phase 5)app/Data/companies-seed/uk.yaml: 50 verified top UK startups across 8 sectors. Fintech (Revolut, Wise, Monzo, Starling, Checkout.com, GoCardless, Tide, Atom Bank, Iwoca, ClearBank), SaaS (Onfido, Quantexa, Improbable, Tessian, Multiverse, Cytora, Pleo, Cera), AI (DeepMind, Stability AI, Synthesia, Builder.ai, Tractable, PolyAI), Climate (Octopus Energy, ZeroAvia, Newcleo, Faradion, Brilliant Planet, Britishvolt), D2C (Gymshark, Bloom & Wild, Pact, Lucky Saint, Mous, Wild), Health (BenevolentAI, Numan, Voy, Babylon), E-commerce (Lyst, Trustpilot, Depop, Cazoo, Wayve), Gaming (Sumo Group, Frontier, Bossa, nDreams). Idempotent loader picks up the file via php spark pitched:ingest-companies-seed /full/path/uk.yaml.
  • Country chips/companies index now shows geography pills (All / India / UK + counts) and the filter cascades through ?country=GB into both the index grid and the sector pages.
  • Sector heatmap (Phase 4) — each sector card on the index now shows a coloured "🔥 N" badge counting signals in the last 30 days for companies in that sector. Three thresholds: cool (1-9) blue, warm (10-29) amber, hot (30+) red. Empty sectors show the company count instead. Once the laptop crawler is running, this visualises which sectors are heating up.
  • 2026 trending names added to India seed — Snabbit, Pronto, Urban Company, Atomberg, Boult Audio, DaMENSCH, Heads Up For Tails, Pumpumpum, MyMuse, NoBroker, Furlenco, Wint Wealth, Skydo, OneCard, Stable Money, Convin, CoRover, Inferless, Soket Labs, Fyle, Volopay, Loop Health, Even Healthcare, Convin, BharatRohan, PowerPlay, Tata Neu, Eatfit, Newtrace, Hyfun Foods + others. 36 additions, 300 existing companies updated in place.
  • Indian seed currency — Byju's, WhiteHat Jr, Toppr, Eruditus removed entirely (collapsed/absorbed). Aknamed, ProbablyMonsters (US-HQ), Inspirage (Oracle consulting acquired by Accenture), Spinny mis-label, Showcase, GalaxySpace (govt agency) — all pruned. Duplicates across sectors cleaned (Vedantu was listed 3× in edtech; Tonbo, Stellapps, Niramai, Practo, MFine, Curefoods, Stage all had dups). Total directory now: ~385 companies across IN + UK with 333 real logos cached.
  • pitched:ingest-companies-seed got a --prune flag — deletes is_directory=1 rows whose domain isn't in the latest seed. Safe-guard: only removes rows with no founder claim + no pitch attached. Used to clear the 10 stale Byju's-era entries from prod.
  • Index sector ordering preserved under country filter — indexBundle() accepts an optional $countryFilter argument and filters all three queries (top companies, total count, signals_30d) consistently.

2026-05-18 (evening) — Companies tracker: Crunchbase-style directory for the Indian startup ecosystem

The biggest discovery surface to land on Pitched yet. The /companies page used to be a sparse internal list of canonical rows. It's now a mini-Crunchbase populated with 308 Indian startups across 15 sectors — Fintech, SaaS, D2C, E-commerce, EdTech, HealthTech, Mobility/EV, Logistics, Agritech, Gaming, Climate, AI, Creator, Enterprise/Deeptech, Food/Hospitality. Each company gets a proper detail page with logo, sector, stage, funding, description, news feed, similar-companies carousel, and a one-tap Follow.

  • /companies rebuilt as a 15-sector grid with logo previews + sector counts. Click a sector → ranked card grid with stage / sort filters. Click a company → full detail page. Inter Tight + Fraunces editorial language, persona-aware sidebar colours preserved.
  • /companies/{slug} detail page for directory rows — large logo, sector chip, stage badge, HQ + founded year + funding raised, description, action row (Follow / Website / Blog / LinkedIn / Twitter / Crunchbase), signals feed with empty state, similar-companies carousel (5 sector siblings ranked by SimilarCompanies::rank()), at-a-glance side panel. Founder-claimed or VC-tracked rows still render the existing 1827-line VC-grade view — the controller branches on is_directory + relationship.
  • /feed — Following feed at /feed (sidebar nav under Intelligence). Signals from every company the tenant follows, newest first. Empty state with "Browse the directory" CTA. Pill row at the top showing every followed brand.
  • Follow / unfollow — pink-gradient CTA on the detail page hero, optimistic UI flip, persists via POST/DELETE /api/companies/{slug}/follow. New company_follows table is tenant-scoped + has notify_news / notify_funding / notify_product flags for future email/push integration.
  • SimilarCompanies deterministic ranking — sector +3, sub-sector +2, stage proximity 0–2, geography 0–2, description Jaccard 0–3 (max 10). Ties broken by last_signal_at DESC. No AI/embeddings until the corpus is meaningful.
  • LogoFetcher waterfall — Google s2 favicons → site /favicon.ico → WebCrawler og:image → deterministic initial-letter SVG placeholder. 259 real logos cached for the seed (84%) + 49 SVG fallbacks. Hostinger split-layout-aware: writes to public_html/uploads/_directory/logos/{slug}.{ext}.
  • pitched:ingest-companies-seed spark command — idempotent loader for the hand-curated YAML at app/Data/companies-seed/india.yaml. Domain-keyed dedup. First-occurrence wins on cross-sector duplicates (Stellapps appears in logistics + agritech).
  • pitched:refresh-logos [--sector=fintech] spark command — sweeps directory companies + caches via LogoFetcher waterfall.
  • 9-endpoint API under /api/companies/* — directory index + sector + profile + follow/unfollow + feed + 2 internal-only shared-secret endpoints (signals + videos) for the laptop crawler.
  • pitched-crawler Python repo at ~/Development/pitched-crawler/ (separate git project). Phase A — RSS sweep across 7 startup-news feeds (Inc42, Entrackr, YourStory, MoneyControl, ET Tech, TechCrunch Startups, Mint). Tight word-boundary matcher with ambiguous-stem guard avoids false positives like generic English words ("renew", "stan") triggering brand matches. launchd plist in the README for 30-min scheduling. --dry-run flag for safe iteration.
  • 3 new migrationscompanies gained is_directory / directory_rank / stage / funding_raised_usd / blog_url / twitter_handle / youtube_channel_id / last_crawled_at / follower_count. New company_follows table. New company_videos cache table for future YouTube Phase D.
  • Existing /companies filters (tab=mine / tracking / discover) continue to work via auto-fallback to the legacy CompaniesPage controller when those query params are present.
  • Tighter matcher precision — initial dry run produced 89 matches/129 articles (~69%) but with obvious false positives ("Stan" matching "Stan Lee" headlines, "renew" matching every "renewable" article). Replaced rapidfuzz partial_ratio with word-boundary exact matching + ambiguous-stem whitelist. Re-run: 25 matches/129 (~19%) — all sampled previews are real signal.
  • /companies/{slug} blank page for directory-only canonical rows — the legacy CompanyDetailPage was built around founder pitches + tracker relationships + metric updates and rendered nothing meaningful for seeded directory entries. Branched the controller: is_directory=1 + relationship=viewer routes to a new company-detail-directory.php view that owns the Crunchbase-style profile.

Marketing site rebuild, real signup flow, Modern as default theme, revenue-inversion rescue

Long Sunday. Rebuilt the public marketing surface end-to-end (home, about, privacy, terms, signup), shipped a real account-creation flow at /signup that wires through Api\AuthController::signup, promoted Modern (v2) to the default theme across the picker stack, and chased down a class of AI chart-reading errors that was producing strictly-decreasing revenue forecasts on real founder pitches. Plus a one-shot rescue on pitch 102 (Zouk) where the 6-year projection slipped through every existing guard.

  • Marketing site rebuild at pitched.vc/home. Sixty section ("Deck to live investor page in 60 seconds.") is now the hero — copy column with 3-step list + pink gradient primary CTA on the left, wide→portrait morph frame on the right (MacBook auto-renders into a chunky 10/19 phone after 1.2s of viewport entry). Glassmorphism What changes band with frosted-card grid + brand-tinted radial aura behind. New convert band tucked under the glass-box quote with eyebrow Try it now, gradient-italic headline, and the full email + drag-and-drop quickstart form. Proof bar swapped from fake-SVG icons to typographic wordmarks across 8 real investors (Peak XV, Accel, Lightspeed, Elevation, Blume, Matrix, Nexus, 3one4 — each with its own font/weight to read as a brand mark). Old <section class="hero"> and <section class="portrait"> deleted; their best lines folded into the new layout.
  • /about page. Editorial three-founder layout in Pankaj → Deepak → Rishi order. Real headshots wired through <img> tags with gradient-initial fallback. Circular photo containers (border-radius: 50%, max-width: 190px) clip Deepak's orange ring naturally. Stats strip (3,000+ founders / $2.1B raised / 40K+ slides / 7 unicorns). Dark mission band at the bottom with brand-pink CTAs.
  • /privacy + /terms pages. Editorial layout matching the home page (Inter Tight 800 hero + Instrument Serif italic accent + brand-pink eyebrow pill). Sticky TOC with mono-numbered leaders on desktop, collapsing inline on mobile. 11-section privacy policy (who we are / what we collect / why / sub-processors / where it lives / retention / your rights / security / cookies / changes / contact). 12-section terms of use (accepting / accounts / billing / your content / AI output / acceptable use / IP / availability / termination / warranties / governing law / contact). Both deep-link from footers + login bottom-row + signup terms note.
  • /signup page + flow. Split-pane layout matching /login. Form fields: first name, last name (optional), company, work email, password (min 8). tenant_type defaulted to founder (persona picker wired but hidden until next week). Right pane shows three "what you get" feature cards (Deck → live in 60s · Know who's reading · Always-fresh metrics) over the gridded brand-tinted backdrop. Wires through the existing POST /api/auth/signup — same backend used by mode=signup previously.
  • All Start free / hero CTAs route to /signup. Home nav pill, home hero pill (relabeled "Start free — drop your deck"), home footer column, final-CTA box (relabeled "Create your workspace"), About nav + mission CTA, Privacy + Terms navs, login "Don't have an account?" link. The convert-band drop-deck form on the homepage stays as a lighter quickstart path (just email, no password — feeds Api\QuickStartController::start).
  • SignupPage controller. New app/Controllers/Pages/SignupPage.php at /signup. Redirects to / when already authenticated. Replaces the prior signup → /login?mode=signup redirect with a real view.
  • Modern is the default theme. Reorder across both pickers (v1 build chrome + v2 floating toolbar): Modern · Showcase · Editorial · Dashy. New pitches built via SkeletonToPitchBuilder now persist display.layout = 'modern' on first build. The renderer fallback flipped from editorial to modern. Allow-list normalizes any unknown value (including legacy 'im') to modern. Existing pitches with an explicit layout keep their choice — only the default + IM fallback change.
  • Mobile pass across home / about / privacy / terms. Tightened typography (h1 clamped 28→38px on small screens), full-width pink CTAs with 44px min tap height, vertical-stack email + button on the convert band, proof wordmarks shrink to 14px so 4-col grid fits 320px viewports, founder photos center-align on mobile (170px → 150px on iPhone SE), TOC collapses inline above legal-body content. Everything passes 320px without horizontal scroll. All tap targets ≥44px.
  • Hero typography pass. Removed the "Live now · For founders raising $250K–$5M" pill that was getting hidden under the sticky nav. Removed the "T H E P R O B L E M" letter-spaced example from step 01 — each step is now one beat (action + payoff) instead of two beats. Step 02 shortened from "AI coach normalizes your deck into the 19-block format investors expect, rewrites for clarity, flags gaps, proposes a thesis-fit narrative" to "AI Coach restructures it the way investors expect — clearer narrative, flagged gaps, thesis-fit framing." Step 03 ditto.
  • Phone frame in the morph re-balanced. Width bumped 300px → 330px (10% wider) AND aspect ratio shifted 9/19 → 10/19 so total height stays roughly constant. Reads less elongated, more iPhone-natural. Vertical alignment of the morph column flipped to center so the device sits at the vertical midpoint of the copy column instead of pinned to the top (was getting clipped above the fold on tall hero copy).
  • Antfarm references cleaned out of marketing footers + privacy/terms operator entity. Pitched is no longer positioned as "An Antfarm company" publicly. Rishi's bio on /about keeps the Antfarm mention (it's his studio — that context is about him, not Pitched).
  • Theme picker reorder in /v2/{slug}?mode=build floating toolbar. Same Modern → Showcase → Editorial → Dashy order as the v1 picker. IM tile removed.
  • Zouk (pitch 102) projections were strictly decreasing across 6 years. Stored value sequence was FY26: ₹1,800 Cr → FY31: ₹1,000 Cr — a perfect monotonic decline that's virtually never a real fundraise forecast. Slipped through both the digest-time sanitiser (DocumentDigester::sanitiseSkeleton) and the render-time guard because the 1.8× spread sat just under the 2× cutoff designed to avoid flipping noisy-flat triples. One-shot rescue applied: flipped the revenues across the year axis in place (years preserved, only values reordered), now correctly reads FY26: ₹1,000 Cr → FY31: ₹1,800 Cr in Numbers / Coach / Plan / chart. Audit warning attached on the skeleton.
  • Inverted-projection guard relaxed for 4+ row series. Both DocumentDigester::revenueSeriesIsMonotonicDecrease and the renderer-side combined-array check in skeleton-v1.php now use >1.15× spread when there are 4+ strictly-decreasing rows. 3-row series keep the >2× guard. New heuristic: 4+ consecutive years of strict decline is essentially never a real projection — that pattern is the AI reading chart bars right-to-left.
  • Cross-array decline now caught at render time. The digest sanitiser checks historical and projections independently. If the AI inverted the chart-reading order across BOTH arrays, each alone can look fine while the year-sorted combined series is strictly decreasing. Renderer now detects post-sort monotonic decrease across the concatenated points and auto-flips the values back, surfacing a build-mode warning so the founder can verify the year ↔ value mapping in Numbers.

2026-05-15 (evening) — Build-mode toolbar v1: floating chrome, layout previews, working bubble bar

The build-mode editing surface on the Modern (v2) layout got a proper toolbar. Premium chrome (layered shadows + glass + inline SVG icons), Substack-style floating bubble bar on text selection, and a Theme popover that actually shows the 5 page styles as visual previews instead of plain text buttons. Plus the format bubble bar now actually does something — six key text fields are inline-editable with rich formatting that persists.

  • Floating build toolbar at /v2/{slug}?mode=build. Six chips: Insert, Theme, Format, Modules, Numbers, AI. Premium chrome — 14px rounded corners, layered shadows (close + mid + far + atmospheric), 0.5px hairline stroke, 28px backdrop blur with 180% saturate, inline-SVG stroke icons at 1.6 weight. Auto-respects prefers-color-scheme: dark. Status pip ("Saving / Saved / Error") with colour-coded dot and soft glow ring. Toolbar sits 64px from bottom (was 24px — was too cramped).
  • Theme popover with full visual system. Four colour swatches (Primary / Accent / Dark / Light) showing live preview chips + hex codes — clicking opens the native picker, change re-applies to the page CSS variables instantly. Five page style tiles (Editorial / Showcase / Modern / Dashy / IM) each with a hand-drawn SVG mockup of that layout's structural personality — editorial = paper magazine columns, showcase = single-column hero, modern = bento grid, dashy = card matrix, IM = formal document lines. Density picker (Compact / Normal / Roomy) underneath.
  • Working format bubble bar. Six fields on v2 are now contenteditable="true" in build mode: hero tagline, summary elevator, problem, solution, why-now, business model GTM. Each carries data-edit-rich="<path>" and saves innerHTML to the skeleton on blur (400ms debounce). Selecting text inside any of them pops up a small black formatting bar with B / I / U / H2 / H3 / Link / Clear. ⌘B / ⌘I / ⌘U keyboard shortcuts route through the same handlers. Active state on the bubble buttons reflects current format (queryCommandState).
  • $rich helper for safe inline HTML. New PHP helper allowlists <b><strong><i><em><u><br><p><h2><h3> and strips all attributes (kills <b onclick=…> style XSS payloads). Used on every rich-text render site so formatted text persists across reloads. Renderer falls back to empty string if value isn't a string.
  • Rich-edit visual affordance. .pt-rich class applies a 4px brand-coloured halo on focus, soft tint on hover — same vocabulary as the toolbar's accent.
  • All six popovers redesigned to match the toolbar's premium feel. Glass background, layered shadow, 14px corners. Section headings now have a small brand-coloured gradient bar accent. Inline-SVG icons everywhere (Insert tiles, AI send button, Theme swatches). Tighter typography — Inter Tight 12.5px with letter-spacing -0.005em for chip labels, JetBrains Mono 10px with 0.12em tracking for monospace headers.
  • Insert popover — 6 tiles with inline-SVG Phosphor-style icons (image, video, quote, figure, divider, custom section). Hover lifts the tile 1px and scales the icon 1.08×.
  • Modules popover — toggle switches refined: 30×18px pill with bouncier easing (cubic-bezier(0.34, 1.56, 0.64, 1)), 14px white knob with double shadow. "Empty" meta chip in mono caps replaces the inline (no data) parenthetical.
  • Numbers popover — group headers in proper mono caps, inputs with focus halo matching the rich-text edit field, tabular-num font, em-dash placeholder for empty values.
  • AI popover — bigger textarea with brand-coloured focus halo, paper-plane SVG send button in pill form, "Send" action right-aligned.
  • Format popover — clearer hint explaining how to use the bubble bar, with <kbd> styled keyboard shortcut chips for the keyboard shortcuts.
  • Bubble bar bolding did nothing. Root cause: the page had no contenteditable surfaces, so document.execCommand('bold') was acting on a non-editable target and silently dropping. Fix: six curated rich-text fields are now contenteditable in build mode, and the bubble bar only appears when selection is inside one of them. Format applies, and the new HTML persists to the skeleton via a debounced PATCH.

Source anchoring: every number on the v2 page is now a verified quote from the deck

Hardest day of the platform. The v2 page (/v2/{slug}) was rendering plausible numbers that hadn't actually come out of the deck — a quiet form of hallucination that no test would catch. Closed it by making the AI emit a _sources[] array — every leaf field paired with a verbatim deck quote — and bolting a verifier on after extraction that drops anything the deck doesn't actually say. Plus the Traction bento got an upgrade so early-stage decks (no ARR / MRR / customer counts) never feel sparse anymore.

  • Source anchoring on every extracted number. DocumentDigester::systemExtract() now requires the model to return _sources: [{path, evidence}] alongside the skeleton — one entry per non-empty leaf field, where evidence is the verbatim string from the deck that supports the value. JSON schema enforces the shape; system prompt makes the rule explicit ("QUOTE WHAT'S IN THE DECK, NOT WHAT YOU INFER"). 51 verified anchors on the Luma re-digest, vs 0 before.
  • verifyAnchors() post-extraction sweep. After sanitiseSkeleton(), every value referenced by _sources[] is checked against the raw deck text. Three match tiers: exact substring → punctuation-relaxed (pipes / colons / slashes stripped, for table-cell quotes) → fragment-window (longest 30-char shingle from the evidence found within the deck). Anything that fails all three gets moved into _unverified[] and removed from the rendered field — the page can't show a number that didn't survive the round-trip. Confidence tag (exact / relaxed / fragment) attached to each surviving source for future provenance UI.
  • Traction bento backfills from market / funding / unit-economics / financials. When traction.metrics[] is thin (early-stage decks with no ARR / MRR / customer counts), the bento now pulls the next-strongest numbers from funding.asking_amount, funding.valuation_*, market.tam/sam/som/cagr, unit_economics.aov/ltv/cac/payback/gross_margin, and financials.projections[last].revenue — in that priority order. Dedupe is label-keyed (lowercase) so an extracted "ARPU" metric never collides with a backfilled "ARPU" from another field. Cap at 7 cells. The bento now always renders dense, regardless of how revenue-mature the deck is.
  • Luma /v2/luma traction bento. Was: two ARPU cells ($1528 / $753) and four empty slots — read as "we don't know much about this company." Now: ARPU $1528 (hero) · Raising $8.4Mn · TAM $54.8Bn · SAM $11.2Bn · SOM $74Mn · Market CAGR 5.7% · Year 5 revenue $2,10,239K. Same skeleton data, smarter render.
  • Hallucinated traction.metrics[].value values silently dropping into the v2 page. Specifically: a phantom "$15M ARR" that wasn't anywhere in the actual Luma deck (the deck shows $1528 annual ARPU, not $15M ARR). The AI was conflating "annual revenue per user" with "annual recurring revenue." verifyAnchors() catches this class of error post-extraction by requiring every shown value to map to a real deck quote.

Launch day: founder-first homepage, drop-deck flow, and the digester learns to stop guessing

Long arc spent ahead of the public launch. The homepage was rewritten for founder-only positioning with a live drop-deck widget that anonymous visitors can use without an account. The digester learned six new classification rules after a hard post-mortem on the Quantum Energy run (founded year was inventing dates, ARR was duplicated, govt mandates were being shown as company KPIs, an entire OEM revenue branch was disappearing into prose). Email design got an editorial pass. The sidebar's collapsed state got a small but overdue tidy. Plus a gnarly two-file-pickers bug.

  • Homepage rebuilt founder-first. /home and / now serve the same marketing page — institutional weight up top, then a hero quick-start widget (email + drop-deck zone), then a "From a black box to a glass box" 6-row before/after grid, the 60-seconds aha section now with a live deck ↔ live page reveal slider in its right column, three-question FAQ, gradient-glow final CTA. IB / Fund / Family-Office content stripped — those personas come back when we open up beyond the founder launch. Net file size dropped from 2,001 → 1,699 lines after 332 lines of dead persona / bento / sx-frame / IB-Fund-FO mock CSS got removed.
  • Drop-deck quick-start, no account required. Anonymous visitor on /home types email + drags a deck → hits POST /api/quick-start → file lands under writable/uploads/quickstart/{Y-m}/ → 48-hour confirmation link emailed via Resend. New pending_registrations table tracks the pending row; same email retrying reuses the row instead of spamming. New /verify/{token} page handles the second half: founder sets name + company + password, we create the tenant + user, move their deck into the tenant's public uploads, create the lead + deal_documents row, fire extract + digest + build in register_shutdown_function so the pipeline keeps running past the redirect, auto-login, and land them on a personalised first-time experience.
  • Quickstart resume on verify return. /app/pitches/new?from=quickstart&doc={id} is now smart — looks up the doc, and if the digester has already produced a pitch it redirects instantly to /app/pitches/{id}/build?welcome=1. If still building, the page renders the live-processing splash with "Building your pitch from {deck name}" as the heading, jumps straight to Stage C, and polls idempotently against the existing doc rows. A small "Wrong deck? ↻ Try with a different deck" link under the progress track points to /app/pitches/studio for re-entry.
  • Deck ↔ live page reveal slider on the homepage. Real Luma deck cover on the left (PdfThumb-resolved from the actual deck), live /luma?embed=1 iframe on the right inside a browser-chrome wrapper. Drag the white handle to wipe between them; the iframe stays scrollable so visitors can scroll the actual live page inside the frame. Keyboard arrows + Home/End supported. The "Open live page" link in the chrome jumps to the un-embedded /luma in a new tab.
  • ?embed=1 mode for any public pitch. Strips the visitor-feedback FAB, "Powered by Pitched.vc" footer, and forces display.layout = "showcase" (right facts rail hidden, left nav-rail kept). Used by the homepage slider iframe today; available for any embedding context tomorrow. Override patches both pitch.skeleton_json and pitch.display_json so every render path picks it up.
  • Six-rule "DON'T FABRICATE — DON'T MIS-BUCKET — DON'T MIS-GEO" block in the digester prompt. Six classes of error that killed a live Quantum Energy pitch all become explicit: (1) founded_year must be empty unless literally stated — never inferred from copyright footers or the current year. (2) financials.projections[] is for P&L forecast tables only; deployment ramps and "Revenue potential by 20XX" callouts go to a new aspiration_targets[] field. (3) Every traction.metrics[] row carries a category (company_metric / market_context / regulatory_target) so govt-mandate numbers and industry CAGRs never get shown as the company's own KPIs. (4) Every TAM / SAM / SOM figure pairs with a geo qualifier; "hybrid" is the answer when the deck blends domestic + global framing. (5) OEM / contract manufacturing / anchor-client revenue gets its own business_model.revenue_streams[] entry — never collapsed into the direct-sales prose. (6) Global outlook signals (CES Vegas, "3-5 global clients by 2028", named overseas partners) populate a new expansion_plan block.
  • Deterministic thread-signal pre-detector. DocumentDigester::detectThreadSignals() scans raw deck text for OEM / aspirational-ramp / market-infrastructure signals BEFORE the AI sees the prompt, and prepends a per-deck "MUST-CAPTURE THESE SIGNALS" block when found. Models routinely ignore generic schema asks; surfacing the actual matched text from the deck makes the rule unavoidable.
  • Deterministic sanitiser fallbacks for the rules the model still fights. When the AI resists a new schema field (specifically business_model.revenue_streams[]), sanitiseSkeleton() synthesises a minimal OEM entry from the existing revenue_model / channels signals so the page renders the branch correctly with a verification warning instead of silently swallowing the whole revenue stream. Same for tam_geo — derived from geo_market country count when the model forgets. Plus: founded_year > (current_year - 1) nullified, page-number artifacts ("P 20") dropped from metrics, charging-infra / fleet-on-road totals routed to market.tailwinds[], projection rows with unitless revenue moved to aspiration_targets[], scalar↔metric ARR/MRR dedupe, identity name-leak guard.
  • "Revenue branches" render block. Once business_model.revenue_streams[] is populated, each kind (oem, direct_sales, contract_mfg, white_label, etc.) gets its own card in the Business section with description, optional client list, geo chip, and stage label. Editorial card layout, no SVG drama.
  • Gallery lightbox. Tile click no longer opens a new tab. New full-screen overlay (rgba black + backdrop blur), object-fit: contain so portrait + landscape both fit whole, prev / next circular buttons when there are 2+ images, position counter (2 / 6) in mono caps, Fraunces italic caption under the image, keyboard nav ( / / Esc), click-outside-image to close, body scroll lock when open, image src cleared on close so huge photos don't pin memory. Thumb crop moved from center center50% 12% so the top of every shot (faces, headers, hero subject) stays in frame.
  • Email template editorial pass. Warm cream background (#F5F2EC) matching the homepage. Pitched brand mark switched to a gradient square (blue → pink) with Georgia "P". Wordmark in italic Georgia at 18px. Tone gets a small-caps eyebrow (SUCCESS, HEADS UP, IMPORTANT). Headline jumped from 22px sans-bold to 28px Georgia regular — feels editorial without losing weight. Meta lines auto-split on · or : into a real label/value table (mono caps label, ink body value). CTA button now has Outlook VML fallback so it renders as a real button in Outlook too, gradient pill style elsewhere. Multi-line footer: italic Georgia signature, sans link row, then the close line *"Your deck does not go dark after you send it."* Dark-mode media query covers surface + text + meta-row + footer. Mobile breakpoint at 480px tightens padding + headline size. Backward compatible — every sendNotification() caller renders without touching code.
  • Section-colored sidebar flyouts. Each collapsed-state nav-group's flyout banner now uses that section's signature colour (pitched = hot pink, tools = indigo, analytics = sky, origination = green, fund = blue, family = purple, sales = orange, intelligence = coral, etc.). Same colour as the rail icon — visual continuity between the icon you hover and the menu that opens. SECTION_COLORS map in crm-core.js mirrors the --m-c-* tokens already in pitched-monday.css.
  • pitched.vc/ root now serves marketing for anonymous, dashboard for logged-in. Anonymous visitors no longer bounce through /login; they land on the homepage. Logged-in visitors redirect to /dashboard for the persona-branching DashboardPage. Single tiny lambda route, no controller indirection.
  • Page rhythm tightened ~30% across the board. Hero padding 132→100, change / sixty / tour 130→80, faq 130→72, final-cta 80/130→56/80, footer 56→36. h1-h4 default margin-bottom 16→12. Section-head margin 56→36. Hero h1 22/22→14/16. Hero lead bottom 32→22. Column gaps 60/80→48/56. Everything still has rhythmic breathing room but the cathedral-sized gaps are gone.
  • Founder dashboard empty-state CTAs. "Create your first pitch" went from three buttons (Upload deck / Start from template / Blank canvas) to two: Upload deck/app/pitches/studio (the cinematic multi-file studio, our most polished upload), and Start with a wizard/app/pitches/wizard (adaptive Q&A intake for founders without a deck). Template + Blank dropped — they were noise on the most decisive screen in the funnel.
  • Sidebar collapsed footer. When the rail is collapsed, the footer now stacks profile avatar + sign-out icon vertically. Both visible. Previously sign-out hid behind a display: none on the whole actions block; now it's a soft pill that brightens on hover. The profile flyout's "Rewards & XP" link and XP bar are gone too — collapsed state is profile + sign out, nothing else.
  • Theme switcher commented out (the immersive / moon toggle in the sidebar footer). Wrapped in a <?php /* … */ ?> block so it's a one-line uncomment when we bring it back. JS handler in the layout already had an if (immBtn) guard, so the removal is a safe no-op.
  • Gallery thumb interaction. Tile lifts 2px on hover with a deeper shadow; image inside scales 1.04; the caption strip (if set) fades in from the bottom via a gradient overlay. Tile size minmax bumped 180px → 200px with 10px gap for cleaner editorial density.
  • Legal-name pill suppression on the public pitch. Renderer no longer shows the "Entity" / "Legal name" row when the legal name only differs from the display name by a corporate suffix (Limited, Ltd, Pvt, Inc, LLC, Corp, Holdings, GmbH, etc.). Strip both, lowercase, drop punctuation, compare — same → hide the pill. Fixes a complaint from the Quantum Energy review: "Quantum Energy Limited" appearing as a separate "Entity" tag right next to the company name read like noise.
  • Founder photo upload opened a second file picker for the first founder you ever clicked. openHeadshotMenu() was wiring the Upload-photo button's click handler in two places — once at menu creation (addEventListener, frozen-closure over the first card hovered) and once at every show (.onclick, current card). Both fired on click. So after picking a file for founder #2, a second picker auto-opened for founder #1. Removed the menu-creation addEventListener; only .onclick is bound, replaced fresh on every show.
  • identity.founded_year was being set to the current year on the Quantum Energy run. The deck never stated a year, but the model defaulted to "2026" instead of leaving the field empty. Prompt now bans inference from copyright footers, file metadata, slide timestamps, and the calendar year; sanitiser nullifies any founded_year > (current_year - 1) regardless.
  • 72,300 charging stations was being shown as a Quantum Energy company metric. That number is the national government's FAME-II target. New category field on every traction.metrics[] row, plus a sanitiser regex that catches infrastructure totals (charging infrastructure, swapping infrastructure, public chargers, fleet on road, etc.) and routes them to market.tailwinds[] even when the model forgets to tag them.
  • Fabricated revenue projections (₹6,000 Cr / ₹10,000 Cr / ₹15,000 Cr over 2028-2030). The model was reading Quantum Energy's monthly vehicle-deployment ramp as a revenue P&L. Prompt now distinguishes aspiration_targets[] (deployment / capacity / "revenue potential by YYYY" callouts) from financials.projections[] (real P&L tables). Sanitiser also strips projection rows whose revenue cell parses as a unitless integer (no Cr / L / M / Bn / $ / ) — those are vehicle counts, not money.
  • The OEM / contract-manufacturing narrative was disappearing. Quantum's anchor-client deal (US automotive OEM, $1B valuation, post-Series C) was the heart of the fundraise, and the model was collapsing it into the direct-sales prose. New Tier-1 business_model.revenue_streams[] field + deterministic pre-detector + sanitiser synthesis fallback when the model still resists. The OEM branch now renders as its own "Revenue branches" card with a verification chip so the founder knows to add partner specifics.
  • tam_geo and geo_market were India-only on a globally-pitched company. Quantum's deck literally said *"$17B at the intersection of India's EV shift and global 2W electrification"* — the renderer was showing India-only. Sanitiser now synthesises market.tam_geo = "hybrid" (or "global" / specific country) from the count of geo_market[] rows, and adds a {country: "global"} entry whenever any expansion signal is detected.
  • Funding ask was being read as empty on decks with placeholder slides. Quantum's "Ask and Spend" slide had real categories (Sales & Marketing, CapEx, Corporate team, Working capital) with ₹XX Cr placeholder values — the model returned empty use_of_funds[]. Prompt now explicitly captures the categories even when values are placeholders; funding.amount_status field tags the row as "placeholder", "stated", or "absent". Also added an explicit anchor-client trap guard so partner "Total Raised" / "Valuation" figures don't bleed into the company's own ask.

Mobile-first pass, investor reactions, the numbers are honest now

A long day spent inside two surfaces: the authed app on phones (founder dashboard down through build mode), and the public pitch view that investors actually open. Plus a quiet but important correctness fix — the revenue chart was reading multi-currency strings wrong and showing growth as decline.

  • Build mode top bar — mobile rework. The cramped 5-button row (Preview · Numbers · Data Room · Share · Publish) is replaced by a single brand-coloured Tools pill on phones. Tapping it opens the editor drawer at a new Actions tab — clean editorial list, each row with icon, title, and a one-line context note. Desktop top bar is untouched. The mobile drawer itself is now a proper bottom sheet at 88vh with three dismiss affordances: × close button top-right, tap-outside backdrop, and ESC for external keyboards.
  • Editorial → showcase on mobile. Editorial and showcase layouts now both render as showcase on phones (facts rail hidden, identity / team / investor blocks weave inline with the main flow). Dashy and IM keep their dashboard / investment-memo feel — the rail moves above main so team + identity reach the eye HIGH in the scroll. Desktop unchanged across all four layouts.
  • Section reactions on every public pitch. Inline 👍 / 👎 buttons anchored top-right of every section. Tap and you've left a section-level reaction with one click — no modal, no email field. After voting, a small inline text field slides in for an optional note (Enter to send, Esc to close). Re-tapping the same thumb un-votes; switching from 👍 to 👎 changes the reaction. Founder inbox at /app/feedback shows the thumb + section + optional note. Backed by a new reaction column on pitch_visitor_feedback and the existing /api/public/pitches/{id}/feedback route.
  • "Let's tidy a few numbers" build-mode prompt. When the digester flags anything dodgy in the financials (degrowth detected, year labels that don't look like years, revenue rows missing a financial unit, chart corruption) a single friendly card slides in bottom-right of the build view. Fraunces title, lists up to four specific issues with their field path, two buttons: Open Numbers (primary, brand-coloured) and Later. Dismissal is session-scoped and warning-hash keyed — re-fires if a re-digest produces new issues, stays away if the founder dismissed the same set last time.
  • Chart-suitability guard. The revenue chart now refuses to plot non-chartable inputs. Year labels must match a year pattern ((19|20)\d{2}, FY##/####, \d{4}E/F), and every revenue cell must carry a financial-unit marker (Cr / L / M / Bn / $ / ₹ / £ / €) AND parse to a positive number. Decks like Bushido where "projections" were really milestones ("Next 12 Months · 1 Million Students onboarded") now show no chart and surface the founder prompt instead of a misleading line.
  • AI Coach: scroll, highlight, undo. When Coach applies an action, the page now (a) maps the touched fields to their parent section and scrolls the first one into view, (b) flashes the section with a brand-tinted glow for 2.4s so the founder can see exactly what changed, and (c) shows an Undo toast for 10 seconds. Undo replays the patches in reverse with the captured pre-change values — full restore from one click.
  • Sidebar Analytics group on the public pitch nav. The left-rail icons now read in the actual content order, not a hardcoded one. Sections without an id now get one from their data-section value so deep-link anchors work everywhere (Problem and Solution were silently failing before).
  • Hover-delete on facts-rail rows + empty-row hide. Geo-market rows with only a country label and no numbers are skipped in the public view and surfaced (with a "No data yet" hint + trash control) in build mode. The pattern is generic — the setByPath server helper now reindexes lists after a delete so removing geo_market.1 leaves a clean array, not a sparse object. More row types coming next session.
  • Top-bar buttons (desktop). Refined Preview / Numbers / Data Room / Share / Publish styling: 8px radius, subtle inset highlight, brand-tinted hover shadow, icon opacity that lifts on hover. Primary button (Publish) carries a soft brand-glow shadow. Reads more polished, less workmanlike.
  • Clickable URLs in the facts rail. The "Web" row now renders as a proper <a target="_blank"> with a dotted brand-accent underline that solidifies on hover. Showcase identity strip already did this — facts rail now matches.
  • Sidebar nav order matches content. When a founder toggles sections off or the rendered order changes, the nav-rail icons reorder via DOM order on load. Leftover icons whose target section doesn't exist get pruned.
  • Revenue chart was inverting growth into decline. skel_v1_num (the chart's number parser) was globally stripping every non-digit/non-dot character. On strings like "₹6,000 Cr / $0.7B" that concatenated the two numbers into "60000.7" — so 2028's value was read as ~60,000, pinned to the chart's max, while real-2030 (15,000) sat near the floor. The line drew from top-left to bottom-right and Quantum Energy's growth pitch looked like a managed decline. New parser takes only the first numeric block and applies a unit multiplier (Cr / L / Bn / M / K) so mixed-format strings still scale correctly. Same logic the digester uses on the prompt side.
  • Section thumb widgets were invisible. CSS gated visibility on .sec.is-visible and .sec[data-revealed="1"] — but the public-pitch reveal observer adds the class is-revealed. The widgets injected fine but never had their opacity: 0 lifted. Selector fixed to .sec.is-revealed; reduced-motion users get an immediate-visible override too.
  • Sidebar tap on mobile. Three-strike fix: removed touch-action: none on body (was propagating to all descendants), removed visibility: hidden on closed-state children (sticking through the transition), and offset the backdrop to start where the drawer ends (left: min(280px, 84vw)) so it physically can't intercept drawer taps. Sidebar z-index bumped to 1100 so it sits above topbar + backdrop + everything.

Funding tracker, properly populated

Three arcs on the funding tracker today: source mix doubled (and the two RSS-free sites got scraped via Firecrawl), every event row is now personalisable (region slider + follow-sector chips with a per-user prefs row), and a silent dedup bug got caught that had been quietly piling up ~128 duplicate rows.

  • Four new sources added to the tracker ingestion: TechFundingNews (RSS, global feed), Inc42 Startups (RSS, the industry/startup-ecosystem category — broader than the main Inc42 feed), plus Entrackr and VCCircle via Firecrawl since neither exposes RSS. The Firecrawl path is a two-phase scrape — index page for article links, then per-article scrape for body + metadata — pipes the markdown into the same AI extraction the RSS path uses. Total source count is now 9 active feeds (was 6).
  • Region focus slider on /funding-tracker. Drag from India ←→ Global; readout updates live ("India-focused / India-leaning / Balanced / Global-leaning / Global-focused"). Extremes (±70) hard-filter by region; everything in between feeds a score that nudges matching deals up the ranking. Server-side region classifier tags every new event into one of india / us / uk / eu / sea / mena / apac_other / latam / africa.
  • Follow-sector chips: 12 quick-pick sectors (Fintech, SaaS, AI, Healthtech, Climate, D2C, Mobility, Gaming, Logistics, Cybersecurity, Edtech, Enterprise). Click to follow — matching deals get a +5 score in the "For you" sort. Combined with stage matches (+2) and region bias (driven by the slider) the ranker surfaces what's actually relevant to your thesis.
  • Per-user prefs persistence: new user_funding_prefs table (region_skew, follow_sectors, follow_stages). Saves on every chip click or slider change.
  • pitched:backfill-funding-investors spark command — re-fetches every event missing one of (lead_investor, sector, hq_country, amount_usd), runs the article through the same AI extraction, and patches whatever's recoverable. Also runs a region classifier sweep on the existing rows. Total cost on the 224-row backfill: ~$0.50; runtime ~8 min.
  • Cron dispatcher upgraded to fire all 9 sources in parallel via one /cron/pitched/funding-ingest-all call instead of 6 staggered entries. Firecrawl sources auto-throttled to once every 4h to stay within the credit budget.
  • Coverage uplift after the backfill + dedup cleanup: lead_investor 44% → 55%, sector 61% → 75%, hq_country 41% → 43%, amount_usd 85% → 89%, plus region_class 0% → 62% (new column entirely). ~85 rows also gained a populated participating_investors_json ("also-in" investor list).
  • Auto-personalisation when sort is left on default — if the user has follows or has touched the slider, the "For you" sort kicks in automatically. Explicit recency / largest-first / smallest-first sorts still available in the dropdown.
  • Founder dashboard "Latest funding" widget carries over from yesterday's swap — same data, now properly ranked when the user has prefs set.
  • Same article appearing 3× on a company detail page (e.g. /funding-tracker/c/dailyobjects). Two bugs stacked: (a) the pre-dedup query hashed (host|title) but compared it against the dedup_hash column which actually stores (name|domain|stage|day) — the check never matched. (b) The canonical hash included the announcement day, so when the AI returned slightly different announced_at values across re-fetches (or fell back to published_at = today), every cron tick inserted a fresh row. Fixed the pre-dedup to query source_url directly, then collapsed the historical pile: 128 duplicate rows merged into 132 unique (kept the oldest per URL — that's typically the one with the freshest AI extraction).
  • Legacy foundersday rows (28 rows from a deprecated scraper) pruned. Source removed from the active mix; dead code left in the service file as a historical reference.

Evening update · Workspace settings, team invites, dashboard refresh

A second pass on the operating surfaces around the pitch. Settings got a complete editorial rewrite, the founder dashboard swaps "Recent viewers" for live market funding news, team invites now actually email the new teammate, and three pieces of the UI we hadn't shipped yet got tidied out of the way until they're ready.

  • /settings rewrite — editorial Pitched-native. Sticky left rail anchor nav · six sections in one scroll: Account (avatar, name, phone, timezone, email signature), Workspace (logo, name, brand colour, currency, persona pill — owner/admin only), Security (password change + 2FA placeholder + owner-only delete-workspace surface), Notifications (per-module in-app + email toggles for feedback / data-room / legal / intel / analytics / security / product), Team (member list with role dropdowns + invite modal), Billing (trial card + upgrade-soon CTA). Save-on-blur across every text field — no explicit save buttons. Active rail item tracks scroll position via IntersectionObserver. The 1,251-line kaam-crm-era settings page is gone.
  • Avatar upload now works. New POST /api/settings/avatar endpoint (any logged-in user can update their own — no role check), JPG/PNG/GIF/WebP/SVG up to 5 MB, writes to public_html/uploads/{tenant}/avatars/{YYYY-MM}/. Hot-swaps the topbar avatar live (no reload) and the file input clears so re-upload of the same file works. Same flow wired for workspace logo upload.
  • Team invites send a Resend email. The existing invite endpoint created the user + handed the temp password back to the inviter's screen — never delivered it. Now the new teammate gets a Resend email from info@pitched.vc with their email, the temp password, role, and a "Sign in to Pitched" CTA. The settings invite modal accepts the canonical owner / admin / member role set; legacy manager / bd_manager / user / viewer still accepted for older callers.
  • Founder dashboard: "Recent viewers" → "Latest funding". The right column widget now shows the 6 most recent rounds from the funding-tracker ingestion (TechCrunch / Inc42 / YourStory / Crunchbase / ET / Mint feeds), each card linking to the source article in a new tab. "View all →" jumps to /funding-tracker. Editorial styling — purple accent, tabular-num amounts, stage badge, location + sector context line.
  • Founder dashboard cleaned up. Removed the "Templates" pill from the hero header — wasn't pulling its weight. Hot Leads block hidden until the IB/VC sourcing side that feeds it is finished. Billing item hidden from the sidebar until Razorpay subscriptions ship; restoring is a single uncomment in CrmModules.php.
  • Settings avatar rendered as ? after a successful upload. The server stored the upload correctly and the URL was viewable directly, but the view checked $user['avatar_url'] while BaseController::loadUser() maps the DB column to the key avatar. The fallback initials also mis-read first_name instead of firstName. Now the view reads both shapes — works whether you're freshly invited (combined name field) or signed in via the legacy keys.

Data room access, transactional email, pipeline that doesn't 504

Three big arcs: every published pitch now exposes its data room as a request-access library, every transactional touchpoint on the platform runs through one verified Resend sender (info@pitched.vc), and the deck-upload pipeline stops hitting the gateway timeout on 30+ page decks.

  • Data room on every published pitch. Below the deck section, an editorial card grid of the founder's data-room documents — each tile has a typed icon (PDF / Excel / PowerPoint / Word / image / video, picked from MIME), Fraunces title, doc-kind label, file size, and an explicit "Request access →" affordance at the bottom of the card. Hover lifts the card, brightens the brand wash across the top edge, scales the icon, rotates the lock, and slides the arrow. Layout-aware: tighter on IM, single-column on mobile.
  • Request access modal. Click any document tile and a modal opens. Anonymous visitors fill name + work email + firm + optional note. Signed-in fund / family-office / IB users skip the form entirely — a green identity card confirms they're recognised and the request is one click. 10-minute idempotency window per email + pitch so an over-clicker doesn't stack duplicate rows.
  • Founder approval panel. New "Access requests" block on /app/pitches/{id}/data-room, above the share links. Pending count badge in the header. Each request card shows requester name + email + firm + persona pill + city/country, what they asked for (specific doc or whole room), the optional note as a pull-quote, status badge, and relative timestamp. Approve + send link generates a tracked /dr/{token} share and emails it through Resend. Deny closes silently.
  • Transactional email on Resend, info@pitched.vc. New ResendMailer library, drop-in shape match for the legacy Brevo path. Every notification that previously rode email now goes through Resend with the verified domain. Brevo path stays in the tree as a one-line rollback.
  • Email on signup. Every new account gets a persona-aware welcome email — founders land on "Start your pitch" (→ /app/pitches/new), funds / family offices / IBs land on "Open dashboard". Subject and body match the workspace the founder just created.
  • Email on password flows. Forgot-password sends a reset link (1-hour expiry, shown in the email's meta lines). When the reset completes, a security confirmation fires with When / IP / Browser so an unauthorised change gets spotted.
  • Email on data-room share. Founder fills "Recipient email" when creating a share link → recipient gets a tracked /dr/{token} invite with password / NDA / expiry / max-views constraints surfaced as meta.
  • Email on legal-doc signature request. Founder includes counterparty email when generating a /sign/{token} link → counterparty gets a "Review and sign" email with the doc title and type.
  • Email on visitor feedback. Every new submission from the public-pitch FAB now fans out as both an in-app notification AND a Resend email to every active user in the founder's tenant. Subject is "{sender} sent a message / left feedback on a section / left overall feedback".
  • Single-image add in the editor. Build mode → Add → Single image opens an inline editor that takes one image + optional caption + a "where on the pitch" dropdown (auto-built from the sections currently rendered — "At the top", "After Problem", "After Traction", "At the end" etc.). Drop it in, the page auto-refreshes 450ms later with the figure already placed in position, and the editor re-opens so you can add another without re-navigating. Hover trash icon for delete. Images render at native pixel resolutionmax-width: 100%; width: auto so smaller-than-column files stay crisp instead of being CSS-upscaled into blur. The upload cap is now 25 MB (was 10 MB) so high-res DSLR / phone shots stop being rejected; server keeps every byte (no resize, no re-encode).
  • Deck upload pipeline doesn't 504 anymore on big decks. LlamaParse v2 takes ~78s on a 32-page deck; Hostinger's nginx gateway times out at ~60s. Now /extract and /digest set ignore_user_abort(true) server-side, the parse continues even after the client connection drops, and the browser uses a fire-and-poll pattern: short 55-second fetch + then polls /extractions and /digestion for the completion row. The wall-clock for the founder is unchanged — the failure mode is gone. The pre-existing bug where the polling endpoint hid llamaparse_v2 rows from its parser filter is also fixed.
  • Data-room cards designed to look clickable. Replaced the first-cut flat tiles with a richer editorial vault aesthetic: bigger 52×52 icon tiles with inset brand-tinted rings, two-line Fraunces titles, in-card "Request access →" CTA that brightens to the brand colour on hover, brand-gradient wash across the top edge that fades from 18% to 85% opacity. Animation curve matches the rest of the pitch (cubic-bezier(0.22, 1, 0.36, 1) at 260ms).
  • Hero KPI strip stops stacking when labels are long. Pitch 81 surfaced this — the AI had extracted 13-word sentence labels ("Projected revenue within the next 2 FY's") and flex-wrap: wrap pushed each one to its own line. .hero-strip switched to CSS grid auto-fit minmax(110px, 1fr) with min-width: 0 per cell and a 2-line label clamp. Mobile collapses to 2-up. Bonus: the extraction prompt now enforces a 4-word maximum for metric.label (qualifiers go into period / segment / note instead) so new digests produce tile-style labels by default.
  • LinkedIn captured and rendered. The extraction prompt explicitly looks for LinkedIn URLs on founder + advisor slides — handles linkedin.com/in/handle, bare in/handle, icons next to names, even labelled QR codes. Founders + advisors now display a small LinkedIn icon link in the facts rail and showcase layouts. In build mode, a + Add LinkedIn dashed pill appears on anyone who doesn't have one yet — click, paste the URL or just the handle, done.
  • HTTP 500 on visitor feedbackPublicFeedbackController extends ResourceController (not BaseController), so the app's response helpers weren't auto-loaded and apiSuccess() was undefined. The fix is one line (protected $helpers = ['response'];) but the bug ate three duplicate "Good to see this traction" rows before it surfaced. Idempotency guard at the API level now catches the retry pattern even if a future controller has the same scoping miss.
  • Founder feedback inbox redesign. The first cut used a pink-dot eyebrow header pattern that felt like an AI-app tell. Replaced with a 2px ink-coloured vertical hairline + restrained Inter Tight eyebrow + clean Fraunces headline (no inline accent span). New editorial pattern for founder-workspace pages going forward.

Evening update · Visitor feedback, company linkage, performance

A second pass on today's pitch list and public viewer. Investors and prospects can now message you straight from a published pitch; every founder pitch links to a canonical company so you can pitch the same company to different investors; the pitches page paints noticeably faster.

  • Visitor feedback FAB on every public pitch. Floating button bottom-right with three actions: *Message the founder*, *Feedback on a section* (auto-populates from the sections currently rendered), *Overall feedback*. Anonymous viewers leave an email; a cookie remembers them next time so identity is captured once. Founder side: every submission lands in a new inbox at /app/feedback with status filters (new / read / responded / archived), per-pitch + kind filters, and reply-in-place.
  • FAB picks up each pitch's brand colour — the button and the modal's send button read from the same --rail-bg token the left side rail uses, so Foxtale's orange rail = orange FAB, Dosa Coffee's red = red. In the editorial / dashy / IM layouts the FAB anchors at the right edge of the main column (just left of the facts rail) so it never overlaps the data; in showcase it sits at the viewport edge.
  • Pitches ↔ canonical companies. "+ New company" button next to "+ New pitch" on /app/pitches. A filter strip at the top lets you scope the grid to one company. Every card shows a glass-pill badge top-right of the cover — already-linked pitches link through to that company; unlinked cards get a + Company affordance that opens a picker (existing companies + create-and-link in one step). One company can carry multiple pitches (different investor cuts of the same deck).
  • Sidebar Analytics group. Viewers, Analytics, and Feedback now live together under their own "Analytics" header (separated from Pitched + Tools). In collapsed mode the group icons are persona-coloured — sky for Analytics, indigo for Tools, pink for Pitched — so the rail reads at a glance.
  • Powered-by Pitched.vc footer on every published pitch, below the last section. Editorial weight: thin top border, small Inter Tight "Powered by", Fraunces "Pitched.vc" wordmark in the body colour that hover-shifts to the pitch's brand primary.
  • Pitches page is faster. Three changes: (a) PdfThumb now returns the cached cover URL immediately instead of rasterising the source PDF on every render just to verify aspect ratio (~100–200ms saved per pitch); (b) the controller pre-resolves every card's cover in two batched IN(...) queries instead of three SELECTs per card; (c) cover thumbnails switched from CSS background-image to <img loading="lazy" decoding="async"> so off-screen cards no longer block first paint. Net effect on a 15-pitch dashboard: skeleton paints near-instantly, thumbnails fill in as you scroll.
  • AI Coach send button — paper-plane icon (centred in the circle), Enter now sends (Shift+Enter for newline). The old upward-arrow only fired on Cmd+Enter; the new behaviour matches every other chat surface.
  • Default hero banner = slide 1 of your deck. Every new deck build sets display.hero_image_url to the page-1 thumbnail with vertical position centred. The existing focal-point slider in build mode lets you drag the visible portion up or down without a re-upload. First-time tooltip explains the slider + side-panel-upload option, then never shows again.
  • Companies are now properly deduped. CompanyModel::findOrCreate was only matching on domain; if you created a company without a website it cut a fresh row every time (so "Byde" became Byde / byde-2 / byde-3 / byde-4). Now does a case-insensitive name match too, with a domain-conflict guard so different companies with the same name stay distinct. Backfill spark command (pitched:dedupe-companies) merged the existing duplicates: pitches got repointed to the surviving canonical, NULL fields patched onto the winner, the orphan rows deleted.
  • Linking a pitch to a company silently dropped. company_id was missing from PitchModel::$allowedFields — CodeIgniter's model layer strips unknown fields before writing, so the endpoint returned success while the column stayed NULL. Added to allowedFields; backfilled the orphaned attempts.
  • Link-company popover was failing two ways. The list-item click "did nothing" because the raw fetch() didn't send an X-CSRF-TOKEN header and the CSRF filter rejected it silently — switched to the platform's CrmAPI.post helper which handles rotation. Scrolling inside the popover closed it because the close-on-scroll listener was registered with capture: true and intercepted inner scroll events before they reached the list. Internal scroll now stays internal.
  • Tools + Analytics group icons rendered white-on-white in collapsed sidebar mode under the Monday theme. The --m-c-* token chain didn't include analytics; added the variable + the per-group rules that were missing.

Morning update · Investor Intel × Live Numbers

The Live Numbers system now feeds the investor side. When a founder edits a metric on /numbers, the same value (with vintage) appears on the canonical company page that VCs tracking them see. Plus a clutch of UX fixes around the pitch list, analytics, and founder dashboards.

  • Live Numbers feeds investor intel. The canonical company page (/companies/{slug}) now has a "Live deck numbers" card pulling per-deck values straight from each linked pitch's Numbers editor. When a founder has multiple decks pointing at the same company, each deck shows its own block with its own freshness state — investors see who edited what, when. Built on the new PitchMetricExtractor::extractForCompany() aggregator.
  • Founder Intel rewired around Numbers. /founder-intel "Recent Metric Snapshots" widget became "Recent Numbers Edits" — every metric you touch on a Numbers page lands here as a freshness signal your trackers can see. The "Push metrics" snapshot button became "Edit numbers" — picker modal listing your published pitches (drafts excluded — those edits wouldn't reach trackers).
  • Pitch list actions reorganised — the action toolbar (Match · Edit · Numbers · Analytics · Delete) now overlays the bottom of the deck cover image as a center-aligned glass pill instead of clashing with the views/unique/conv stats row.
  • Pitch analytics page repainted. Cards had no backgrounds or borders because the page referenced CSS variables (--ed-surface etc.) that aren't loaded outside the editor. Repainted with brand-pink + Fraunces serif headers + per-card brand-color dots — matches the editorial cadence of every other founder page. Charts switched from blue to brand pink. Added a Numbers shortcut to the page header. Empty states upgraded to match the Numbers page idiom.
  • Last Update KPI on Founder Intel now reads from the latest Numbers edit (with relative "3h ago" formatting), falling back to the legacy snapshot date for accounts that haven't touched the new system yet.
  • Deck card click did nothing on landscape decks — the modal <div> was nested inside the wrong branch of the conditional. Click now opens the full-screen PDF viewer.

Live numbers, founder video, smarter parsing

A long Sunday's worth of upgrades: a brand-new way to keep your pitch's metrics current, an in-browser elevator-pitch recorder, and a parsing engine that pulls out structurally-correct numbers instead of flat text.

  • Live Numbers page/app/pitches/{id}/numbers. Every metric on your pitch in one editable view, grouped by section (Traction / Market / Funding / Unit Economics / Financials / Distribution / Team). Inline edit auto-saves and updates the public pitch instantly. Each row carries an "updated N ago" timestamp — hit your pitch quarterly to keep your investors looking at fresh numbers, not last quarter's.
  • Stale-metric tracking — every edit recorded with a full audit trail. Summary chips at the top of the Numbers page tell you how many metrics are over 60 days old, how many were touched this fortnight, and how many haven't been edited yet.
  • Founder elevator pitch recorder — Build mode → Add → "Record elevator pitch". Full-screen recording studio with a 45-second hard cap, live camera preview, lighting/posture tips, and an optional teleprompter that scrolls your script over the preview as you record. Native MediaRecorder — no plugin to install.
  • Custom play-button overlay for the founder pitch — gradient veil, brand-coloured play disc, "View founder pitch" serif label. Click → fades to the native player. Build mode includes a discreet trash icon top-right to delete + re-record.
  • Adaptive wizard intake/app/pitches/wizard. The AI picks the next question every turn based on what you've answered so far + your sector + geography. Built for founders who don't have a deck yet — start with the company name, market + geography, and the AI walks you through the rest.
  • Synthesis pass on wizard build — when you hit "Build now" the wizard's accumulated answers get fed through the same 3-phase pipeline (extract → enrich with web research → finalise) that powers deck uploads. You get a 25-section pitch from a few paragraphs of input.
  • Default + Custom theme tiles in the build-mode theme picker — ↺ Default reverts to your deck-derived brand colours; + Custom opens four colour pickers (Primary / Accent / Dark / Light) that recolour the page live as you tweak.
  • Approx-time-remaining indicator on the upload page — small pill in the live-processing block tells you "About 2 min remaining" so the wait feels finite.
  • Public changelog at /changelog for everyone (the page you're reading).
  • LlamaParse v2 is now the default for every new deck upload. Pitch-deck-aware extraction prompt (preserves arrow-separated growth values as proper tables, tags slide titles, keeps numerical tables intact) plus structured JSON tables/charts that the AI digester anchors against. Result: ~13% denser skeletons, structurally-correct period-tagged metrics (no more "$20K → $75K → $437K → $865K → $1.3M" packed into a single string).
  • Deeper pattern recognition in the deck → pitch pipeline. Added 15 patterns from real-world decks: AOV cohort ladders (Foxtale-style new/repeat/app), customer-case-study triple-KPI cards (Awiros DIAL/Cummins/P&W), competitor founded-year + geography, q-comm platform breakdowns (Blinkit/Zepto/Instamart), cost-of-disease quantification figures, conceptual reframes ("vs convention"), industry-trend tile grids, manufacturing/architecture stages, per-month/quarterly trend bars, engagement KPIs, sales-incentive structures, channel revenue/order share.
  • Wizard rider expanded to demand 14 missing field categories — every wizard pitch now ships with full target_segments, geo_market, regulatory, partnerships, vision_pillars, hero_quote, competitive_landscape (alternatives + indirect competitors), valuation comparables, team-by-capability, and full social_proof groups.
  • Three-tier extraction priority hierarchy — the deck-extract prompt now strictly prioritises core schema density (Tier 1: identity, founders, advisors, problem, solution, business model, traction, funding, competitors) over standard expansions (Tier 2) over pattern-library extras (Tier 3). When output budget is tight, Tier 3 drops first — Tier 1 stays full.
  • Renderer surfaces 5 fields we used to capture but never display — Unit Economics block (CAC/LTV/Payback/Margin/AOV), Partnerships tile grid (when 3+), Valuation multiples chip row above comparables, embedded product demo videos, product screenshots gallery.
  • Theme picker eyebrow + custom-colour panel styled to match the editorial chrome — restrained, no neon.
  • Onboarding clock pill is now slightly more prominent on the upload page without being tacky.
  • Deck card click was a no-op for landscape decks (the cinematic-card path) — the modal <div> was nested inside the wrong branch of the conditional. Click now opens the full-screen PDF viewer correctly.
  • Camera permission was being blocked at the browser level by an over-strict Permissions-Policy: camera=() header on prod — now camera=(self) so the recorder works.
  • Founder pitch video renders inline with a <video> element instead of trying to iframe-embed direct file URLs.

Evening update · Voice memo + URL crawler in Coach

Coach now hears you talk and reads what you point it at. Speak your update, paste your raw thoughts, or drop a URL — Coach researches, gap-fills, and adds across the entire pitch automatically.

  • Voice memo button in the build mode Add tab. Hit record, talk freely about your plan for a minute or two, and Coach transcribes (Whisper), cleans the transcript (GPT-4o-mini), and applies changes across the pitch — no chat back required. The cleaned transcript is logged to your Coach history so you can reference it later.
  • URL crawler in AI Coach — mention any link or bare domain in a Coach message ("see priveat.in" / "look at https://foxtale.in/about") and Coach auto-fetches up to three pages, reads the title + body text, and uses real site copy as ground truth when adding entries to your pitch.
  • Aggressive gap-filling — Coach now scans the skeleton on every voice memo / brief and proactively fills empty strategic fields (tagline, elevator, why_now, market sizing, moats, risks, category leaders) without being asked. Existing problem / solution / founder bios stay sacred unless you explicitly request a rewrite.
  • Three-tier field discipline — Coach treats fields as Sacred (never touch), Always Enhance (proactively sharpen on every brief), or Fill If Empty. Plus a server-side guardrail that refuses to overwrite a populated array via patch — your curated SKUs / competitors / advisors can never get nuked again.
  • Free-form JSON Coach response — dropped strict schema constraints so Coach can emit objects/arrays directly. Token budget bumped 4× (16K for voice memos / long pastes), temperature warmed up so Coach is more decisive about expanding strategic sections.

Founder fundraising loop closed

Pitched now covers the full founder fundraising journey end-to-end — pitch, match, share, sign, track — without leaving the platform.

  • Data Room — private docs + tracked share links per pitch. Per-doc + per-share view tracking with IP geolocation. Optional password / NDA / expiry / max-views on each share. Build-mode top bar entry.
  • Legal Room — 9 founder-friendly templates (Mutual NDA, One-Way NDA, LOI, SAFE, Term Sheet, Advisor Agreement, Side Letter, MOU, Blank). Variable substitution (counterparty, company, date, governing law). Editor with autosave. E-signing via canvas pad (mouse + touch + stylus) on both founder and counterparty sides. Push-to-data-room finalises a signed PDF-ready HTML into the pitch's data room.
  • Headshot Studio/app/headshot-studio standalone page + inline access from any founder avatar in build mode. 7 styles: Studio Natural, Formal, Casual, Touched Up, Caricature, Pop / Comic, Pencil Sketch. Apply to any founder slot on any pitch.
  • Google Studio (Nano Banana) — Build mode → Add → "Enhance with Google Studio". Search Unsplash, upload a reference, or just describe — Gemini generates a 1600×900 hero banner. Two output buttons: "Use as-is" (skip AI) or "Generate with AI".
  • Cinematic Studio (multi-file)/app/pitches/studio parallel to /new. Full-screen, no chrome. Drop your deck plus financial model XLS, references, and product images together — the AI fuses them into one richer pitch.
  • Wishlist + Match — Per-pitch investor pipeline with status walker (saved → contacted → meeting set → in talks → committed/passed). AI-powered match button finds the best investors for your round.
  • Smart deck cover thumbnails — every pitch card now shows the actual page-1 of your deck as a cover. Auto-generated on upload.
  • Visitor analytics with city + ISP — every pitch view + data-room access enriched with country, city, and ISP. Aggregate /app/analytics + per-pitch analytics + recent-visitors feed on the dashboard.
  • Founder photo lightbox — click any founder's photo on a published pitch to see a clean polaroid-style zoom.
  • Smart header banner positioning — when you upload a hero image, we auto-detect the most interesting region (faces, focal subjects) for the 16:9 crop. Drag the slider on hover to fine-tune.
  • Three new themes — Citrus, Meyer Lemon, Blood Orange (now 22 brand presets in total).
  • Brand colour now comes from your deck cover first, website second. Even if your site is rate-limiting our crawler, your deck's brand colour gets picked up.
  • Web crawler now sends a real browser User-Agent — no more 429s from Cloudflare-fronted sites.
  • Numbers sanity — auto-detect inverted projection charts (no founder pitches a planned decline) and flag unit mismatches (Cr vs Lakh vs M jumps) in the build view.
  • AI Coach now applies changes live without reload — text, themes, layouts, photos, headers, all swap in place.
  • Theme picker recolours the entire page (rail + facts panel + accents) in real time.
  • Pitched favicon is now the proper brand mark across the whole platform (was the CodeIgniter default in some browsers).
  • "Empty skeleton" bug — uploads now produce real content even when one phase of the pipeline silently crashes.
  • Founder photos no longer revert to the original after switching layouts.
  • Image uploads now visibly swap on the page (was silently saving but not showing).
  • AI Coach landing page no longer crashes on first visit.
  • Coach actions read from the correct response level (was off by one nesting layer).
  • Headshot Studio prompts simplified — no more "Gemini returned no image" refusals on regular portraits.

AI Coach + immersive theme

Shipped - AI Coach end-to-end with structured tool-calls, smart array merge, and per-conversation history. - Immersive dark mode (toggle 🌙 in sidebar footer), persisted via localStorage with FOUC-free pre-paint. - Persona-coloured scrollbars (founder=pink, fund=blue, IB=green, family=purple). - Marketing site at /home rebuilt with Monday-inspired bento + persona pivot. - Login page rewrite — split pane with animated showcase.

  • AI Coach end-to-end with structured tool-calls, smart array merge, and per-conversation history.
  • Immersive dark mode (toggle 🌙 in sidebar footer), persisted via localStorage with FOUC-free pre-paint.
  • Persona-coloured scrollbars (founder=pink, fund=blue, IB=green, family=purple).
  • Marketing site at /home rebuilt with Monday-inspired bento + persona pivot.
  • Login page rewrite — split pane with animated showcase.
  • Deck upload pipeline shipped end-to-end — LlamaParse + smalot fallback for Hostinger.
  • Tightened extraction prompt with case normalisation (no more "THE 1% EXPERIENCE" headlines).
  • Editor coach panel rendering — single x-for loop with defensive null guards.
  • Coach-history page response-shape mismatch.
  • Pitch preview blank screen (reveal observer was inside an unreached branch).

Multi-tenant platform substrate (Phase 0)

Foundational multi-tenant work — every persona (founder, IB, fund, family office) now lives in the same product, with persona-aware sidebars, dashboards, and routes.

  • tenant_type on every tenant (founder / ib / fund / family_office / internal).
  • Persona-aware sidebar (CrmModules registry).
  • Per-persona dashboard branching.
  • IB schema migrated (investors / matrix / docs / revenue / CP / sectors).
  • Public pitch render at /{slug} and /p/{token} — sidebar nav, top bar, 12-column card grid, reveal animations.
Want to be told the moment we ship something? Email info@craise.ai and we'll add you to the release-notes list.