feat: Card-based email system implementation
## ✅ Core Card System Complete! ### base.html Template - ✅ Single, theme-agnostic template - ✅ Card system CSS (default, highlight, info, warning, success, bg) - ✅ Customizable header (logo/text) - ✅ Customizable footer + social icons - ✅ Customizable body background - ✅ Mobile responsive - ✅ Email client compatible (Outlook, Gmail, etc.) ### EmailRenderer.php - Card Parser - ✅ `parse_cards()` - Parses [card]...[/card] syntax - ✅ `parse_card_attributes()` - Extracts type and bg attributes - ✅ `render_card()` - Renders card HTML - ✅ `render_card_spacing()` - 24px spacing between cards - ✅ `render_html()` - Email customization support - ✅ `get_social_icon_url()` - Social media icons ### Card Types Supported ``` [card] → Default white card [card type="highlight"] → Purple gradient card [card type="info"] → Blue info card [card type="warning"] → Yellow warning card [card type="success"] → Green success card [card bg="https://..."] → Background image card ``` ### Email Customization - ✅ Header: Logo or text - ✅ Body background color - ✅ Footer text - ✅ Social media links (Facebook, Instagram, Twitter, LinkedIn) - ✅ Stored in `woonoow_notification_settings[email_appearance]` ### Default Templates Updated - ✅ order_placed_email - Multi-card layout - ✅ order_processing_email - Success card + summary - ✅ Other templates ready to update --- **Architecture:** ``` Content with [card] tags ↓ parse_cards() ↓ render_card() × N ↓ base.html template ↓ Beautiful HTML email! 🎨 ``` **Next:** Settings UI + Live Preview 🚀
This commit is contained in:
@@ -57,11 +57,14 @@ class EmailRenderer {
|
||||
$subject = $this->replace_variables($template_settings['subject'], $variables);
|
||||
$content = $this->replace_variables($template_settings['body'], $variables);
|
||||
|
||||
// Get HTML template design
|
||||
$design_template = $this->get_design_template($template_settings['design'] ?? 'modern');
|
||||
// Parse cards in content
|
||||
$content = $this->parse_cards($content);
|
||||
|
||||
// Get HTML template
|
||||
$template_path = $this->get_design_template();
|
||||
|
||||
// Render final HTML
|
||||
$html = $this->render_html($design_template, $content, $subject, $variables);
|
||||
$html = $this->render_html($template_path, $content, $subject, $variables);
|
||||
|
||||
return [
|
||||
'to' => $to,
|
||||
@@ -204,6 +207,111 @@ class EmailRenderer {
|
||||
return apply_filters('woonoow_email_variables', $variables, $event_id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse [card] tags and convert to HTML
|
||||
*
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
private function parse_cards($content) {
|
||||
// Match [card ...] ... [/card] patterns
|
||||
preg_match_all('/\[card([^\]]*)\](.*?)\[\/card\]/s', $content, $matches, PREG_SET_ORDER);
|
||||
|
||||
if (empty($matches)) {
|
||||
// No cards found, wrap entire content in a single card
|
||||
return $this->render_card($content, []);
|
||||
}
|
||||
|
||||
$html = '';
|
||||
foreach ($matches as $match) {
|
||||
$attributes = $this->parse_card_attributes($match[1]);
|
||||
$card_content = $match[2];
|
||||
|
||||
$html .= $this->render_card($card_content, $attributes);
|
||||
$html .= $this->render_card_spacing();
|
||||
}
|
||||
|
||||
// Remove last spacing
|
||||
$html = preg_replace('/<table[^>]*class="card-spacing"[^>]*>.*?<\/table>\s*$/s', '', $html);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse card attributes from [card ...] tag
|
||||
*
|
||||
* @param string $attr_string
|
||||
* @return array
|
||||
*/
|
||||
private function parse_card_attributes($attr_string) {
|
||||
$attributes = [
|
||||
'type' => 'default',
|
||||
'bg' => null,
|
||||
];
|
||||
|
||||
// Parse type="highlight"
|
||||
if (preg_match('/type=["\']([^"\']+)["\']/', $attr_string, $match)) {
|
||||
$attributes['type'] = $match[1];
|
||||
}
|
||||
|
||||
// Parse bg="url"
|
||||
if (preg_match('/bg=["\']([^"\']+)["\']/', $attr_string, $match)) {
|
||||
$attributes['bg'] = $match[1];
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a single card
|
||||
*
|
||||
* @param string $content
|
||||
* @param array $attributes
|
||||
* @return string
|
||||
*/
|
||||
private function render_card($content, $attributes) {
|
||||
$type = $attributes['type'] ?? 'default';
|
||||
$bg = $attributes['bg'] ?? null;
|
||||
|
||||
$class = 'card';
|
||||
$style = 'width: 100%; background-color: #ffffff; border-radius: 8px;';
|
||||
|
||||
// Add type class
|
||||
if ($type !== 'default') {
|
||||
$class .= ' card-' . esc_attr($type);
|
||||
}
|
||||
|
||||
// Add background image
|
||||
if ($bg) {
|
||||
$class .= ' card-bg';
|
||||
$style .= ' background-image: url(' . esc_url($bg) . ');';
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<table role="presentation" class="%s" border="0" cellpadding="0" cellspacing="0" style="%s">
|
||||
<tr>
|
||||
<td class="content" style="padding: 32px 40px;">
|
||||
%s
|
||||
</td>
|
||||
</tr>
|
||||
</table>',
|
||||
$class,
|
||||
$style,
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render card spacing
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function render_card_spacing() {
|
||||
return '<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr><td class="card-spacing" style="height: 24px; font-size: 24px; line-height: 24px;"> </td></tr>
|
||||
</table>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace variables in text
|
||||
*
|
||||
@@ -222,18 +330,18 @@ class EmailRenderer {
|
||||
/**
|
||||
* Get design template path
|
||||
*
|
||||
* @param string $design Template name (modern, classic, minimal)
|
||||
* @return string
|
||||
*/
|
||||
private function get_design_template($design) {
|
||||
$template_path = WOONOOW_PATH . 'templates/emails/' . $design . '.html';
|
||||
private function get_design_template() {
|
||||
// Use single base template (theme-agnostic)
|
||||
$template_path = WOONOOW_PATH . 'templates/emails/base.html';
|
||||
|
||||
// Allow filtering template path
|
||||
$template_path = apply_filters('woonoow_email_template', $template_path, $design);
|
||||
$template_path = apply_filters('woonoow_email_template', $template_path);
|
||||
|
||||
// Fallback to modern if template doesn't exist
|
||||
// Fallback to base if custom template doesn't exist
|
||||
if (!file_exists($template_path)) {
|
||||
$template_path = WOONOOW_PATH . 'templates/emails/modern.html';
|
||||
$template_path = WOONOOW_PATH . 'templates/emails/base.html';
|
||||
}
|
||||
|
||||
return $template_path;
|
||||
@@ -257,11 +365,69 @@ class EmailRenderer {
|
||||
// Load template
|
||||
$html = file_get_contents($template_path);
|
||||
|
||||
// Get email customization settings
|
||||
$settings = get_option('woonoow_notification_settings', []);
|
||||
$email_settings = $settings['email_appearance'] ?? [];
|
||||
|
||||
// Email body background
|
||||
$body_bg = $email_settings['body_bg'] ?? '#f8f8f8';
|
||||
|
||||
// Email header (logo or text)
|
||||
$header_type = $email_settings['header_type'] ?? 'text';
|
||||
if ($header_type === 'logo' && !empty($email_settings['header_logo'])) {
|
||||
$header = sprintf(
|
||||
'<a href="%s"><img src="%s" alt="%s" style="max-width: 140px;"></a>',
|
||||
esc_url($variables['store_url']),
|
||||
esc_url($email_settings['header_logo']),
|
||||
esc_attr($variables['store_name'])
|
||||
);
|
||||
} else {
|
||||
$header_text = $email_settings['header_text'] ?? $variables['store_name'];
|
||||
$header = sprintf(
|
||||
'<a href="%s" style="font-size: 24px; font-weight: 700; color: #333; text-decoration: none;">%s</a>',
|
||||
esc_url($variables['store_url']),
|
||||
esc_html($header_text)
|
||||
);
|
||||
}
|
||||
|
||||
// Email footer
|
||||
$footer_text = $email_settings['footer_text'] ?? sprintf(
|
||||
'© %s %s. All rights reserved.',
|
||||
date('Y'),
|
||||
$variables['store_name']
|
||||
);
|
||||
|
||||
// Social icons
|
||||
$social_html = '';
|
||||
if (!empty($email_settings['social_links'])) {
|
||||
$social_html = '<div class="social-icons" style="margin-top: 16px;">';
|
||||
foreach ($email_settings['social_links'] as $platform => $url) {
|
||||
if (!empty($url)) {
|
||||
$social_html .= sprintf(
|
||||
'<a href="%s" style="display: inline-block; margin: 0 8px;"><img src="%s" alt="%s" style="width: 24px; height: 24px;"></a>',
|
||||
esc_url($url),
|
||||
$this->get_social_icon_url($platform),
|
||||
esc_attr(ucfirst($platform))
|
||||
);
|
||||
}
|
||||
}
|
||||
$social_html .= '</div>';
|
||||
}
|
||||
|
||||
$footer = sprintf(
|
||||
'<p style="font-family: \'Inter\', Arial, sans-serif; font-size: 13px; line-height: 1.5; color: #888888; margin: 0 0 8px 0;">%s</p>%s',
|
||||
nl2br(esc_html($footer_text)),
|
||||
$social_html
|
||||
);
|
||||
|
||||
// Replace placeholders
|
||||
$html = str_replace('{{email_heading}}', $subject, $html);
|
||||
$html = str_replace('{{email_subject}}', esc_html($subject), $html);
|
||||
$html = str_replace('{{email_body_bg}}', esc_attr($body_bg), $html);
|
||||
$html = str_replace('{{email_header}}', $header, $html);
|
||||
$html = str_replace('{{email_content}}', $content, $html);
|
||||
$html = str_replace('{{store_name}}', $variables['store_name'], $html);
|
||||
$html = str_replace('{{store_url}}', $variables['store_url'], $html);
|
||||
$html = str_replace('{{email_footer}}', $footer, $html);
|
||||
$html = str_replace('{{store_name}}', esc_html($variables['store_name']), $html);
|
||||
$html = str_replace('{{store_url}}', esc_url($variables['store_url']), $html);
|
||||
$html = str_replace('{{current_year}}', date('Y'), $html);
|
||||
|
||||
// Replace all other variables
|
||||
@@ -271,4 +437,22 @@ class EmailRenderer {
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get social icon URL
|
||||
*
|
||||
* @param string $platform
|
||||
* @return string
|
||||
*/
|
||||
private function get_social_icon_url($platform) {
|
||||
// You can host these icons or use a CDN
|
||||
$icons = [
|
||||
'facebook' => 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/facebook.svg',
|
||||
'instagram' => 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/instagram.svg',
|
||||
'twitter' => 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/twitter.svg',
|
||||
'linkedin' => 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/linkedin.svg',
|
||||
];
|
||||
|
||||
return $icons[$platform] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,26 @@ class TemplateProvider {
|
||||
'event_id' => 'order_placed',
|
||||
'channel_id' => 'email',
|
||||
'subject' => $wc_new_order['subject'] ?? __('New Order #{order_number}', 'woonoow'),
|
||||
'body' => __("Hi Admin,\n\nYou have received a new order.\n\nOrder Number: {order_number}\nOrder Total: {order_total}\nCustomer: {customer_name}\nEmail: {customer_email}\n\nView order: {order_url}", 'woonoow'),
|
||||
'body' => __('[card]
|
||||
<h1>New Order Received</h1>
|
||||
<p>Hi Admin,</p>
|
||||
<p>You have received a new order from <strong>{customer_name}</strong>.</p>
|
||||
<div class="info-box">
|
||||
<p style="margin: 0;"><strong>Order #{order_number}</strong></p>
|
||||
<p style="margin: 0;">Total: {order_total}</p>
|
||||
</div>
|
||||
[/card]
|
||||
|
||||
[card]
|
||||
<h2>Customer Details</h2>
|
||||
<p><strong>Name:</strong> {customer_name}<br>
|
||||
<strong>Email:</strong> {customer_email}<br>
|
||||
<strong>Phone:</strong> {customer_phone}</p>
|
||||
[/card]
|
||||
|
||||
[card]
|
||||
<p style="text-align: center;"><a href="{order_url}" class="button">View Order Details</a></p>
|
||||
[/card]', 'woonoow'),
|
||||
'variables' => self::get_order_variables(),
|
||||
'wc_email_id' => 'WC_Email_New_Order',
|
||||
],
|
||||
@@ -151,7 +170,26 @@ class TemplateProvider {
|
||||
'event_id' => 'order_processing',
|
||||
'channel_id' => 'email',
|
||||
'subject' => $wc_processing['subject'] ?? __('Your order #{order_number} is being processed', 'woonoow'),
|
||||
'body' => __("Hi {customer_name},\n\nThank you for your order! We're now processing it.\n\nOrder Number: {order_number}\nOrder Total: {order_total}\nPayment Method: {payment_method}\n\nYou can track your order here: {order_url}\n\nBest regards,\n{store_name}", 'woonoow'),
|
||||
'body' => __('[card type="success"]
|
||||
<h1>✅ Order Confirmed!</h1>
|
||||
<p>Hi {customer_name},</p>
|
||||
<p>Thank you for your order! We\'re now processing it and will notify you once it ships.</p>
|
||||
[/card]
|
||||
|
||||
[card]
|
||||
<h2>Order Summary</h2>
|
||||
<div class="info-box">
|
||||
<p style="margin: 0;"><strong>Order #{order_number}</strong></p>
|
||||
<p style="margin: 0;">Total: {order_total}</p>
|
||||
<p style="margin: 0;">Payment: {payment_method}</p>
|
||||
</div>
|
||||
{order_items}
|
||||
[/card]
|
||||
|
||||
[card]
|
||||
<p style="text-align: center;"><a href="{order_url}" class="button">Track Your Order</a></p>
|
||||
<p style="text-align: center; font-size: 14px; color: #888;">Questions? Reply to this email or contact us.</p>
|
||||
[/card]', 'woonoow'),
|
||||
'variables' => self::get_order_variables(),
|
||||
'wc_email_id' => 'WC_Email_Customer_Processing_Order',
|
||||
],
|
||||
|
||||
363
templates/emails/base.html
Normal file
363
templates/emails/base.html
Normal file
@@ -0,0 +1,363 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="format-detection" content="telephone=no, date=no, address=no, email=no">
|
||||
<!--[if mso]>
|
||||
<xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml>
|
||||
<style>
|
||||
td,th,div,p,a,h1,h2,h3,h4,h5,h6 {font-family: "Segoe UI", sans-serif; mso-line-height-rule: exactly;}
|
||||
</style>
|
||||
<![endif]-->
|
||||
<title>{{email_subject}}</title>
|
||||
<!--[if !mso]>-->
|
||||
<link href="https://fonts.googleapis.com/css?family=Inter:400,700&display=swap" rel="stylesheet" type="text/css">
|
||||
<!--<![endif]-->
|
||||
<style>
|
||||
/* Reset styles */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
background-color: {{email_body_bg}};
|
||||
color: #333333;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
height: auto;
|
||||
line-height: 100%;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse !important;
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
}
|
||||
td {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Main styles */
|
||||
.body-bg {
|
||||
background-color: {{email_body_bg}};
|
||||
width: 100%;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.header {
|
||||
padding: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
.logo img {
|
||||
max-width: 140px;
|
||||
}
|
||||
|
||||
/* Card System */
|
||||
.card {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.card-gutter {
|
||||
padding: 0 16px;
|
||||
}
|
||||
.card-spacing {
|
||||
height: 24px;
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
.card-spacing-sm {
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
/* Card Types */
|
||||
.card-highlight {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
.card-highlight .content,
|
||||
.card-highlight .content h1,
|
||||
.card-highlight .content h2,
|
||||
.card-highlight .content h3,
|
||||
.card-highlight .content p,
|
||||
.card-highlight .content a {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.card-info {
|
||||
background-color: #f0f7ff;
|
||||
border: 1px solid #0071e3;
|
||||
}
|
||||
|
||||
.card-warning {
|
||||
background-color: #fff8e1;
|
||||
border: 1px solid #ff9800;
|
||||
}
|
||||
|
||||
.card-success {
|
||||
background-color: #e8f5e9;
|
||||
border: 1px solid #4caf50;
|
||||
}
|
||||
|
||||
.card-bg {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.content {
|
||||
padding: 32px 40px;
|
||||
}
|
||||
.content h1 {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: #333333;
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.content h2 {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #333333;
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.content h3 {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #333333;
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.content p {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: #555555;
|
||||
margin-bottom: 16px;
|
||||
margin-top: 0;
|
||||
}
|
||||
.content a {
|
||||
color: #7f54b3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.button {
|
||||
display: inline-block;
|
||||
background-color: #7f54b3;
|
||||
color: #ffffff !important;
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
padding: 14px 28px;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Order/Product Tables */
|
||||
.order-details {
|
||||
width: 100%;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.order-details th {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
color: #888;
|
||||
padding: 12px 0;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
.order-details td {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
.order-details .product-name {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
.order-details .product-qty {
|
||||
color: #555;
|
||||
}
|
||||
.order-details .product-price {
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
}
|
||||
.order-details .align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Totals */
|
||||
.totals-table {
|
||||
width: 100%;
|
||||
}
|
||||
.totals-table td {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
padding: 8px 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.totals-table .label {
|
||||
color: #555;
|
||||
}
|
||||
.totals-table .value {
|
||||
text-align: right;
|
||||
font-weight: 600;
|
||||
}
|
||||
.totals-table .total-row td {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
padding-top: 16px;
|
||||
border-top: 2px solid #e5e5e5;
|
||||
}
|
||||
|
||||
/* Info Box */
|
||||
.info-box {
|
||||
background-color: #f6f6f6;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/* Address section */
|
||||
.address-details {
|
||||
width: 100%;
|
||||
}
|
||||
.address-details td {
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.address-box {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
color: #555555;
|
||||
}
|
||||
.address-box h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #333333;
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
padding: 32px 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.footer p {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #888888;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
.footer a {
|
||||
color: #7f54b3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Social Icons */
|
||||
.social-icons {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.social-icons a {
|
||||
display: inline-block;
|
||||
margin: 0 8px;
|
||||
}
|
||||
.social-icons img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* Responsive styles */
|
||||
@media screen and (max-width: 600px) {
|
||||
.content {
|
||||
padding: 24px !important;
|
||||
}
|
||||
.content h1 {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
.address-details td {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.address-details td:last-child {
|
||||
padding-top: 24px;
|
||||
}
|
||||
.order-details .product-price {
|
||||
padding-left: 8px;
|
||||
}
|
||||
.card-gutter {
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color: {{email_body_bg}}; color: #333333;">
|
||||
<center class="body-bg">
|
||||
<!--[if mso]>
|
||||
<table role="presentation" width="100%" align="center" style="background-color:{{email_body_bg}};">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td width="600">
|
||||
<![endif]-->
|
||||
|
||||
<table role="presentation" class="container" border="0" cellpadding="0" cellspacing="0" style="width: 100%; max-width: 600px; margin: 0 auto; border-radius: 8px;">
|
||||
<!-- Header with Logo -->
|
||||
<tr>
|
||||
<td class="header" style="padding: 32px; text-align: center;">
|
||||
{{email_header}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Main Content: Cards will be injected here -->
|
||||
<tr>
|
||||
<td class="card-gutter" style="padding: 0 16px;">
|
||||
{{email_content}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="footer" style="padding: 32px 40px; text-align: center;">
|
||||
{{email_footer}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!--[if mso]>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user