+
+
Odoo & n8n Automation Experts
We charge upfront — this lets us skip the sales talk and give serious clients immediate access to our best engineers.
- One-hour get-to-know session included — not satisfied? Full refund, no questions asked
@@ -169,8 +172,20 @@
- Hosting solutions for Odoo & n8n available
- Custom development tailored to your workflows
-
-
+
+
+
+
+
+
+
+
diff --git a/public/style.css b/public/style.css
index 665f013..15bc9ff 100644
--- a/public/style.css
+++ b/public/style.css
@@ -114,12 +114,22 @@ header.hero {
}
.hero-content {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 40px; /* space between text and widget */
max-width: 80%;
margin: 0 auto;
padding-top: 200px;
padding-bottom: 150px;
}
+.hero-left {
+ flex: 1; /* text column grows */
+}
+.hero-right {
+ flex: 0 0 420px; /* fixed width for widget */
+}
header.hero h1 {
font-size: 3rem;
margin-bottom: 20px;
@@ -890,4 +900,4 @@ footer a:hover {
/* Hover effect for card badges */
.blog-teaser > [class*="-tag"]:hover {
opacity: 0.9;
-}
\ No newline at end of file
+}
diff --git a/public/widget-signup/widget.js b/public/widget-signup/widget.js
new file mode 100644
index 0000000..18b1b90
--- /dev/null
+++ b/public/widget-signup/widget.js
@@ -0,0 +1,186 @@
+(function() {
+ // Locate the script tag
+ const currentScript = document.currentScript;
+ const affiliateFromAttr = currentScript.getAttribute("data-affiliate");
+
+ // Allow ?affiliate=... from URL
+ const params = new URLSearchParams(window.location.search);
+ const affiliateFromURL = params.get("affiliate");
+
+ const affiliateCode = affiliateFromURL || affiliateFromAttr || "None";
+
+ // Container element
+ const container = document.getElementById("my-signup-widget");
+ if (!container) return;
+
+ // Attach shadow DOM
+ const shadow = container.attachShadow({ mode: "open" });
+
+ // CSS for the widget (isolated)
+ const styles = `
+ :host {
+ all: initial;
+ font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Inter,Arial,sans-serif;
+ display: block;
+ max-width: 420px;
+ margin: 0 auto;
+ }
+
+ .card {
+ background: linear-gradient(135deg,#ffffff 0%,#f7fafc 60%);
+ border: 1px solid #e6e8eb;
+ border-radius: 16px;
+ box-shadow: 0 6px 20px rgba(16,24,40,.08);
+ padding: 20px;
+ }
+
+ .header {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 12px;
+ }
+ .icon {
+ width: 36px;
+ height: 36px;
+ border-radius: 12px;
+ background: linear-gradient(135deg,#6ee7b7,#3b82f6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: 700;
+ color: #fff;
+ }
+ .title {
+ font-size: 18px;
+ line-height: 1.2;
+ font-weight: 800;
+ color: #0f172a;
+ }
+ .subtitle {
+ font-size: 13px;
+ color: #475569;
+ }
+
+ label,
+ .label {
+ display: block;
+ font-size: 12px;
+ color: #334155;
+ font-weight: 600;
+ margin: 12px 0 6px;
+ }
+
+ .options {
+ display: flex;
+ gap: 12px;
+ flex-wrap: wrap;
+ margin-bottom: 6px;
+ }
+
+ .option {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ border: 1px solid #cbd5e1;
+ border-radius: 10px;
+ padding: 10px 12px;
+ cursor: pointer;
+ background: #fff;
+ }
+
+ input[type="radio"] {
+ accent-color: #3b82f6;
+ margin: 0;
+ }
+
+ select, input[type="email"], affiliate-display {
+ width: 100%;
+ background: #fff;
+ border: 1px solid #cbd5e1;
+ border-radius: 10px;
+ padding: 10px 12px;
+ font-size: 14px;
+ color: #0f172a;
+ outline: none;
+ box-sizing: border-box;
+ }
+
+ .affiliate-display {
+ background: #f8fafc;
+ }
+
+ button {
+ margin-top: 16px;
+ width: 100%;
+ border: none;
+ border-radius: 12px;
+ padding: 12px 14px;
+ font-size: 15px;
+ font-weight: 800;
+ background: linear-gradient(135deg,#22c55e,#3b82f6);
+ color: #fff;
+ cursor: pointer;
+ box-shadow: 0 8px 18px rgba(37,99,235,.25);
+ }
+
+ .footnote {
+ margin-top: 10px;
+ font-size: 11px;
+ color: #64748b;
+ text-align: center;
+ }
+ `;
+
+ // HTML structure
+ const html = `
+