diff --git a/src/Abstracts/ConditionInterface.php b/src/Abstracts/ConditionInterface.php index 46cbf9fc2e3fe3d72fc3073f3a0aef212e7f37f6..94bc2569919fd1e363d3062fc17a5eabe7f96711 100644 --- a/src/Abstracts/ConditionInterface.php +++ b/src/Abstracts/ConditionInterface.php @@ -6,7 +6,6 @@ use WPDesk\View\Renderer\Renderer; interface ConditionInterface { - public function is_valid(): bool; } diff --git a/src/EmailSender.php b/src/EmailSender.php deleted file mode 100644 index e0a83e666e751cd25186fe0d826d00c0e52d7187..0000000000000000000000000000000000000000 --- a/src/EmailSender.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -namespace WPDesk\Library\WPEmail; - -use WPDesk\Library\WPEmail\Abstracts\EmailInterface; -use WPDesk\Library\WPEmail\Parser\HTMLDecorator; -use WPDesk\View\Renderer\Renderer; -use WPDesk\View\Renderer\SimplePhpRenderer; -use WPDesk\View\Resolver\ChainResolver; -use WPDesk\View\Resolver\DirResolver; -use WPDesk\View\Resolver\WPThemeResolver; - -class EmailSender { - - /** - * @var EmailInterface[] - */ - private $emails = []; - - /** - * @var string - */ - private $from = 'wordpress@wordpress.org'; - - /** - * @var string - */ - private $from_name = 'WordPress'; - - /** - * @var Renderer - */ - private $renderer; - - /** - * @param $from - * @param $from_name - */ - public function __construct() { - $this->init_renderer(); - } - - public function init_renderer() { - $resolver = new ChainResolver(); - $resolver->appendResolver( new DirResolver( __DIR__ ) ); - - $this->renderer = new SimplePhpRenderer( $resolver ); - } - - public function set_renderer( Renderer $renderer ) { - $this->renderer = $renderer; - } - - public function add_email( EmailInterface $email ) { - $this->emails[ $email->get_id() ] = $email; - } - - public function get_emails(): array { - return $this->emails; - } - - public function set_from( string $from ) { - $this->from = $from; - } - - - /** - * WordPress callback for setting the from email - * - * @param string $email - * - * @return string - */ - public function from( $email ): string { - if ( ! empty( $this->from ) && is_email( $this->from ) ) { - $email = $this->from; - } - - return $email; - } - - - public function set_from_name( string $from_name ) { - $this->from_name = $from_name; - } - - - /** - * WordPress callback for setting the from name - * - * @param string $name - * - * @return string - */ - public function from_name( $name ) { - if ( ! empty( $this->from_name ) ) { - $name = html_entity_decode( sanitize_text_field( $this->from_name ) ); - } - - return $name; - } - - /** - * Add filters before fire wp_mail. - * - * @return void - */ - private function before_wp_mail() { - add_filter( 'wp_mail_from', array( $this, 'from' ) ); - add_filter( 'wp_mail_from_name', array( $this, 'from_name' ) ); - } - - public function send( array $placeholders = [] ) { - foreach ( $this->get_emails() as $email ) { - $template = $this->get_template( $email, $placeholders ); - if ( $email->get_is_enable() ) { - $this->before_wp_mail(); - wp_mail( - $email->get_recipients(), $email->get_subject(), $this->css_inline( $template ), $email->get_headers(), $email->get_attachments() - ); - $this->after_wp_mail(); - } - } - } - - public function get_template( EmailInterface $email, $placeholders = [] ): string { - $content = $this->replace_placeholders( $email->get_content(), $placeholders ); - $output = $this->renderer->render( 'html/email-header', [ 'heading' => $email->get_heading(), 'logo' => '' ] ); - $output .= $this->renderer->render( 'html/' . $email->get_id(), [ 'content' => $content ] ); - $output .= $this->renderer->render( 'html/email-footer', [] ); - - return $output; - } - - /** - * @param string $content - * @param array $placeholders - * - * @return array|string|string[] - */ - private function replace_placeholders( string $content, array $placeholders = [] ): string { - return str_replace( array_keys( $placeholders ), array_values( $placeholders ), $content ); - } - - /** - * @param string $content - * - * @return mixed|string - */ - private function css_inline( string $content ): string { - $styles = $this->renderer->render( 'html/email-styles', [] ); - - return HTMLDecorator::style_inline( $content, $styles ); - } - - /** - * Remove filters after fire wp_mail. - * - * @return void - */ - private function after_wp_mail() { - remove_filter( 'wp_mail_from', array( $this, 'from' ) ); - remove_filter( 'wp_mail_from_name', array( $this, 'from_name' ) ); - } - -} diff --git a/src/Parser/HTMLDecorator.php b/src/Helpers/HTML.php similarity index 94% rename from src/Parser/HTMLDecorator.php rename to src/Helpers/HTML.php index baac6b18572556c45c84e77b0f903897177596fa..aace0afe080492ebe87a68601ae58f6d332b4c80 100644 --- a/src/Parser/HTMLDecorator.php +++ b/src/Helpers/HTML.php @@ -1,12 +1,12 @@ <?php -namespace WPDesk\Library\WPEmail\Parser; +namespace WPDesk\Library\WPEmail\Helpers; use Pelago\Emogrifier\CssInliner; use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter; use Pelago\Emogrifier\HtmlProcessor\HtmlPruner; -class HTMLDecorator { +class HTML { public static function style_inline( $content, $styles = '' ) { if ( class_exists( 'DOMDocument' ) ) { diff --git a/src/Helpers/Template.php b/src/Helpers/Template.php new file mode 100644 index 0000000000000000000000000000000000000000..0096d9d3824df52ef1c611caf92088d20918fc22 --- /dev/null +++ b/src/Helpers/Template.php @@ -0,0 +1,125 @@ +<?php + +namespace WPDesk\Library\WPEmail\Helpers; + +class Template { + + /** + * Determine whether a hex color is light. + * + * @param mixed $color Color. + * + * @return bool True if a light color. + */ + public static function is_hex_light( $color ) { + $hex = str_replace( '#', '', $color ); + + $c_r = hexdec( substr( $hex, 0, 2 ) ); + $c_g = hexdec( substr( $hex, 2, 2 ) ); + $c_b = hexdec( substr( $hex, 4, 2 ) ); + + $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000; + + return $brightness > 155; + } + + public static function light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) { + return self::is_hex_light( $color ) ? $dark : $light; + } + + + /** + * Convert RGB to HEX. + * + * @param mixed $color Color. + * + * @return array + */ + public static function rgb_from_hex( $color ) { + $color = str_replace( '#', '', $color ); + // Convert shorthand colors to full format, e.g. "FFF" -> "FFFFFF". + $color = preg_replace( '~^(.)(.)(.)$~', '$1$1$2$2$3$3', $color ); + + $rgb = []; + $rgb['R'] = hexdec( $color[0] . $color[1] ); + $rgb['G'] = hexdec( $color[2] . $color[3] ); + $rgb['B'] = hexdec( $color[4] . $color[5] ); + + return $rgb; + } + + + /** + * Make HEX color darker. + * + * @param mixed $color Color. + * @param int $factor Darker factor. + * Defaults to 30. + * + * @return string + */ + public static function hex_darker( $color, $factor = 30 ) { + $base = self::rgb_from_hex( $color ); + $color = '#'; + + foreach ( $base as $k => $v ) { + $amount = $v / 100; + $amount = self::round( $amount * $factor ); + $new_decimal = $v - $amount; + + $new_hex_component = dechex( $new_decimal ); + if ( strlen( $new_hex_component ) < 2 ) { + $new_hex_component = '0' . $new_hex_component; + } + $color .= $new_hex_component; + } + + return $color; + } + + + /** + * Make HEX color lighter. + * + * @param mixed $color Color. + * @param int $factor Lighter factor. + * Defaults to 30. + * + * @return string + */ + public static function hex_lighter( $color, $factor = 30 ) { + $base = self::rgb_from_hex( $color ); + $color = '#'; + + foreach ( $base as $k => $v ) { + $amount = 255 - $v; + $amount = $amount / 100; + $amount = self::round( $amount * $factor ); + $new_decimal = $v + $amount; + + $new_hex_component = dechex( $new_decimal ); + if ( strlen( $new_hex_component ) < 2 ) { + $new_hex_component = '0' . $new_hex_component; + } + $color .= $new_hex_component; + } + + return $color; + } + + /** + * @param $val + * @param int $precision + * @param int $mode + * + * @return float + */ + public static function round( $val, int $precision = 0, int $mode = PHP_ROUND_HALF_UP ): float { + if ( ! is_numeric( $val ) ) { + $val = floatval( $val ); + } + + return round( $val, $precision, $mode ); + } + +} diff --git a/src/Mailer.php b/src/Mailer.php new file mode 100644 index 0000000000000000000000000000000000000000..cc1d146edd6ae714c137e812243e2a9c7250725a --- /dev/null +++ b/src/Mailer.php @@ -0,0 +1,213 @@ +<?php + +namespace WPDesk\Library\WPEmail; + +use WPDesk\Library\WPEmail\Abstracts\EmailInterface; +use WPDesk\Library\WPEmail\Helpers\HTML; +use WPDesk\View\Renderer\Renderer; +use WPDesk\View\Renderer\SimplePhpRenderer; +use WPDesk\View\Resolver\ChainResolver; +use WPDesk\View\Resolver\DirResolver; +use WPDesk\View\Resolver\Resolver; + +class Mailer { + + /** + * @var EmailInterface[] + */ + private $emails = []; + + /** + * @var string + */ + private $from; + + /** + * @var string + */ + private $from_name; + + /** + * @var Renderer + */ + private $renderer; + + /** + * @var array + */ + protected $placeholders = []; + + /** + * @param string $from + * @param string $from_name + * @param Resolver[] $dir_resolvers + */ + public function __construct( + string $from = 'wordpress@wordpress.org', + string $from_name = 'WordPress', + array $dir_resolvers = [] + ) { + $this->from = $from; + $this->from_name = $from_name; + $this->set_renderer( $this->init_renderer( $dir_resolvers ) ); + } + + /** + * @param array $dir_resolvers + * + * @return Renderer + */ + private function init_renderer( array $dir_resolvers ): Renderer { + $resolver = new ChainResolver(); + foreach ( $dir_resolvers as $dir_resolver ) { + if ( $dir_resolver instanceof Resolver ) { + $resolver->appendResolver( $dir_resolver ); + } + } + $resolver->appendResolver( new DirResolver( __DIR__ ) ); + + return new SimplePhpRenderer( $resolver ); + } + + /** + * @param Renderer $renderer + * + * @return void + */ + public function set_renderer( Renderer $renderer ) { + $this->renderer = $renderer; + } + + /** + * @param EmailInterface $email + * + * @return void + */ + public function add_email( EmailInterface $email ) { + $this->emails[ $email->get_id() ] = $email; + } + + /** + * @return EmailInterface[] + */ + public function get_emails(): array { + return $this->emails; + } + + + /** + * Set placeholders. + * + * @param array $placeholders + * + * @return self + */ + public function set_placeholders( array $placeholders = [] ): self { + $this->placeholders = array_merge( $this->placeholders, $placeholders ); + + return $this; + } + + /** + * Get defined placeholders. + * + * @return string[] + */ + public function get_placeholders(): array { + return $this->placeholders; + } + + /** + * WordPress callback for setting the from email + * + * @param string $email + * + * @return string + */ + public function from_filter( string $email ): string { + if ( ! empty( $this->from ) && is_email( $this->from ) ) { + $email = $this->from; + } + + return $email; + } + + + /** + * WordPress callback for setting the from name + * + * @param string $name + * + * @return string + */ + public function from_name_filter( string $name ): string { + if ( ! empty( $this->from_name ) ) { + $name = html_entity_decode( sanitize_text_field( $this->from_name ) ); + } + + return $name; + } + + /** + * Add filters before fire wp_mail. + * + * @return void + */ + protected function before_wp_mail() { + add_filter( 'wp_mail_from', array( $this, 'from_filter' ) ); + add_filter( 'wp_mail_from_name', array( $this, 'from_name_filter' ) ); + } + + public function send() { + $this->before_wp_mail(); + foreach ( $this->get_emails() as $email ) { + $subject = $this->replace_placeholders( $email->get_subject() ); + if ( $email->get_is_enable() ) { + wp_mail( + $email->get_recipients(), $subject, $this->get_body( $email ), $email->get_headers(), $email->get_attachments() + ); + } + } + $this->after_wp_mail(); + } + + protected function get_body( EmailInterface $email ): string { + $content = $this->replace_placeholders( $email->get_content() ); + $output = $this->renderer->render( 'html/email-header', [ 'heading' => $email->get_heading(), 'logo' => '' ] ); + $output .= $this->renderer->render( 'html/' . $email->get_id(), [ 'content' => $content ] ); + $output .= $this->renderer->render( 'html/email-footer', [ 'footer' => '' ] ); + + return $this->css_inline( $output ); + } + + /** + * @param string $string + * + * @return array|string|string[] + */ + protected function replace_placeholders( string $string ): string { + return (string) str_replace( array_keys( $this->placeholders ), array_values( $this->placeholders ), $string ); + } + + /** + * @param string $content + * + * @return mixed|string + */ + protected function css_inline( string $content ): string { + $styles = $this->renderer->render( 'html/email-styles', [] ); + + return HTML::style_inline( $content, $styles ); + } + + /** + * Remove filters after fire wp_mail. + * + * @return void + */ + protected function after_wp_mail() { + remove_filter( 'wp_mail_from', array( $this, 'from_filter' ) ); + remove_filter( 'wp_mail_from_name', array( $this, 'from_name_filter' ) ); + } + +} diff --git a/src/MailerException.php b/src/MailerException.php new file mode 100644 index 0000000000000000000000000000000000000000..9dd31547c57459530437bcfe38f7bc95c2201255 --- /dev/null +++ b/src/MailerException.php @@ -0,0 +1,16 @@ +<?php + +declare( strict_types=1 ); + +namespace WPDesk\Library\WPEmail; + +class MailerException extends \RuntimeException { + + public static function with_wp_error( \WP_Error $error ): self { + $errors = $error->get_error_messages( 'wp_mail_failed' ); + $message = implode( "\n", $errors ); + + return new self( sprintf( 'wp_mail() failure. Message [%s]', $message ) ); + } +} + diff --git a/src/tempates/html/email-footer.php b/src/tempates/html/email-footer.php index f3c00715ba00bb5cdb75d058f8a8ad5444e2a9ef..e5aab55503c0b7d692076e03de17219f28fc689f 100644 --- a/src/tempates/html/email-footer.php +++ b/src/tempates/html/email-footer.php @@ -40,7 +40,7 @@ defined( 'ABSPATH' ) || exit; <table border="0" cellpadding="10" cellspacing="0" width="100%"> <tr> <td colspan="2" valign="middle" id="credit"> - <?php echo wp_kses_post( wpautop( wptexturize( apply_filters( 'wpdesk/wp_mail/template/footer', '' ) ) ) ); ?> + <?php echo $params['footer'] ?? ''; ?> </td> </tr> </table> diff --git a/src/tempates/html/email-header.php b/src/tempates/html/email-header.php index 2a6ffecf57c99140551ad815a12ce91bb491f060..d73b5a0f780ba83a7e1a9f7db3c8c11a840da03f 100644 --- a/src/tempates/html/email-header.php +++ b/src/tempates/html/email-header.php @@ -47,7 +47,7 @@ $params = isset( $params ) ? $params : []; <table border="0" cellpadding="0" cellspacing="0" width="100%" id="template_header"> <tr> <td id="header_wrapper"> - <h1><?php echo $params['heading']; ?></h1> + <h1><?php echo $params['heading'] ?? 'Header'; ?></h1> </td> </tr> </table> diff --git a/src/tempates/html/email-styles.php b/src/tempates/html/email-styles.php index 6b4a2fd10f17f90370e231a9f980d2479d370c5d..6f4339982407a1b9e800774b3c8fd0da3e0beb4e 100644 --- a/src/tempates/html/email-styles.php +++ b/src/tempates/html/email-styles.php @@ -1,228 +1,217 @@ <?php -/** - * Email Styles - * - * This template can be overridden by copying it to yourtheme/woocommerce/emails/email-styles.php. - * - * HOWEVER, on occasion WooCommerce will need to update template files and you - * (the theme developer) will need to copy the new files to your theme to - * maintain compatibility. We try to do this as little as possible, but it does - * happen. When this occurs the version of the template file will be bumped and - * the readme will list any important changes. - * - * @see https://docs.woocommerce.com/document/template-structure/ - * @package WooCommerce\Templates\Emails - * @version 4.0.0 - */ + +use WPDesk\Library\WPEmail\Helpers\Template; + +$params = isset( $params ) ? $params : []; if ( ! defined( 'ABSPATH' ) ) { - exit; + exit; } // Load colors. -$bg = get_option( 'woocommerce_email_background_color' ); -$body = get_option( 'woocommerce_email_body_background_color' ); -$base = get_option( 'woocommerce_email_base_color' ); -$base_text = wc_light_or_dark( $base, '#202020', '#ffffff' ); -$text = get_option( 'woocommerce_email_text_color' ); +$bg = $params['bg'] ?? '#f9f9f9'; +$body = $params['body'] ?? '#ffffff'; +$base = $params['base'] ?? '#d15291'; +$base_text = Template::light_or_dark( $base, '#171717', '#ffffff' ); +$text = $params['text'] ?? '#303030'; // Pick a contrasting color for links. -$link_color = wc_hex_is_light( $base ) ? $base : $base_text; +$link_color = Template::is_hex_light( $base ) ? $base : $base_text; -if ( wc_hex_is_light( $body ) ) { - $link_color = wc_hex_is_light( $base ) ? $base_text : $base; +if ( Template::is_hex_light( $body ) ) { + $link_color = Template::is_hex_light( $base ) ? $base_text : $base; } -$bg_darker_10 = wc_hex_darker( $bg, 10 ); -$body_darker_10 = wc_hex_darker( $body, 10 ); -$base_lighter_20 = wc_hex_lighter( $base, 20 ); -$base_lighter_40 = wc_hex_lighter( $base, 40 ); -$text_lighter_20 = wc_hex_lighter( $text, 20 ); -$text_lighter_40 = wc_hex_lighter( $text, 40 ); +$bg_darker_10 = Template::hex_darker( $bg, 10 ); +$body_darker_10 = Template::hex_darker( $body, 10 ); +$base_lighter_20 = Template::hex_lighter( $base, 20 ); +$base_lighter_40 = Template::hex_lighter( $base, 40 ); +$text_lighter_20 = Template::hex_lighter( $text, 20 ); +$text_lighter_40 = Template::hex_lighter( $text, 40 ); // !important; is a gmail hack to prevent styles being stripped if it doesn't like something. // body{padding: 0;} ensures proper scale/positioning of the email in the iOS native email app. ?> -body { - padding: 0; -} - -#wrapper { - background-color: <?php echo esc_attr( $bg ); ?>; - margin: 0; - padding: 70px 0; - -webkit-text-size-adjust: none !important; - width: 100%; -} - -#template_container { - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1) !important; - background-color: <?php echo esc_attr( $body ); ?>; - border: 1px solid <?php echo esc_attr( $bg_darker_10 ); ?>; - border-radius: 3px !important; -} - -#template_header { - background-color: <?php echo esc_attr( $base ); ?>; - border-radius: 3px 3px 0 0 !important; - color: <?php echo esc_attr( $base_text ); ?>; - border-bottom: 0; - font-weight: bold; - line-height: 100%; - vertical-align: middle; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; -} - -#template_header h1, -#template_header h1 a { - color: <?php echo esc_attr( $base_text ); ?>; - background-color: inherit; -} - -#template_header_image img { - margin-left: 0; - margin-right: 0; -} - -#template_footer td { - padding: 0; - border-radius: 6px; -} - -#template_footer #credit { - border: 0; - color: <?php echo esc_attr( $text_lighter_40 ); ?>; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; - font-size: 12px; - line-height: 150%; - text-align: center; - padding: 24px 0; -} - -#template_footer #credit p { - margin: 0 0 16px; -} - -#body_content { - background-color: <?php echo esc_attr( $body ); ?>; -} - -#body_content table td { - padding: 48px 48px 32px; -} - -#body_content table td td { - padding: 12px; -} - -#body_content table td th { - padding: 12px; -} - -#body_content td ul.wc-item-meta { - font-size: small; - margin: 1em 0 0; - padding: 0; - list-style: none; -} - -#body_content td ul.wc-item-meta li { - margin: 0.5em 0 0; - padding: 0; -} - -#body_content td ul.wc-item-meta li p { - margin: 0; -} - -#body_content p { - margin: 0 0 16px; -} - -#body_content_inner { - color: <?php echo esc_attr( $text_lighter_20 ); ?>; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; - font-size: 14px; - line-height: 150%; - text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; -} - -.td { - color: <?php echo esc_attr( $text_lighter_20 ); ?>; - border: 1px solid <?php echo esc_attr( $body_darker_10 ); ?>; - vertical-align: middle; -} - -.address { - padding: 12px; - color: <?php echo esc_attr( $text_lighter_20 ); ?>; - border: 1px solid <?php echo esc_attr( $body_darker_10 ); ?>; -} - -.text { - color: <?php echo esc_attr( $text ); ?>; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; -} - -.link { - color: <?php echo esc_attr( $link_color ); ?>; -} - -#header_wrapper { - padding: 36px 48px; - display: block; -} - -h1 { - color: <?php echo esc_attr( $base ); ?>; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; - font-size: 30px; - font-weight: 300; - line-height: 150%; - margin: 0; - text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; - text-shadow: 0 1px 0 <?php echo esc_attr( $base_lighter_20 ); ?>; -} - -h2 { - color: <?php echo esc_attr( $base ); ?>; - display: block; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; - font-size: 18px; - font-weight: bold; - line-height: 130%; - margin: 0 0 18px; - text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; -} - -h3 { - color: <?php echo esc_attr( $base ); ?>; - display: block; - font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; - font-size: 16px; - font-weight: bold; - line-height: 130%; - margin: 16px 0 8px; - text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; -} - -a { - color: <?php echo esc_attr( $link_color ); ?>; - font-weight: normal; - text-decoration: underline; -} - -img { - border: none; - display: inline-block; - font-size: 14px; - font-weight: bold; - height: auto; - outline: none; - text-decoration: none; - text-transform: capitalize; - vertical-align: middle; - margin-<?php echo is_rtl() ? 'left' : 'right'; ?>: 10px; - max-width: 100%; -} + body { + padding: 0; + } + + #wrapper { + background-color: <?php echo esc_attr( $bg ); ?>; + margin: 0; + padding: 70px 0; + -webkit-text-size-adjust: none !important; + width: 100%; + } + + #template_container { + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1) !important; + background-color: <?php echo esc_attr( $body ); ?>; + border: 1px solid <?php echo esc_attr( $bg_darker_10 ); ?>; + border-radius: 3px !important; + } + + #template_header { + background-color: <?php echo esc_attr( $base ); ?>; + border-radius: 3px 3px 0 0 !important; + color: <?php echo esc_attr( $base_text ); ?>; + border-bottom: 0; + font-weight: bold; + line-height: 100%; + vertical-align: middle; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + } + + #template_header h1, + #template_header h1 a { + color: <?php echo esc_attr( $base_text ); ?>; + background-color: inherit; + } + + #template_header_image img { + margin-left: 0; + margin-right: 0; + } + + #template_footer td { + padding: 0; + border-radius: 6px; + } + + #template_footer #credit { + border: 0; + color: <?php echo esc_attr( $text_lighter_40 ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 12px; + line-height: 150%; + text-align: center; + padding: 24px 0; + } + + #template_footer #credit p { + margin: 0 0 16px; + } + + #body_content { + background-color: <?php echo esc_attr( $body ); ?>; + } + + #body_content table td { + padding: 48px 48px 32px; + } + + #body_content table td td { + padding: 12px; + } + + #body_content table td th { + padding: 12px; + } + + #body_content td ul.wc-item-meta { + font-size: small; + margin: 1em 0 0; + padding: 0; + list-style: none; + } + + #body_content td ul.wc-item-meta li { + margin: 0.5em 0 0; + padding: 0; + } + + #body_content td ul.wc-item-meta li p { + margin: 0; + } + + #body_content p { + margin: 0 0 16px; + } + + #body_content_inner { + color: <?php echo esc_attr( $text_lighter_20 ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 14px; + line-height: 150%; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + } + + .td { + color: <?php echo esc_attr( $text_lighter_20 ); ?>; + border: 1px solid <?php echo esc_attr( $body_darker_10 ); ?>; + vertical-align: middle; + } + + .address { + padding: 12px; + color: <?php echo esc_attr( $text_lighter_20 ); ?>; + border: 1px solid <?php echo esc_attr( $body_darker_10 ); ?>; + } + + .text { + color: <?php echo esc_attr( $text ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + } + + .link { + color: <?php echo esc_attr( $link_color ); ?>; + } + + #header_wrapper { + padding: 36px 48px; + display: block; + } + + h1 { + color: <?php echo esc_attr( $base ); ?>; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 30px; + font-weight: 300; + line-height: 150%; + margin: 0; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + text-shadow: 0 1px 0 <?php echo esc_attr( $base_lighter_20 ); ?>; + } + + h2 { + color: <?php echo esc_attr( $base ); ?>; + display: block; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 18px; + font-weight: bold; + line-height: 130%; + margin: 0 0 18px; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + } + + h3 { + color: <?php echo esc_attr( $base ); ?>; + display: block; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-size: 16px; + font-weight: bold; + line-height: 130%; + margin: 16px 0 8px; + text-align: <?php echo is_rtl() ? 'right' : 'left'; ?>; + } + + a { + color: <?php echo esc_attr( $link_color ); ?>; + font-weight: normal; + text-decoration: underline; + } + + img { + border: none; + display: inline-block; + font-size: 14px; + font-weight: bold; + height: auto; + outline: none; + text-decoration: none; + text-transform: capitalize; + vertical-align: middle; + margin-<?php echo is_rtl() ? 'left' : 'right'; ?>: 10px; + max-width: 100%; + } <?php