3530 lines
187 KiB
PHP
3530 lines
187 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],
|
||
'cloudAnim' => ['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],
|
||
'scene' => ['type' => 'string', 'default' => ''],
|
||
],
|
||
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],
|
||
'hospitalityAnim' => ['type' => 'boolean', 'default' => false],
|
||
'retailAnim' => ['type' => 'boolean', 'default' => false],
|
||
'corporateAnim' => ['type' => 'boolean', 'default' => false],
|
||
'educationAnim' => ['type' => 'boolean', 'default' => false],
|
||
'outdoorAnim' => ['type' => 'boolean', 'default' => false],
|
||
'liveDataAnim' => ['type' => 'boolean', 'default' => false],
|
||
'healthcareAnim' => ['type' => 'boolean', 'default' => false],
|
||
'transitAnim' => ['type' => 'boolean', 'default' => false],
|
||
'fitnessAnim' => ['type' => 'boolean', 'default' => false],
|
||
'lobbyAnim' => ['type' => 'boolean', 'default' => false],
|
||
'conferenceAnim' => ['type' => 'boolean', 'default' => false],
|
||
'dayPartAnim' => ['type' => 'boolean', 'default' => false],
|
||
'wayfindAnim' => ['type' => 'boolean', 'default' => false],
|
||
'storefrontAnim' => ['type' => 'boolean', 'default' => false],
|
||
'announcementAnim' => ['type' => 'boolean', 'default' => false],
|
||
'campusWayfindAnim' => ['type' => 'boolean', 'default' => false],
|
||
'emergencyAnim' => ['type' => 'boolean', 'default' => false],
|
||
'enclosureAnim' => ['type' => 'boolean', 'default' => false],
|
||
'brightnessAnim' => ['type' => 'boolean', 'default' => false],
|
||
'cellularAnim' => ['type' => 'boolean', 'default' => false],
|
||
'designerAnim' => ['type' => 'boolean', 'default' => false],
|
||
'mediaLibraryAnim' => ['type' => 'boolean', 'default' => false],
|
||
'publishAnim' => ['type' => 'boolean', 'default' => false],
|
||
'screenGroupsAnim' => ['type' => 'boolean', 'default' => false],
|
||
'monitoringAnim' => ['type' => 'boolean', 'default' => false],
|
||
'patientWayfindAnim' => ['type' => 'boolean', 'default' => false],
|
||
'waitingRoomAnim' => ['type' => 'boolean', 'default' => false],
|
||
'multiZoneAnim' => ['type' => 'boolean', 'default' => false],
|
||
'membershipAnim' => ['type' => 'boolean', 'default' => false],
|
||
'videoMotionAnim' => ['type' => 'boolean', 'default' => false],
|
||
'brandLayoutAnim' => ['type' => 'boolean', 'default' => false],
|
||
'menuBoardAnim' => ['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>
|
||
</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 class="nav-contact"><a href="' . esc_url(home_url('/contact')) . '" class="btn btn-primary">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">
|
||
<a href="<?php echo esc_url(home_url('/')); ?>" class="logo-text"><strong>OTS</strong> Signs</a>
|
||
</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>
|
||
<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>
|
||
</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 !empty($a['cloudAnim']) ? ' has-cloud-anim' : ''; ?>"<?php echo $ltr; ?>>
|
||
<?php
|
||
if (!empty($a['cloudAnim'])) {
|
||
echo '<div class="ds-anim-container">';
|
||
echo '<div class="ds-tv"><i class="fas fa-tv" aria-hidden="true"></i><div class="ds-tv-screen"></div></div>';
|
||
echo '<div class="ds-line"><div class="ds-packet ds-packet-1"></div><div class="ds-packet ds-packet-2"></div><div class="ds-packet ds-packet-3"></div></div>';
|
||
echo '<div class="ds-cloud"><i class="fas fa-cloud" aria-hidden="true"></i></div>';
|
||
echo '</div>';
|
||
}
|
||
else {
|
||
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']);
|
||
$scene = !empty($a['scene']) ? trim($a['scene']) : '';
|
||
$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 ($scene): ?>
|
||
<?php echo oribi_render_card_scene($scene); ?>
|
||
<?php elseif ((!$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();
|
||
}
|
||
|
||
/* ── Card Scene Renderer ────────────────────────────────────────────────────── */
|
||
function oribi_render_card_scene($scene)
|
||
{
|
||
switch ($scene) {
|
||
|
||
case 'cms':
|
||
return
|
||
'<div class="card-scene cs-cms" aria-hidden="true">'
|
||
. '<div class="cs-screen">'
|
||
. '<div class="cs-topbar"><div class="cs-dots"><span></span><span></span><span></span></div><div class="cs-title">Media Library</div></div>'
|
||
. '<div class="cs-files">'
|
||
. '<div class="cs-file cs-file--1"><span class="cs-ftype cs-ftype-img">IMG</span><div class="cs-fbar"></div><span class="cs-fsize">2.4 MB</span></div>'
|
||
. '<div class="cs-file cs-file--2"><span class="cs-ftype cs-ftype-vid">VID</span><div class="cs-fbar"></div><span class="cs-fsize">18 MB</span></div>'
|
||
. '<div class="cs-file cs-file--3"><span class="cs-ftype cs-ftype-html">HTML</span><div class="cs-fbar"></div><span class="cs-fsize">64 KB</span></div>'
|
||
. '</div>'
|
||
. '<div class="cs-upload">+ Upload</div>'
|
||
. '</div></div>';
|
||
|
||
case 'scheduler':
|
||
return
|
||
'<div class="card-scene cs-scheduler" aria-hidden="true">'
|
||
. '<div class="cs-screen">'
|
||
. '<div class="cs-topbar"><div class="cs-dots"><span></span><span></span><span></span></div><div class="cs-title">Scheduler</div></div>'
|
||
. '<div class="cs-week">'
|
||
. '<div class="cs-cal-day"><span>M</span><div class="cs-cal-bar"></div></div>'
|
||
. '<div class="cs-cal-day"><span>T</span><div class="cs-cal-bar"></div></div>'
|
||
. '<div class="cs-cal-day"><span>W</span><div class="cs-cal-bar"></div></div>'
|
||
. '<div class="cs-cal-day"><span>T</span><div class="cs-cal-bar"></div></div>'
|
||
. '<div class="cs-cal-day"><span>F</span><div class="cs-cal-bar"></div></div>'
|
||
. '<div class="cs-cal-day"><span>S</span><div class="cs-cal-bar"></div></div>'
|
||
. '<div class="cs-cal-day"><span>S</span><div class="cs-cal-bar"></div></div>'
|
||
. '</div>'
|
||
. '</div></div>';
|
||
|
||
case 'data-feed':
|
||
return
|
||
'<div class="card-scene cs-data-feed" aria-hidden="true">'
|
||
. '<div class="cs-screen">'
|
||
. '<div class="cs-topbar"><div class="cs-live-dot"></div><div class="cs-title">Live Feed</div></div>'
|
||
. '<div class="cs-feed-rows">'
|
||
. '<div class="cs-feed-row"><span class="cs-feed-label">TEMP</span><div class="cs-feed-val"><span class="cs-fv1-a">22.4°C</span><span class="cs-fv1-b">23.1°C</span><span class="cs-fv1-c">21.8°C</span></div></div>'
|
||
. '<div class="cs-feed-row"><span class="cs-feed-label">QUEUE</span><div class="cs-feed-val"><span class="cs-fv2-a">14</span><span class="cs-fv2-b">17</span><span class="cs-fv2-c">11</span></div></div>'
|
||
. '<div class="cs-feed-row"><span class="cs-feed-label">SALES</span><div class="cs-feed-val"><span class="cs-fv3-a">\$1,204</span><span class="cs-fv3-b">\$1,318</span><span class="cs-fv3-c">\$1,271</span></div></div>'
|
||
. '</div>'
|
||
. '</div></div>';
|
||
|
||
case 'templates':
|
||
return
|
||
'<div class="card-scene cs-templates" aria-hidden="true">'
|
||
. '<div class="cs-screen">'
|
||
. '<div class="cs-topbar"><div class="cs-dots"><span></span><span></span><span></span></div><div class="cs-title">Templates</div></div>'
|
||
. '<div class="cs-tmpl-grid">'
|
||
. '<div class="cs-tmpl cs-tmpl--1"><div class="cs-tmpl-thumb"></div><div class="cs-tmpl-line cs-tmpl-line--med"></div></div>'
|
||
. '<div class="cs-tmpl cs-tmpl--2"><div class="cs-tmpl-line cs-tmpl-line--short"></div><div class="cs-tmpl-thumb"></div></div>'
|
||
. '<div class="cs-tmpl cs-tmpl--3"><div class="cs-tmpl-thumb cs-tmpl-thumb--full"></div></div>'
|
||
. '<div class="cs-tmpl cs-tmpl--4"><div class="cs-tmpl-line cs-tmpl-line--med"></div><div class="cs-tmpl-line cs-tmpl-line--short"></div><div class="cs-tmpl-line cs-tmpl-line--short"></div></div>'
|
||
. '</div>'
|
||
. '</div></div>';
|
||
|
||
case 'team':
|
||
return
|
||
'<div class="card-scene cs-team" aria-hidden="true">'
|
||
. '<div class="cs-screen">'
|
||
. '<div class="cs-topbar"><div class="cs-dots"><span></span><span></span><span></span></div><div class="cs-title">Team</div></div>'
|
||
. '<div class="cs-team-avatars">'
|
||
. '<div class="cs-avatar cs-avatar--1"><div class="cs-av-circle">A</div><div class="cs-av-role cs-role-admin">Admin</div></div>'
|
||
. '<div class="cs-avatar cs-avatar--2"><div class="cs-av-circle">E</div><div class="cs-av-role cs-role-editor">Editor</div></div>'
|
||
. '<div class="cs-avatar cs-avatar--3"><div class="cs-av-circle">V</div><div class="cs-av-role cs-role-viewer">Viewer</div></div>'
|
||
. '</div>'
|
||
. '<div class="cs-perm-strip"><div class="cs-perm-dot cs-perm-dot--1"></div><div class="cs-perm-dot cs-perm-dot--2"></div><div class="cs-perm-dot cs-perm-dot--3"></div></div>'
|
||
. '</div></div>';
|
||
|
||
case 'analytics':
|
||
return
|
||
'<div class="card-scene cs-analytics" aria-hidden="true">'
|
||
. '<div class="cs-screen">'
|
||
. '<div class="cs-topbar"><div class="cs-live-dot"></div><div class="cs-title">Analytics</div></div>'
|
||
. '<div class="cs-analytics-body">'
|
||
. '<div class="cs-ring-wrap"><div class="cs-ring"></div><div class="cs-ring-val">94%</div></div>'
|
||
. '<div class="cs-bars"><div class="cs-sbar cs-sbar--1"></div><div class="cs-sbar cs-sbar--2"></div><div class="cs-sbar cs-sbar--3"></div><div class="cs-sbar cs-sbar--4"></div><div class="cs-sbar cs-sbar--5"></div><div class="cs-sbar cs-sbar--6"></div></div>'
|
||
. '</div>'
|
||
. '</div></div>';
|
||
|
||
default:
|
||
return '';
|
||
}
|
||
}
|
||
|
||
/* ── 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);
|
||
$has_label = !empty($a['label']);
|
||
ob_start();
|
||
if ($has_label): ?>
|
||
<section class="<?php echo esc_attr($cls); ?>">
|
||
<div class="container">
|
||
<div class="pricing-track-layout">
|
||
<div class="pricing-track-header">
|
||
<span class="section-label"><?php echo esc_html($a['label']); ?></span>
|
||
<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>
|
||
</div>
|
||
</section>
|
||
<?php else: ?>
|
||
<section class="<?php echo esc_attr($cls); ?>">
|
||
<div class="container">
|
||
<div class="section-header">
|
||
<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 endif;
|
||
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['retailAnim'])) {
|
||
/* ── Retail Sign: TV cycling 3 promo slides ── */
|
||
$ra = '<div class="retail-stage" aria-hidden="true">';
|
||
$ra .= '<div class="retail-tv">';
|
||
$ra .= '<div class="retail-tv__body">';
|
||
$ra .= '<div class="retail-tv__screen">';
|
||
$ra .= '<div class="retail-slides">';
|
||
|
||
// Slide 1: Flash Sale
|
||
$ra .= '<div class="retail-slide retail-slide--sale">';
|
||
$ra .= '<div class="retail-promo">';
|
||
$ra .= '<div class="retail-promo__eyebrow">Today Only</div>';
|
||
$ra .= '<div class="retail-promo__headline">Flash Sale</div>';
|
||
$ra .= '<div class="retail-promo__badge">Up to 40% Off</div>';
|
||
$ra .= '<div class="retail-promo__items">';
|
||
$ra .= '<div class="retail-promo__item"><span class="retail-promo__dot"></span><span class="retail-promo__lbl">Select Apparel</span></div>';
|
||
$ra .= '<div class="retail-promo__item"><span class="retail-promo__dot"></span><span class="retail-promo__lbl">Footwear Range</span></div>';
|
||
$ra .= '<div class="retail-promo__item"><span class="retail-promo__dot"></span><span class="retail-promo__lbl">Accessories</span></div>';
|
||
$ra .= '</div>';
|
||
$ra .= '<div class="retail-promo__cta">In-Store Only</div>';
|
||
$ra .= '</div>';
|
||
$ra .= '</div>';
|
||
|
||
// Slide 2: New Arrivals
|
||
$ra .= '<div class="retail-slide retail-slide--new">';
|
||
$ra .= '<div class="retail-promo">';
|
||
$ra .= '<div class="retail-promo__eyebrow">Just Landed</div>';
|
||
$ra .= '<div class="retail-promo__headline">New In Store</div>';
|
||
$ra .= '<div class="retail-promo__grid">';
|
||
$ra .= '<div class="retail-promo__swatch retail-promo__swatch--a"></div>';
|
||
$ra .= '<div class="retail-promo__swatch retail-promo__swatch--b"></div>';
|
||
$ra .= '<div class="retail-promo__swatch retail-promo__swatch--c"></div>';
|
||
$ra .= '<div class="retail-promo__swatch retail-promo__swatch--d"></div>';
|
||
$ra .= '</div>';
|
||
$ra .= '<div class="retail-promo__sub">Spring/Summer Collection</div>';
|
||
$ra .= '</div>';
|
||
$ra .= '</div>';
|
||
|
||
// Slide 3: Loyalty Rewards
|
||
$ra .= '<div class="retail-slide retail-slide--loyalty">';
|
||
$ra .= '<div class="retail-promo">';
|
||
$ra .= '<div class="retail-promo__eyebrow">Member Exclusive</div>';
|
||
$ra .= '<div class="retail-promo__headline">Earn Points</div>';
|
||
$ra .= '<div class="retail-promo__points">';
|
||
$ra .= '<div class="retail-promo__pts-val">2x</div>';
|
||
$ra .= '<div class="retail-promo__pts-lbl">Points This Weekend</div>';
|
||
$ra .= '</div>';
|
||
$ra .= '<div class="retail-promo__bar"><div class="retail-promo__bar-fill"></div></div>';
|
||
$ra .= '<div class="retail-promo__sub">Scan your card at checkout</div>';
|
||
$ra .= '</div>';
|
||
$ra .= '</div>';
|
||
|
||
$ra .= '</div>'; // retail-slides
|
||
$ra .= '</div>'; // retail-tv__screen
|
||
$ra .= '</div>'; // retail-tv__body
|
||
$ra .= '<div class="retail-tv__feet"><div class="retail-tv__foot"></div><div class="retail-tv__foot"></div></div>';
|
||
$ra .= '</div>'; // retail-tv
|
||
$ra .= '</div>'; // retail-stage
|
||
|
||
$visual_html = $ra;
|
||
$visual_cls = 'platform-visual has-retail';
|
||
}
|
||
elseif (!empty($a['corporateAnim'])) {
|
||
/* ── Corporate: Meeting room door panel ── */
|
||
$ca = '<div class="corp-stage" aria-hidden="true">';
|
||
$ca .= '<div class="corp-panel">';
|
||
$ca .= '<div class="corp-panel__header">';
|
||
$ca .= '<div class="corp-panel__room">Boardroom A</div>';
|
||
$ca .= '<div class="corp-panel__status corp-panel__status--busy"><span class="corp-panel__dot"></span>In Use</div>';
|
||
$ca .= '</div>';
|
||
$ca .= '<div class="corp-panel__meeting">';
|
||
$ca .= '<div class="corp-panel__meeting-name">Q2 Strategy Review</div>';
|
||
$ca .= '<div class="corp-panel__meeting-time">10:00 – 11:30</div>';
|
||
$ca .= '<div class="corp-panel__organiser">Sarah Mitchell</div>';
|
||
$ca .= '</div>';
|
||
$ca .= '<div class="corp-panel__timeline">';
|
||
$ca .= '<div class="corp-panel__tl-track"><div class="corp-panel__tl-fill"></div><div class="corp-panel__tl-now"></div></div>';
|
||
$ca .= '<div class="corp-panel__tl-labels"><span>09:00</span><span>12:00</span><span>17:00</span></div>';
|
||
$ca .= '</div>';
|
||
$ca .= '<div class="corp-panel__next">';
|
||
$ca .= '<div class="corp-panel__next-lbl">Next</div>';
|
||
$ca .= '<div class="corp-panel__next-name">Design Sprint Planning</div>';
|
||
$ca .= '<div class="corp-panel__next-time">13:00 – 14:00</div>';
|
||
$ca .= '</div>';
|
||
$ca .= '<div class="corp-panel__teams"><div class="corp-panel__teams-icon"></div><span>Teams Meeting Active</span></div>';
|
||
$ca .= '</div>'; // corp-panel
|
||
$ca .= '</div>'; // corp-stage
|
||
|
||
$visual_html = $ca;
|
||
$visual_cls = 'platform-visual has-corporate';
|
||
}
|
||
elseif (!empty($a['educationAnim'])) {
|
||
/* ── Education: Campus schedule board ── */
|
||
$ea = '<div class="edu-stage" aria-hidden="true">';
|
||
$ea .= '<div class="edu-board">';
|
||
$ea .= '<div class="edu-board__header">';
|
||
$ea .= '<div class="edu-board__title">Today\'s Timetable</div>';
|
||
$ea .= '<div class="edu-board__date">Monday, 16 Mar</div>';
|
||
$ea .= '</div>';
|
||
$ea .= '<div class="edu-board__rows">';
|
||
|
||
$rows = [
|
||
['time' => '09:00', 'subject' => 'Advanced Mathematics', 'room' => 'B204', 'state' => 'done'],
|
||
['time' => '10:30', 'subject' => 'Physics Lab', 'room' => 'Lab 3', 'state' => 'now'],
|
||
['time' => '13:00', 'subject' => 'English Literature', 'room' => 'A101', 'state' => ''],
|
||
['time' => '14:30', 'subject' => 'Computer Science', 'room' => 'IT Suite', 'state' => ''],
|
||
['time' => '16:00', 'subject' => 'Art & Design', 'room' => 'Studio 1', 'state' => ''],
|
||
];
|
||
foreach ($rows as $row) {
|
||
$state_cls = $row['state'] ? ' edu-row--' . $row['state'] : '';
|
||
$ea .= '<div class="edu-board__row' . $state_cls . '">';
|
||
$ea .= '<span class="edu-row__time">' . esc_html($row['time']) . '</span>';
|
||
$ea .= '<span class="edu-row__subject">' . esc_html($row['subject']) . '</span>';
|
||
$ea .= '<span class="edu-row__room">' . esc_html($row['room']) . '</span>';
|
||
if ($row['state'] === 'now') {
|
||
$ea .= '<span class="edu-row__badge">Now</span>';
|
||
}
|
||
$ea .= '</div>';
|
||
}
|
||
|
||
$ea .= '</div>'; // edu-board__rows
|
||
$ea .= '<div class="edu-board__alert">';
|
||
$ea .= '<span class="edu-alert__icon">!</span>';
|
||
$ea .= '<span class="edu-alert__txt">Fire drill scheduled — 15:45 today</span>';
|
||
$ea .= '</div>';
|
||
$ea .= '</div>'; // edu-board
|
||
$ea .= '</div>'; // edu-stage
|
||
|
||
$visual_html = $ea;
|
||
$visual_cls = 'platform-visual has-education';
|
||
}
|
||
elseif (!empty($a['outdoorAnim'])) {
|
||
/* ── Outdoor Marketplace: wide board cycling 2 slides ── */
|
||
$oa = '<div class="outdoor-stage" aria-hidden="true">';
|
||
$oa .= '<div class="outdoor-board">';
|
||
$oa .= '<div class="outdoor-board__screen">';
|
||
$oa .= '<div class="outdoor-slides">';
|
||
|
||
// Slide 1: Market Info
|
||
$oa .= '<div class="outdoor-slide outdoor-slide--info">';
|
||
$oa .= '<div class="outdoor-info">';
|
||
$oa .= '<div class="outdoor-info__header">';
|
||
$oa .= '<div class="outdoor-info__name">Riverside Market</div>';
|
||
$oa .= '<div class="outdoor-info__weather"><span class="outdoor-info__temp">18°</span><span class="outdoor-info__cond">Mostly Sunny</span></div>';
|
||
$oa .= '</div>';
|
||
$oa .= '<div class="outdoor-info__details">';
|
||
$oa .= '<div class="outdoor-info__row"><span class="outdoor-info__icon outdoor-info__icon--clock"></span><span>Open 8am – 3pm</span></div>';
|
||
$oa .= '<div class="outdoor-info__row"><span class="outdoor-info__icon outdoor-info__icon--pin"></span><span>Victoria Embankment</span></div>';
|
||
$oa .= '<div class="outdoor-info__row"><span class="outdoor-info__icon outdoor-info__icon--stall"></span><span>42 Stallholders Today</span></div>';
|
||
$oa .= '</div>';
|
||
$oa .= '</div>';
|
||
$oa .= '</div>';
|
||
|
||
// Slide 2: Stall Directory
|
||
$oa .= '<div class="outdoor-slide outdoor-slide--directory">';
|
||
$oa .= '<div class="outdoor-dir">';
|
||
$oa .= '<div class="outdoor-dir__title">Stall Directory</div>';
|
||
$oa .= '<div class="outdoor-dir__grid">';
|
||
$stalls = [['A1–A5', 'Produce & Veg'], ['B1–B4', 'Artisan Bakery'], ['C1–C6', 'Street Food'], ['D1–D3', 'Crafts & Gifts']];
|
||
foreach ($stalls as $s) {
|
||
$oa .= '<div class="outdoor-dir__cell"><span class="outdoor-dir__zone">' . esc_html($s[0]) . '</span><span class="outdoor-dir__cat">' . esc_html($s[1]) . '</span></div>';
|
||
}
|
||
$oa .= '</div>';
|
||
$oa .= '</div>';
|
||
$oa .= '</div>';
|
||
|
||
$oa .= '</div>'; // outdoor-slides
|
||
$oa .= '</div>'; // outdoor-board__screen
|
||
$oa .= '<div class="outdoor-board__bezel"></div>';
|
||
$oa .= '</div>'; // outdoor-board
|
||
$oa .= '</div>'; // outdoor-stage
|
||
|
||
$visual_html = $oa;
|
||
$visual_cls = 'platform-visual has-outdoor';
|
||
}
|
||
elseif (!empty($a['liveDataAnim'])) {
|
||
/* ── Live Data: Operations centre KPI board ── */
|
||
$la = '<div class="ld-stage" aria-hidden="true">';
|
||
$la .= '<div class="ld-board">';
|
||
$la .= '<div class="ld-board__header">';
|
||
$la .= '<div class="ld-board__title">Operations Dashboard</div>';
|
||
$la .= '<div class="ld-board__live"><span class="ld-board__live-dot"></span>LIVE</div>';
|
||
$la .= '</div>';
|
||
$la .= '<div class="ld-kpis">';
|
||
|
||
$kpis = [
|
||
['id' => 'ld-orders', 'label' => 'Orders / hr', 'value' => '1,847', 'trend' => 'up'],
|
||
['id' => 'ld-uptime', 'label' => 'Uptime', 'value' => '99.97%', 'trend' => 'up'],
|
||
['id' => 'ld-alerts', 'label' => 'Active Alerts', 'value' => '3', 'trend' => 'down'],
|
||
['id' => 'ld-latency', 'label' => 'Avg Latency', 'value' => '42ms', 'trend' => 'neutral'],
|
||
];
|
||
foreach ($kpis as $k) {
|
||
$la .= '<div class="ld-kpi ld-kpi--' . esc_attr($k['trend']) . '">';
|
||
$la .= '<div class="ld-kpi__label">' . esc_html($k['label']) . '</div>';
|
||
$la .= '<div class="ld-kpi__value" id="' . esc_attr($k['id']) . '">' . esc_html($k['value']) . '</div>';
|
||
$la .= '<div class="ld-kpi__trend"></div>';
|
||
$la .= '</div>';
|
||
}
|
||
|
||
$la .= '</div>'; // ld-kpis
|
||
$la .= '<div class="ld-chart">';
|
||
$la .= '<svg class="ld-sparkline" viewBox="0 0 260 60" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">';
|
||
$la .= '<defs><linearGradient id="ld-grad" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#4CAF50" stop-opacity=".35"/><stop offset="100%" stop-color="#4CAF50" stop-opacity="0"/></linearGradient></defs>';
|
||
$la .= '<path id="ld-fill-path" d="M0,40 L0,40 L260,40 Z" fill="url(#ld-grad)"/>';
|
||
$la .= '<path id="ld-line-path" d="M0,40 L260,40" stroke="#4CAF50" stroke-width="2" fill="none" stroke-linejoin="round"/>';
|
||
$la .= '</svg>';
|
||
$la .= '<div class="ld-chart__label">Orders / hr — last 60 min</div>';
|
||
$la .= '</div>'; // ld-chart
|
||
$la .= '<div class="ld-status">';
|
||
|
||
$services = [
|
||
['API Gateway', 'ok'],
|
||
['Payment Proc.', 'ok'],
|
||
['Warehouse Feed', 'warn'],
|
||
['CDN', 'ok'],
|
||
];
|
||
foreach ($services as $svc) {
|
||
$la .= '<div class="ld-svc ld-svc--' . esc_attr($svc[1]) . '"><span class="ld-svc__dot"></span><span class="ld-svc__name">' . esc_html($svc[0]) . '</span></div>';
|
||
}
|
||
|
||
$la .= '</div>'; // ld-status
|
||
$la .= '</div>'; // ld-board
|
||
$la .= '</div>'; // ld-stage
|
||
|
||
$visual_html = $la;
|
||
$visual_cls = 'platform-visual has-live-data';
|
||
}
|
||
elseif (!empty($a['healthcareAnim'])) {
|
||
/* ── Healthcare: Queue management display ── */
|
||
$hca = '<div class="hc-stage" aria-hidden="true">';
|
||
$hca .= '<div class="hc-board">';
|
||
$hca .= '<div class="hc-board__header">';
|
||
$hca .= '<div class="hc-board__logo"></div>';
|
||
$hca .= '<div class="hc-board__title">Patient Queue</div>';
|
||
$hca .= '</div>';
|
||
$hca .= '<div class="hc-now">';
|
||
$hca .= '<div class="hc-now__lbl">Now Serving</div>';
|
||
$hca .= '<div class="hc-now__number hc-ticker">A042</div>';
|
||
$hca .= '<div class="hc-now__counter">Counter 3 — Dr. Patel</div>';
|
||
$hca .= '</div>';
|
||
$hca .= '<div class="hc-counters">';
|
||
|
||
$counters = [
|
||
['id' => 'C1', 'doctor' => 'Dr. Patel', 'ticket' => 'A042', 'wait' => '0 min', 'state' => 'active'],
|
||
['id' => 'C2', 'doctor' => 'Dr. Okonkwo', 'ticket' => 'B018', 'wait' => '4 min', 'state' => 'active'],
|
||
['id' => 'C3', 'doctor' => 'Dr. Williams', 'ticket' => 'A041', 'wait' => '8 min', 'state' => 'active'],
|
||
['id' => 'C4', 'doctor' => 'Dr. Nguyen', 'ticket' => '—', 'wait' => 'Closed', 'state' => 'closed'],
|
||
];
|
||
foreach ($counters as $c) {
|
||
$hca .= '<div class="hc-counter hc-counter--' . esc_attr($c['state']) . '">';
|
||
$hca .= '<span class="hc-counter__id">' . esc_html($c['id']) . '</span>';
|
||
$hca .= '<span class="hc-counter__doctor">' . esc_html($c['doctor']) . '</span>';
|
||
$hca .= '<span class="hc-counter__ticket">' . esc_html($c['ticket']) . '</span>';
|
||
$hca .= '<span class="hc-counter__wait">' . esc_html($c['wait']) . '</span>';
|
||
$hca .= '</div>';
|
||
}
|
||
|
||
$hca .= '</div>'; // hc-counters
|
||
$hca .= '<div class="hc-board__footer">Take a seat — your number will be called</div>';
|
||
$hca .= '</div>'; // hc-board
|
||
$hca .= '</div>'; // hc-stage
|
||
|
||
$visual_html = $hca;
|
||
$visual_cls = 'platform-visual has-healthcare';
|
||
}
|
||
elseif (!empty($a['transitAnim'])) {
|
||
/* ── Transit: Split-flap departure board ── */
|
||
$ta = '<div class="transit-stage" aria-hidden="true">';
|
||
$ta .= '<div class="transit-board">';
|
||
$ta .= '<div class="transit-board__header">';
|
||
$ta .= '<div class="transit-board__title">Departures</div>';
|
||
$ta .= '<div class="transit-board__clock" id="transit-clock">--:--</div>';
|
||
$ta .= '</div>';
|
||
$ta .= '<div class="transit-board__cols">';
|
||
$ta .= '<span class="transit-col-hd">Time</span><span class="transit-col-hd">Destination</span><span class="transit-col-hd">Platform</span><span class="transit-col-hd">Status</span>';
|
||
$ta .= '</div>';
|
||
$ta .= '<div class="transit-rows" id="transit-rows">';
|
||
|
||
$departures = [
|
||
['time' => '10:14', 'destination' => 'London Victoria', 'platform' => '2', 'status' => 'On Time', 'status_cls' => 'on-time'],
|
||
['time' => '10:22', 'destination' => 'Brighton', 'platform' => '4', 'status' => 'On Time', 'status_cls' => 'on-time'],
|
||
['time' => '10:31', 'destination' => 'Gatwick Airport', 'platform' => '1', 'status' => 'Delayed', 'status_cls' => 'delayed'],
|
||
['time' => '10:45', 'destination' => 'London Bridge', 'platform' => '3', 'status' => 'On Time', 'status_cls' => 'on-time'],
|
||
['time' => '11:02', 'destination' => 'East Croydon', 'platform' => '2', 'status' => 'On Time', 'status_cls' => 'on-time'],
|
||
];
|
||
foreach ($departures as $d) {
|
||
$ta .= '<div class="transit-row">';
|
||
$ta .= '<span class="transit-cell transit-cell--time">' . esc_html($d['time']) . '</span>';
|
||
$ta .= '<span class="transit-cell transit-cell--dest">';
|
||
// Each character gets a flap span for the CSS flip animation
|
||
$dest = esc_html($d['destination']);
|
||
foreach (str_split($dest) as $ch) {
|
||
$ta .= '<span class="transit-flap">' . ($ch === ' ' ? ' ' : htmlspecialchars($ch)) . '</span>';
|
||
}
|
||
$ta .= '</span>';
|
||
$ta .= '<span class="transit-cell transit-cell--plat">' . esc_html($d['platform']) . '</span>';
|
||
$ta .= '<span class="transit-cell transit-cell--status transit-status--' . esc_attr($d['status_cls']) . '">' . esc_html($d['status']) . '</span>';
|
||
$ta .= '</div>';
|
||
}
|
||
|
||
$ta .= '</div>'; // transit-rows
|
||
$ta .= '</div>'; // transit-board
|
||
$ta .= '</div>'; // transit-stage
|
||
|
||
$visual_html = $ta;
|
||
$visual_cls = 'platform-visual has-transit';
|
||
}
|
||
elseif (!empty($a['fitnessAnim'])) {
|
||
/* ── Fitness: Class schedule with live capacity bar ── */
|
||
$fa = '<div class="fit-stage" aria-hidden="true">';
|
||
$fa .= '<div class="fit-board">';
|
||
$fa .= '<div class="fit-board__header">';
|
||
$fa .= '<div class="fit-board__logo"></div>';
|
||
$fa .= '<div class="fit-board__title">Today\'s Classes</div>';
|
||
$fa .= '</div>';
|
||
$fa .= '<div class="fit-now">';
|
||
$fa .= '<div class="fit-now__badge">LIVE NOW</div>';
|
||
$fa .= '<div class="fit-now__name">HIIT Circuit</div>';
|
||
$fa .= '<div class="fit-now__detail">Studio 1 · Coach: Emma T · Ends 10:45</div>';
|
||
$fa .= '<div class="fit-now__capacity">';
|
||
$fa .= '<span class="fit-cap__lbl">Capacity</span>';
|
||
$fa .= '<div class="fit-cap__track"><div class="fit-cap__fill"></div></div>';
|
||
$fa .= '<span class="fit-cap__val">24/30</span>';
|
||
$fa .= '</div>';
|
||
$fa .= '</div>';
|
||
$fa .= '<div class="fit-upcoming">';
|
||
|
||
$classes = [
|
||
['time' => '11:00', 'name' => 'Yoga Flow', 'coach' => 'Sarah K', 'spaces' => 6],
|
||
['time' => '12:15', 'name' => 'Spin & Burn', 'coach' => 'James R', 'spaces' => 2],
|
||
['time' => '13:30', 'name' => 'Pilates Core', 'coach' => 'Lisa M', 'spaces' => 12],
|
||
];
|
||
foreach ($classes as $cls) {
|
||
$full_cls = $cls['spaces'] <= 3 ? ' fit-class--filling' : '';
|
||
$fa .= '<div class="fit-class' . $full_cls . '">';
|
||
$fa .= '<span class="fit-class__time">' . esc_html($cls['time']) . '</span>';
|
||
$fa .= '<span class="fit-class__name">' . esc_html($cls['name']) . '</span>';
|
||
$fa .= '<span class="fit-class__coach">' . esc_html($cls['coach']) . '</span>';
|
||
$fa .= '<span class="fit-class__spaces">' . esc_html($cls['spaces']) . ' spaces</span>';
|
||
$fa .= '</div>';
|
||
}
|
||
|
||
$fa .= '</div>'; // fit-upcoming
|
||
$fa .= '</div>'; // fit-board
|
||
$fa .= '</div>'; // fit-stage
|
||
|
||
$visual_html = $fa;
|
||
$visual_cls = 'platform-visual has-fitness';
|
||
}
|
||
elseif (!empty($a['lobbyAnim'])) {
|
||
/* ── Hotel Lobby Welcome Display ── */
|
||
$lb = '<div class="lobby-stage" aria-hidden="true">';
|
||
$lb .= '<div class="lobby-screen">';
|
||
$lb .= '<div class="lobby-hdr"><span class="lobby-hdr__logo">◆ Grand Hotel</span><span class="lobby-hdr__time">3:42 PM</span></div>';
|
||
$lb .= '<div class="lobby-slides">';
|
||
$lb .= '<div class="lobby-slide lobby-slide--welcome"><div class="lobby-welcome__msg">Welcome</div><div class="lobby-welcome__sub">We hope you enjoy your stay</div></div>';
|
||
$lb .= '<div class="lobby-slide lobby-slide--amenities"><div class="lobby-amen__title">Hotel Amenities</div><div class="lobby-amen__grid"><div class="lobby-amen__item">☉ Pool</div><div class="lobby-amen__item">⚛ Spa</div><div class="lobby-amen__item">♨ Restaurant</div><div class="lobby-amen__item">⌖ Gym</div></div></div>';
|
||
$lb .= '<div class="lobby-slide lobby-slide--events"><div class="lobby-events__title">Today\'s Events</div><div class="lobby-events__list"><div class="lobby-events__item"><span class="lobby-events__time">10:00</span><span class="lobby-events__name">Yoga on the Terrace</span></div><div class="lobby-events__item"><span class="lobby-events__time">14:00</span><span class="lobby-events__name">Wine Tasting</span></div><div class="lobby-events__item"><span class="lobby-events__time">19:00</span><span class="lobby-events__name">Live Jazz — Lobby Bar</span></div></div></div>';
|
||
$lb .= '</div>';
|
||
$lb .= '<div class="lobby-wifi">Wi-Fi: <strong>GrandGuest</strong></div>';
|
||
$lb .= '</div>';
|
||
$lb .= '</div>';
|
||
$visual_html = $lb;
|
||
$visual_cls = 'platform-visual has-lobby';
|
||
}
|
||
elseif (!empty($a['conferenceAnim'])) {
|
||
/* ── Conference Room Door Panel ── */
|
||
$cf = '<div class="conf-stage" aria-hidden="true">';
|
||
$cf .= '<div class="conf-panel">';
|
||
$cf .= '<div class="conf-panel__room">Boardroom A</div>';
|
||
$cf .= '<div class="conf-panel__status"><span class="conf-status__dot"></span>In Use</div>';
|
||
$cf .= '<div class="conf-panel__current"><div class="conf-current__label">Current Session</div><div class="conf-current__title">Q1 Strategy Review</div><div class="conf-current__meta">09:00 – 10:30 · Sarah Mitchell</div></div>';
|
||
$cf .= '<div class="conf-panel__timeline">';
|
||
$cf .= '<div class="conf-tl__bar"><div class="conf-tl__fill"></div></div>';
|
||
$cf .= '</div>';
|
||
$cf .= '<div class="conf-panel__next"><span class="conf-next__label">Next:</span> <span class="conf-next__title">Design Sprint Kickoff</span> <span class="conf-next__time">11:00</span></div>';
|
||
$cf .= '</div>';
|
||
$cf .= '</div>';
|
||
$visual_html = $cf;
|
||
$visual_cls = 'platform-visual has-conference';
|
||
}
|
||
elseif (!empty($a['dayPartAnim'])) {
|
||
/* ── Day-Part Retail Promo Display (JS-driven clock) ── */
|
||
$dp = '<div class="daypart-stage" aria-hidden="true">';
|
||
$dp .= '<div class="daypart-screen">';
|
||
$dp .= '<div class="daypart-hdr"><span class="daypart-hdr__clock" data-daypart-clock>12:00</span><span class="daypart-hdr__badge" data-daypart-badge>Afternoon</span></div>';
|
||
$dp .= '<div class="daypart-slides">';
|
||
$dp .= '<div class="daypart-slide daypart-slide--morning"><div class="daypart-promo__tag">Morning</div><div class="daypart-promo__title">Breakfast Deals</div><div class="daypart-promo__sub">Fresh pastries & coffee combos from $4.99</div></div>';
|
||
$dp .= '<div class="daypart-slide daypart-slide--afternoon"><div class="daypart-promo__tag">Afternoon</div><div class="daypart-promo__title">Lunch Specials</div><div class="daypart-promo__sub">Meal deals & combo offers until 4 PM</div></div>';
|
||
$dp .= '<div class="daypart-slide daypart-slide--evening"><div class="daypart-promo__tag">Evening</div><div class="daypart-promo__title">Happy Hour</div><div class="daypart-promo__sub">2-for-1 drinks & 20% off appetisers</div></div>';
|
||
$dp .= '</div>';
|
||
$dp .= '</div>';
|
||
$dp .= '</div>';
|
||
$visual_html = $dp;
|
||
$visual_cls = 'platform-visual has-daypart';
|
||
}
|
||
elseif (!empty($a['wayfindAnim'])) {
|
||
/* ── In-Store Wayfinding Kiosk ── */
|
||
$wf = '<div class="wayfind-stage" aria-hidden="true">';
|
||
$wf .= '<div class="wayfind-kiosk">';
|
||
$wf .= '<div class="wayfind-kiosk__search"><span class="wayfind-search__icon">🔍</span><span class="wayfind-search__text">Search departments...</span></div>';
|
||
$wf .= '<div class="wayfind-kiosk__map">';
|
||
$wf .= '<div class="wayfind-zone wayfind-zone--a">Fashion</div>';
|
||
$wf .= '<div class="wayfind-zone wayfind-zone--b">Electronics</div>';
|
||
$wf .= '<div class="wayfind-zone wayfind-zone--c">Home</div>';
|
||
$wf .= '<div class="wayfind-zone wayfind-zone--d">Food Hall</div>';
|
||
$wf .= '<div class="wayfind-pin"><span class="wayfind-pin__dot"></span><span class="wayfind-pin__label">You are here</span></div>';
|
||
$wf .= '</div>';
|
||
$wf .= '<div class="wayfind-kiosk__dir">';
|
||
$wf .= '<div class="wayfind-dir__item"><span class="wayfind-dir__arrow">↑</span> Fashion — Level 1</div>';
|
||
$wf .= '<div class="wayfind-dir__item"><span class="wayfind-dir__arrow">→</span> Electronics — Level 2</div>';
|
||
$wf .= '<div class="wayfind-dir__item"><span class="wayfind-dir__arrow">↓</span> Food Hall — Ground</div>';
|
||
$wf .= '</div>';
|
||
$wf .= '</div>';
|
||
$wf .= '</div>';
|
||
$visual_html = $wf;
|
||
$visual_cls = 'platform-visual has-wayfind';
|
||
}
|
||
elseif (!empty($a['storefrontAnim'])) {
|
||
/* ── Window / Storefront Display ── */
|
||
$sf = '<div class="store-stage" aria-hidden="true">';
|
||
$sf .= '<div class="store-window">';
|
||
$sf .= '<div class="store-window__sun"></div>';
|
||
$sf .= '<div class="store-window__screen">';
|
||
$sf .= '<div class="store-slides">';
|
||
$sf .= '<div class="store-slide store-slide--new"><div class="store-slide__tag">New Arrivals</div><div class="store-slide__title">Spring Collection</div><div class="store-slide__cta">Shop Now →</div></div>';
|
||
$sf .= '<div class="store-slide store-slide--sale"><div class="store-slide__tag">Limited Time</div><div class="store-slide__title">Up to 50% Off</div><div class="store-slide__cta">View Offers →</div></div>';
|
||
$sf .= '<div class="store-slide store-slide--hours"><div class="store-slide__tag">Opening Hours</div><div class="store-slide__title">Mon–Sat 9am–9pm</div><div class="store-slide__sub">Sunday 10am–6pm</div></div>';
|
||
$sf .= '</div>';
|
||
$sf .= '</div>';
|
||
$sf .= '<div class="store-window__glare"></div>';
|
||
$sf .= '</div>';
|
||
$sf .= '</div>';
|
||
$visual_html = $sf;
|
||
$visual_cls = 'platform-visual has-storefront';
|
||
}
|
||
elseif (!empty($a['announcementAnim'])) {
|
||
/* ── Corporate Announcement Board ── */
|
||
$an = '<div class="announce-stage" aria-hidden="true">';
|
||
$an .= '<div class="announce-board">';
|
||
$an .= '<div class="announce-hdr"><span class="announce-hdr__title">Company Updates</span><span class="announce-hdr__live">● Live</span></div>';
|
||
$an .= '<div class="announce-cards">';
|
||
$an .= '<div class="announce-card announce-card--urgent"><div class="announce-card__badge">Urgent</div><div class="announce-card__title">Fire Drill — 2 PM Today</div><div class="announce-card__body">All staff evacuate via nearest exit. Assembly point: Car Park B.</div></div>';
|
||
$an .= '<div class="announce-card announce-card--celebration"><div class="announce-card__badge">Celebration</div><div class="announce-card__title">Welcome New Starters!</div><div class="announce-card__body">Say hello to 5 new team members joining Engineering & Design.</div></div>';
|
||
$an .= '<div class="announce-card announce-card--hr"><div class="announce-card__badge">HR Notice</div><div class="announce-card__title">Benefits Enrolment Open</div><div class="announce-card__body">Deadline: March 31. Visit the HR portal to review your options.</div></div>';
|
||
$an .= '</div>';
|
||
$an .= '</div>';
|
||
$an .= '</div>';
|
||
$visual_html = $an;
|
||
$visual_cls = 'platform-visual has-announcement';
|
||
}
|
||
elseif (!empty($a['campusWayfindAnim'])) {
|
||
/* ── Campus Wayfinding Kiosk ── */
|
||
$cw = '<div class="campus-stage" aria-hidden="true">';
|
||
$cw .= '<div class="campus-kiosk">';
|
||
$cw .= '<div class="campus-kiosk__hdr">Campus Directory</div>';
|
||
$cw .= '<div class="campus-kiosk__search"><span class="campus-search__icon">🔍</span><span class="campus-search__text">Find a building...</span></div>';
|
||
$cw .= '<div class="campus-kiosk__map">';
|
||
$cw .= '<div class="campus-bldg campus-bldg--lib">Library</div>';
|
||
$cw .= '<div class="campus-bldg campus-bldg--sci">Science</div>';
|
||
$cw .= '<div class="campus-bldg campus-bldg--arts">Arts</div>';
|
||
$cw .= '<div class="campus-bldg campus-bldg--sports">Sports</div>';
|
||
$cw .= '<div class="campus-pin"><span class="campus-pin__dot"></span></div>';
|
||
$cw .= '</div>';
|
||
$cw .= '<div class="campus-kiosk__legend"><span class="campus-legend__dot campus-legend__dot--you"></span> You are here</div>';
|
||
$cw .= '</div>';
|
||
$cw .= '</div>';
|
||
$visual_html = $cw;
|
||
$visual_cls = 'platform-visual has-campus-wayfind';
|
||
}
|
||
elseif (!empty($a['emergencyAnim'])) {
|
||
/* ── Emergency Override Alert ── */
|
||
$em = '<div class="emerg-stage" aria-hidden="true">';
|
||
$em .= '<div class="emerg-screen">';
|
||
$em .= '<div class="emerg-screen__normal">';
|
||
$em .= '<div class="emerg-normal__hdr">Campus Notices</div>';
|
||
$em .= '<div class="emerg-normal__item">Library open until 10 PM</div>';
|
||
$em .= '<div class="emerg-normal__item">Café special: Flat white $3</div>';
|
||
$em .= '</div>';
|
||
$em .= '<div class="emerg-screen__alert">';
|
||
$em .= '<div class="emerg-alert__icon">⚠</div>';
|
||
$em .= '<div class="emerg-alert__title">EMERGENCY ALERT</div>';
|
||
$em .= '<div class="emerg-alert__msg">Building lockdown in effect. Remain indoors. Follow staff instructions.</div>';
|
||
$em .= '<div class="emerg-alert__pulse"></div>';
|
||
$em .= '</div>';
|
||
$em .= '</div>';
|
||
$em .= '</div>';
|
||
$visual_html = $em;
|
||
$visual_cls = 'platform-visual has-emergency';
|
||
}
|
||
elseif (!empty($a['enclosureAnim'])) {
|
||
/* ── Outdoor Weather-Resistant Enclosure ── */
|
||
$en = '<div class="encl-stage" aria-hidden="true">';
|
||
$en .= '<div class="encl-rain">';
|
||
for ($i = 0; $i < 12; $i++) {
|
||
$en .= '<div class="encl-rain__drop"></div>';
|
||
}
|
||
$en .= '</div>';
|
||
$en .= '<div class="encl-unit">';
|
||
$en .= '<div class="encl-unit__body">';
|
||
$en .= '<div class="encl-unit__screen"><div class="encl-screen__content">Your Content Here</div></div>';
|
||
$en .= '</div>';
|
||
$en .= '<div class="encl-unit__badge">IP65</div>';
|
||
$en .= '<div class="encl-unit__temp"><span class="encl-temp__icon">🌡</span> <span class="encl-temp__range">-20°C to 50°C</span></div>';
|
||
$en .= '</div>';
|
||
$en .= '</div>';
|
||
$visual_html = $en;
|
||
$visual_cls = 'platform-visual has-enclosure';
|
||
}
|
||
elseif (!empty($a['brightnessAnim'])) {
|
||
/* ── High-Brightness Comparison ── */
|
||
$br = '<div class="bright-stage" aria-hidden="true">';
|
||
$br .= '<div class="bright-sun"></div>';
|
||
$br .= '<div class="bright-compare">';
|
||
$br .= '<div class="bright-panel bright-panel--indoor"><div class="bright-panel__screen bright-panel__screen--dim"><span class="bright-panel__text">Hello World</span></div><div class="bright-panel__label">Indoor 350 nits</div></div>';
|
||
$br .= '<div class="bright-vs">vs</div>';
|
||
$br .= '<div class="bright-panel bright-panel--outdoor"><div class="bright-panel__screen bright-panel__screen--vivid"><span class="bright-panel__text">Hello World</span></div><div class="bright-panel__label">Outdoor 2,500+ nits</div></div>';
|
||
$br .= '</div>';
|
||
$br .= '</div>';
|
||
$visual_html = $br;
|
||
$visual_cls = 'platform-visual has-brightness';
|
||
}
|
||
elseif (!empty($a['cellularAnim'])) {
|
||
/* ── Cellular Connectivity Tower ── */
|
||
$cl = '<div class="cell-stage" aria-hidden="true">';
|
||
$cl .= '<div class="cell-tower">';
|
||
$cl .= '<div class="cell-tower__mast"></div>';
|
||
$cl .= '<div class="cell-tower__base"></div>';
|
||
$cl .= '<div class="cell-wave cell-wave--1"></div>';
|
||
$cl .= '<div class="cell-wave cell-wave--2"></div>';
|
||
$cl .= '<div class="cell-wave cell-wave--3"></div>';
|
||
$cl .= '</div>';
|
||
$cl .= '<div class="cell-badge">4G / 5G</div>';
|
||
$cl .= '<div class="cell-signal"><div class="cell-signal__bar cell-signal__bar--1"></div><div class="cell-signal__bar cell-signal__bar--2"></div><div class="cell-signal__bar cell-signal__bar--3"></div><div class="cell-signal__bar cell-signal__bar--4"></div></div>';
|
||
$cl .= '<div class="cell-status">Connected ●</div>';
|
||
$cl .= '</div>';
|
||
$visual_html = $cl;
|
||
$visual_cls = 'platform-visual has-cellular';
|
||
}
|
||
elseif (!empty($a['designerAnim'])) {
|
||
/* ── Drag-and-Drop Editor Canvas ── */
|
||
$ds = '<div class="designer-stage" aria-hidden="true">';
|
||
$ds .= '<div class="designer-editor">';
|
||
$ds .= '<div class="designer-toolbar"><span class="designer-tool">T</span><span class="designer-tool">□</span><span class="designer-tool">▶</span><span class="designer-tool">⋯</span></div>';
|
||
$ds .= '<div class="designer-canvas">';
|
||
$ds .= '<div class="designer-widget designer-widget--text"><span class="designer-widget__label">Heading</span></div>';
|
||
$ds .= '<div class="designer-widget designer-widget--img"><span class="designer-widget__label">Image</span></div>';
|
||
$ds .= '<div class="designer-widget designer-widget--ticker"><span class="designer-widget__label">Ticker</span></div>';
|
||
$ds .= '<div class="designer-widget designer-widget--video"><span class="designer-widget__label">Video</span></div>';
|
||
$ds .= '</div>';
|
||
$ds .= '<div class="designer-layers"><div class="designer-layers__title">Layers</div><div class="designer-layer">Heading</div><div class="designer-layer">Image</div><div class="designer-layer">Ticker</div><div class="designer-layer">Video</div></div>';
|
||
$ds .= '</div>';
|
||
$ds .= '</div>';
|
||
$visual_html = $ds;
|
||
$visual_cls = 'platform-visual has-designer';
|
||
}
|
||
elseif (!empty($a['mediaLibraryAnim'])) {
|
||
/* ── Media Library Grid ── */
|
||
$ml = '<div class="medialib-stage" aria-hidden="true">';
|
||
$ml .= '<div class="medialib-panel">';
|
||
$ml .= '<div class="medialib-hdr"><span class="medialib-hdr__title">Media Library</span><span class="medialib-hdr__count">24 assets</span></div>';
|
||
$ml .= '<div class="medialib-grid">';
|
||
$ml .= '<div class="medialib-thumb medialib-thumb--img"><span class="medialib-thumb__icon">📷</span></div>';
|
||
$ml .= '<div class="medialib-thumb medialib-thumb--vid"><span class="medialib-thumb__icon">▶</span></div>';
|
||
$ml .= '<div class="medialib-thumb medialib-thumb--pdf"><span class="medialib-thumb__icon">PDF</span></div>';
|
||
$ml .= '<div class="medialib-thumb medialib-thumb--ppt"><span class="medialib-thumb__icon">PPT</span></div>';
|
||
$ml .= '<div class="medialib-thumb medialib-thumb--img2"><span class="medialib-thumb__icon">📷</span></div>';
|
||
$ml .= '<div class="medialib-thumb medialib-thumb--audio"><span class="medialib-thumb__icon">♫</span></div>';
|
||
$ml .= '</div>';
|
||
$ml .= '<div class="medialib-upload"><div class="medialib-upload__bar"></div><span class="medialib-upload__text">Uploading...</span></div>';
|
||
$ml .= '</div>';
|
||
$ml .= '</div>';
|
||
$visual_html = $ml;
|
||
$visual_cls = 'platform-visual has-media-library';
|
||
}
|
||
elseif (!empty($a['publishAnim'])) {
|
||
/* ── Draft → Publish Workflow ── */
|
||
$pb = '<div class="publish-stage" aria-hidden="true">';
|
||
$pb .= '<div class="publish-flow">';
|
||
$pb .= '<div class="publish-step publish-step--draft"><span class="publish-step__badge">Draft</span><span class="publish-step__label">Edit safely</span></div>';
|
||
$pb .= '<div class="publish-arrow">→</div>';
|
||
$pb .= '<div class="publish-step publish-step--review"><span class="publish-step__badge">Review</span><span class="publish-step__label">Preview on screen</span></div>';
|
||
$pb .= '<div class="publish-arrow">→</div>';
|
||
$pb .= '<div class="publish-step publish-step--live"><span class="publish-step__badge">Live</span><span class="publish-step__label">Instant publish</span></div>';
|
||
$pb .= '</div>';
|
||
$pb .= '<div class="publish-bar"><div class="publish-bar__fill"></div></div>';
|
||
$pb .= '<div class="publish-status">Publishing to 48 screens...</div>';
|
||
$pb .= '</div>';
|
||
$visual_html = $pb;
|
||
$visual_cls = 'platform-visual has-publish';
|
||
}
|
||
elseif (!empty($a['screenGroupsAnim'])) {
|
||
/* ── Screen Group Hierarchy Tree ── */
|
||
$sg = '<div class="groups-stage" aria-hidden="true">';
|
||
$sg .= '<div class="groups-tree">';
|
||
$sg .= '<div class="groups-node groups-node--root"><span class="groups-node__icon">●</span><span class="groups-node__name">HQ</span><span class="groups-node__count">48</span></div>';
|
||
$sg .= '<div class="groups-branch">';
|
||
$sg .= '<div class="groups-node groups-node--region"><span class="groups-node__icon">●</span><span class="groups-node__name">London</span><span class="groups-node__count">24</span></div>';
|
||
$sg .= '<div class="groups-branch groups-branch--deep">';
|
||
$sg .= '<div class="groups-node groups-node--site"><span class="groups-node__icon">●</span><span class="groups-node__name">Oxford St</span><span class="groups-node__count">12</span></div>';
|
||
$sg .= '<div class="groups-node groups-node--site"><span class="groups-node__icon">●</span><span class="groups-node__name">Canary Wharf</span><span class="groups-node__count">12</span></div>';
|
||
$sg .= '</div>';
|
||
$sg .= '<div class="groups-node groups-node--region"><span class="groups-node__icon">●</span><span class="groups-node__name">Manchester</span><span class="groups-node__count">24</span></div>';
|
||
$sg .= '</div>';
|
||
$sg .= '</div>';
|
||
$sg .= '<div class="groups-push"><div class="groups-push__ripple"></div><span class="groups-push__label">Push Update</span></div>';
|
||
$sg .= '</div>';
|
||
$visual_html = $sg;
|
||
$visual_cls = 'platform-visual has-screen-groups';
|
||
}
|
||
elseif (!empty($a['monitoringAnim'])) {
|
||
/* ── Remote Monitoring Dashboard ── */
|
||
$mo = '<div class="monitor-stage" aria-hidden="true">';
|
||
$mo .= '<div class="monitor-dash">';
|
||
$mo .= '<div class="monitor-hdr"><span class="monitor-hdr__title">Display Status</span><span class="monitor-hdr__count">48/48 Online</span></div>';
|
||
$mo .= '<div class="monitor-grid">';
|
||
$mo .= '<div class="monitor-tile monitor-tile--ok"><span class="monitor-tile__dot"></span><span class="monitor-tile__name">Lobby-01</span></div>';
|
||
$mo .= '<div class="monitor-tile monitor-tile--ok"><span class="monitor-tile__dot"></span><span class="monitor-tile__name">Lobby-02</span></div>';
|
||
$mo .= '<div class="monitor-tile monitor-tile--warn"><span class="monitor-tile__dot"></span><span class="monitor-tile__name">Floor3-01</span></div>';
|
||
$mo .= '<div class="monitor-tile monitor-tile--ok"><span class="monitor-tile__dot"></span><span class="monitor-tile__name">Café-01</span></div>';
|
||
$mo .= '<div class="monitor-tile monitor-tile--ok"><span class="monitor-tile__dot"></span><span class="monitor-tile__name">Conf-A</span></div>';
|
||
$mo .= '<div class="monitor-tile monitor-tile--ok"><span class="monitor-tile__dot"></span><span class="monitor-tile__name">Conf-B</span></div>';
|
||
$mo .= '</div>';
|
||
$mo .= '<div class="monitor-screenshot"><div class="monitor-screenshot__img"></div><span class="monitor-screenshot__label">Live Screenshot — Lobby-01</span></div>';
|
||
$mo .= '</div>';
|
||
$mo .= '</div>';
|
||
$visual_html = $mo;
|
||
$visual_cls = 'platform-visual has-monitoring';
|
||
}
|
||
elseif (!empty($a['patientWayfindAnim'])) {
|
||
/* ── Hospital Patient Wayfinding Kiosk ── */
|
||
$pw = '<div class="pwayfind-stage" aria-hidden="true">';
|
||
$pw .= '<div class="pwayfind-kiosk">';
|
||
$pw .= '<div class="pwayfind-hdr"><span class="pwayfind-hdr__title">Find Department</span><span class="pwayfind-hdr__a11y">♿</span></div>';
|
||
$pw .= '<div class="pwayfind-search"><span class="pwayfind-search__icon">🔍</span><span class="pwayfind-search__text">Cardiology...</span></div>';
|
||
$pw .= '<div class="pwayfind-result">';
|
||
$pw .= '<div class="pwayfind-result__dept">Cardiology — Level 3, Wing B</div>';
|
||
$pw .= '<div class="pwayfind-result__route"><div class="pwayfind-route__line"></div><div class="pwayfind-route__start">You are here</div><div class="pwayfind-route__end">Cardiology</div></div>';
|
||
$pw .= '</div>';
|
||
$pw .= '<div class="pwayfind-quick"><span class="pwayfind-quick__item">A&E</span><span class="pwayfind-quick__item">Pharmacy</span><span class="pwayfind-quick__item">Radiology</span></div>';
|
||
$pw .= '</div>';
|
||
$pw .= '</div>';
|
||
$visual_html = $pw;
|
||
$visual_cls = 'platform-visual has-patient-wayfind';
|
||
}
|
||
elseif (!empty($a['waitingRoomAnim'])) {
|
||
/* ── Waiting Room Information Display ── */
|
||
$wr = '<div class="waitroom-stage" aria-hidden="true">';
|
||
$wr .= '<div class="waitroom-tv">';
|
||
$wr .= '<div class="waitroom-tv__body">';
|
||
$wr .= '<div class="waitroom-tv__screen">';
|
||
$wr .= '<div class="waitroom-slides">';
|
||
$wr .= '<div class="waitroom-slide waitroom-slide--tips"><div class="waitroom-tips__title">Health Tip</div><div class="waitroom-tips__text">Regular hand washing reduces infection spread by up to 50%</div></div>';
|
||
$wr .= '<div class="waitroom-slide waitroom-slide--wait"><div class="waitroom-wait__title">Estimated Wait</div><div class="waitroom-wait__value">~15 min</div><div class="waitroom-wait__queue">Position: 4 of 12</div></div>';
|
||
$wr .= '<div class="waitroom-slide waitroom-slide--info"><div class="waitroom-info__title">Facility Hours</div><div class="waitroom-info__text">Mon–Fri: 8am – 8pm<br>Sat: 9am – 1pm</div></div>';
|
||
$wr .= '</div>';
|
||
$wr .= '</div>';
|
||
$wr .= '</div>';
|
||
$wr .= '<div class="waitroom-tv__feet"><div class="waitroom-tv__foot"></div><div class="waitroom-tv__foot"></div></div>';
|
||
$wr .= '</div>';
|
||
$wr .= '</div>';
|
||
$visual_html = $wr;
|
||
$visual_cls = 'platform-visual has-waiting-room';
|
||
}
|
||
elseif (!empty($a['multiZoneAnim'])) {
|
||
/* ── Multi-Zone Layout Display ── */
|
||
$mz = '<div class="mzone-stage" aria-hidden="true">';
|
||
$mz .= '<div class="mzone-tv">';
|
||
$mz .= '<div class="mzone-tv__body">';
|
||
$mz .= '<div class="mzone-tv__screen">';
|
||
$mz .= '<div class="mzone-layout">';
|
||
$mz .= '<div class="mzone-main"><div class="mzone-main__label">▶ Live TV</div></div>';
|
||
$mz .= '<div class="mzone-side"><div class="mzone-side__title">Class Schedule</div><div class="mzone-side__item">10:00 Spin</div><div class="mzone-side__item">11:15 Yoga</div><div class="mzone-side__item">12:30 HIIT</div></div>';
|
||
$mz .= '<div class="mzone-ticker">★ Member of the Month: Alex R | Gym closes 10 PM tonight | New PT packages available</div>';
|
||
$mz .= '</div>';
|
||
$mz .= '</div>';
|
||
$mz .= '</div>';
|
||
$mz .= '<div class="mzone-tv__feet"><div class="mzone-tv__foot"></div><div class="mzone-tv__foot"></div></div>';
|
||
$mz .= '</div>';
|
||
$mz .= '</div>';
|
||
$visual_html = $mz;
|
||
$visual_cls = 'platform-visual has-multi-zone';
|
||
}
|
||
elseif (!empty($a['membershipAnim'])) {
|
||
/* ── Seasonal Membership Promo Cycling ── */
|
||
$mb = '<div class="member-stage" aria-hidden="true">';
|
||
$mb .= '<div class="member-screen">';
|
||
$mb .= '<div class="member-slides">';
|
||
$mb .= '<div class="member-slide member-slide--jan"><div class="member-slide__tag">January Offer</div><div class="member-slide__title">New Year, New You</div><div class="member-slide__price">Join from $29/mo</div><div class="member-slide__cta">Sign Up Today →</div></div>';
|
||
$mb .= '<div class="member-slide member-slide--summer"><div class="member-slide__tag">Summer Special</div><div class="member-slide__title">Get Beach Ready</div><div class="member-slide__price">3 months for $79</div><div class="member-slide__cta">Claim Offer →</div></div>';
|
||
$mb .= '<div class="member-slide member-slide--sept"><div class="member-slide__tag">Back to Fitness</div><div class="member-slide__title">Bring a Friend Free</div><div class="member-slide__price">This week only</div><div class="member-slide__cta">Book Now →</div></div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
$visual_html = $mb;
|
||
$visual_cls = 'platform-visual has-membership';
|
||
}
|
||
elseif (!empty($a['hospitalityAnim'])) {
|
||
/* ── Hospitality Sign: Rotating Menu (Breakfast, Lunch, Dinner) ── */
|
||
$ha = '<div class="hosp-stage" aria-hidden="true">';
|
||
$ha .= '<div class="hosp-tv">';
|
||
$ha .= '<div class="hosp-tv__body">';
|
||
$ha .= '<div class="hosp-tv__screen">';
|
||
|
||
// POS Sync Overlay (Pulse)
|
||
$ha .= '<div class="hosp-pos"><div class="hosp-pos__dot"></div><div class="hosp-pos__txt">POS Syncing...</div></div>';
|
||
|
||
$ha .= '<div class="hosp-slides">';
|
||
|
||
// Slide 1: Breakfast
|
||
$ha .= '<div class="hosp-slide hosp-slide--breakfast">';
|
||
$ha .= '<div class="hosp-menu">';
|
||
$ha .= '<div class="hosp-menu__hd"><div class="hosp-menu__badge">Breakfast</div><div class="hosp-menu__time">6am – 11am</div></div>';
|
||
$ha .= '<div class="hosp-menu__title">Morning Classics</div>';
|
||
$ha .= '<div class="hosp-menu__items">';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Eggs Benedict</div><div class="hosp-menu__desc">Hollandaise, smoked ham</div></div><div class="hosp-menu__price">$16</div></div>';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Avocado Toast</div><div class="hosp-menu__desc">Sourdough, chili flakes</div></div><div class="hosp-menu__price">$14</div></div>';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Buttermilk Stacks</div><div class="hosp-menu__desc">Maple syrup, berries</div></div><div class="hosp-menu__price">$12</div></div>';
|
||
$ha .= '</div>';
|
||
$ha .= '</div>';
|
||
$ha .= '</div>';
|
||
|
||
// Slide 2: Lunch
|
||
$ha .= '<div class="hosp-slide hosp-slide--lunch">';
|
||
$ha .= '<div class="hosp-menu">';
|
||
$ha .= '<div class="hosp-menu__hd"><div class="hosp-menu__badge">Lunch</div><div class="hosp-menu__time">12pm – 4pm</div></div>';
|
||
$ha .= '<div class="hosp-menu__title">Fresh & Seasonal</div>';
|
||
$ha .= '<div class="hosp-menu__items">';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Wagyu Burger</div><div class="hosp-menu__desc">Brioche, truffle aioli</div></div><div class="hosp-menu__price">$22</div></div>';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Harvest Bowl</div><div class="hosp-menu__desc">Quinoa, roasted veg</div></div><div class="hosp-menu__price">$18</div></div>';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Grilled Salmon</div><div class="hosp-menu__desc">Lemon, asparagus</div></div><div class="hosp-menu__price">$24</div></div>';
|
||
$ha .= '</div>';
|
||
$ha .= '</div>';
|
||
$ha .= '</div>';
|
||
|
||
// Slide 3: Dinner
|
||
$ha .= '<div class="hosp-slide hosp-slide--dinner">';
|
||
$ha .= '<div class="hosp-menu">';
|
||
$ha .= '<div class="hosp-menu__hd"><div class="hosp-menu__badge">Dinner</div><div class="hosp-menu__time">5pm – late</div></div>';
|
||
$ha .= '<div class="hosp-menu__title">Evening Specials</div>';
|
||
$ha .= '<div class="hosp-menu__items">';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Ribeye Steak</div><div class="hosp-menu__desc">Garlic butter, frites</div></div><div class="hosp-menu__price">$38</div></div>';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Lobster Pasta</div><div class="hosp-menu__desc">Bisque, fresh herbs</div></div><div class="hosp-menu__price">$32</div></div>';
|
||
$ha .= '<div class="hosp-menu__item"><div class="hosp-menu__info"><div class="hosp-menu__name">Rack of Lamb</div><div class="hosp-menu__desc">Mint jus, pea purée</div></div><div class="hosp-menu__price">$36</div></div>';
|
||
$ha .= '</div>';
|
||
$ha .= '</div>';
|
||
$ha .= '</div>';
|
||
|
||
$ha .= '</div>'; // hosp-slides
|
||
$ha .= '</div>'; // hosp-tv__screen
|
||
$ha .= '</div>'; // hosp-tv__body
|
||
$ha .= '<div class="hosp-tv__feet"><div class="hosp-tv__foot"></div><div class="hosp-tv__foot"></div></div>';
|
||
$ha .= '</div>'; // hosp-tv
|
||
$ha .= '</div>'; // hosp-stage
|
||
|
||
$visual_html = $ha;
|
||
$visual_cls = 'platform-visual has-hospitality';
|
||
}
|
||
elseif (!empty($a['videoMotionAnim'])) {
|
||
/* ── Video & Motion Graphics: TV with kinetic text, promo, loop preview ── */
|
||
$vm = '<div class="vidmo-stage" aria-hidden="true">';
|
||
$vm .= '<div class="vidmo-tv">';
|
||
$vm .= '<div class="vidmo-tv__body">';
|
||
$vm .= '<div class="vidmo-tv__screen">';
|
||
$vm .= '<div class="vidmo-slides">';
|
||
|
||
/* Slide 1: Kinetic typography */
|
||
$vm .= '<div class="vidmo-slide vidmo-slide--kinetic">';
|
||
$vm .= '<div class="vidmo-kinetic">';
|
||
$vm .= '<span class="vidmo-kinetic__word vidmo-kinetic__word--1">Engage</span>';
|
||
$vm .= '<span class="vidmo-kinetic__word vidmo-kinetic__word--2">Inform</span>';
|
||
$vm .= '<span class="vidmo-kinetic__word vidmo-kinetic__word--3">Convert</span>';
|
||
$vm .= '</div>';
|
||
$vm .= '</div>';
|
||
|
||
/* Slide 2: Promo graphic */
|
||
$vm .= '<div class="vidmo-slide vidmo-slide--promo">';
|
||
$vm .= '<div class="vidmo-promo">';
|
||
$vm .= '<div class="vidmo-promo__bg"></div>';
|
||
$vm .= '<div class="vidmo-promo__label">Summer Campaign</div>';
|
||
$vm .= '<div class="vidmo-promo__title">Your Brand, Animated</div>';
|
||
$vm .= '<div class="vidmo-promo__sub">15s promotional loop</div>';
|
||
$vm .= '</div>';
|
||
$vm .= '</div>';
|
||
|
||
/* Slide 3: Loop format */
|
||
$vm .= '<div class="vidmo-slide vidmo-slide--loop">';
|
||
$vm .= '<div class="vidmo-loop">';
|
||
$vm .= '<div class="vidmo-loop__icon">▶</div>';
|
||
$vm .= '<div class="vidmo-loop__text">Screen-Ready Formats</div>';
|
||
$vm .= '<div class="vidmo-loop__formats">';
|
||
$vm .= '<span class="vidmo-loop__fmt">MP4</span>';
|
||
$vm .= '<span class="vidmo-loop__fmt">WEBM</span>';
|
||
$vm .= '<span class="vidmo-loop__fmt">GIF</span>';
|
||
$vm .= '</div>';
|
||
$vm .= '</div>';
|
||
$vm .= '</div>';
|
||
|
||
$vm .= '</div>'; // vidmo-slides
|
||
$vm .= '<div class="vidmo-progress"><div class="vidmo-progress__bar"></div></div>';
|
||
$vm .= '</div>'; // vidmo-tv__screen
|
||
$vm .= '</div>'; // vidmo-tv__body
|
||
$vm .= '<div class="vidmo-tv__feet"><div class="vidmo-tv__foot"></div><div class="vidmo-tv__foot"></div></div>';
|
||
$vm .= '</div>'; // vidmo-tv
|
||
$vm .= '</div>'; // vidmo-stage
|
||
|
||
$visual_html = $vm;
|
||
$visual_cls = 'platform-visual has-video-motion';
|
||
}
|
||
elseif (!empty($a['brandLayoutAnim'])) {
|
||
/* ── Branded Layout Design: template builder with brand guide ── */
|
||
$bl = '<div class="blay-stage" aria-hidden="true">';
|
||
$bl .= '<div class="blay-editor">';
|
||
|
||
/* Toolbar */
|
||
$bl .= '<div class="blay-toolbar">';
|
||
$bl .= '<div class="blay-toolbar__dots">';
|
||
$bl .= '<span class="blay-toolbar__dot blay-toolbar__dot--r"></span>';
|
||
$bl .= '<span class="blay-toolbar__dot blay-toolbar__dot--y"></span>';
|
||
$bl .= '<span class="blay-toolbar__dot blay-toolbar__dot--g"></span>';
|
||
$bl .= '</div>';
|
||
$bl .= '<div class="blay-toolbar__title">Layout Editor</div>';
|
||
$bl .= '</div>';
|
||
|
||
/* Body: canvas + panel */
|
||
$bl .= '<div class="blay-body">';
|
||
|
||
/* Canvas */
|
||
$bl .= '<div class="blay-canvas">';
|
||
$bl .= '<div class="blay-preview">';
|
||
$bl .= '<div class="blay-el blay-el--logo"></div>';
|
||
$bl .= '<div class="blay-el blay-el--hero"></div>';
|
||
$bl .= '<div class="blay-el blay-el--headline"></div>';
|
||
$bl .= '<div class="blay-el blay-el--body"></div>';
|
||
$bl .= '<div class="blay-el blay-el--body2"></div>';
|
||
$bl .= '<div class="blay-el blay-el--cta"></div>';
|
||
$bl .= '<div class="blay-el blay-el--accent"></div>';
|
||
$bl .= '</div>';
|
||
$bl .= '</div>';
|
||
|
||
/* Brand guide panel */
|
||
$bl .= '<div class="blay-panel">';
|
||
$bl .= '<div class="blay-panel__title">Brand Guide</div>';
|
||
$bl .= '<div class="blay-colors">';
|
||
$bl .= '<div class="blay-color blay-color--1"></div>';
|
||
$bl .= '<div class="blay-color blay-color--2"></div>';
|
||
$bl .= '<div class="blay-color blay-color--3"></div>';
|
||
$bl .= '<div class="blay-color blay-color--4"></div>';
|
||
$bl .= '</div>';
|
||
$bl .= '<div class="blay-fonts">';
|
||
$bl .= '<div class="blay-font"><span class="blay-font__label">Heading</span><span class="blay-font__sample">Aa</span></div>';
|
||
$bl .= '<div class="blay-font"><span class="blay-font__label">Body</span><span class="blay-font__sample blay-font__sample--body">Aa Bb Cc</span></div>';
|
||
$bl .= '</div>';
|
||
$bl .= '<div class="blay-spacing">';
|
||
$bl .= '<div class="blay-spacing__label">Spacing</div>';
|
||
$bl .= '<div class="blay-spacing__bars">';
|
||
$bl .= '<div class="blay-spacing__bar blay-spacing__bar--sm"></div>';
|
||
$bl .= '<div class="blay-spacing__bar blay-spacing__bar--md"></div>';
|
||
$bl .= '<div class="blay-spacing__bar blay-spacing__bar--lg"></div>';
|
||
$bl .= '<div class="blay-spacing__bar blay-spacing__bar--xl"></div>';
|
||
$bl .= '</div>';
|
||
$bl .= '</div>';
|
||
$bl .= '</div>';
|
||
|
||
$bl .= '</div>'; // blay-body
|
||
$bl .= '</div>'; // blay-editor
|
||
$bl .= '</div>'; // blay-stage
|
||
|
||
$visual_html = $bl;
|
||
$visual_cls = 'platform-visual has-brand-layout';
|
||
}
|
||
elseif (!empty($a['menuBoardAnim'])) {
|
||
/* ── Digital Menu Board: TV with rotating menu categories ── */
|
||
$mb = '<div class="menu-stage" aria-hidden="true">';
|
||
$mb .= '<div class="menu-tv">';
|
||
$mb .= '<div class="menu-tv__body">';
|
||
$mb .= '<div class="menu-tv__screen">';
|
||
|
||
/* Live badge */
|
||
$mb .= '<div class="menu-live"><span class="menu-live__dot"></span><span class="menu-live__text">LIVE</span></div>';
|
||
|
||
$mb .= '<div class="menu-slides">';
|
||
|
||
/* Slide 1: Mains */
|
||
$mb .= '<div class="menu-slide menu-slide--mains">';
|
||
$mb .= '<div class="menu-content">';
|
||
$mb .= '<div class="menu-content__hd"><span class="menu-content__badge">Lunch</span><span class="menu-content__time">11:30 AM</span></div>';
|
||
$mb .= '<div class="menu-content__title">Mains</div>';
|
||
$mb .= '<div class="menu-content__items">';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Grilled Chicken</div><div class="menu-content__desc">Herb-crusted, seasonal veg</div></div><div class="menu-content__price">$16.50</div></div>';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Wild Salmon</div><div class="menu-content__desc">Pan-seared, lemon butter</div></div><div class="menu-content__price">$22.00</div></div>';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Mushroom Risotto</div><div class="menu-content__desc">Truffle oil, parmesan</div></div><div class="menu-content__price">$14.00</div></div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
|
||
/* Slide 2: Drinks */
|
||
$mb .= '<div class="menu-slide menu-slide--drinks">';
|
||
$mb .= '<div class="menu-content">';
|
||
$mb .= '<div class="menu-content__hd"><span class="menu-content__badge">Drinks</span><span class="menu-content__time">11:30 AM</span></div>';
|
||
$mb .= '<div class="menu-content__title">Beverages</div>';
|
||
$mb .= '<div class="menu-content__items">';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Flat White</div><div class="menu-content__desc">Double shot, oat option</div></div><div class="menu-content__price">$5.50</div></div>';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Fresh Juice</div><div class="menu-content__desc">Orange, apple or green</div></div><div class="menu-content__price">$7.00</div></div>';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Sparkling Water</div><div class="menu-content__desc">750ml bottle</div></div><div class="menu-content__price">$4.00</div></div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
|
||
/* Slide 3: Desserts */
|
||
$mb .= '<div class="menu-slide menu-slide--dessert">';
|
||
$mb .= '<div class="menu-content">';
|
||
$mb .= '<div class="menu-content__hd"><span class="menu-content__badge">Dessert</span><span class="menu-content__time">11:30 AM</span></div>';
|
||
$mb .= '<div class="menu-content__title">Something Sweet</div>';
|
||
$mb .= '<div class="menu-content__items">';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Chocolate Fondant</div><div class="menu-content__desc">Molten centre, vanilla ice cream</div></div><div class="menu-content__price">$12.00</div></div>';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Crème Brûlée</div><div class="menu-content__desc">Classic vanilla, caramelised top</div></div><div class="menu-content__price">$10.00</div></div>';
|
||
$mb .= '<div class="menu-content__item"><div><div class="menu-content__name">Seasonal Fruit</div><div class="menu-content__desc">Fresh selection, honey drizzle</div></div><div class="menu-content__price">$8.00</div></div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
$mb .= '</div>';
|
||
|
||
$mb .= '</div>'; // menu-slides
|
||
$mb .= '</div>'; // menu-tv__screen
|
||
$mb .= '</div>'; // menu-tv__body
|
||
$mb .= '<div class="menu-tv__feet"><div class="menu-tv__foot"></div><div class="menu-tv__foot"></div></div>';
|
||
$mb .= '</div>'; // menu-tv
|
||
$mb .= '</div>'; // menu-stage
|
||
|
||
$visual_html = $mb;
|
||
$visual_cls = 'platform-visual has-menu-board';
|
||
}
|
||
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();
|
||
}
|