2292 lines
123 KiB
PHP
2292 lines
123 KiB
PHP
<?php
|
|
/**
|
|
* OTS Theme - Custom Gutenberg Blocks (InnerBlocks Architecture)
|
|
*
|
|
* Blocks:
|
|
* Standalone: hero, page-hero, cta-banner, intro-section, contact-section
|
|
* Parent/child pairs:
|
|
* feature-section → feature-card
|
|
* value-section → value-card
|
|
* addon-section → addon-card
|
|
* image-section → image-card
|
|
* stat-section → stat-card
|
|
* link-section → link-card
|
|
* pricing-section → pricing-card
|
|
* platform-section → platform-row
|
|
* trust-section → trust-item
|
|
* faq-section → faq-item
|
|
*
|
|
* Parent blocks use InnerBlocks (save → InnerBlocks.Content, PHP wraps $content).
|
|
* Child blocks are dynamic (save → null, own render_callback).
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) exit;
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════════
|
|
SHARED HELPERS
|
|
══════════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Shared image attributes for all card blocks.
|
|
* Spread into each card's 'attributes' array.
|
|
*/
|
|
function oribi_card_image_attributes() {
|
|
return [
|
|
'imgId' => [ 'type' => 'number', 'default' => 0 ],
|
|
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgWidth' => [ 'type' => 'number', 'default' => 80 ],
|
|
'imgHeight' => [ 'type' => 'number', 'default' => 0 ],
|
|
'imgFit' => [ 'type' => 'string', 'default' => 'contain' ],
|
|
'imgPosition' => [ 'type' => 'string', 'default' => 'top' ],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Build card image HTML from shared image attributes.
|
|
*
|
|
* @param array $a Block attributes (must include imgId, imgUrl, etc.)
|
|
* @return array [ 'html' => string, 'position' => string, 'card_class' => string ]
|
|
*/
|
|
function oribi_card_image_html( $a ) {
|
|
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
|
|
$img_url = ! empty( $a['imgUrl'] ) ? $a['imgUrl'] : '';
|
|
$img_alt = ! empty( $a['imgAlt'] ) ? $a['imgAlt'] : '';
|
|
$img_w = ! empty( $a['imgWidth'] ) ? intval( $a['imgWidth'] ) : 80;
|
|
$img_h = ! empty( $a['imgHeight'] ) ? intval( $a['imgHeight'] ) : 0;
|
|
$img_fit = ! empty( $a['imgFit'] ) ? $a['imgFit'] : 'contain';
|
|
$img_pos = ! empty( $a['imgPosition'] ) ? $a['imgPosition'] : 'top';
|
|
|
|
$result = [
|
|
'html' => '',
|
|
'position' => $img_pos,
|
|
'card_class' => '',
|
|
];
|
|
|
|
if ( ! $img_url ) {
|
|
return $result;
|
|
}
|
|
|
|
$result['card_class'] = 'img-' . $img_pos;
|
|
|
|
// Build inline style for dimensions
|
|
$styles = [];
|
|
if ( $img_pos !== 'background' ) {
|
|
if ( $img_w > 0 ) $styles[] = 'width:' . $img_w . 'px';
|
|
$styles[] = 'max-width:100%';
|
|
if ( $img_h > 0 ) {
|
|
$styles[] = 'height:' . $img_h . 'px';
|
|
} else {
|
|
$styles[] = 'height:auto';
|
|
}
|
|
}
|
|
$style_str = implode( ';', $styles );
|
|
|
|
$fit_class = 'oribi-card-img oribi-card-img--' . ( $img_pos === 'background' ? 'cover' : esc_attr( $img_fit ) );
|
|
|
|
if ( $img_id ) {
|
|
$result['html'] = wp_get_attachment_image( $img_id, 'large', false, [
|
|
'class' => $fit_class,
|
|
'style' => $style_str,
|
|
'alt' => $img_alt,
|
|
] );
|
|
} else {
|
|
$result['html'] = '<img class="' . esc_attr( $fit_class ) . '" src="' . esc_url( $img_url )
|
|
. '" alt="' . esc_attr( $img_alt )
|
|
. '" style="' . esc_attr( $style_str ) . '">';
|
|
}
|
|
|
|
// Wrap in container
|
|
$result['html'] = '<div class="oribi-card-img-wrap">' . $result['html'] . '</div>';
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Shared icon attributes added to every card block that supports an icon.
|
|
*/
|
|
function oribi_card_icon_attributes() {
|
|
return [
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Render an icon from block attributes.
|
|
*
|
|
* Accepts either:
|
|
* - iconType = 'fontawesome' + faIcon = 'fas fa-cloud' → <i class="fas fa-cloud"></i>
|
|
* - iconType = 'emoji' + icon = 'text' -> text (escaped)
|
|
*
|
|
* Legacy: if $icon_or_attrs is a plain string it behaves like before.
|
|
*
|
|
* @param array|string $icon_or_attrs Block attributes array, or legacy icon string.
|
|
* @return string Rendered HTML.
|
|
*/
|
|
function oribi_render_icon( $icon_or_attrs ) {
|
|
// Legacy string call
|
|
if ( is_string( $icon_or_attrs ) ) {
|
|
$icon = $icon_or_attrs;
|
|
if ( empty( $icon ) ) return '';
|
|
if ( preg_match( '/^fa[srldb]\s+fa-/', $icon ) ) {
|
|
return '<i class="' . esc_attr( $icon ) . '"></i>';
|
|
}
|
|
return wp_kses_post( $icon );
|
|
}
|
|
|
|
// Array (block attributes)
|
|
$a = $icon_or_attrs;
|
|
$iconType = ! empty( $a['iconType'] ) ? $a['iconType'] : 'emoji';
|
|
|
|
if ( $iconType === 'fontawesome' ) {
|
|
$fa = ! empty( $a['faIcon'] ) ? trim( $a['faIcon'] ) : '';
|
|
if ( empty( $fa ) ) return '';
|
|
return '<i class="' . esc_attr( $fa ) . '" aria-hidden="true"></i>';
|
|
}
|
|
|
|
// emoji / text
|
|
$icon = ! empty( $a['icon'] ) ? $a['icon'] : '';
|
|
if ( empty( $icon ) ) return '';
|
|
return wp_kses_post( $icon );
|
|
}
|
|
|
|
/**
|
|
* Return true when the given block attributes specify a non-empty icon.
|
|
*/
|
|
function oribi_has_icon( $a ) {
|
|
$iconType = ! empty( $a['iconType'] ) ? $a['iconType'] : 'emoji';
|
|
if ( $iconType === 'fontawesome' ) {
|
|
return ! empty( $a['faIcon'] );
|
|
}
|
|
return ! empty( $a['icon'] );
|
|
}
|
|
|
|
/**
|
|
* Render a standard card section wrapper.
|
|
*
|
|
* @param array $a Block attributes (variant, label, heading, lead, columns).
|
|
* @param string $content InnerBlocks rendered HTML.
|
|
* @param string $grid_class CSS class for the grid container (e.g. 'grid').
|
|
* @param int $default_cols Default column count if not set in attributes.
|
|
* @return string Rendered HTML.
|
|
*/
|
|
function oribi_render_card_section( $a, $content, $grid_class = 'grid', $default_cols = 3 ) {
|
|
$cls = ( ! empty( $a['variant'] ) && $a['variant'] === 'alt' ) ? 'section section-alt' : 'section';
|
|
$cols = ! empty( $a['columns'] ) ? intval( $a['columns'] ) : $default_cols;
|
|
$grid = $grid_class . '-' . $cols;
|
|
ob_start(); ?>
|
|
<section class="<?php echo esc_attr( $cls ); ?>">
|
|
<div class="container">
|
|
<div class="section-header">
|
|
<?php if ( ! empty( $a['label'] ) ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2><?php echo wp_kses_post( $a['heading'] ?? '' ); ?></h2>
|
|
<?php if ( ! empty( $a['lead'] ) ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<div class="<?php echo esc_attr( $grid ); ?>">
|
|
<?php echo $content; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Standard section attributes shared by all card section wrappers.
|
|
*/
|
|
function oribi_card_section_attributes( $default_cols = 3 ) {
|
|
return [
|
|
'variant' => [ 'type' => 'string', 'default' => 'normal' ],
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
'columns' => [ 'type' => 'number', 'default' => $default_cols ],
|
|
];
|
|
}
|
|
|
|
/* ── Block category ────────────────────────────────────────────────────────── */
|
|
add_filter( 'block_categories_all', function ( $cats ) {
|
|
array_unshift( $cats, [ 'slug' => 'oribi', 'title' => 'OTS Theme' ] );
|
|
return $cats;
|
|
} );
|
|
|
|
/* ── Enqueue editor assets ─────────────────────────────────────────────────── */
|
|
add_action( 'enqueue_block_editor_assets', function () {
|
|
$dir = get_template_directory();
|
|
$uri = get_template_directory_uri();
|
|
wp_enqueue_script(
|
|
'oribi-blocks',
|
|
$uri . '/blocks/editor.js',
|
|
[ 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n' ],
|
|
filemtime( $dir . '/blocks/editor.js' ),
|
|
true
|
|
);
|
|
wp_enqueue_style(
|
|
'oribi-blocks-editor',
|
|
$uri . '/blocks/editor.css',
|
|
[ 'wp-edit-blocks' ],
|
|
filemtime( $dir . '/blocks/editor.css' )
|
|
);
|
|
} );
|
|
|
|
/* ── Register all blocks ───────────────────────────────────────────────────── */
|
|
add_action( 'init', function () {
|
|
|
|
/* Shared supports - exposes color pickers and font-size selector in the
|
|
block inspector for every Oribi block. Individual blocks can override
|
|
these by merging their own array if needed. */
|
|
$block_supports = [
|
|
'color' => [
|
|
'text' => true,
|
|
'background' => true,
|
|
'link' => true,
|
|
],
|
|
'typography' => [
|
|
'fontSize' => true,
|
|
'lineHeight' => true,
|
|
],
|
|
'spacing' => [
|
|
'padding' => true,
|
|
'margin' => true,
|
|
],
|
|
];
|
|
|
|
/* ── TEMPLATE-PART HELPER BLOCKS ──────────────────────────────────────── */
|
|
|
|
register_block_type( 'oribi/site-header', [
|
|
'render_callback' => 'oribi_render_site_header',
|
|
] );
|
|
|
|
register_block_type( 'oribi/site-footer', [
|
|
'render_callback' => 'oribi_render_site_footer',
|
|
] );
|
|
|
|
/* ── STANDALONE BLOCKS ─────────────────────────────────────────────────── */
|
|
|
|
register_block_type( 'oribi/hero', [
|
|
'attributes' => [
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'highlightWord' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'primaryBtnText' => [ 'type' => 'string', 'default' => 'Get in Touch' ],
|
|
'primaryBtnUrl' => [ 'type' => 'string', 'default' => '/contact' ],
|
|
'secondaryBtnText' => [ 'type' => 'string', 'default' => '' ],
|
|
'secondaryBtnUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat1Value' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat1Label' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat2Value' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat2Label' => [ 'type' => 'string', 'default' => '' ],
|
|
'svcLaptop1' => [ 'type' => 'string', 'default' => 'Data Backup' ],
|
|
'svcLaptop2' => [ 'type' => 'string', 'default' => 'Endpoint Security' ],
|
|
'svcLaptop3' => [ 'type' => 'string', 'default' => 'Patch Management' ],
|
|
'svcCloud1' => [ 'type' => 'string', 'default' => 'Email Protection' ],
|
|
'svcCloud2' => [ 'type' => 'string', 'default' => 'License Management' ],
|
|
'svcCloud3' => [ 'type' => 'string', 'default' => 'Cloud Backup' ],
|
|
'svcDesktop1' => [ 'type' => 'string', 'default' => 'Network Monitoring' ],
|
|
'svcDesktop2' => [ 'type' => 'string', 'default' => 'Threat Detection' ],
|
|
'svcDesktop3' => [ 'type' => 'string', 'default' => 'Cloud Management' ],
|
|
'svcPhone1' => [ 'type' => 'string', 'default' => 'Mobile Security' ],
|
|
'svcPhone2' => [ 'type' => 'string', 'default' => 'Data Encryption' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_hero',
|
|
] );
|
|
|
|
register_block_type( 'oribi/page-hero', [
|
|
'attributes' => [
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_page_hero',
|
|
] );
|
|
|
|
register_block_type( 'oribi/cta-banner', [
|
|
'attributes' => [
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'text' => [ 'type' => 'string', 'default' => '' ],
|
|
'btnText' => [ 'type' => 'string', 'default' => '' ],
|
|
'btnUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_cta_banner',
|
|
] );
|
|
|
|
register_block_type( 'oribi/intro-section', [
|
|
'attributes' => [
|
|
'variant' => [ 'type' => 'string', 'default' => 'normal' ],
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'visual' => [ 'type' => 'string', 'default' => '' ],
|
|
'reversed' => [ 'type' => 'boolean', 'default' => false ],
|
|
'imgId' => [ 'type' => 'number', 'default' => 0 ],
|
|
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgWidth' => [ 'type' => 'number', 'default' => 280 ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_intro_section',
|
|
] );
|
|
|
|
register_block_type( 'oribi/contact-section', [
|
|
'attributes' => [
|
|
'heading' => [ 'type' => 'string', 'default' => "Let's Talk" ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
'email' => [ 'type' => 'string', 'default' => 'solutions@oribi-tech.com' ],
|
|
'supportUrl' => [ 'type' => 'string', 'default' => 'https://portal.oribi-tech.com/helpdesk/technical-support-1' ],
|
|
'portalUrl' => [ 'type' => 'string', 'default' => 'https://portal.oribi-tech.com/' ],
|
|
'location' => [ 'type' => 'string', 'default' => 'Saratoga Springs, Upstate New York' ],
|
|
'formHeading' => [ 'type' => 'string', 'default' => 'Want to Learn More?' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_contact_section',
|
|
] );
|
|
|
|
/* ── PARENT / CHILD PAIRS ──────────────────────────────────────────────── */
|
|
|
|
/* Feature Section (parent) */
|
|
register_block_type( 'oribi/feature-section', [
|
|
'attributes' => oribi_card_section_attributes( 3 ),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_feature_section',
|
|
] );
|
|
|
|
/* Feature Card (child) */
|
|
register_block_type( 'oribi/feature-card', [
|
|
'attributes' => array_merge(
|
|
[
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'url' => [ 'type' => 'string', 'default' => '' ],
|
|
'centered' => [ 'type' => 'boolean', 'default' => false ],
|
|
],
|
|
oribi_card_image_attributes()
|
|
),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_feature_card',
|
|
] );
|
|
|
|
/* Value Section (parent) */
|
|
register_block_type( 'oribi/value-section', [
|
|
'attributes' => oribi_card_section_attributes( 3 ),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_value_section',
|
|
] );
|
|
|
|
/* Value Card (child) */
|
|
register_block_type( 'oribi/value-card', [
|
|
'attributes' => array_merge(
|
|
[
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
oribi_card_image_attributes()
|
|
),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_value_card',
|
|
] );
|
|
|
|
/* Addon Section (parent) */
|
|
register_block_type( 'oribi/addon-section', [
|
|
'attributes' => oribi_card_section_attributes( 3 ),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_addon_section',
|
|
] );
|
|
|
|
/* Addon Card (child) */
|
|
register_block_type( 'oribi/addon-card', [
|
|
'attributes' => array_merge(
|
|
[
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'tag' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
oribi_card_image_attributes()
|
|
),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_addon_card',
|
|
] );
|
|
|
|
/* Image Section (parent) */
|
|
register_block_type( 'oribi/image-section', [
|
|
'attributes' => oribi_card_section_attributes( 3 ),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_image_section',
|
|
] );
|
|
|
|
/* Image Card (child) */
|
|
register_block_type( 'oribi/image-card', [
|
|
'attributes' => array_merge(
|
|
[
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'url' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
oribi_card_image_attributes()
|
|
),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_image_card',
|
|
] );
|
|
|
|
/* Stat Section (parent) */
|
|
register_block_type( 'oribi/stat-section', [
|
|
'attributes' => oribi_card_section_attributes( 3 ),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_stat_section',
|
|
] );
|
|
|
|
/* Stat Card (child) */
|
|
register_block_type( 'oribi/stat-card', [
|
|
'attributes' => array_merge(
|
|
[
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'value' => [ 'type' => 'string', 'default' => '' ],
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
oribi_card_image_attributes()
|
|
),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_stat_card',
|
|
] );
|
|
|
|
/* Link Section (parent) */
|
|
register_block_type( 'oribi/link-section', [
|
|
'attributes' => oribi_card_section_attributes( 3 ),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_link_section',
|
|
] );
|
|
|
|
/* Link Card (child) */
|
|
register_block_type( 'oribi/link-card', [
|
|
'attributes' => array_merge(
|
|
[
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'linkText' => [ 'type' => 'string', 'default' => '' ],
|
|
'linkUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
oribi_card_image_attributes()
|
|
),
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_link_card',
|
|
] );
|
|
|
|
/* Pricing Section (parent) */
|
|
register_block_type( 'oribi/pricing-section', [
|
|
'attributes' => [
|
|
'variant' => [ 'type' => 'string', 'default' => 'normal' ],
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_pricing_section',
|
|
] );
|
|
|
|
/* Pricing Card (child) */
|
|
register_block_type( 'oribi/pricing-card', [
|
|
'attributes' => [
|
|
'icon' => [ 'type' => 'string', 'default' => '' ],
|
|
'iconType' => [ 'type' => 'string', 'default' => 'emoji' ],
|
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
|
'name' => [ 'type' => 'string', 'default' => '' ],
|
|
'tagline' => [ 'type' => 'string', 'default' => '' ],
|
|
'price' => [ 'type' => 'string', 'default' => '' ],
|
|
'pricePer' => [ 'type' => 'string', 'default' => '' ],
|
|
'features' => [ 'type' => 'array', 'default' => [] ],
|
|
'btnText' => [ 'type' => 'string', 'default' => 'Get Started' ],
|
|
'btnUrl' => [ 'type' => 'string', 'default' => '/contact' ],
|
|
'featured' => [ 'type' => 'boolean', 'default' => false ],
|
|
'badge' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgId' => [ 'type' => 'number', 'default' => 0 ],
|
|
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgWidth' => [ 'type' => 'number', 'default' => 80 ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_pricing_card',
|
|
] );
|
|
|
|
/* Platform Section (parent) */
|
|
register_block_type( 'oribi/platform-section', [
|
|
'attributes' => [
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_platform_section',
|
|
] );
|
|
|
|
/* Platform Row (child) */
|
|
register_block_type( 'oribi/platform-row', [
|
|
'attributes' => [
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'btnText' => [ 'type' => 'string', 'default' => 'Learn More' ],
|
|
'btnUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'visual' => [ 'type' => 'string', 'default' => '' ],
|
|
'reversed' => [ 'type' => 'boolean', 'default' => false ],
|
|
'imgId' => [ 'type' => 'number', 'default' => 0 ],
|
|
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
|
|
'imgWidth' => [ 'type' => 'number', 'default' => 300 ],
|
|
'isDashboard' => [ 'type' => 'boolean', 'default' => false ],
|
|
'deviceAnim' => [ 'type' => 'boolean', 'default' => false ],
|
|
'tvStick' => [ 'type' => 'boolean', 'default' => false ],
|
|
'cameraAnim' => [ 'type' => 'boolean', 'default' => false ],
|
|
'neverGoesDark'=> [ 'type' => 'boolean', 'default' => false ],
|
|
'brandedAnim' => [ 'type' => 'boolean', 'default' => false ],
|
|
'galleryIds' => [ 'type' => 'array', 'default' => [], 'items' => [ 'type' => 'number' ] ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_platform_row',
|
|
] );
|
|
|
|
/* FAQ Section (parent) */
|
|
register_block_type( 'oribi/faq-section', [
|
|
'attributes' => [
|
|
'variant' => [ 'type' => 'string', 'default' => 'normal' ],
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_faq_section',
|
|
] );
|
|
|
|
/* FAQ Item (child) */
|
|
register_block_type( 'oribi/faq-item', [
|
|
'attributes' => [
|
|
'question' => [ 'type' => 'string', 'default' => '' ],
|
|
'answer' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_faq_item',
|
|
] );
|
|
|
|
/* Comparison Table */
|
|
register_block_type( 'oribi/comparison-table', [
|
|
'attributes' => [
|
|
'variant' => [ 'type' => 'string', 'default' => 'normal' ],
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
'columns' => [ 'type' => 'array', 'default' => [] ],
|
|
'rows' => [ 'type' => 'array', 'default' => [] ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_comparison_table',
|
|
] );
|
|
|
|
/* Trust Section (parent) */
|
|
register_block_type( 'oribi/trust-section', [
|
|
'attributes' => [
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'lead' => [ 'type' => 'string', 'default' => '' ],
|
|
'btnText' => [ 'type' => 'string', 'default' => '' ],
|
|
'btnUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'btnSub' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_trust_section',
|
|
] );
|
|
|
|
/* Trust Item (child) */
|
|
register_block_type( 'oribi/trust-item', [
|
|
'attributes' => [
|
|
'heading' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_trust_item',
|
|
] );
|
|
|
|
/* ── ANIMATED HERO BLOCKS (OTS Signs) ─────────────────────────────────── */
|
|
|
|
/* Animated Hero - full homepage hero with particle background */
|
|
register_block_type( 'oribi/hero-animated', [
|
|
'attributes' => [
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'highlightWord' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
'primaryBtnText' => [ 'type' => 'string', 'default' => 'Get Started' ],
|
|
'primaryBtnUrl' => [ 'type' => 'string', 'default' => '/contact' ],
|
|
'secondaryBtnText' => [ 'type' => 'string', 'default' => '' ],
|
|
'secondaryBtnUrl' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat1Value' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat1Label' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat2Value' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat2Label' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat3Value' => [ 'type' => 'string', 'default' => '' ],
|
|
'stat3Label' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_hero_animated',
|
|
] );
|
|
|
|
/* Animated Page Hero - inner pages with particle background */
|
|
register_block_type( 'oribi/page-hero-animated', [
|
|
'attributes' => [
|
|
'label' => [ 'type' => 'string', 'default' => '' ],
|
|
'title' => [ 'type' => 'string', 'default' => '' ],
|
|
'description' => [ 'type' => 'string', 'default' => '' ],
|
|
],
|
|
'supports' => $block_supports,
|
|
'render_callback' => 'oribi_render_page_hero_animated',
|
|
] );
|
|
|
|
} );
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════════
|
|
RENDER CALLBACKS
|
|
══════════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/* ── Site Header ───────────────────────────────────────────────────────────── */
|
|
function oribi_render_site_header() {
|
|
$has_logo = has_custom_logo();
|
|
ob_start(); ?>
|
|
<header class="site-header" id="site-header">
|
|
<div class="container header-inner">
|
|
<div class="site-logo">
|
|
<?php if ( $has_logo ) : ?>
|
|
<?php the_custom_logo(); ?>
|
|
<?php endif; ?>
|
|
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="logo-text"><strong>OTS</strong> Signs</a>
|
|
</div>
|
|
<button class="nav-toggle" id="nav-toggle" aria-expanded="false" aria-label="<?php esc_attr_e( 'Toggle navigation', 'ots-theme' ); ?>">
|
|
<span></span><span></span><span></span>
|
|
</button>
|
|
<nav class="site-nav" id="site-nav">
|
|
<?php
|
|
wp_nav_menu( [
|
|
'theme_location' => 'primary',
|
|
'container' => false,
|
|
'menu_class' => 'nav-menu',
|
|
'depth' => 2,
|
|
'fallback_cb' => 'oribi_fallback_menu',
|
|
] );
|
|
?>
|
|
</nav>
|
|
<div class="header-cta">
|
|
<button id="theme-toggle" class="theme-toggle" aria-label="<?php esc_attr_e( 'Switch to dark mode', 'ots-theme' ); ?>">
|
|
<svg class="theme-toggle-icon sun-icon" viewBox="0 0 20 20" fill="currentColor"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"/></svg>
|
|
<svg class="theme-toggle-icon moon-icon" viewBox="0 0 20 20" fill="currentColor"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/** Fallback menu when no WP menu is assigned. */
|
|
function oribi_fallback_menu() {
|
|
echo '<ul class="nav-menu">';
|
|
echo '<li><a href="' . esc_url( home_url( '/solutions' ) ) . '">Solutions</a></li>';
|
|
echo '<li><a href="' . esc_url( home_url( '/features' ) ) . '">Features</a></li>';
|
|
echo '<li><a href="' . esc_url( home_url( '/pricing' ) ) . '">Pricing</a></li>';
|
|
echo '<li><a href="' . esc_url( home_url( '/partners' ) ) . '">Partners</a></li>';
|
|
echo '<li><a href="' . esc_url( home_url( '/about' ) ) . '">About</a></li>';
|
|
echo '<li><a href="' . esc_url( home_url( '/contact' ) ) . '">Contact</a></li>';
|
|
echo '</ul>';
|
|
}
|
|
|
|
/* ── Site Footer ───────────────────────────────────────────────────────────── */
|
|
function oribi_render_site_footer() {
|
|
$year = gmdate( 'Y' );
|
|
ob_start(); ?>
|
|
<footer class="site-footer">
|
|
<div class="container">
|
|
<div class="footer-inner">
|
|
<div class="footer-brand">
|
|
<div class="footer-logo-section">
|
|
<?php if ( has_custom_logo() ) : ?>
|
|
<?php the_custom_logo(); ?>
|
|
<?php else : ?>
|
|
<div class="logo-text"><strong>Oribi</strong> Tech</div>
|
|
<?php endif; ?>
|
|
<div class="footer-company-name">
|
|
<div class="company-brand"><strong>Oribi</strong> Tech</div>
|
|
</div>
|
|
</div>
|
|
<p class="footer-tagline">Digital signage solutions that communicate, engage, and grow your business.</p>
|
|
<p class="footer-location">An <a href="https://oribi-tech.com">Oribi Technology Services</a> Company</p>
|
|
</div>
|
|
<div class="footer-links">
|
|
<div class="footer-col">
|
|
<h4>Platform</h4>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url( home_url( '/features' ) ); ?>">Features</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/pricing' ) ); ?>">Pricing</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/devices' ) ); ?>">Devices</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/demo' ) ); ?>">Demo</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/security' ) ); ?>">Security</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer-col">
|
|
<h4>Solutions</h4>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url( home_url( '/solutions' ) ); ?>">Industries</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/kiosks' ) ); ?>">Interactive Kiosks</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/outdoor' ) ); ?>">Outdoor Signage</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/partners' ) ); ?>">Partners</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer-col">
|
|
<h4>Company</h4>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url( home_url( '/about' ) ); ?>">About</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/resources' ) ); ?>">Resources</a></li>
|
|
<li><a href="<?php echo esc_url( home_url( '/faq' ) ); ?>">FAQ</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer-col">
|
|
<h4>Connect</h4>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url( home_url( '/contact' ) ); ?>">Contact</a></li>
|
|
<li><a href="https://ots-signs.com/portal" target="_blank" rel="noopener">Client Portal</a></li>
|
|
<li><a href="mailto:hello@ots-signs.com">Email Us</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="footer-bottom">
|
|
<p>© <?php echo esc_html( $year ); ?> Oribi Technology Services. All rights reserved.</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
<button id="scroll-top" class="scroll-top" aria-label="<?php esc_attr_e( 'Scroll to top', 'ots-theme' ); ?>">↑</button>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/** Helper: highlight a word in a string. */
|
|
function oribi_highlight( $text, $word ) {
|
|
if ( ! $word ) return wp_kses_post( $text );
|
|
return str_replace(
|
|
esc_html( $word ),
|
|
'<span class="highlight">' . esc_html( $word ) . '</span>',
|
|
wp_kses_post( $text )
|
|
);
|
|
}
|
|
|
|
/* ── Hero ──────────────────────────────────────────────────────────────────── */
|
|
function oribi_render_hero( $a ) {
|
|
ob_start();
|
|
?>
|
|
<section class="hero">
|
|
<div class="container hero-inner">
|
|
<div class="hero-content">
|
|
<span class="hero-label"><?php echo wp_kses_post( $a['label'] ); ?></span>
|
|
<h1 class="hero-title"><?php echo oribi_highlight( $a['title'], $a['highlightWord'] ); ?></h1>
|
|
<p class="hero-description"><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
<div class="btn-group">
|
|
<a href="<?php echo esc_url( $a['primaryBtnUrl'] ); ?>" class="btn btn-primary btn-lg"><?php echo esc_html( $a['primaryBtnText'] ); ?></a>
|
|
<?php if ( $a['secondaryBtnUrl'] ) : ?>
|
|
<a href="<?php echo esc_url( $a['secondaryBtnUrl'] ); ?>" target="_blank" rel="noopener" class="btn btn-ghost btn-lg"><?php echo esc_html( $a['secondaryBtnText'] ); ?> →</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="hero-stats">
|
|
<div><div class="hero-stat-value"><?php echo esc_html( $a['stat1Value'] ); ?></div><div class="hero-stat-label"><?php echo esc_html( $a['stat1Label'] ); ?></div></div>
|
|
<div><div class="hero-stat-value"><?php echo esc_html( $a['stat2Value'] ); ?></div><div class="hero-stat-label"><?php echo esc_html( $a['stat2Label'] ); ?></div></div>
|
|
</div>
|
|
</div>
|
|
<div class="hero-visual">
|
|
<div class="hero-devices">
|
|
|
|
<!-- Device 1: Laptop -->
|
|
<div class="hero-device hero-device--laptop">
|
|
<div class="hero-device__frame">
|
|
<div class="hero-device__screen">
|
|
<div class="hero-device__screen-content">
|
|
<div class="hero-device__app-bars">
|
|
<div></div><div></div><div></div><div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="hero-device__base"></div>
|
|
</div>
|
|
<ul class="hero-device__services">
|
|
<li class="svc svc--1"><span class="svc__dot"></span> <?php echo esc_html( $a['svcLaptop1'] ); ?></li>
|
|
<li class="svc svc--2"><span class="svc__dot"></span> <?php echo esc_html( $a['svcLaptop2'] ); ?></li>
|
|
<li class="svc svc--3"><span class="svc__dot"></span> <?php echo esc_html( $a['svcLaptop3'] ); ?></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Device 2: Cloud (365Care) -->
|
|
<div class="hero-device hero-device--cloud">
|
|
<div class="hero-device__frame">
|
|
<div class="hero-device__cloud-icon">
|
|
<svg viewBox="0 0 56 40" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
<path d="M44.8 16.8C44.8 8.4 38 1.6 29.6 1.6c-6.8 0-12.6 4.4-14.6 10.6C8.4 13 3.2 18.6 3.2 25.4c0 7.4 6 13.4 13.4 13.4h27c5.8 0 10.4-4.6 10.4-10.4 0-5.4-4.2-9.8-9.2-10.2z" stroke="var(--color-accent)" stroke-width="2" fill="none"/>
|
|
</svg>
|
|
<span class="hero-device__cloud-label">365</span>
|
|
</div>
|
|
</div>
|
|
<ul class="hero-device__services">
|
|
<li class="svc svc--1"><span class="svc__dot"></span> <?php echo esc_html( $a['svcCloud1'] ); ?></li>
|
|
<li class="svc svc--2"><span class="svc__dot"></span> <?php echo esc_html( $a['svcCloud2'] ); ?></li>
|
|
<li class="svc svc--3"><span class="svc__dot"></span> <?php echo esc_html( $a['svcCloud3'] ); ?></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Device 3: Desktop Monitor -->
|
|
<div class="hero-device hero-device--desktop">
|
|
<div class="hero-device__frame">
|
|
<div class="hero-device__screen">
|
|
<div class="hero-device__screen-content">
|
|
<div class="hero-device__dash-row">
|
|
<div class="hero-device__dash-card"></div>
|
|
<div class="hero-device__dash-card"></div>
|
|
</div>
|
|
<div class="hero-device__dash-bar"></div>
|
|
<div class="hero-device__dash-bar hero-device__dash-bar--short"></div>
|
|
</div>
|
|
</div>
|
|
<div class="hero-device__stand"></div>
|
|
<div class="hero-device__stand-base"></div>
|
|
</div>
|
|
<ul class="hero-device__services">
|
|
<li class="svc svc--1"><span class="svc__dot"></span> <?php echo esc_html( $a['svcDesktop1'] ); ?></li>
|
|
<li class="svc svc--2"><span class="svc__dot"></span> <?php echo esc_html( $a['svcDesktop2'] ); ?></li>
|
|
<li class="svc svc--3"><span class="svc__dot"></span> <?php echo esc_html( $a['svcDesktop3'] ); ?></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Device 4: Phone -->
|
|
<div class="hero-device hero-device--phone">
|
|
<div class="hero-device__frame">
|
|
<div class="hero-device__screen">
|
|
<div class="hero-device__screen-content">
|
|
<div class="hero-device__notif">
|
|
<span class="hero-device__notif-icon">✓</span>
|
|
<span class="hero-device__notif-text">Secure</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ul class="hero-device__services">
|
|
<li class="svc svc--1"><span class="svc__dot"></span> <?php echo esc_html( $a['svcPhone1'] ); ?></li>
|
|
<li class="svc svc--2"><span class="svc__dot"></span> <?php echo esc_html( $a['svcPhone2'] ); ?></li>
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Page Hero ─────────────────────────────────────────────────────────────── */
|
|
function oribi_render_page_hero( $a ) {
|
|
ob_start(); ?>
|
|
<section class="page-hero">
|
|
<canvas id="dc-canvas" class="dc-canvas" aria-hidden="true"></canvas>
|
|
<div class="hero-overlay"></div>
|
|
<div class="container">
|
|
<?php if ( $a['label'] ) : ?><span class="hero-label"><?php echo wp_kses_post( $a['label'] ); ?></span><?php endif; ?>
|
|
<h1><?php echo wp_kses_post( $a['title'] ); ?></h1>
|
|
<p class="lead"><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── CTA Banner ────────────────────────────────────────────────────────────── */
|
|
function oribi_render_cta_banner( $a ) {
|
|
ob_start(); ?>
|
|
<section class="cta-banner">
|
|
<div class="container text-center">
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<p><?php echo wp_kses_post( $a['text'] ); ?></p>
|
|
<a href="<?php echo esc_url( $a['btnUrl'] ); ?>" class="btn btn-primary btn-lg" style="background:#fff;color:var(--color-primary);"><?php echo esc_html( $a['btnText'] ); ?></a>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Intro Section ─────────────────────────────────────────────────────────── */
|
|
function oribi_render_intro_section( $a ) {
|
|
$cls = $a['variant'] === 'alt' ? 'section section-alt' : 'section';
|
|
$rev = $a['reversed'] ? ' style="direction:rtl;"' : '';
|
|
$ltr = $a['reversed'] ? ' style="direction:ltr;"' : '';
|
|
ob_start(); ?>
|
|
<section class="<?php echo esc_attr( $cls ); ?>">
|
|
<div class="container">
|
|
<div class="about-intro"<?php echo $rev; ?>>
|
|
<div<?php echo $ltr; ?>>
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2 style="margin-bottom:1.5rem;"><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<p class="lead"><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
<div class="about-intro-visual"<?php echo $ltr; ?>><?php echo wp_kses_post( $a['visual'] ); ?></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Contact Section ───────────────────────────────────────────────────────── */
|
|
function oribi_render_contact_section( $a ) {
|
|
ob_start(); ?>
|
|
<section class="section">
|
|
<div class="container">
|
|
<div class="contact-layout">
|
|
<div class="contact-info">
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p>
|
|
<div class="contact-method"><div class="contact-method-icon"><i class="fas fa-envelope" aria-hidden="true"></i></div><div><div class="contact-method-label">Email Us</div><div class="contact-method-value"><a href="mailto:<?php echo esc_attr( $a['email'] ); ?>"><?php echo esc_html( $a['email'] ); ?></a></div></div></div>
|
|
<div class="contact-method"><div class="contact-method-icon"><i class="fas fa-headset" aria-hidden="true"></i></div><div><div class="contact-method-label">Existing Customer Support</div><div class="contact-method-value"><a href="<?php echo esc_url( $a['supportUrl'] ); ?>" target="_blank" rel="noopener">Open a Support Ticket</a></div></div></div>
|
|
<div class="contact-method"><div class="contact-method-icon"><i class="fas fa-globe" aria-hidden="true"></i></div><div><div class="contact-method-label">Client Portal</div><div class="contact-method-value"><a href="<?php echo esc_url( $a['portalUrl'] ); ?>" target="_blank" rel="noopener"><?php echo esc_html( wp_parse_url( $a['portalUrl'], PHP_URL_HOST ) ); ?></a></div></div></div>
|
|
<div class="contact-method"><div class="contact-method-icon"><i class="fas fa-map-marker-alt" aria-hidden="true"></i></div><div><div class="contact-method-label">Location</div><div class="contact-method-value"><?php echo esc_html( $a['location'] ); ?></div></div></div>
|
|
</div>
|
|
<div class="contact-form-wrap">
|
|
<h3 style="margin-bottom:1.5rem;"><?php echo esc_html( $a['formHeading'] ); ?></h3>
|
|
<form id="contact-form">
|
|
<div class="form-row">
|
|
<div class="form-group"><label for="cf-name">Name <span class="req">*</span></label><input type="text" id="cf-name" name="name" required></div>
|
|
<div class="form-group"><label for="cf-email">Email <span class="req">*</span></label><input type="email" id="cf-email" name="email" required></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="cf-interest">Interested In</label>
|
|
<select id="cf-interest" name="interest">
|
|
<option value="">Select a topic…</option>
|
|
<option value="Digital Signage">Digital Signage Solutions</option>
|
|
<option value="Content Creation">Content Creation</option>
|
|
<option value="Hardware">Player Devices & Hardware</option>
|
|
<option value="Pricing">Pricing & Plans</option>
|
|
<option value="Demo">Request a Demo</option>
|
|
<option value="Support">Technical Support</option>
|
|
<option value="Other">Other / Not sure</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group"><label for="cf-message">Message <span class="req">*</span></label><textarea id="cf-message" name="message" required></textarea></div>
|
|
<button type="submit" class="btn btn-primary btn-lg" style="width:100%;justify-content:center;">Submit</button>
|
|
<div class="form-notice" id="form-notice"></div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Feature Section (parent - wraps child feature-card blocks) ────────────── */
|
|
function oribi_render_feature_section( $a, $content ) {
|
|
return oribi_render_card_section( $a, $content, 'grid', 3 );
|
|
}
|
|
|
|
/* ── Feature Card (child - renders one card) ───────────────────────────────── */
|
|
function oribi_render_feature_card( $a ) {
|
|
$tag = ! empty( $a['url'] ) ? 'a' : 'div';
|
|
$href = ! empty( $a['url'] ) ? ' href="' . esc_url( $a['url'] ) . '"' : '';
|
|
$link_cls = ! empty( $a['url'] ) ? ' feature-card-link' : '';
|
|
$center = ! empty( $a['centered'] );
|
|
$img = oribi_card_image_html( $a );
|
|
$img_cls = $img['card_class'] ? ' ' . $img['card_class'] : '';
|
|
|
|
ob_start();
|
|
if ( $img['html'] && $img['position'] === 'left' ) : ?>
|
|
<<?php echo $tag . $href; ?> class="oribi-card<?php echo esc_attr( $link_cls . $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</<?php echo $tag; ?>>
|
|
<?php elseif ( $img['html'] && $img['position'] === 'background' ) : ?>
|
|
<<?php echo $tag . $href; ?> class="oribi-card<?php echo esc_attr( $link_cls . $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"<?php echo $center ? ' style="margin-inline:auto;"' : ''; ?>><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</<?php echo $tag; ?>>
|
|
<?php else : ?>
|
|
<<?php echo $tag . $href; ?> class="oribi-card<?php echo esc_attr( $link_cls . $img_cls ); ?><?php echo $center ? ' text-center' : ''; ?>">
|
|
<?php if ( $img['html'] && ( $img['position'] === 'top' || $img['position'] === 'replace-icon' ) ) : ?>
|
|
<?php echo $img['html']; ?>
|
|
<?php endif; ?>
|
|
<?php if ( ( ! $img['html'] || $img['position'] !== 'replace-icon' ) && oribi_has_icon( $a ) ) : ?>
|
|
<div class="feature-icon"<?php echo $center ? ' style="margin-inline:auto;"' : ''; ?>><?php echo oribi_render_icon( $a ); ?></div>
|
|
<?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</<?php echo $tag; ?>>
|
|
<?php endif;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/* ── Value Section ─────────────────────────────────────────────────────────── */
|
|
function oribi_render_value_section( $a, $content ) {
|
|
return oribi_render_card_section( $a, $content, 'grid', 3 );
|
|
}
|
|
|
|
/* ── Value Card ────────────────────────────────────────────────────────────── */
|
|
function oribi_render_value_card( $a ) {
|
|
$img = oribi_card_image_html( $a );
|
|
$img_cls = $img['card_class'] ? ' ' . $img['card_class'] : '';
|
|
|
|
ob_start();
|
|
if ( $img['html'] && $img['position'] === 'background' ) : ?>
|
|
<div class="oribi-card value-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="value-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php elseif ( $img['html'] && $img['position'] === 'left' ) : ?>
|
|
<div class="oribi-card value-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php else : ?>
|
|
<div class="oribi-card value-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php if ( $img['html'] && ( $img['position'] === 'top' || $img['position'] === 'replace-icon' ) ) echo $img['html']; ?>
|
|
<?php if ( ( ! $img['html'] || $img['position'] !== 'replace-icon' ) && oribi_has_icon( $a ) ) : ?>
|
|
<div class="value-icon"><?php echo oribi_render_icon( $a ); ?></div>
|
|
<?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
<?php endif;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/* ── Addon Section ─────────────────────────────────────────────────────────── */
|
|
function oribi_render_addon_section( $a, $content ) {
|
|
return oribi_render_card_section( $a, $content, 'grid', 3 );
|
|
}
|
|
|
|
/* ── Addon Card ────────────────────────────────────────────────────────────── */
|
|
function oribi_render_addon_card( $a ) {
|
|
$img = oribi_card_image_html( $a );
|
|
$img_cls = $img['card_class'] ? ' ' . $img['card_class'] : '';
|
|
|
|
ob_start();
|
|
if ( $img['html'] && $img['position'] === 'left' ) : ?>
|
|
<div class="oribi-card addon-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( ! empty( $a['tag'] ) ) : ?><span class="addon-tag"><?php echo esc_html( $a['tag'] ); ?></span><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php elseif ( $img['html'] && $img['position'] === 'background' ) : ?>
|
|
<div class="oribi-card addon-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<?php if ( ! empty( $a['tag'] ) ) : ?><span class="addon-tag"><?php echo esc_html( $a['tag'] ); ?></span><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php else : ?>
|
|
<div class="oribi-card addon-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php if ( $img['html'] && ( $img['position'] === 'top' || $img['position'] === 'replace-icon' ) ) echo $img['html']; ?>
|
|
<?php if ( ( ! $img['html'] || $img['position'] !== 'replace-icon' ) && oribi_has_icon( $a ) ) : ?>
|
|
<div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div>
|
|
<?php endif; ?>
|
|
<?php if ( ! empty( $a['tag'] ) ) : ?><span class="addon-tag"><?php echo esc_html( $a['tag'] ); ?></span><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
<?php endif;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/* ── Image Section ─────────────────────────────────────────────────────────── */
|
|
function oribi_render_image_section( $a, $content ) {
|
|
return oribi_render_card_section( $a, $content, 'grid', 3 );
|
|
}
|
|
|
|
/* ── Image Card ────────────────────────────────────────────────────────────── */
|
|
function oribi_render_image_card( $a ) {
|
|
$tag = ! empty( $a['url'] ) ? 'a' : 'div';
|
|
$href = ! empty( $a['url'] ) ? ' href="' . esc_url( $a['url'] ) . '"' : '';
|
|
$link_cls = ! empty( $a['url'] ) ? ' feature-card-link' : '';
|
|
$img = oribi_card_image_html( $a );
|
|
$img_cls = $img['card_class'] ? ' ' . $img['card_class'] : '';
|
|
|
|
ob_start();
|
|
if ( $img['html'] && $img['position'] === 'left' ) : ?>
|
|
<<?php echo $tag . $href; ?> class="oribi-card image-card<?php echo esc_attr( $link_cls . $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</<?php echo $tag; ?>>
|
|
<?php elseif ( $img['html'] && $img['position'] === 'background' ) : ?>
|
|
<<?php echo $tag . $href; ?> class="oribi-card image-card<?php echo esc_attr( $link_cls . $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</<?php echo $tag; ?>>
|
|
<?php else : ?>
|
|
<<?php echo $tag . $href; ?> class="oribi-card image-card<?php echo esc_attr( $link_cls . $img_cls ); ?>">
|
|
<?php if ( $img['html'] && ( $img['position'] === 'top' || $img['position'] === 'replace-icon' ) ) echo $img['html']; ?>
|
|
<?php if ( ( ! $img['html'] || $img['position'] !== 'replace-icon' ) && oribi_has_icon( $a ) ) : ?>
|
|
<div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div>
|
|
<?php endif; ?>
|
|
<div class="oribi-card-body">
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</<?php echo $tag; ?>>
|
|
<?php endif;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/* ── Stat Section ──────────────────────────────────────────────────────────── */
|
|
function oribi_render_stat_section( $a, $content ) {
|
|
return oribi_render_card_section( $a, $content, 'grid', 3 );
|
|
}
|
|
|
|
/* ── Stat Card ─────────────────────────────────────────────────────────────── */
|
|
function oribi_render_stat_card( $a ) {
|
|
$img = oribi_card_image_html( $a );
|
|
$img_cls = $img['card_class'] ? ' ' . $img['card_class'] : '';
|
|
|
|
ob_start();
|
|
if ( $img['html'] && $img['position'] === 'background' ) : ?>
|
|
<div class="oribi-card stat-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<div class="stat-value"><?php echo esc_html( $a['value'] ?? '' ); ?></div>
|
|
<div class="stat-label"><?php echo esc_html( $a['label'] ?? '' ); ?></div>
|
|
<?php if ( ! empty( $a['description'] ) ) : ?><p><?php echo wp_kses_post( $a['description'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php elseif ( $img['html'] && $img['position'] === 'left' ) : ?>
|
|
<div class="oribi-card stat-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<div class="stat-value"><?php echo esc_html( $a['value'] ?? '' ); ?></div>
|
|
<div class="stat-label"><?php echo esc_html( $a['label'] ?? '' ); ?></div>
|
|
<?php if ( ! empty( $a['description'] ) ) : ?><p><?php echo wp_kses_post( $a['description'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php else : ?>
|
|
<div class="oribi-card stat-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php if ( $img['html'] ) echo $img['html']; ?>
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<div class="stat-value"><?php echo esc_html( $a['value'] ?? '' ); ?></div>
|
|
<div class="stat-label"><?php echo esc_html( $a['label'] ?? '' ); ?></div>
|
|
<?php if ( ! empty( $a['description'] ) ) : ?><p><?php echo wp_kses_post( $a['description'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<?php endif;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/* ── Link Section ──────────────────────────────────────────────────────────── */
|
|
function oribi_render_link_section( $a, $content ) {
|
|
return oribi_render_card_section( $a, $content, 'grid', 3 );
|
|
}
|
|
|
|
/* ── Link Card ─────────────────────────────────────────────────────────────── */
|
|
function oribi_render_link_card( $a ) {
|
|
$img = oribi_card_image_html( $a );
|
|
$img_cls = $img['card_class'] ? ' ' . $img['card_class'] : '';
|
|
|
|
$cta = '';
|
|
if ( ! empty( $a['linkUrl'] ) ) {
|
|
$cta = '<a href="' . esc_url( $a['linkUrl'] ) . '" class="link-card-cta">'
|
|
. esc_html( $a['linkText'] ?? 'Learn More' ) . '</a>';
|
|
}
|
|
|
|
ob_start();
|
|
if ( $img['html'] && $img['position'] === 'left' ) : ?>
|
|
<div class="oribi-card link-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
<?php echo $cta; ?>
|
|
</div>
|
|
</div>
|
|
<?php elseif ( $img['html'] && $img['position'] === 'background' ) : ?>
|
|
<div class="oribi-card link-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php echo $img['html']; ?>
|
|
<div class="oribi-card-body">
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
<?php echo $cta; ?>
|
|
</div>
|
|
</div>
|
|
<?php else : ?>
|
|
<div class="oribi-card link-card<?php echo esc_attr( $img_cls ); ?>">
|
|
<?php if ( $img['html'] && ( $img['position'] === 'top' || $img['position'] === 'replace-icon' ) ) echo $img['html']; ?>
|
|
<?php if ( ( ! $img['html'] || $img['position'] !== 'replace-icon' ) && oribi_has_icon( $a ) ) : ?>
|
|
<div class="feature-icon"><?php echo oribi_render_icon( $a ); ?></div>
|
|
<?php endif; ?>
|
|
<h3><?php echo wp_kses_post( $a['title'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
<?php echo $cta; ?>
|
|
</div>
|
|
<?php endif;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/* ── Pricing Section (parent - wraps child pricing-card blocks) ────────────── */
|
|
function oribi_render_pricing_section( $a, $content, $block ) {
|
|
$cls = $a['variant'] === 'alt' ? 'section section-alt' : 'section';
|
|
$count = count( $block->inner_blocks );
|
|
ob_start(); ?>
|
|
<section class="<?php echo esc_attr( $cls ); ?>">
|
|
<div class="container">
|
|
<div class="section-header">
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<div class="pricing-grid pricing-grid-<?php echo intval( $count ); ?>">
|
|
<?php echo $content; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Pricing Card (child - renders one pricing tier) ───────────────────────── */
|
|
function oribi_render_pricing_card( $a ) {
|
|
$featured = ! empty( $a['featured'] );
|
|
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
|
|
$img_url = ! empty( $a['imgUrl'] ) ? $a['imgUrl'] : '';
|
|
$img_alt = ! empty( $a['imgAlt'] ) ? $a['imgAlt'] : '';
|
|
$img_w = ! empty( $a['imgWidth'] ) ? intval( $a['imgWidth'] ) : 80;
|
|
|
|
$img_html = '';
|
|
if ( $img_url ) {
|
|
$img_style = 'width:' . $img_w . 'px;max-width:100%;height:auto;border-radius:var(--radius-sm);object-fit:contain;display:block;margin-inline:auto;';
|
|
if ( $img_id ) {
|
|
$img_html = wp_get_attachment_image( $img_id, 'full', false, [
|
|
'class' => 'card-image',
|
|
'style' => $img_style,
|
|
'alt' => $img_alt,
|
|
] );
|
|
} else {
|
|
$img_html = '<img class="card-image" src="' . esc_url( $img_url ) . '" alt="' . esc_attr( $img_alt ) . '" style="' . esc_attr( $img_style ) . '">';
|
|
}
|
|
}
|
|
|
|
ob_start(); ?>
|
|
<div class="pricing-card<?php echo $featured ? ' featured' : ''; ?>">
|
|
<?php if ( $featured && ! empty( $a['badge'] ) ) : ?>
|
|
<span class="pricing-badge"><?php echo esc_html( $a['badge'] ); ?></span>
|
|
<?php endif; ?>
|
|
<?php if ( $img_html ) : ?>
|
|
<div class="card-image-wrap" style="text-align:center;margin-bottom:1.25rem;"><?php echo $img_html; ?></div>
|
|
<?php endif; ?>
|
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon" style="margin-inline:auto;"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
|
<div class="pricing-name"><?php echo esc_html( $a['name'] ); ?></div>
|
|
<p class="pricing-tagline"><?php echo wp_kses_post( $a['tagline'] ); ?></p>
|
|
<?php if ( ! empty( $a['price'] ) ) : ?>
|
|
<div class="pricing-price">
|
|
<div class="pricing-amount"><?php echo wp_kses_post( $a['price'] ); ?></div>
|
|
<?php if ( ! empty( $a['pricePer'] ) ) : ?><div class="pricing-per"><?php echo wp_kses_post( $a['pricePer'] ); ?></div><?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<ul class="pricing-features">
|
|
<?php foreach ( ( $a['features'] ?? [] ) as $f ) : ?>
|
|
<li><span class="pricing-check">✓</span> <?php echo wp_kses_post( $f ); ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<a href="<?php echo esc_url( $a['btnUrl'] ?? '' ); ?>" class="btn <?php echo $featured ? 'btn-primary' : 'btn-outline'; ?>" style="width:100%;justify-content:center;"><?php echo esc_html( $a['btnText'] ?? 'Get Started' ); ?></a>
|
|
</div>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Platform Section (parent - wraps child platform-row blocks) ───────────── */
|
|
function oribi_render_platform_section( $a, $content ) {
|
|
ob_start(); ?>
|
|
<section class="section">
|
|
<div class="container">
|
|
<div class="section-header">
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<?php echo $content; ?>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Platform Row (child - renders one service row) ────────────────────────── */
|
|
function oribi_render_camera_animation() {
|
|
return <<<'HTML'
|
|
<div class="ve-stage" aria-hidden="true"><svg viewBox="0 0 540 360" xmlns="http://www.w3.org/2000/svg" class="ve-svg" role="img" aria-label="Animated video editor timeline">
|
|
<defs>
|
|
<clipPath id="ve-preview-clip">
|
|
<rect x="54" y="36" width="256" height="184"/>
|
|
</clipPath>
|
|
<linearGradient id="ve-sg-warm" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stop-color="#3d0800"/>
|
|
<stop offset="50%" stop-color="#a02500"/>
|
|
<stop offset="100%" stop-color="#1d0400"/>
|
|
</linearGradient>
|
|
<linearGradient id="ve-sg-cold" x1="100%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#0a1f3d"/>
|
|
<stop offset="50%" stop-color="#0e3d6e"/>
|
|
<stop offset="100%" stop-color="#06111e"/>
|
|
</linearGradient>
|
|
<linearGradient id="ve-sg-go" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stop-color="#07180d"/>
|
|
<stop offset="50%" stop-color="#1c6038"/>
|
|
<stop offset="100%" stop-color="#040e07"/>
|
|
</linearGradient>
|
|
<linearGradient id="ve-scr-warm" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stop-color="#ff9500"/>
|
|
<stop offset="100%" stop-color="#ff4500"/>
|
|
</linearGradient>
|
|
<linearGradient id="ve-scr-cold" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stop-color="#1a8aff"/>
|
|
<stop offset="100%" stop-color="#0055cc"/>
|
|
</linearGradient>
|
|
<linearGradient id="ve-scr-go" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" stop-color="#00cc66"/>
|
|
<stop offset="100%" stop-color="#008844"/>
|
|
</linearGradient>
|
|
<pattern id="ve-scanlines" x="0" y="0" width="1" height="3" patternUnits="userSpaceOnUse">
|
|
<rect width="1" height="1" fill="rgba(0,0,0,0.18)"/>
|
|
</pattern>
|
|
</defs>
|
|
|
|
<!-- Laptop lid outer shell -->
|
|
<rect x="20" y="5" width="500" height="300" rx="12" fill="#d2d2d0" stroke="#b0aca8" stroke-width="1.5"/>
|
|
<rect x="28" y="12" width="484" height="280" rx="8" fill="#1c1c1c"/>
|
|
<rect x="32" y="16" width="476" height="272" rx="5" fill="#0e1117"/>
|
|
<!-- Laptop base -->
|
|
<rect x="10" y="305" width="520" height="26" rx="5" fill="#c8c8c8" stroke="#b0ada8" stroke-width="0.8"/>
|
|
<rect x="80" y="301" width="380" height="5" rx="2" fill="#a8a6a2"/>
|
|
<rect x="205" y="311" width="130" height="13" rx="5" fill="#b8b5b0" stroke="#a0a09a" stroke-width="0.7"/>
|
|
<rect x="38" y="306" width="155" height="18" rx="2" fill="#bcbab6" opacity="0.45"/>
|
|
<rect x="347" y="306" width="155" height="18" rx="2" fill="#bcbab6" opacity="0.45"/>
|
|
|
|
<!-- Editor title bar -->
|
|
<rect x="32" y="16" width="476" height="20" rx="4" fill="#1e2229"/>
|
|
<circle cx="50" cy="26" r="5" fill="#FF5F56"/>
|
|
<circle cx="66" cy="26" r="5" fill="#FFBD2E"/>
|
|
<circle cx="82" cy="26" r="5" fill="#27C93F"/>
|
|
<rect x="180" y="21" width="180" height="10" rx="3" fill="#3a3f48"/>
|
|
<rect x="100" y="22" width="28" height="8" rx="2" fill="#2e333c"/>
|
|
<rect x="132" y="22" width="24" height="8" rx="2" fill="#2e333c"/>
|
|
<rect x="160" y="22" width="16" height="8" rx="2" fill="#2e333c"/>
|
|
|
|
<!-- Left toolbar -->
|
|
<rect x="32" y="36" width="22" height="184" fill="#181c22"/>
|
|
<line x1="54" y1="36" x2="54" y2="220" stroke="#2a2e38" stroke-width="1"/>
|
|
<rect x="36" y="46" width="14" height="14" rx="2" fill="#3a4152"/>
|
|
<rect x="36" y="66" width="14" height="14" rx="2" fill="#3a4152"/>
|
|
<rect x="36" y="86" width="14" height="14" rx="2" fill="#3a4152"/>
|
|
<rect x="36" y="106" width="14" height="14" rx="2" fill="#3a4152"/>
|
|
<rect x="36" y="126" width="14" height="14" rx="2" fill="#3a4152"/>
|
|
<rect x="33" y="46" width="3" height="14" rx="1" fill="#D83302"/>
|
|
|
|
<!-- Preview pane -->
|
|
<rect x="54" y="36" width="256" height="184" fill="#0a0b0e"/>
|
|
<g clip-path="url(#ve-preview-clip)">
|
|
<rect id="ve-scene-1" x="54" y="36" width="256" height="184" fill="url(#ve-sg-warm)" opacity="1"/>
|
|
<rect id="ve-scene-2" x="54" y="36" width="256" height="184" fill="url(#ve-sg-cold)" opacity="0"/>
|
|
<rect id="ve-scene-3" x="54" y="36" width="256" height="184" fill="url(#ve-sg-go)" opacity="0"/>
|
|
<!-- Laptop in the preview video -->
|
|
<rect x="102" y="52" width="156" height="106" rx="5" fill="#1c1c1c" stroke="#2e2e2e" stroke-width="1"/>
|
|
<rect x="106" y="56" width="148" height="98" rx="3" fill="#111111"/>
|
|
<rect id="ve-inner-screen" x="108" y="58" width="144" height="94" rx="1" fill="url(#ve-scr-warm)"/>
|
|
<polygon points="108,58 160,58 108,88" fill="white" opacity="0.04"/>
|
|
<rect x="108" y="58" width="144" height="94" fill="url(#ve-scanlines)" opacity="0.45"/>
|
|
<circle cx="180" cy="55" r="2.5" fill="#232323" stroke="#2e2e2e" stroke-width="0.5"/>
|
|
<rect x="92" y="158" width="176" height="17" rx="2" fill="#222222" stroke="#2d2d2d" stroke-width="0.5"/>
|
|
<rect x="150" y="162" width="60" height="9" rx="3" fill="#2a2a2a" stroke="#353535" stroke-width="0.5"/>
|
|
<rect x="97" y="159" width="166" height="1" fill="#2c2c2c"/>
|
|
<line x1="54" y1="175" x2="310" y2="175" stroke="#1c1c1c" stroke-width="2"/>
|
|
<rect x="54" y="175" width="256" height="45" fill="#040507" opacity="0.75"/>
|
|
<rect x="54" y="36" width="256" height="184" fill="url(#ve-scanlines)" opacity="0.25"/>
|
|
</g>
|
|
<rect x="54" y="36" width="256" height="184" fill="none" stroke="#2a2e38" stroke-width="0.5"/>
|
|
<line x1="310" y1="36" x2="310" y2="220" stroke="#2a2e38" stroke-width="1"/>
|
|
|
|
<!-- Inspector / Properties panel -->
|
|
<rect x="310" y="36" width="198" height="184" fill="#141619"/>
|
|
<rect x="310" y="36" width="198" height="20" fill="#1a1e25"/>
|
|
<rect x="318" y="42" width="80" height="8" rx="2" fill="#3a3f48"/>
|
|
<rect x="318" y="64" width="50" height="7" rx="2" fill="#2a2e38"/>
|
|
<rect x="378" y="64" width="82" height="7" rx="2" fill="#333a45"/>
|
|
<rect x="318" y="78" width="45" height="7" rx="2" fill="#2a2e38"/>
|
|
<rect x="378" y="78" width="96" height="7" rx="2" fill="#333a45"/>
|
|
<rect x="318" y="92" width="35" height="7" rx="2" fill="#2a2e38"/>
|
|
<rect x="378" y="92" width="62" height="7" rx="2" fill="#333a45"/>
|
|
<rect x="318" y="106" width="55" height="7" rx="2" fill="#2a2e38"/>
|
|
<rect x="378" y="106" width="72" height="7" rx="2" fill="#333a45"/>
|
|
<rect x="318" y="120" width="40" height="7" rx="2" fill="#2a2e38"/>
|
|
<rect x="378" y="120" width="54" height="7" rx="2" fill="#333a45"/>
|
|
<line x1="318" y1="136" x2="498" y2="136" stroke="#2a2e38" stroke-width="0.5"/>
|
|
<rect x="310" y="136" width="198" height="12" fill="#1a1e25"/>
|
|
<rect x="318" y="140" width="60" height="6" rx="2" fill="#2a2e38"/>
|
|
<rect x="318" y="150" width="32" height="24" rx="1" fill="#C0390A" opacity="0.8"/>
|
|
<rect x="354" y="150" width="32" height="24" rx="1" fill="#1a52c8" opacity="0.8"/>
|
|
<rect x="390" y="150" width="32" height="24" rx="1" fill="#1a7a3d" opacity="0.8"/>
|
|
<rect x="426" y="150" width="32" height="24" rx="1" fill="#c07800" opacity="0.8"/>
|
|
<rect x="462" y="150" width="32" height="24" rx="1" fill="#7030d0" opacity="0.8"/>
|
|
|
|
<!-- Timeline section -->
|
|
<rect x="32" y="220" width="476" height="68" fill="#161616"/>
|
|
<line x1="32" y1="220" x2="508" y2="220" stroke="#2a2e38" stroke-width="1"/>
|
|
<rect x="32" y="220" width="476" height="14" fill="#1a1e24"/>
|
|
<rect x="32" y="220" width="72" height="68" fill="#1a1e24"/>
|
|
<line x1="104" y1="220" x2="104" y2="288" stroke="#2a2e38" stroke-width="1"/>
|
|
<!-- Ruler ticks and labels -->
|
|
<line x1="104" y1="220" x2="104" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
|
<text x="105" y="231" fill="#565a64" font-size="8" font-family="monospace">0:00</text>
|
|
<line x1="184" y1="220" x2="184" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
|
<text x="185" y="231" fill="#565a64" font-size="8" font-family="monospace">0:02</text>
|
|
<line x1="264" y1="220" x2="264" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
|
<text x="265" y="231" fill="#565a64" font-size="8" font-family="monospace">0:04</text>
|
|
<line x1="344" y1="220" x2="344" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
|
<text x="345" y="231" fill="#565a64" font-size="8" font-family="monospace">0:06</text>
|
|
<line x1="424" y1="220" x2="424" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
|
<text x="425" y="231" fill="#565a64" font-size="8" font-family="monospace">0:08</text>
|
|
<line x1="144" y1="220" x2="144" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
|
<line x1="224" y1="220" x2="224" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
|
<line x1="304" y1="220" x2="304" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
|
<line x1="384" y1="220" x2="384" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
|
<line x1="464" y1="220" x2="464" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
|
<!-- Track label colour strips -->
|
|
<rect x="36" y="237" width="56" height="14" rx="2" fill="#283040"/>
|
|
<rect x="36" y="255" width="56" height="14" rx="2" fill="#203020"/>
|
|
<rect x="36" y="273" width="56" height="14" rx="2" fill="#302818"/>
|
|
|
|
<!-- Track 1: VIDEO clips -->
|
|
<rect x="104" y="234" width="404" height="18" fill="#1a1a22"/>
|
|
<rect x="104" y="235" width="88" height="16" rx="2" fill="#2563EB"/>
|
|
<rect x="104" y="235" width="88" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
<rect x="196" y="235" width="66" height="16" rx="2" fill="#1D4ED8"/>
|
|
<rect x="196" y="235" width="66" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
<rect x="266" y="235" width="106" height="16" rx="2" fill="#2563EB"/>
|
|
<rect x="266" y="235" width="106" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
<rect x="376" y="235" width="88" height="16" rx="2" fill="#1E40AF"/>
|
|
<rect x="376" y="235" width="88" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
|
|
<!-- Track 2: AUDIO/MUSIC clips -->
|
|
<rect x="104" y="252" width="404" height="18" fill="#141c12"/>
|
|
<rect x="104" y="253" width="178" height="16" rx="2" fill="#15803D"/>
|
|
<rect x="104" y="253" width="178" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
|
|
<!-- Inline waveform bars -->
|
|
<rect x="108" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="112" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="116" y="260" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="120" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="124" y="260" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="128" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="132" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="136" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="140" y="260" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="144" y="258" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="148" y="261" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="152" y="258" width="2" height="6" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="156" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="160" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="164" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="168" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="172" y="261" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="176" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
|
<rect x="286" y="253" width="148" height="16" rx="2" fill="#166534"/>
|
|
<rect x="286" y="253" width="148" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
|
|
<rect x="438" y="253" width="66" height="16" rx="2" fill="#15803D"/>
|
|
<rect x="438" y="253" width="66" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
|
|
|
|
<!-- Track 3: GFX / TEXT clips -->
|
|
<rect x="104" y="270" width="404" height="18" fill="#181710"/>
|
|
<rect x="120" y="271" width="60" height="16" rx="2" fill="#D97706"/>
|
|
<rect x="120" y="271" width="60" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
<rect x="226" y="271" width="52" height="16" rx="2" fill="#B45309"/>
|
|
<rect x="226" y="271" width="52" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
<rect x="334" y="271" width="78" height="16" rx="2" fill="#D97706"/>
|
|
<rect x="334" y="271" width="78" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
<rect x="452" y="271" width="50" height="16" rx="2" fill="#B45309"/>
|
|
<rect x="452" y="271" width="50" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
|
|
|
<!-- Animated playhead -->
|
|
<polygon id="ve-playhead-head" points="0,-8 -6,-2 6,-2" transform="translate(104,234)" fill="#FF4500"/>
|
|
<rect id="ve-playhead-line" x="103" y="220" width="2" height="68" fill="#FF4500" opacity="0.92"/>
|
|
<!-- Timecode display -->
|
|
<text id="ve-timecode" x="36" y="230" fill="#8a8e98" font-size="8" font-family="monospace">0:00</text>
|
|
</svg></div>
|
|
HTML;
|
|
}
|
|
|
|
function oribi_render_platform_row( $a ) {
|
|
$rev = ! empty( $a['reversed'] ) ? ' reverse' : '';
|
|
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
|
|
$img_url = ! empty( $a['imgUrl'] ) ? $a['imgUrl'] : '';
|
|
$img_alt = ! empty( $a['imgAlt'] ) ? $a['imgAlt'] : '';
|
|
$img_w = ! empty( $a['imgWidth'] ) ? intval( $a['imgWidth'] ) : 300;
|
|
|
|
// Only render animated dashboard when explicitly flagged
|
|
$is_dashboard = ! empty( $a['isDashboard'] );
|
|
|
|
if ( $is_dashboard ) {
|
|
// Render animated dashboard chart SVG
|
|
// Text uses class hooks: .ct = title, .cl = label, .cv = value
|
|
// JS will dynamically set fill colours based on data-theme
|
|
$visual_html = '<div class="dashboard-tv" data-dashboard-container="true">
|
|
<div class="dashboard-tv__body">
|
|
<div class="dashboard-tv__screen">
|
|
<svg viewBox="0 0 800 450" xmlns="http://www.w3.org/2000/svg" class="dashboard-chart" role="img" aria-label="Animated dashboard charts">
|
|
<defs>
|
|
<linearGradient id="barGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#D83302" stop-opacity="1"/>
|
|
<stop offset="100%" stop-color="#4CAF50" stop-opacity=".8"/>
|
|
</linearGradient>
|
|
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
<stop offset="0%" stop-color="#4CAF50" stop-opacity=".3"/>
|
|
<stop offset="100%" stop-color="#4CAF50" stop-opacity="0"/>
|
|
</linearGradient>
|
|
</defs>
|
|
|
|
<!-- ── Top-left: Performance bars ── -->
|
|
<g transform="translate(35,20)">
|
|
<text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#333">Performance</text>
|
|
<g id="bars-group-1" transform="translate(0,25)">
|
|
<rect class="bar" x="0" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="40" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="80" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="120" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="160" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
</g>
|
|
<g transform="translate(0,152)">
|
|
<text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#666">API</text>
|
|
<text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#666">Cache</text>
|
|
<text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#666">DB</text>
|
|
<text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#666">Queue</text>
|
|
<text class="cl" x="174" y="0" font-size="10" text-anchor="middle" fill="#666">Worker</text>
|
|
</g>
|
|
<g id="values-group-1" transform="translate(0,168)">
|
|
<text class="cv" x="14" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
|
<text class="cv" x="54" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
|
<text class="cv" x="94" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
|
<text class="cv" x="134" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
|
<text class="cv" x="174" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
|
</g>
|
|
</g>
|
|
|
|
<!-- ── Top-right: Requests/sec bars ── -->
|
|
<g transform="translate(430,20)">
|
|
<text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#333">Requests/sec</text>
|
|
<g id="bars-group-2" transform="translate(0,25)">
|
|
<rect class="bar" x="0" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="40" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="80" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
<rect class="bar" x="120" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
|
</g>
|
|
<g transform="translate(0,152)">
|
|
<text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#666">Read</text>
|
|
<text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#666">Write</text>
|
|
<text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#666">Update</text>
|
|
<text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#666">Delete</text>
|
|
</g>
|
|
<g id="values-group-2" transform="translate(0,168)">
|
|
<text class="cv" x="14" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
|
<text class="cv" x="54" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
|
<text class="cv" x="94" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
|
<text class="cv" x="134" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
|
</g>
|
|
</g>
|
|
|
|
<!-- ── Bottom-left: Traffic Trend line ── -->
|
|
<g id="line-graph" transform="translate(35,245)">
|
|
<text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#333">Traffic Trend</text>
|
|
<g transform="translate(0,25)">
|
|
<line class="grid-line" x1="0" y1="0" x2="340" y2="0" stroke="#E0E0E0" stroke-width=".5"/>
|
|
<line class="grid-line" x1="0" y1="40" x2="340" y2="40" stroke="#E0E0E0" stroke-width=".5"/>
|
|
<line class="grid-line" x1="0" y1="80" x2="340" y2="80" stroke="#E0E0E0" stroke-width=".5"/>
|
|
<line class="grid-line" x1="0" y1="120" x2="340" y2="120" stroke="#E0E0E0" stroke-width=".5"/>
|
|
</g>
|
|
<g transform="translate(0,25)">
|
|
<path id="line-fill" d="M0,80 L340,80 L340,145 L0,145 Z" fill="url(#lineGradient)"/>
|
|
<path id="line-path" d="M0,80 L340,80" stroke="#4CAF50" stroke-width="2.5" fill="none" stroke-linecap="round"/>
|
|
</g>
|
|
</g>
|
|
|
|
<!-- ── Bottom-right: Distribution pie ── -->
|
|
<g transform="translate(490,245)">
|
|
<text class="ct" x="100" y="0" font-size="14" font-weight="600" text-anchor="middle" fill="#333">Distribution</text>
|
|
<g transform="translate(100,90)">
|
|
<g class="pie-segment" transform="rotate(0)">
|
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#D83302" opacity=".9"/>
|
|
</g>
|
|
<g class="pie-segment" transform="rotate(90)">
|
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#4CAF50" opacity=".8"/>
|
|
</g>
|
|
<g class="pie-segment" transform="rotate(180)">
|
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#f59e0b" opacity=".7"/>
|
|
</g>
|
|
<g class="pie-segment" transform="rotate(270)">
|
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#ef4444" opacity=".7"/>
|
|
</g>
|
|
<circle id="pie-center" cx="0" cy="0" r="22" fill="#fff" stroke="#E0E0E0" stroke-width="1"/>
|
|
<text id="pie-center-text" x="0" y="5" text-anchor="middle" font-size="13" font-weight="600" fill="#333">100%</text>
|
|
</g>
|
|
<g transform="translate(30,170)">
|
|
<rect x="0" y="0" width="8" height="8" fill="#D83302"/>
|
|
<text class="cl" x="12" y="8" font-size="11" fill="#666">Service A</text>
|
|
<rect x="0" y="15" width="8" height="8" fill="#4CAF50"/>
|
|
<text class="cl" x="12" y="23" font-size="11" fill="#666">Service B</text>
|
|
<rect x="100" y="0" width="8" height="8" fill="#f59e0b"/>
|
|
<text class="cl" x="112" y="8" font-size="11" fill="#666">Service C</text>
|
|
<rect x="100" y="15" width="8" height="8" fill="#ef4444"/>
|
|
<text class="cl" x="112" y="23" font-size="11" fill="#666">Service D</text>
|
|
</g>
|
|
</g>
|
|
</svg>
|
|
</div></div>
|
|
<div class="dashboard-tv__feet"><div class="dashboard-tv__foot"></div><div class="dashboard-tv__foot"></div></div>
|
|
</div>';
|
|
$visual_cls = 'platform-visual has-dashboard';
|
|
} elseif ( $img_url ) {
|
|
$img_style = 'width:' . $img_w . 'px;max-width:100%;height:auto;border-radius:var(--radius-sm);object-fit:contain;display:block;margin-inline:auto;';
|
|
if ( $img_id ) {
|
|
$visual_html = wp_get_attachment_image( $img_id, 'full', false, [ 'style' => $img_style, 'alt' => $img_alt ] );
|
|
} else {
|
|
$visual_html = '<img src="' . esc_url( $img_url ) . '" alt="' . esc_attr( $img_alt ) . '" style="' . esc_attr( $img_style ) . '">';
|
|
}
|
|
$visual_cls = 'platform-visual has-img';
|
|
} elseif ( ! empty( $a['deviceAnim'] ) ) {
|
|
$da_screen = '<div class="da-screen"><div class="da-promo"><div class="da-promo__top"><span class="da-promo__dot"></span><span class="da-promo__brand"></span></div><div class="da-promo__hero"></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--lg"></span><span class="da-promo__line da-promo__line--sm"></span></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--md"></span><span class="da-promo__line da-promo__line--xs"></span></div><div class="da-promo__ticker"><span class="da-promo__chip"></span><span class="da-promo__chip"></span><span class="da-promo__chip"></span></div></div></div>';
|
|
$da = '<div class="da-stage" aria-hidden="true">';
|
|
$da .= '<div class="da-device da-tablet"><div class="da-body">' . $da_screen . '</div><span class="da-label">Tablet</span></div>';
|
|
$da .= '<div class="da-device da-monitor-sm"><div class="da-body">' . $da_screen . '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Small Monitor</span></div>';
|
|
$da .= '<div class="da-device da-monitor-lg"><div class="da-body">' . $da_screen . '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Large Monitor</span></div>';
|
|
$da .= '<div class="da-device da-tv"><div class="da-body">' . $da_screen . '</div><div class="da-feet"><div class="da-foot"></div><div class="da-foot"></div></div><span class="da-label">TV</span></div>';
|
|
$da .= '<div class="da-device da-projector"><div class="da-proj-layout"><div class="da-proj-body"><div class="da-lens"></div></div><div class="da-beam"></div><div class="da-proj-screen">' . $da_screen . '</div></div><span class="da-label">Projector</span></div>';
|
|
$da .= '<div class="da-device da-vwall"><div class="da-vwall-grid"><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div></div><span class="da-label">Video Wall</span></div>';
|
|
$da .= '</div>';
|
|
$visual_html = $da;
|
|
$visual_cls = 'platform-visual has-anim';
|
|
} elseif ( ! empty( $a['tvStick'] ) ) {
|
|
$ts = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">';
|
|
$ts .= '<div class="ts-tv">';
|
|
$ts .= '<div class="ts-tv__body">';
|
|
$ts .= '<div class="ts-tv__screen">';
|
|
$ts .= '<div class="ts-slides">';
|
|
|
|
// Slide 1 — Menu Board
|
|
$ts .= '<div class="ts-slide ts-slide--menu">';
|
|
$ts .= '<div class="ts-menu">';
|
|
$ts .= '<div class="ts-menu__header"><div class="ts-menu__logo"></div><div class="ts-menu__title"></div></div>';
|
|
$ts .= '<div class="ts-menu__cols">';
|
|
$ts .= '<div class="ts-menu__col">';
|
|
$ts .= '<div class="ts-menu__cat"></div>';
|
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '<div class="ts-menu__col">';
|
|
$ts .= '<div class="ts-menu__cat"></div>';
|
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
|
|
// Slide 2 — Wayfinding Sign
|
|
$ts .= '<div class="ts-slide ts-slide--wayfind">';
|
|
$ts .= '<div class="ts-wf">';
|
|
$ts .= '<div class="ts-wf__header"><div class="ts-wf__building"></div></div>';
|
|
$ts .= '<div class="ts-wf__rows">';
|
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w1"></span><span class="ts-wf__floor"></span></div>';
|
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--right"></span><span class="ts-wf__label ts-wf__label--w2"></span><span class="ts-wf__floor"></span></div>';
|
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--up"></span><span class="ts-wf__label ts-wf__label--w3"></span><span class="ts-wf__floor"></span></div>';
|
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w4"></span><span class="ts-wf__floor"></span></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
|
|
// Slide 3 — Schedule / Timetable
|
|
$ts .= '<div class="ts-slide ts-slide--sched">';
|
|
$ts .= '<div class="ts-sched">';
|
|
$ts .= '<div class="ts-sched__header"><div class="ts-sched__title"></div><div class="ts-sched__date"></div></div>';
|
|
$ts .= '<div class="ts-sched__table">';
|
|
$ts .= '<div class="ts-sched__hrow"><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span></div>';
|
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span></div>';
|
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div>';
|
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--c"></span></div>';
|
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
|
|
$ts .= '</div>'; // ts-slides
|
|
$ts .= '</div>'; // ts-tv__screen
|
|
$ts .= '<div class="ts-tv__port"></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '<div class="ts-tv__feet"><div class="ts-tv__foot"></div><div class="ts-tv__foot"></div></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '<div class="ts-stick">';
|
|
$ts .= '<div class="ts-stick__body">';
|
|
$ts .= '<div class="ts-stick__led"></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '<div class="ts-stick__connector"></div>';
|
|
$ts .= '</div>';
|
|
$ts .= '</div>';
|
|
$visual_html = $ts;
|
|
$visual_cls = 'platform-visual has-tv-stick';
|
|
} elseif ( ! empty( $a['neverGoesDark'] ) ) {
|
|
/* ── Never Goes Dark: player + TV + cloud connection/break animation ── */
|
|
$ngd = '<div class="ngd-stage" aria-hidden="true">';
|
|
|
|
/* TV */
|
|
$ngd .= '<div class="ngd-tv">';
|
|
$ngd .= '<div class="ngd-tv__body">';
|
|
$ngd .= '<div class="ngd-tv__screen">';
|
|
$ngd .= '<div class="ngd-menu">';
|
|
$ngd .= '<div class="ngd-menu__hd">';
|
|
$ngd .= '<div class="ngd-menu__logo"></div>';
|
|
$ngd .= '<div class="ngd-menu__ttl"></div>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '<div class="ngd-menu__cols">';
|
|
$ngd .= '<div class="ngd-menu__col">';
|
|
$ngd .= '<div class="ngd-menu__cat"></div>';
|
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
|
$ngd .= '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '<div class="ngd-menu__col">';
|
|
$ngd .= '<div class="ngd-menu__cat"></div>';
|
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
|
$ngd .= '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '</div>'; /* cols */
|
|
$ngd .= '<div class="ngd-menu__ticker"><div class="ngd-menu__ticker-inner"></div></div>';
|
|
$ngd .= '</div>'; /* ngd-menu */
|
|
$ngd .= '</div>'; /* ngd-tv__screen */
|
|
$ngd .= '<div class="ngd-tv__port"></div>';
|
|
$ngd .= '</div>'; /* ngd-tv__body */
|
|
$ngd .= '<div class="ngd-tv__feet"><div class="ngd-tv__foot"></div><div class="ngd-tv__foot"></div></div>';
|
|
$ngd .= '</div>'; /* ngd-tv */
|
|
|
|
/* Player device (stick style, plugged into TV right-side HDMI port) */
|
|
$ngd .= '<div class="ngd-player">';
|
|
$ngd .= '<div class="ngd-player__connector"></div>';
|
|
$ngd .= '<div class="ngd-player__body">';
|
|
$ngd .= '<div class="ngd-player__led"></div>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '<div class="ngd-player__check">';
|
|
$ngd .= '<svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
|
$ngd .= '<circle cx="11" cy="11" r="10" stroke="#4CAF50" stroke-width="1.5"/>';
|
|
$ngd .= '<polyline points="6,11 9.5,14.5 16,7.5" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
|
|
$ngd .= '</svg>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '</div>'; /* ngd-player */
|
|
|
|
/* Signal wrap: vertical line connecting player to globe above */
|
|
$ngd .= '<div class="ngd-signal-wrap">';
|
|
$ngd .= '<div class="ngd-cloud">';
|
|
$ngd .= '<svg class="ngd-cloud__svg" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
|
$ngd .= '<circle class="ngd-cloud__path" cx="32" cy="23" r="14" stroke-width="2.2" fill="none"/>';
|
|
$ngd .= '<path class="ngd-cloud__path" d="M18.5 23C23 20 41 20 45.5 23" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
|
$ngd .= '<path class="ngd-cloud__path" d="M20.5 29C25.5 31 38.5 31 43.5 29" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
|
$ngd .= '<path class="ngd-cloud__path" d="M24.5 12C21.5 16.5 21.5 29.5 24.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
|
$ngd .= '<path class="ngd-cloud__path" d="M39.5 12C42.5 16.5 42.5 29.5 39.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
|
$ngd .= '</svg>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '<div class="ngd-signal-line">';
|
|
$ngd .= '<div class="ngd-signal__dots">';
|
|
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--1"></div>';
|
|
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--2"></div>';
|
|
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--3"></div>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '<div class="ngd-signal__break">';
|
|
$ngd .= '<svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
|
$ngd .= '<circle cx="9" cy="9" r="8" fill="rgba(239,68,68,0.12)" stroke="#ef4444" stroke-width="1.2"/>';
|
|
$ngd .= '<line x1="5.5" y1="5.5" x2="12.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>';
|
|
$ngd .= '<line x1="12.5" y1="5.5" x2="5.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>';
|
|
$ngd .= '</svg>';
|
|
$ngd .= '</div>';
|
|
$ngd .= '</div>'; /* ngd-signal-line */
|
|
$ngd .= '</div>'; /* ngd-signal-wrap */
|
|
|
|
$ngd .= '</div>'; /* ngd-stage */
|
|
|
|
$visual_html = $ngd;
|
|
$visual_cls = 'platform-visual has-ngd';
|
|
} elseif ( ! empty( $a['brandedAnim'] ) ) {
|
|
/* ── Custom Display Solutions: branded screens cascade animation ── */
|
|
$bd = '<div class="bd-stage" aria-hidden="true">';
|
|
|
|
/* ── Screen 1: Tablet (portrait kiosk) ── */
|
|
$bd .= '<div class="bd-device bd-device--tablet">';
|
|
$bd .= '<span class="bd-device__label">Kiosk</span>';
|
|
$bd .= '<div class="bd-device__body">';
|
|
$bd .= '<div class="bd-device__screen">';
|
|
$bd .= '<div class="bd-splash">';
|
|
$bd .= '<div class="bd-splash__logo"></div>';
|
|
$bd .= '</div>';
|
|
$bd .= '<div class="bd-ui">';
|
|
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
|
$bd .= '<div class="bd-ui__content">';
|
|
$bd .= '<div class="bd-promo bd-promo--welcome">';
|
|
$bd .= '<div class="bd-promo__hero"></div>';
|
|
$bd .= '<div class="bd-promo__heading"></div>';
|
|
$bd .= '<div class="bd-promo__text"></div>';
|
|
$bd .= '<div class="bd-promo__btn"></div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
|
|
/* ── Screen 2: Wide wall-mount (landscape) ── */
|
|
$bd .= '<div class="bd-device bd-device--wall">';
|
|
$bd .= '<span class="bd-device__label">Wall Display</span>';
|
|
$bd .= '<div class="bd-device__body">';
|
|
$bd .= '<div class="bd-device__screen">';
|
|
$bd .= '<div class="bd-splash">';
|
|
$bd .= '<div class="bd-splash__logo"></div>';
|
|
$bd .= '</div>';
|
|
$bd .= '<div class="bd-ui">';
|
|
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
|
$bd .= '<div class="bd-ui__content">';
|
|
$bd .= '<div class="bd-promo bd-promo--sale">';
|
|
$bd .= '<div class="bd-promo__cols">';
|
|
$bd .= '<div class="bd-promo__visual"></div>';
|
|
$bd .= '<div class="bd-promo__info">';
|
|
$bd .= '<div class="bd-promo__badge"></div>';
|
|
$bd .= '<div class="bd-promo__heading"></div>';
|
|
$bd .= '<div class="bd-promo__text"></div>';
|
|
$bd .= '<div class="bd-promo__text bd-promo__text--short"></div>';
|
|
$bd .= '<div class="bd-promo__price"></div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '<div class="bd-mount"></div>';
|
|
$bd .= '</div>';
|
|
|
|
/* ── Screen 3: Interactive tablet on table ── */
|
|
$bd .= '<div class="bd-device bd-device--interactive">';
|
|
$bd .= '<span class="bd-device__label">Interactive</span>';
|
|
$bd .= '<div class="bd-device__body">';
|
|
$bd .= '<div class="bd-device__screen">';
|
|
$bd .= '<div class="bd-splash">';
|
|
$bd .= '<div class="bd-splash__logo"></div>';
|
|
$bd .= '</div>';
|
|
$bd .= '<div class="bd-ui">';
|
|
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
|
$bd .= '<div class="bd-ui__content">';
|
|
$bd .= '<div class="bd-promo bd-promo--menu">';
|
|
$bd .= '<div class="bd-promo__heading"></div>';
|
|
$bd .= '<div class="bd-promo__grid">';
|
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '</div>';
|
|
$bd .= '<div class="bd-table"></div>';
|
|
$bd .= '</div>';
|
|
|
|
$bd .= '</div>'; /* bd-stage */
|
|
$visual_html = $bd;
|
|
$visual_cls = 'platform-visual has-branded';
|
|
} elseif ( ! empty( $a['cameraAnim'] ) ) {
|
|
$visual_html = oribi_render_camera_animation();
|
|
$visual_cls = 'platform-visual has-video-editor';
|
|
|
|
/* ── Gallery TV Slideshow ───────────────────────────────── */
|
|
} elseif ( ! empty( $a['galleryIds'] ) && is_array( $a['galleryIds'] ) && count( $a['galleryIds'] ) > 0 ) {
|
|
$slides = '';
|
|
$count = 0;
|
|
foreach ( $a['galleryIds'] as $gid ) {
|
|
$gid = intval( $gid );
|
|
if ( ! $gid ) continue;
|
|
$url = wp_get_attachment_url( $gid );
|
|
$alt = get_post_meta( $gid, '_wp_attachment_image_alt', true );
|
|
if ( ! $url ) continue;
|
|
$active = $count === 0 ? ' is-active' : '';
|
|
$slides .= '<div class="gtv-slide' . $active . '">';
|
|
$slides .= '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt ) . '" loading="lazy" />';
|
|
$slides .= '</div>';
|
|
$count++;
|
|
}
|
|
if ( $count > 0 ) {
|
|
$visual_html = '<div class="gtv-stage" data-gtv-slideshow aria-hidden="true">';
|
|
$visual_html .= '<div class="gtv-tv">';
|
|
$visual_html .= '<div class="gtv-tv__body">';
|
|
$visual_html .= '<div class="gtv-tv__screen">';
|
|
$visual_html .= '<div class="gtv-slides">' . $slides . '</div>';
|
|
$visual_html .= '</div>'; // screen
|
|
$visual_html .= '</div>'; // body
|
|
$visual_html .= '<div class="gtv-tv__feet"><div class="gtv-tv__foot"></div><div class="gtv-tv__foot"></div></div>';
|
|
$visual_html .= '</div>'; // tv
|
|
$visual_html .= '</div>'; // stage
|
|
$visual_cls = 'platform-visual has-gallery-tv';
|
|
} else {
|
|
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
|
|
$visual_cls = 'platform-visual';
|
|
}
|
|
|
|
} else {
|
|
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
|
|
$visual_cls = 'platform-visual';
|
|
}
|
|
|
|
ob_start(); ?>
|
|
<div class="platform-row<?php echo $rev; ?>">
|
|
<div class="platform-text">
|
|
<h3><?php echo wp_kses_post( $a['heading'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
<?php if ( ! empty( $a['btnUrl'] ) ) : ?>
|
|
<a href="<?php echo esc_url( $a['btnUrl'] ); ?>" class="btn btn-outline mt-3"><?php echo esc_html( $a['btnText'] ?? 'Learn More' ); ?> →</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="<?php echo esc_attr( $visual_cls ); ?>"><?php echo $visual_html; ?></div>
|
|
</div>
|
|
<?php return ob_get_clean();
|
|
}
|
|
/* ── Trust Section (parent - wraps child trust-item blocks) ────────────────── */
|
|
function oribi_render_trust_section( $a, $content ) {
|
|
ob_start(); ?>
|
|
<section class="section">
|
|
<div class="container">
|
|
<div class="section-header">
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<div class="grid-2" style="align-items:center;">
|
|
<div style="display:flex;flex-direction:column;gap:1.5rem;">
|
|
<?php echo $content; ?>
|
|
</div>
|
|
<div style="text-align:center;">
|
|
<a href="<?php echo esc_url( $a['btnUrl'] ); ?>" target="_blank" rel="noopener" class="btn btn-primary btn-lg"><?php echo esc_html( $a['btnText'] ); ?></a>
|
|
<?php if ( $a['btnSub'] ) : ?><p class="lead mt-2" style="font-size:.9rem;"><?php echo esc_html( $a['btnSub'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Trust Item (child - renders one heading + description pair) ────────────── */
|
|
function oribi_render_trust_item( $a ) {
|
|
ob_start(); ?>
|
|
<div class="trust-item">
|
|
<h3 style="margin-bottom:1rem;"><?php echo wp_kses_post( $a['heading'] ); ?></h3>
|
|
<p><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── FAQ Section (parent - wraps child faq-item blocks) ────────────────────── */
|
|
function oribi_render_faq_section( $a, $content ) {
|
|
$cls = $a['variant'] === 'alt' ? 'section section-alt' : 'section';
|
|
ob_start(); ?>
|
|
<section class="<?php echo esc_attr( $cls ); ?>">
|
|
<div class="container">
|
|
<div class="section-header">
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<div class="faq-list">
|
|
<?php echo $content; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── FAQ Item (child - renders one accordion item) ─────────────────────────── */
|
|
function oribi_render_faq_item( $a ) {
|
|
ob_start(); ?>
|
|
<details class="faq-item">
|
|
<summary class="faq-question"><?php echo wp_kses_post( $a['question'] ); ?><span class="faq-toggle" aria-hidden="true"></span></summary>
|
|
<div class="faq-answer"><p><?php echo wp_kses_post( $a['answer'] ); ?></p></div>
|
|
</details>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Comparison Table (standalone - renders a feature matrix) ──────────────── */
|
|
function oribi_render_comparison_table( $a ) {
|
|
$cls = $a['variant'] === 'alt' ? 'section section-alt' : 'section';
|
|
$cols = $a['columns'] ?? [];
|
|
$rows = $a['rows'] ?? [];
|
|
ob_start(); ?>
|
|
<section class="<?php echo esc_attr( $cls ); ?>">
|
|
<div class="container">
|
|
<div class="section-header">
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<h2><?php echo wp_kses_post( $a['heading'] ); ?></h2>
|
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<div class="comparison-table-wrap">
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th class="comparison-feature-col">Feature</th>
|
|
<?php foreach ( $cols as $col ) : ?>
|
|
<th><?php echo esc_html( $col ); ?></th>
|
|
<?php endforeach; ?>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ( $rows as $row ) :
|
|
$is_group = ! empty( $row['group'] );
|
|
?>
|
|
<?php if ( $is_group ) : ?>
|
|
<tr class="comparison-group-row">
|
|
<td colspan="<?php echo count( $cols ) + 1; ?>"><?php echo esc_html( $row['group'] ); ?></td>
|
|
</tr>
|
|
<?php else : ?>
|
|
<tr>
|
|
<td class="comparison-feature-name"><?php echo wp_kses_post( $row['feature'] ?? '' ); ?></td>
|
|
<?php foreach ( ( $row['values'] ?? [] ) as $val ) : ?>
|
|
<td class="comparison-cell"><?php
|
|
if ( $val === true ) echo '<span class="comparison-yes">✓</span>';
|
|
elseif ( $val === false ) echo '<span class="comparison-no">✗</span>';
|
|
else echo wp_kses_post( $val );
|
|
?></td>
|
|
<?php endforeach; ?>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════════════════
|
|
ANIMATED HERO BLOCKS (OTS Signs)
|
|
══════════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Generate particle divs for the animated hero background.
|
|
* Each particle gets a unique modifier class for staggered animation.
|
|
*
|
|
* @param int $count Number of particles (default 12).
|
|
* @return string Rendered HTML.
|
|
*/
|
|
function oribi_render_particles( $count = 12 ) {
|
|
$html = '<div class="hero-particles" aria-hidden="true">';
|
|
for ( $i = 1; $i <= $count; $i++ ) {
|
|
$html .= '<div class="hero-particle hero-particle--' . $i . '"></div>';
|
|
}
|
|
$html .= '</div>';
|
|
return $html;
|
|
}
|
|
|
|
/* ── Animated Hero (homepage) ──────────────────────────────────────────────── */
|
|
function oribi_render_hero_animated( $a ) {
|
|
ob_start();
|
|
?>
|
|
<section class="hero hero-animated">
|
|
<?php echo oribi_render_particles( 12 ); ?>
|
|
<div class="hero-animated__glow"></div>
|
|
<div class="container hero-animated__inner">
|
|
<div class="hero-animated__content">
|
|
<?php if ( $a['label'] ) : ?>
|
|
<span class="hero-label"><?php echo wp_kses_post( $a['label'] ); ?></span>
|
|
<?php endif; ?>
|
|
<h1 class="hero-title"><?php echo oribi_highlight( $a['title'], $a['highlightWord'] ); ?></h1>
|
|
<p class="hero-description"><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
<div class="btn-group">
|
|
<?php if ( $a['primaryBtnText'] ) : ?>
|
|
<a href="<?php echo esc_url( $a['primaryBtnUrl'] ); ?>" class="btn btn-primary btn-lg"><?php echo esc_html( $a['primaryBtnText'] ); ?></a>
|
|
<?php endif; ?>
|
|
<?php if ( $a['secondaryBtnText'] ) : ?>
|
|
<a href="<?php echo esc_url( $a['secondaryBtnUrl'] ); ?>" class="btn btn-ghost btn-lg"><?php echo esc_html( $a['secondaryBtnText'] ); ?> →</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php if ( $a['stat1Value'] || $a['stat2Value'] || $a['stat3Value'] ) : ?>
|
|
<div class="hero-stats hero-stats--three">
|
|
<?php if ( $a['stat1Value'] ) : ?>
|
|
<div><div class="hero-stat-value"><?php echo esc_html( $a['stat1Value'] ); ?></div><div class="hero-stat-label"><?php echo esc_html( $a['stat1Label'] ); ?></div></div>
|
|
<?php endif; ?>
|
|
<?php if ( $a['stat2Value'] ) : ?>
|
|
<div><div class="hero-stat-value"><?php echo esc_html( $a['stat2Value'] ); ?></div><div class="hero-stat-label"><?php echo esc_html( $a['stat2Label'] ); ?></div></div>
|
|
<?php endif; ?>
|
|
<?php if ( $a['stat3Value'] ) : ?>
|
|
<div><div class="hero-stat-value"><?php echo esc_html( $a['stat3Value'] ); ?></div><div class="hero-stat-label"><?php echo esc_html( $a['stat3Label'] ); ?></div></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Animated Page Hero (inner pages) ──────────────────────────────────────── */
|
|
function oribi_render_page_hero_animated( $a ) {
|
|
ob_start(); ?>
|
|
<section class="page-hero page-hero-animated">
|
|
<?php echo oribi_render_particles( 8 ); ?>
|
|
<div class="hero-animated__glow"></div>
|
|
<div class="hero-overlay"></div>
|
|
<div class="container">
|
|
<?php if ( $a['label'] ) : ?><span class="hero-label"><?php echo wp_kses_post( $a['label'] ); ?></span><?php endif; ?>
|
|
<h1><?php echo wp_kses_post( $a['title'] ); ?></h1>
|
|
<p class="lead"><?php echo wp_kses_post( $a['description'] ); ?></p>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|
|
|
|
/* ── Use Cases Showcase ────────────────────────────────────────────────── */
|
|
function oribi_uc_anim_inner( $mod ) {
|
|
switch ( $mod ) {
|
|
case 'menu':
|
|
return '
|
|
<div class="uc-inner uc-inner--menu" aria-hidden="true">
|
|
<div class="uc-menu-header"></div>
|
|
<div class="uc-menu-row"><span class="uc-menu-name"></span><span class="uc-menu-price"></span></div>
|
|
<div class="uc-menu-row uc-menu-row--highlight"><span class="uc-menu-name"></span><span class="uc-menu-price"></span></div>
|
|
<div class="uc-menu-row"><span class="uc-menu-name uc-menu-name--sm"></span><span class="uc-menu-price"></span></div>
|
|
<div class="uc-menu-row"><span class="uc-menu-name"></span><span class="uc-menu-price"></span></div>
|
|
<div class="uc-menu-divider"></div>
|
|
<div class="uc-menu-row"><span class="uc-menu-name uc-menu-name--sm"></span><span class="uc-menu-price"></span></div>
|
|
</div>';
|
|
case 'event':
|
|
return '
|
|
<div class="uc-inner uc-inner--event" aria-hidden="true">
|
|
<div class="uc-event-cursor"></div>
|
|
<div class="uc-event-header">Schedule</div>
|
|
<div class="uc-event-row">
|
|
<div class="uc-event-time">9:00</div>
|
|
<div class="uc-event-title uc-event-title--active">Keynote Speech</div>
|
|
</div>
|
|
<div class="uc-event-row">
|
|
<div class="uc-event-time">10:30</div>
|
|
<div class="uc-event-title">Panel Discussion</div>
|
|
</div>
|
|
<div class="uc-event-row">
|
|
<div class="uc-event-time">11:45</div>
|
|
<div class="uc-event-title uc-event-title--accent">Coffee Break</div>
|
|
</div>
|
|
<div class="uc-event-row">
|
|
<div class="uc-event-time">12:30</div>
|
|
<div class="uc-event-title">Networking Lunch</div>
|
|
</div>
|
|
</div>';
|
|
case 'dashboard':
|
|
return '
|
|
<div class="uc-inner uc-inner--dashboard" aria-hidden="true">
|
|
<div class="uc-db-bars">
|
|
<div class="uc-db-bar uc-db-bar--1"></div>
|
|
<div class="uc-db-bar uc-db-bar--2"></div>
|
|
<div class="uc-db-bar uc-db-bar--3"></div>
|
|
<div class="uc-db-bar uc-db-bar--4"></div>
|
|
</div>
|
|
<div class="uc-db-baseline"></div>
|
|
<div class="uc-db-labels">
|
|
<div class="uc-db-lbl"></div>
|
|
<div class="uc-db-lbl"></div>
|
|
<div class="uc-db-lbl"></div>
|
|
<div class="uc-db-lbl"></div>
|
|
</div>
|
|
</div>';
|
|
case 'wayfinding':
|
|
return '
|
|
<div class="uc-inner uc-inner--wayfinding" aria-hidden="true">
|
|
<div class="uc-wf-corridor uc-wf-corridor--h"></div>
|
|
<div class="uc-wf-corridor uc-wf-corridor--v"></div>
|
|
<div class="uc-wf-room uc-wf-room--1"></div>
|
|
<div class="uc-wf-room uc-wf-room--2"></div>
|
|
<div class="uc-wf-room uc-wf-room--3"></div>
|
|
<div class="uc-wf-dot"></div>
|
|
<div class="uc-wf-arrow"></div>
|
|
</div>';
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function oribi_render_use_cases( $a ) {
|
|
$cases = [
|
|
[ 'title' => $a['case1Title'], 'desc' => $a['case1Desc'], 'mod' => 'menu' ],
|
|
[ 'title' => $a['case2Title'], 'desc' => $a['case2Desc'], 'mod' => 'event' ],
|
|
[ 'title' => $a['case3Title'], 'desc' => $a['case3Desc'], 'mod' => 'dashboard' ],
|
|
[ 'title' => $a['case4Title'], 'desc' => $a['case4Desc'], 'mod' => 'wayfinding' ],
|
|
];
|
|
ob_start(); ?>
|
|
<section class="section use-cases-section">
|
|
<div class="container">
|
|
<?php if ( $a['label'] || $a['heading'] || $a['lead'] ) : ?>
|
|
<div class="section-header">
|
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
|
<?php if ( $a['heading'] ) : ?><h2><?php echo wp_kses_post( $a['heading'] ); ?></h2><?php endif; ?>
|
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="uc-track">
|
|
<?php foreach ( $cases as $c ) : ?>
|
|
<div class="uc-item">
|
|
<div class="uc-circle uc-anim--<?php echo esc_attr( $c['mod'] ); ?>">
|
|
<?php echo oribi_uc_anim_inner( $c['mod'] ); ?>
|
|
</div>
|
|
<div class="uc-item-body">
|
|
<div class="uc-item-title"><?php echo esc_html( $c['title'] ); ?></div>
|
|
<?php if ( $c['desc'] ) : ?><p class="uc-item-desc"><?php echo esc_html( $c['desc'] ); ?></p><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php return ob_get_clean();
|
|
}
|