diff --git a/.node-version b/.node-version
new file mode 100644
index 0000000..d845d9d
--- /dev/null
+++ b/.node-version
@@ -0,0 +1 @@
+24.14.0
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..31abfe3
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+app/routeTree.gen.ts
diff --git a/.vite-hooks/pre-commit b/.vite-hooks/pre-commit
new file mode 100755
index 0000000..85fb65b
--- /dev/null
+++ b/.vite-hooks/pre-commit
@@ -0,0 +1 @@
+vp staged
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..46cef3b
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["VoidZero.vite-plus-extension-pack"]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b653bd4
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,9 @@
+{
+ "editor.defaultFormatter": "oxc.oxc-vscode",
+ "oxc.fmt.configPath": "./vite.config.ts",
+ "editor.formatOnSave": true,
+ "editor.formatOnSaveMode": "file",
+ "editor.codeActionsOnSave": {
+ "source.fixAll.oxc": "explicit"
+ }
+}
diff --git a/CLAUDE.md b/CLAUDE.md
index 6e9f98d..e69116b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -5,9 +5,11 @@ Video review platform for creative teams. Built by Theo.
## Design Language
### Philosophy
+
Brutalist, typographic, minimal. The design should feel bold and direct—like a poster, not a dashboard. Prioritize clarity over decoration. Let typography and whitespace do the heavy lifting.
### Colors
+
- **Background**: `#f0f0e8` (warm cream)
- **Text**: `#1a1a1a` (near-black)
- **Muted text**: `#888888`
@@ -18,34 +20,40 @@ Brutalist, typographic, minimal. The design should feel bold and direct—like a
- **Inverted sections**: `#1a1a1a` background with `#f0f0e8` text
### Typography
+
- **Headings**: Font-black (900 weight), tight tracking
- **Body**: Regular weight, clean and readable
- **Monospace**: For technical info, timestamps, stats
- Use size contrast dramatically—massive headlines with small supporting text
### Borders & Spacing
+
- Strong 2px borders in `#1a1a1a` for section dividers and cards
- Generous padding (p-6 to p-8 typical)
- Clear visual hierarchy through spacing
### Interactive Elements
+
- Buttons: Solid backgrounds with bold text, clear hover states
- Links: Underlines, not color-only differentiation
- Hover states: Background fills or color shifts, no subtle opacity changes
### Component Patterns
+
- **Cards**: 2px black border, cream background, bold title
- **Sections**: Often alternate between cream and dark backgrounds
- **Forms**: Simple inputs with strong borders, no rounded corners or minimal
- **Navigation**: Minimal, text-based, appears on scroll when needed
### Do's
+
- Use bold typography to create hierarchy
- Embrace whitespace
- Keep interactions obvious and direct
- Use green sparingly as accent, not primary
### Don'ts
+
- No gradients or shadows (except subtle where functional)
- No rounded corners on primary UI (square/sharp edges)
- No decorative icons—only functional ones
diff --git a/app/app.css b/app/app.css
index c32491f..c300273 100644
--- a/app/app.css
+++ b/app/app.css
@@ -1,59 +1,64 @@
-/* Fonts */
-@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&display=block');
-
-@import "tailwindcss";
+/* vite+ SSR currently fails to resolve package CSS imports during transform-only */
+@import "../node_modules/tailwindcss/index.css";
@font-face {
- font-family: 'Geist';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Regular.woff2') format('woff2');
+ font-family: "Geist";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Regular.woff2")
+ format("woff2");
font-weight: 400;
font-style: normal;
font-display: block;
}
@font-face {
- font-family: 'Geist';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Medium.woff2') format('woff2');
+ font-family: "Geist";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Medium.woff2")
+ format("woff2");
font-weight: 500;
font-style: normal;
font-display: block;
}
@font-face {
- font-family: 'Geist';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-SemiBold.woff2') format('woff2');
+ font-family: "Geist";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-SemiBold.woff2")
+ format("woff2");
font-weight: 600;
font-style: normal;
font-display: block;
}
@font-face {
- font-family: 'Geist';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Bold.woff2') format('woff2');
+ font-family: "Geist";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Bold.woff2")
+ format("woff2");
font-weight: 700;
font-style: normal;
font-display: block;
}
@font-face {
- font-family: 'Geist';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Black.woff2') format('woff2');
+ font-family: "Geist";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-sans/Geist-Black.woff2")
+ format("woff2");
font-weight: 900;
font-style: normal;
font-display: block;
}
@font-face {
- font-family: 'Geist Mono';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-mono/GeistMono-Regular.woff2') format('woff2');
+ font-family: "Geist Mono";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-mono/GeistMono-Regular.woff2")
+ format("woff2");
font-weight: 400;
font-style: normal;
font-display: block;
}
@font-face {
- font-family: 'Geist Mono';
- src: url('https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-mono/GeistMono-Medium.woff2') format('woff2');
+ font-family: "Geist Mono";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.2.0/dist/fonts/geist-mono/GeistMono-Medium.woff2")
+ format("woff2");
font-weight: 500;
font-style: normal;
font-display: block;
@@ -78,7 +83,7 @@
--border: #1a1a1a;
--border-subtle: #cccccc;
--shadow-color: #1a1a1a;
- --shadow-accent: rgba(45,90,45,1);
+ --shadow-accent: rgba(45, 90, 45, 1);
/* Accent - forest green */
--accent: #2d5a2d;
@@ -177,9 +182,9 @@
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
- --font-sans: 'Geist', system-ui, -apple-system, sans-serif;
- --font-mono: 'Geist Mono', ui-monospace, monospace;
- --font-serif: 'Instrument Serif', Georgia, serif;
+ --font-sans: "Geist", system-ui, -apple-system, sans-serif;
+ --font-mono: "Geist Mono", ui-monospace, monospace;
+ --font-serif: "Instrument Serif", Georgia, serif;
}
* {
@@ -193,7 +198,7 @@ html {
body {
background: var(--background);
color: var(--foreground);
- font-family: 'Geist Mono', ui-monospace, monospace;
+ font-family: "Geist Mono", ui-monospace, monospace;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@@ -284,45 +289,83 @@ body {
}
.video-js .vjs-time-control {
- font-family: 'Geist Mono', monospace;
+ font-family: "Geist Mono", monospace;
font-size: 12px;
color: rgba(255, 255, 255, 0.7);
}
/* Animation keyframes */
@keyframes fade-in {
- from { opacity: 0; }
- to { opacity: 1; }
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
}
@keyframes fade-out {
- from { opacity: 1; }
- to { opacity: 0; }
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
}
@keyframes slide-up {
- from { opacity: 0; transform: translateY(20px); }
- to { opacity: 1; transform: translateY(0); }
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
@keyframes slide-in-from-top {
- from { transform: translateY(-8px); opacity: 0; }
- to { transform: translateY(0); opacity: 1; }
+ from {
+ transform: translateY(-8px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
}
@keyframes slide-in-from-bottom {
- from { transform: translateY(8px); opacity: 0; }
- to { transform: translateY(0); opacity: 1; }
+ from {
+ transform: translateY(8px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
}
@keyframes slide-in-from-left {
- from { transform: translateX(-8px); opacity: 0; }
- to { transform: translateX(0); opacity: 1; }
+ from {
+ transform: translateX(-8px);
+ opacity: 0;
+ }
+ to {
+ transform: translateX(0);
+ opacity: 1;
+ }
}
@keyframes slide-in-from-right {
- from { transform: translateX(8px); opacity: 0; }
- to { transform: translateX(0); opacity: 1; }
+ from {
+ transform: translateX(8px);
+ opacity: 0;
+ }
+ to {
+ transform: translateX(0);
+ opacity: 1;
+ }
}
.animate-in {
@@ -336,12 +379,24 @@ body {
animation-fill-mode: forwards;
}
-.fade-in-0 { animation-name: fade-in; }
-.fade-out-0 { animation-name: fade-out; }
-.slide-in-from-top-2 { animation-name: slide-in-from-top; }
-.slide-in-from-bottom-2 { animation-name: slide-in-from-bottom; }
-.slide-in-from-left-2 { animation-name: slide-in-from-left; }
-.slide-in-from-right-2 { animation-name: slide-in-from-right; }
+.fade-in-0 {
+ animation-name: fade-in;
+}
+.fade-out-0 {
+ animation-name: fade-out;
+}
+.slide-in-from-top-2 {
+ animation-name: slide-in-from-top;
+}
+.slide-in-from-bottom-2 {
+ animation-name: slide-in-from-bottom;
+}
+.slide-in-from-left-2 {
+ animation-name: slide-in-from-left;
+}
+.slide-in-from-right-2 {
+ animation-name: slide-in-from-right;
+}
/* Focus visible styles */
.focus-ring {
@@ -355,73 +410,151 @@ body {
/* Font utilities */
.font-serif {
- font-family: 'Instrument Serif', Georgia, serif;
+ font-family: "Instrument Serif", Georgia, serif;
}
.font-mono {
- font-family: 'Geist Mono', ui-monospace, monospace;
+ font-family: "Geist Mono", ui-monospace, monospace;
}
/* Map legacy hardcoded utility tokens to theme vars so dark mode works app-wide */
-[class~="bg-[#f0f0e8]"] { background-color: var(--background) !important; }
-[class~="text-[#f0f0e8]"] { color: var(--foreground-inverse) !important; }
-
-[class~="bg-[#1a1a1a]"] { background-color: var(--foreground) !important; }
-[class~="text-[#1a1a1a]"] { color: var(--foreground) !important; }
-[class~="border-[#1a1a1a]"] { border-color: var(--border) !important; }
-
-[class~="bg-[#e8e8e0]"] { background-color: var(--surface-alt) !important; }
-[class~="text-[#e8e8e0]"] { color: var(--foreground-inverse) !important; }
-[class~="border-[#e8e8e0]"] { border-color: var(--border-subtle) !important; }
-
-[class~="bg-[#d8d8d0]"] { background-color: var(--surface-muted) !important; }
-[class~="bg-[#333333]"] { background-color: var(--surface-muted) !important; }
-[class~="bg-[#333]"] { background-color: var(--surface-muted) !important; }
-[class~="border-[#333]"] { border-color: var(--border-subtle) !important; }
-
-[class~="text-[#888]"] { color: var(--foreground-muted) !important; }
-[class~="text-[#888888]"] { color: var(--foreground-muted) !important; }
-[class~="bg-[#888]"] { background-color: var(--foreground-muted) !important; }
-
-[class~="text-[#ccc]"] { color: var(--border-subtle) !important; }
-[class~="border-[#ccc]"] { border-color: var(--border-subtle) !important; }
-[class~="text-[#cccccc]"] { color: var(--border-subtle) !important; }
-[class~="border-[#cccccc]"] { border-color: var(--border-subtle) !important; }
-
-[class~="bg-[#2d5a2d]"] { background-color: var(--accent) !important; }
-[class~="text-[#2d5a2d]"] { color: var(--accent) !important; }
-[class~="border-[#2d5a2d]"] { border-color: var(--accent) !important; }
-
-[class~="bg-[#3a6a3a]"] { background-color: var(--accent-hover) !important; }
-[class~="text-[#7cb87c]"] { color: var(--accent-light) !important; }
-[class~="bg-[#7cb87c]"] { background-color: var(--accent-light) !important; }
-[class~="border-[#7cb87c]"] { border-color: var(--accent-light) !important; }
-
-[class~="text-[#dc2626]"] { color: var(--destructive) !important; }
-[class~="bg-[#dc2626]"] { background-color: var(--destructive) !important; }
-[class~="border-[#dc2626]"] { border-color: var(--destructive) !important; }
+[class~="bg-[#f0f0e8]"] {
+ background-color: var(--background) !important;
+}
+[class~="text-[#f0f0e8]"] {
+ color: var(--foreground-inverse) !important;
+}
+
+[class~="bg-[#1a1a1a]"] {
+ background-color: var(--foreground) !important;
+}
+[class~="text-[#1a1a1a]"] {
+ color: var(--foreground) !important;
+}
+[class~="border-[#1a1a1a]"] {
+ border-color: var(--border) !important;
+}
+
+[class~="bg-[#e8e8e0]"] {
+ background-color: var(--surface-alt) !important;
+}
+[class~="text-[#e8e8e0]"] {
+ color: var(--foreground-inverse) !important;
+}
+[class~="border-[#e8e8e0]"] {
+ border-color: var(--border-subtle) !important;
+}
+
+[class~="bg-[#d8d8d0]"] {
+ background-color: var(--surface-muted) !important;
+}
+[class~="bg-[#333333]"] {
+ background-color: var(--surface-muted) !important;
+}
+[class~="bg-[#333]"] {
+ background-color: var(--surface-muted) !important;
+}
+[class~="border-[#333]"] {
+ border-color: var(--border-subtle) !important;
+}
+
+[class~="text-[#888]"] {
+ color: var(--foreground-muted) !important;
+}
+[class~="text-[#888888]"] {
+ color: var(--foreground-muted) !important;
+}
+[class~="bg-[#888]"] {
+ background-color: var(--foreground-muted) !important;
+}
+
+[class~="text-[#ccc]"] {
+ color: var(--border-subtle) !important;
+}
+[class~="border-[#ccc]"] {
+ border-color: var(--border-subtle) !important;
+}
+[class~="text-[#cccccc]"] {
+ color: var(--border-subtle) !important;
+}
+[class~="border-[#cccccc]"] {
+ border-color: var(--border-subtle) !important;
+}
+
+[class~="bg-[#2d5a2d]"] {
+ background-color: var(--accent) !important;
+}
+[class~="text-[#2d5a2d]"] {
+ color: var(--accent) !important;
+}
+[class~="border-[#2d5a2d]"] {
+ border-color: var(--accent) !important;
+}
+
+[class~="bg-[#3a6a3a]"] {
+ background-color: var(--accent-hover) !important;
+}
+[class~="text-[#7cb87c]"] {
+ color: var(--accent-light) !important;
+}
+[class~="bg-[#7cb87c]"] {
+ background-color: var(--accent-light) !important;
+}
+[class~="border-[#7cb87c]"] {
+ border-color: var(--accent-light) !important;
+}
+
+[class~="text-[#dc2626]"] {
+ color: var(--destructive) !important;
+}
+[class~="bg-[#dc2626]"] {
+ background-color: var(--destructive) !important;
+}
+[class~="border-[#dc2626]"] {
+ border-color: var(--destructive) !important;
+}
[class~="bg-[#dc2626]/10"] {
background-color: color-mix(in srgb, var(--destructive) 10%, transparent) !important;
}
-[class~="text-[#ca8a04]"] { color: var(--warning) !important; }
-[class~="bg-[#ca8a04]"] { background-color: var(--warning) !important; }
-[class~="border-[#ca8a04]"] { border-color: var(--warning) !important; }
+[class~="text-[#ca8a04]"] {
+ color: var(--warning) !important;
+}
+[class~="bg-[#ca8a04]"] {
+ background-color: var(--warning) !important;
+}
+[class~="border-[#ca8a04]"] {
+ border-color: var(--warning) !important;
+}
[class~="bg-[#ca8a04]/10"] {
background-color: color-mix(in srgb, var(--warning) 10%, transparent) !important;
}
-[class~="hover:bg-[#1a1a1a]"]:hover { background-color: var(--foreground) !important; }
-[class~="hover:bg-[#e8e8e0]"]:hover { background-color: var(--surface-alt) !important; }
-[class~="hover:bg-[#d8d8d0]"]:hover { background-color: var(--surface-muted) !important; }
-[class~="hover:bg-[#3a6a3a]"]:hover { background-color: var(--accent-hover) !important; }
+[class~="hover:bg-[#1a1a1a]"]:hover {
+ background-color: var(--foreground) !important;
+}
+[class~="hover:bg-[#e8e8e0]"]:hover {
+ background-color: var(--surface-alt) !important;
+}
+[class~="hover:bg-[#d8d8d0]"]:hover {
+ background-color: var(--surface-muted) !important;
+}
+[class~="hover:bg-[#3a6a3a]"]:hover {
+ background-color: var(--accent-hover) !important;
+}
[class~="hover:bg-[#dc2626]/10"]:hover {
background-color: color-mix(in srgb, var(--destructive) 10%, transparent) !important;
}
-[class~="hover:text-[#1a1a1a]"]:hover { color: var(--foreground) !important; }
-[class~="hover:text-[#f0f0e8]"]:hover { color: var(--foreground-inverse) !important; }
-[class~="hover:text-[#2d5a2d]"]:hover { color: var(--accent) !important; }
+[class~="hover:text-[#1a1a1a]"]:hover {
+ color: var(--foreground) !important;
+}
+[class~="hover:text-[#f0f0e8]"]:hover {
+ color: var(--foreground-inverse) !important;
+}
+[class~="hover:text-[#2d5a2d]"]:hover {
+ color: var(--accent) !important;
+}
[class~="group-hover:text-[#1a1a1a]"] {
transition: color 150ms ease;
}
diff --git a/app/routes/-compare-frameio.tsx b/app/routes/-compare-frameio.tsx
index 07206c8..fd209b5 100644
--- a/app/routes/-compare-frameio.tsx
+++ b/app/routes/-compare-frameio.tsx
@@ -73,15 +73,12 @@ export default function CompareFrameio() {
We're cheaper and faster.
-
- That might be better.
-
+ That might be better.
- Frame.io is a great product built for enterprise teams with - enterprise budgets. lawn is a scrappy little tool that does the - important stuff for $5/month flat. No per-seat math. No PhD in - procurement required. + Frame.io is a great product built for enterprise teams with enterprise budgets. lawn + is a scrappy little tool that does the important stuff for $5/month flat. No per-seat + math. No PhD in procurement required.
@@ -99,9 +96,7 @@ export default function CompareFrameio() {- Frame.io charges $19 per user per month. lawn charges $5 per month. - Not per user. Just $5. Here's what that means annually. + Frame.io charges $19 per user per month. lawn charges $5 per month. Not per user. Just + $5. Here's what that means annually.
- We could trash-talk Frame.io but that would be dishonest and also - they have way more employees than us. Here's the real deal. + We could trash-talk Frame.io but that would be dishonest and also they have way more + employees than us. Here's the real deal.
- Genuinely, Frame.io is solid software. If this is you, go use - it. We won't be offended. (Okay maybe a little.) + Genuinely, Frame.io is solid software. If this is you, go use it. We won't be + offended. (Okay maybe a little.)
- We do less than Frame.io. Proudly. Turns out "upload, share, - comment" is 90% of what anyone actually needs. + We do less than Frame.io. Proudly. Turns out "upload, share, comment" is 90% of + what anyone actually needs.
- $5/month. Unlimited seats. No sales call required. No credit card to - start. + $5/month. Unlimited seats. No sales call required. No credit card to start.
- Wipster is a solid tool with real approval workflows and a proper - feature set. lawn is smaller, cheaper, and open source. We do less - for less money, and that's the whole pitch. + Wipster is a solid tool with real approval workflows and a proper feature set. lawn is + smaller, cheaper, and open source. We do less for less money, and that's the whole + pitch.
- * Wipster pricing based on their per-user model. Actual pricing may - vary by plan. + * Wipster pricing based on their per-user model. Actual pricing may vary by plan.
- Wipster charges per user. lawn charges $5 per month total. Not per - user. Just $5. The math gets increasingly silly as your team grows. + Wipster charges per user. lawn charges $5 per month total. Not per user. Just $5. The + math gets increasingly silly as your team grows.
- lawn is fully open source. Every line. The elegant parts and the - parts where we left a TODO from three months ago. No black box. No - trust required. Just code you can read, fork, and judge silently. + lawn is fully open source. Every line. The elegant parts and the parts where we left a + TODO from three months ago. No black box. No trust required. Just code you can read, + fork, and judge silently.
- Wipster is genuinely good software built by people who care about - video review. We just think there's room for something simpler. Here - are the facts. + Wipster is genuinely good software built by people who care about video review. We just + think there's room for something simpler. Here are the facts.
- Seriously, Wipster is good. If this is you, go use it. We'll - be here if you change your mind later. + Seriously, Wipster is good. If this is you, go use it. We'll be here if you change + your mind later.
- We do less than Wipster. Proudly. Upload, share, comment. Go - home. That's 90% of what anyone actually needs. + We do less than Wipster. Proudly. Upload, share, comment. Go home. That's 90% of + what anyone actually needs.
- You're a 15-person agency with 30 freelancers rotating through. - Per-seat pricing wasn't built for you. It was built to charge you - more. + You're a 15-person agency with 30 freelancers rotating through. Per-seat pricing + wasn't built for you. It was built to charge you more.
- lawn is video review for creative teams. Unlimited seats. $5/month. - The whole agency, not per editor. + lawn is video review for creative teams. Unlimited seats. $5/month. The whole agency, + not per editor.
- Your video review tool shouldn't make it harder. Here are the - problems we actually solve. + Your video review tool shouldn't make it harder. Here are the problems we actually + solve.
- Frame.io charges $19/user/month. lawn charges $5/month total. - Here's what that looks like at agency scale. + Frame.io charges $19/user/month. lawn charges $5/month total. Here's what that looks + like at agency scale.
- {row.commentary} -
+ {row.saved} +{row.commentary}
- The pattern: They - charge more as you grow. We don't. Your 50th seat costs the - same as your first — $0 extra. + The pattern: They charge more as you grow. + We don't. Your 50th seat costs the same as your first — $0 extra.
- $5/month. Unlimited seats. Unlimited projects. No per-user pricing. - Ever. + $5/month. Unlimited seats. Unlimited projects. No per-user pricing. Ever.
Set up takes about 2 minutes. Your first freelancer will thank you. diff --git a/app/routes/-for-video-editors.tsx b/app/routes/-for-video-editors.tsx index 80dd11b..3e27732 100644 --- a/app/routes/-for-video-editors.tsx +++ b/app/routes/-for-video-editors.tsx @@ -62,10 +62,9 @@ export default function ForVideoEditors() { VIDEO REVIEW THAT EDITORS ACTUALLY WANT TO USE.
- Your client said "make it pop" on a 47-minute timeline. You deserve - a review tool that at least tells you where they meant. lawn gives - you frame-accurate feedback, instant playback, and a workflow that - doesn't fight your NLE. + Your client said "make it pop" on a 47-minute timeline. You deserve a review tool that + at least tells you where they meant. lawn gives you frame-accurate feedback, instant + playback, and a workflow that doesn't fight your NLE.
- Three steps. No onboarding calls, no training videos, no "schedule a - demo" buttons. + Three steps. No onboarding calls, no training videos, no "schedule a demo" buttons.
- Unlimited seats. Unlimited projects. Unlimited reviewers. Your - entire team, your clients, your client's clients — everyone gets - access for one flat price. + Unlimited seats. Unlimited projects. Unlimited reviewers. Your entire team, your + clients, your client's clients — everyone gets access for one flat price.
Stop paying per-seat tax on collaboration. @@ -189,8 +180,7 @@ export default function ForVideoEditors() { START EDITING FASTER.
- Free trial, no credit card. Set up your first review in under a - minute. + Free trial, no credit card. Set up your first review in under a minute.
{/* Minimal nav */} -
/share/{link.token}
- {link.isExpired ? (
-