diff --git a/README.md b/README.md
index 532b3ba..dfb0a0a 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ Open [http://localhost:3000](http://localhost:3000) in your browser.
1. **Iframe-based preview** - Uses `srcdoc` with strict sandboxing for security. This shows how the email renders in a modern browser, not specific email clients.
-2. **Regex-based CSS extraction** - Simple and fast for the MVP. Could be upgraded to PostCSS for more robust parsing.
+2. **PostCSS-based CSS extraction** - Uses PostCSS with safe-parser for robust CSS parsing, handling nested rules, @-rules, and malformed CSS gracefully.
3. **Client-side analysis** - All processing happens in the browser. The caniemail data is fetched once and cached.
@@ -116,8 +116,13 @@ For true cross-client preview screenshots, commercial tools like [Litmus](https:
- [Next.js 16](https://nextjs.org) - React framework
- [TypeScript](https://typescriptlang.org) - Type safety
- [Tailwind CSS](https://tailwindcss.com) - Styling
+- [PostCSS](https://postcss.org) - CSS parsing
- [caniemail.com](https://caniemail.com) - Compatibility data
+## Author
+
+**Dominik Hryshaiev** - [LinkedIn](https://www.linkedin.com/in/domhhv) · [GitHub](https://github.com/domhhv)
+
## License
MIT
@@ -125,5 +130,3 @@ MIT
## Acknowledgments
- [caniemail.com](https://www.caniemail.com) for their comprehensive email client support data
-- [Resend](https://resend.com) for the interesting challenge
-- [Email favicon](https://www.flaticon.com/free-icon/email_9840614?term=mail&page=1&position=53&origin=search&related_id=9840614) is created by [lakonicon](https://www.flaticon.com/authors/lakonicon) on Flaticon
diff --git a/src/app/favicon.ico b/src/app/favicon.ico
index 9769b2c..6a4c629 100644
Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ
diff --git a/src/app/globals.css b/src/app/globals.css
index 9390f63..05247c4 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -44,30 +44,31 @@
}
:root {
- --radius: 0.625rem;
- --background: oklch(1 0 0);
- --foreground: oklch(0.129 0.042 264.695);
- --card: oklch(1 0 0);
- --card-foreground: oklch(0.129 0.042 264.695);
- --popover: oklch(1 0 0);
- --popover-foreground: oklch(0.129 0.042 264.695);
- --primary: oklch(0.208 0.042 265.755);
- --primary-foreground: oklch(0.984 0.003 247.858);
- --secondary: oklch(0.968 0.007 247.896);
- --secondary-foreground: oklch(0.208 0.042 265.755);
- --muted: oklch(0.968 0.007 247.896);
- --muted-foreground: oklch(0.554 0.046 257.417);
- --accent: oklch(0.968 0.007 247.896);
- --accent-foreground: oklch(0.208 0.042 265.755);
- --destructive: oklch(0.577 0.245 27.325);
- --border: oklch(0.929 0.013 255.508);
- --input: oklch(0.929 0.013 255.508);
- --ring: oklch(0.704 0.04 256.788);
- --chart-1: oklch(0.646 0.222 41.116);
- --chart-2: oklch(0.6 0.118 184.704);
- --chart-3: oklch(0.398 0.07 227.392);
- --chart-4: oklch(0.828 0.189 84.429);
- --chart-5: oklch(0.769 0.188 70.08);
+ --radius: 0.5rem;
+ --background: oklch(0.982 0 161.565);
+ --foreground: oklch(0.244 0 169.695);
+ --muted: oklch(0.952 0 165.964);
+ --muted-foreground: oklch(0.503 0 180);
+ --popover: oklch(0.991 0 180);
+ --popover-foreground: oklch(0.244 0 169.695);
+ --card: oklch(0.991 0 180);
+ --card-foreground: oklch(0.244 0 169.695);
+ --border: oklch(0.882 0 180);
+ --input: oklch(0.955 0 180);
+ --primary: oklch(0.689 0.19 45.166);
+ --primary-foreground: oklch(1 0 180);
+ --secondary: oklch(0.92 0.065 74.362);
+ --secondary-foreground: oklch(0.35 0.069 40.827);
+ --accent: oklch(0.931 0 171.254);
+ --accent-foreground: oklch(0.244 0 169.695);
+ --destructive: oklch(0.627 0.194 33.336);
+ --destructive-foreground: oklch(1 0 180);
+ --ring: oklch(0.745 0.132 54.33);
+ --chart-1: oklch(0.689 0.19 45.166);
+ --chart-2: oklch(0.92 0.065 74.362);
+ --chart-3: oklch(0.931 0 171.254);
+ --chart-4: oklch(0.936 0.052 74.572);
+ --chart-5: oklch(0.693 0.195 44.608);
--sidebar: oklch(0.984 0.003 247.858);
--sidebar-foreground: oklch(0.129 0.042 264.695);
--sidebar-primary: oklch(0.208 0.042 265.755);
@@ -79,29 +80,31 @@
}
.dark {
- --background: oklch(0.129 0.042 264.695);
- --foreground: oklch(0.984 0.003 247.858);
- --card: oklch(0.208 0.042 265.755);
- --card-foreground: oklch(0.984 0.003 247.858);
- --popover: oklch(0.208 0.042 265.755);
- --popover-foreground: oklch(0.984 0.003 247.858);
- --primary: oklch(0.929 0.013 255.508);
- --primary-foreground: oklch(0.208 0.042 265.755);
- --secondary: oklch(0.279 0.041 260.031);
- --secondary-foreground: oklch(0.984 0.003 247.858);
- --muted: oklch(0.279 0.041 260.031);
- --muted-foreground: oklch(0.704 0.04 256.788);
- --accent: oklch(0.279 0.041 260.031);
- --accent-foreground: oklch(0.984 0.003 247.858);
- --destructive: oklch(0.704 0.191 22.216);
- --border: oklch(1 0 0 / 10%);
- --input: oklch(1 0 0 / 15%);
- --ring: oklch(0.551 0.027 264.364);
- --chart-1: oklch(0.488 0.243 264.376);
- --chart-2: oklch(0.696 0.17 162.48);
- --chart-3: oklch(0.769 0.188 70.08);
- --chart-4: oklch(0.627 0.265 303.9);
- --chart-5: oklch(0.645 0.246 16.439);
+ --radius: 0.5rem;
+ --background: oklch(0.178 0 180);
+ --foreground: oklch(0.949 0 180);
+ --muted: oklch(0.252 0 180);
+ --muted-foreground: oklch(0.77 0 141.34);
+ --popover: oklch(0.213 0 168.69);
+ --popover-foreground: oklch(0.949 0 180);
+ --card: oklch(0.213 0 168.69);
+ --card-foreground: oklch(0.949 0 180);
+ --border: oklch(0.235 0.011 90.394);
+ --input: oklch(0.402 0 195.945);
+ --primary: oklch(0.689 0.19 45.166);
+ --primary-foreground: oklch(1 0 180);
+ --secondary: oklch(0.258 0.045 60.789);
+ --secondary-foreground: oklch(0.925 0.052 66.177);
+ --accent: oklch(0.285 0 168.69);
+ --accent-foreground: oklch(0.949 0 180);
+ --destructive: oklch(0.627 0.194 33.336);
+ --destructive-foreground: oklch(1 0 180);
+ --ring: oklch(0.541 0.116 50.039);
+ --chart-1: oklch(0.689 0.19 45.166);
+ --chart-2: oklch(0.258 0.045 60.789);
+ --chart-3: oklch(0.285 0 168.69);
+ --chart-4: oklch(0.294 0.053 60.297);
+ --chart-5: oklch(0.693 0.195 44.608);
--sidebar: oklch(0.208 0.042 265.755);
--sidebar-foreground: oklch(0.984 0.003 247.858);
--sidebar-primary: oklch(0.488 0.243 264.376);
diff --git a/src/components/custom/email-content-input.tsx b/src/components/custom/email-content-input.tsx
index 1fd86b6..a759076 100644
--- a/src/components/custom/email-content-input.tsx
+++ b/src/components/custom/email-content-input.tsx
@@ -8,7 +8,6 @@ import { useTheme } from 'next-themes';
import * as React from 'react';
import { TooltipButton } from '@/components/custom/tooltip-button';
-import { Button } from '@/components/ui/button';
import { Kbd, KbdGroup } from '@/components/ui/kbd';
import { useHasKeyboard } from '@/hooks/use-has-keyboard';
import { useModifierKeys } from '@/hooks/use-modifier-keys';
@@ -82,16 +81,22 @@ export function EmailContentInput({ onChange, placeholder = 'Paste your HTML ema