2026-02-20 21:28:00 -05:00
< ? php
/**
2026-02-20 22:06:53 -05:00
* OTS Theme - Custom Gutenberg Blocks ( InnerBlocks Architecture )
2026-02-20 21:28:00 -05:00
*
* 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 ) .
*/
2026-02-23 06:57:08 -05:00
if ( ! defined ( 'ABSPATH' ))
exit ;
2026-02-20 21:28:00 -05:00
/* ══════════════════════════════════════════════════════════════════════════════
2026-02-23 06:57:08 -05:00
SHARED HELPERS
══════════════════════════════════════════════════════════════════════════════ */
2026-02-20 21:28:00 -05:00
/**
* Shared image attributes for all card blocks .
* Spread into each card 's ' attributes ' array .
*/
2026-02-23 06:57:08 -05:00
function oribi_card_image_attributes ()
{
2026-02-20 21:28:00 -05:00
return [
2026-02-23 06:57:08 -05:00
'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' ],
2026-02-20 21:28:00 -05:00
];
}
/**
* 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 ]
*/
2026-02-23 06:57:08 -05:00
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' ;
2026-02-20 21:28:00 -05:00
$result = [
2026-02-23 06:57:08 -05:00
'html' => '' ,
'position' => $img_pos ,
2026-02-20 21:28:00 -05:00
'card_class' => '' ,
];
2026-02-23 06:57:08 -05:00
if ( ! $img_url ) {
2026-02-20 21:28:00 -05:00
return $result ;
}
$result [ 'card_class' ] = 'img-' . $img_pos ;
// Build inline style for dimensions
$styles = [];
2026-02-23 06:57:08 -05:00
if ( $img_pos !== 'background' ) {
if ( $img_w > 0 )
$styles [] = 'width:' . $img_w . 'px' ;
2026-02-20 21:28:00 -05:00
$styles [] = 'max-width:100%' ;
2026-02-23 06:57:08 -05:00
if ( $img_h > 0 ) {
2026-02-20 21:28:00 -05:00
$styles [] = 'height:' . $img_h . 'px' ;
2026-02-23 06:57:08 -05:00
}
else {
2026-02-20 21:28:00 -05:00
$styles [] = 'height:auto' ;
}
}
2026-02-23 06:57:08 -05:00
$style_str = implode ( ';' , $styles );
2026-02-20 21:28:00 -05:00
2026-02-23 06:57:08 -05:00
$fit_class = 'oribi-card-img oribi-card-img--' . ( $img_pos === 'background' ? 'cover' : esc_attr ( $img_fit ));
2026-02-20 21:28:00 -05:00
2026-02-23 06:57:08 -05:00
if ( $img_id ) {
$result [ 'html' ] = wp_get_attachment_image ( $img_id , 'large' , false , [
2026-02-20 21:28:00 -05:00
'class' => $fit_class ,
'style' => $style_str ,
2026-02-23 06:57:08 -05:00
'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 ) . '">' ;
2026-02-20 21:28:00 -05:00
}
// 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 .
*/
2026-02-23 06:57:08 -05:00
function oribi_card_icon_attributes ()
{
2026-02-20 21:28:00 -05:00
return [
2026-02-23 06:57:08 -05:00
'icon' => [ 'type' => 'string' , 'default' => '' ],
'iconType' => [ 'type' => 'string' , 'default' => 'emoji' ],
'faIcon' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
];
}
/**
* Render an icon from block attributes .
*
* Accepts either :
* - iconType = 'fontawesome' + faIcon = 'fas fa-cloud' → < i class = " fas fa-cloud " ></ i >
2026-02-20 22:06:53 -05:00
* - iconType = 'emoji' + icon = 'text' -> text ( escaped )
2026-02-20 21:28:00 -05:00
*
* 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 .
*/
2026-02-23 06:57:08 -05:00
function oribi_render_icon ( $icon_or_attrs )
{
2026-02-20 21:28:00 -05:00
// Legacy string call
2026-02-23 06:57:08 -05:00
if ( is_string ( $icon_or_attrs )) {
2026-02-20 21:28:00 -05:00
$icon = $icon_or_attrs ;
2026-02-23 06:57:08 -05:00
if ( empty ( $icon ))
return '' ;
if ( preg_match ( '/^fa[srldb]\s+fa-/' , $icon )) {
return '<i class="' . esc_attr ( $icon ) . '"></i>' ;
2026-02-20 21:28:00 -05:00
}
2026-02-23 06:57:08 -05:00
return wp_kses_post ( $icon );
2026-02-20 21:28:00 -05:00
}
// Array (block attributes)
2026-02-23 06:57:08 -05:00
$a = $icon_or_attrs ;
$iconType = ! empty ( $a [ 'iconType' ]) ? $a [ 'iconType' ] : 'emoji' ;
2026-02-20 21:28:00 -05:00
2026-02-23 06:57:08 -05:00
if ( $iconType === 'fontawesome' ) {
$fa = ! empty ( $a [ 'faIcon' ]) ? trim ( $a [ 'faIcon' ]) : '' ;
if ( empty ( $fa ))
return '' ;
return '<i class="' . esc_attr ( $fa ) . '" aria-hidden="true"></i>' ;
2026-02-20 21:28:00 -05:00
}
// emoji / text
2026-02-23 06:57:08 -05:00
$icon = ! empty ( $a [ 'icon' ]) ? $a [ 'icon' ] : '' ;
if ( empty ( $icon ))
return '' ;
return wp_kses_post ( $icon );
2026-02-20 21:28:00 -05:00
}
/**
* Return true when the given block attributes specify a non - empty icon .
*/
2026-02-23 06:57:08 -05:00
function oribi_has_icon ( $a )
{
$iconType = ! empty ( $a [ 'iconType' ]) ? $a [ 'iconType' ] : 'emoji' ;
if ( $iconType === 'fontawesome' ) {
return ! empty ( $a [ 'faIcon' ]);
2026-02-20 21:28:00 -05:00
}
2026-02-23 06:57:08 -05:00
return ! empty ( $a [ 'icon' ]);
2026-02-20 21:28:00 -05:00
}
/**
* 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 .
*/
2026-02-23 06:57:08 -05:00
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 ;
2026-02-20 21:28:00 -05:00
$grid = $grid_class . '-' . $cols ;
ob_start (); ?>
2026-02-23 06:57:08 -05:00
< section class = " <?php echo esc_attr( $cls ); ?> " >
2026-02-20 21:28:00 -05:00
< div class = " container " >
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< div class = " <?php echo esc_attr( $grid ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $content ; ?>
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
/**
* Standard section attributes shared by all card section wrappers .
*/
2026-02-23 06:57:08 -05:00
function oribi_card_section_attributes ( $default_cols = 3 )
{
2026-02-20 21:28:00 -05:00
return [
2026-02-23 06:57:08 -05:00
'variant' => [ 'type' => 'string' , 'default' => 'normal' ],
'label' => [ 'type' => 'string' , 'default' => '' ],
'heading' => [ 'type' => 'string' , 'default' => '' ],
'lead' => [ 'type' => 'string' , 'default' => '' ],
'columns' => [ 'type' => 'number' , 'default' => $default_cols ],
2026-02-20 21:28:00 -05:00
];
}
/* ── Block category ────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
add_filter ( 'block_categories_all' , function ( $cats ) {
array_unshift ( $cats , [ 'slug' => 'oribi' , 'title' => 'OTS Theme' ]);
2026-02-20 21:28:00 -05:00
return $cats ;
2026-02-23 06:57:08 -05:00
});
2026-02-20 21:28:00 -05:00
/* ── Enqueue editor assets ─────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
add_action ( 'enqueue_block_editor_assets' , function () {
2026-02-20 21:28:00 -05:00
$dir = get_template_directory ();
$uri = get_template_directory_uri ();
wp_enqueue_script (
'oribi-blocks' ,
$uri . '/blocks/editor.js' ,
2026-02-23 06:57:08 -05:00
[ 'wp-blocks' , 'wp-element' , 'wp-block-editor' , 'wp-components' , 'wp-i18n' ],
filemtime ( $dir . '/blocks/editor.js' ),
2026-02-20 21:28:00 -05:00
true
);
wp_enqueue_style (
'oribi-blocks-editor' ,
$uri . '/blocks/editor.css' ,
2026-02-23 06:57:08 -05:00
[ 'wp-edit-blocks' ],
filemtime ( $dir . '/blocks/editor.css' )
2026-02-20 21:28:00 -05:00
);
2026-02-23 06:57:08 -05:00
});
2026-02-20 21:28:00 -05:00
/* ── Register all blocks ───────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
add_action ( 'init' , function () {
2026-02-20 21:28:00 -05:00
2026-02-20 22:06:53 -05:00
/* Shared supports - exposes color pickers and font - size selector in the
2026-02-23 06:57:08 -05:00
block inspector for every Oribi block . Individual blocks can override
these by merging their own array if needed . */
2026-02-20 21:28:00 -05:00
$block_supports = [
2026-02-23 06:57:08 -05:00
'color' => [
'text' => true ,
2026-02-20 21:28:00 -05:00
'background' => true ,
2026-02-23 06:57:08 -05:00
'link' => true ,
2026-02-20 21:28:00 -05:00
],
'typography' => [
2026-02-23 06:57:08 -05:00
'fontSize' => true ,
2026-02-20 21:28:00 -05:00
'lineHeight' => true ,
],
2026-02-23 06:57:08 -05:00
'spacing' => [
2026-02-20 21:28:00 -05:00
'padding' => true ,
2026-02-23 06:57:08 -05:00
'margin' => true ,
2026-02-20 21:28:00 -05:00
],
];
/* ── TEMPLATE-PART HELPER BLOCKS ──────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/site-header' , [
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_site_header' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/site-footer' , [
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_site_footer' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* ── STANDALONE BLOCKS ─────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
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' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_hero' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/page-hero' , [
'attributes' => [
'label' => [ 'type' => 'string' , 'default' => '' ],
'title' => [ 'type' => 'string' , 'default' => '' ],
'description' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_page_hero' ,
2026-02-23 06:57:08 -05:00
]);
register_block_type ( 'oribi/cta-banner' , [
'attributes' => [
'heading' => [ 'type' => 'string' , 'default' => '' ],
'text' => [ 'type' => 'string' , 'default' => '' ],
'btnText' => [ 'type' => 'string' , 'default' => '' ],
'btnUrl' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_cta_banner' ,
2026-02-23 06:57:08 -05:00
]);
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 ],
2026-02-27 17:57:59 -05:00
'cloudAnim' => [ 'type' => 'boolean' , 'default' => false ],
2026-02-23 06:57:08 -05:00
'imgId' => [ 'type' => 'number' , 'default' => 0 ],
'imgUrl' => [ 'type' => 'string' , 'default' => '' ],
'imgAlt' => [ 'type' => 'string' , 'default' => '' ],
'imgWidth' => [ 'type' => 'number' , 'default' => 280 ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_intro_section' ,
2026-02-23 06:57:08 -05:00
]);
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?' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_contact_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* ── PARENT / CHILD PAIRS ──────────────────────────────────────────────── */
/* Feature Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/feature-section' , [
'attributes' => oribi_card_section_attributes ( 3 ),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_feature_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Feature Card (child) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/feature-card' , [
'attributes' => array_merge (
[
'icon' => [ 'type' => 'string' , 'default' => '' ],
'iconType' => [ 'type' => 'string' , 'default' => 'emoji' ],
'faIcon' => [ 'type' => 'string' , 'default' => '' ],
'title' => [ 'type' => 'string' , 'default' => '' ],
'description' => [ 'type' => 'string' , 'default' => '' ],
'url' => [ 'type' => 'string' , 'default' => '' ],
'centered' => [ 'type' => 'boolean' , 'default' => false ],
],
oribi_card_image_attributes ()
),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_feature_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Value Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/value-section' , [
'attributes' => oribi_card_section_attributes ( 3 ),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_value_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Value Card (child) */
2026-02-23 06:57:08 -05:00
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 ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_value_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Addon Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/addon-section' , [
'attributes' => oribi_card_section_attributes ( 3 ),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_addon_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Addon Card (child) */
2026-02-23 06:57:08 -05:00
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 ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_addon_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Image Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/image-section' , [
'attributes' => oribi_card_section_attributes ( 3 ),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_image_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Image Card (child) */
2026-02-23 06:57:08 -05:00
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 ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_image_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Stat Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/stat-section' , [
'attributes' => oribi_card_section_attributes ( 3 ),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_stat_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Stat Card (child) */
2026-02-23 06:57:08 -05:00
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 ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_stat_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Link Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/link-section' , [
'attributes' => oribi_card_section_attributes ( 3 ),
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_link_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Link Card (child) */
2026-02-23 06:57:08 -05:00
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 ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_link_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Pricing Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/pricing-section' , [
'attributes' => [
'variant' => [ 'type' => 'string' , 'default' => 'normal' ],
'label' => [ 'type' => 'string' , 'default' => '' ],
'heading' => [ 'type' => 'string' , 'default' => '' ],
'lead' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_pricing_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Pricing Card (child) */
2026-02-23 06:57:08 -05:00
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 ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_pricing_card' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Platform Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/platform-section' , [
'attributes' => [
'label' => [ 'type' => 'string' , 'default' => '' ],
'heading' => [ 'type' => 'string' , 'default' => '' ],
'lead' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_platform_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Platform Row (child) */
2026-02-23 06:57:08 -05:00
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 ],
2026-03-16 20:29:15 -04:00
'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 ],
Add Day-Part Clock Animator and multiple animation options for various displays
- Implemented a new Day-Part Clock Animator in `solutions-animator.js` that updates a clock and badge based on simulated time.
- Updated `index.php` to include new animation options for lobby, conference, day-part, wayfinding, storefront, announcement, campus wayfinding, emergency, enclosure, brightness, cellular, designer, media library, publish, screen groups, monitoring, patient wayfinding, waiting room, multi-zone, and membership displays.
- Each animation option includes HTML structure for respective displays.
2026-03-16 22:32:57 -04:00
'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 ],
2026-03-16 23:47:21 -04:00
'videoMotionAnim' => [ 'type' => 'boolean' , 'default' => false ],
'brandLayoutAnim' => [ 'type' => 'boolean' , 'default' => false ],
'menuBoardAnim' => [ 'type' => 'boolean' , 'default' => false ],
2026-02-23 06:57:08 -05:00
'galleryIds' => [ 'type' => 'array' , 'default' => [], 'items' => [ 'type' => 'number' ]],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_platform_row' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* FAQ Section (parent) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/faq-section' , [
'attributes' => [
'variant' => [ 'type' => 'string' , 'default' => 'normal' ],
'label' => [ 'type' => 'string' , 'default' => '' ],
'heading' => [ 'type' => 'string' , 'default' => '' ],
'lead' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_faq_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* FAQ Item (child) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/faq-item' , [
'attributes' => [
'question' => [ 'type' => 'string' , 'default' => '' ],
'answer' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_faq_item' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Comparison Table */
2026-02-23 06:57:08 -05:00
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' => []],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_comparison_table' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Trust Section (parent) */
2026-02-23 06:57:08 -05:00
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' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_trust_section' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* Trust Item (child) */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/trust-item' , [
'attributes' => [
'heading' => [ 'type' => 'string' , 'default' => '' ],
'description' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_trust_item' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
/* ── ANIMATED HERO BLOCKS (OTS Signs) ─────────────────────────────────── */
2026-02-20 22:06:53 -05:00
/* Animated Hero - full homepage hero with particle background */
2026-02-23 06:57:08 -05:00
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' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_hero_animated' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
2026-02-20 22:06:53 -05:00
/* Animated Page Hero - inner pages with particle background */
2026-02-23 06:57:08 -05:00
register_block_type ( 'oribi/page-hero-animated' , [
'attributes' => [
'label' => [ 'type' => 'string' , 'default' => '' ],
'title' => [ 'type' => 'string' , 'default' => '' ],
'description' => [ 'type' => 'string' , 'default' => '' ],
2026-02-20 21:28:00 -05:00
],
2026-02-23 06:57:08 -05:00
'supports' => $block_supports ,
2026-02-20 21:28:00 -05:00
'render_callback' => 'oribi_render_page_hero_animated' ,
2026-02-23 06:57:08 -05:00
]);
2026-02-20 21:28:00 -05:00
2026-02-23 06:57:08 -05:00
});
2026-02-20 21:28:00 -05:00
/* ══════════════════════════════════════════════════════════════════════════════
2026-02-23 06:57:08 -05:00
RENDER CALLBACKS
══════════════════════════════════════════════════════════════════════════════ */
2026-02-20 21:28:00 -05:00
/* ── Site Header ───────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_site_header ()
{
2026-02-20 21:28:00 -05:00
$has_logo = has_custom_logo ();
ob_start (); ?>
< header class = " site-header " id = " site-header " >
< div class = " container header-inner " >
< div class = " site-logo " >
2026-02-23 06:57:08 -05:00
< ? php if ( $has_logo ) : ?>
2026-02-20 21:28:00 -05:00
< ? php the_custom_logo (); ?>
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
< a href = " <?php echo esc_url(home_url('/')); ?> " class = " logo-text " >< strong > OTS </ strong > Signs </ a >
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< button class = " nav-toggle " id = " nav-toggle " aria - expanded = " false " aria - label = " <?php esc_attr_e('Toggle navigation', 'ots-theme'); ?> " >
2026-02-20 21:28:00 -05:00
< span ></ span >< span ></ span >< span ></ span >
</ button >
< nav class = " site-nav " id = " site-nav " >
< ? php
2026-02-23 06:57:08 -05:00
wp_nav_menu ([
'theme_location' => 'primary' ,
'container' => false ,
'menu_class' => 'nav-menu' ,
'depth' => 2 ,
'fallback_cb' => 'oribi_fallback_menu' ,
]);
?>
2026-02-20 21:28:00 -05:00
</ nav >
</ div >
</ header >
< ? php return ob_get_clean ();
}
/** Fallback menu when no WP menu is assigned. */
2026-02-23 06:57:08 -05:00
function oribi_fallback_menu ()
{
2026-02-20 21:28:00 -05:00
echo '<ul class="nav-menu">' ;
2026-02-23 06:57:08 -05:00
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>' ;
2026-02-20 21:28:00 -05:00
echo '</ul>' ;
}
/* ── Site Footer ───────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_site_footer ()
{
$year = gmdate ( 'Y' );
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< footer class = " site-footer " >
< div class = " container " >
< div class = " footer-inner " >
< div class = " footer-brand " >
2026-02-22 12:20:30 -05:00
< div class = " footer-logo-section " >
2026-02-23 06:57:08 -05:00
< ? php if ( has_custom_logo ()) : ?>
2026-02-22 12:20:30 -05:00
< ? php the_custom_logo (); ?>
2026-02-23 06:57:08 -05:00
< ? php
else : ?>
2026-02-22 12:20:30 -05:00
< div class = " logo-text " >< strong > Oribi </ strong > Tech </ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
2026-02-22 12:20:30 -05:00
< div class = " footer-company-name " >
2026-02-23 06:57:08 -05:00
< a href = " <?php echo esc_url(home_url('/')); ?> " class = " logo-text " >< strong > OTS </ strong > Signs </ a >
2026-02-22 12:20:30 -05:00
</ div >
</ div >
2026-02-20 22:46:20 -05:00
< p class = " footer-tagline " > Digital signage solutions that communicate , engage , and grow your business .</ p >
2026-02-22 12:13:50 -05:00
< p class = " footer-location " > An < a href = " https://oribi-tech.com " > Oribi Technology Services </ a > Company </ p >
2026-02-20 21:28:00 -05:00
</ div >
< div class = " footer-links " >
< div class = " footer-col " >
2026-02-20 22:46:20 -05:00
< h4 > Platform </ h4 >
2026-02-20 21:28:00 -05:00
< ul >
2026-02-23 06:57:08 -05:00
< 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 >
2026-02-22 11:00:10 -05:00
</ ul >
</ div >
< div class = " footer-col " >
< h4 > Solutions </ h4 >
< ul >
2026-02-23 06:57:08 -05:00
< 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 >
2026-02-20 21:28:00 -05:00
</ ul >
</ div >
< div class = " footer-col " >
< h4 > Company </ h4 >
< ul >
2026-02-23 06:57:08 -05:00
< 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 >
2026-02-20 21:28:00 -05:00
</ ul >
</ div >
< div class = " footer-col " >
< h4 > Connect </ h4 >
< ul >
2026-02-23 06:57:08 -05:00
< li >< a href = " <?php echo esc_url(home_url('/contact')); ?> " > Contact </ a ></ li >
2026-02-20 22:46:20 -05:00
< 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 >
2026-02-20 21:28:00 -05:00
</ ul >
</ div >
</ div >
</ div >
< div class = " footer-bottom " >
2026-02-23 06:57:08 -05:00
< p >& copy ; < ? 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'); ?> " >
2026-02-22 12:24:46 -05:00
< 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 >
2026-02-20 21:28:00 -05:00
</ div >
</ div >
</ footer >
2026-02-23 06:57:08 -05:00
< button id = " scroll-top " class = " scroll-top " aria - label = " <?php esc_attr_e('Scroll to top', 'ots-theme'); ?> " >& #8593;</button>
2026-02-20 21:28:00 -05:00
< ? php return ob_get_clean ();
}
/** Helper: highlight a word in a string. */
2026-02-23 06:57:08 -05:00
function oribi_highlight ( $text , $word )
{
if ( ! $word )
return wp_kses_post ( $text );
2026-02-20 21:28:00 -05:00
return str_replace (
2026-02-23 06:57:08 -05:00
esc_html ( $word ),
'<span class="highlight">' . esc_html ( $word ) . '</span>' ,
wp_kses_post ( $text )
2026-02-20 21:28:00 -05:00
);
}
/* ── Hero ──────────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_hero ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start ();
2026-02-23 06:57:08 -05:00
?>
2026-02-20 21:28:00 -05:00
< section class = " hero " >
< div class = " container hero-inner " >
< div class = " hero-content " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
< div class = " btn-group " >
2026-02-23 06:57:08 -05:00
< 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
< div class = " hero-stats " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ 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 " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ ul >
</ div >
<!-- Device 2 : Cloud ( 365 Care ) -->
< 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 " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ 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 " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ 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 " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ ul >
</ div >
</ div >
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
/* ── Page Hero ─────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_page_hero ( $a )
{
2026-02-20 21:28:00 -05:00
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 " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</ section >
< ? php return ob_get_clean ();
}
/* ── CTA Banner ────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_cta_banner ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< section class = " cta-banner " >
< div class = " container text-center " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ div >
</ section >
< ? php return ob_get_clean ();
}
/* ── Intro Section ─────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_intro_section ( $a )
{
2026-02-20 21:28:00 -05:00
$cls = $a [ 'variant' ] === 'alt' ? 'section section-alt' : 'section' ;
$rev = $a [ 'reversed' ] ? ' style="direction:rtl;"' : '' ;
$ltr = $a [ 'reversed' ] ? ' style="direction:ltr;"' : '' ;
ob_start (); ?>
2026-02-23 06:57:08 -05:00
< section class = " <?php echo esc_attr( $cls ); ?> " >
2026-02-20 21:28:00 -05:00
< div class = " container " >
< div class = " about-intro " < ? php echo $rev ; ?> >
< div < ? php echo $ltr ; ?> >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-27 17:57:59 -05:00
< 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 >
2026-02-20 21:28:00 -05:00
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
/* ── Contact Section ───────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_contact_section ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< section class = " section " >
< div class = " container " >
< div class = " contact-layout " >
< div class = " contact-info " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ div >
< div class = " contact-form-wrap " >
2026-02-23 06:57:08 -05:00
< h3 style = " margin-bottom:1.5rem; " >< ? php echo esc_html ( $a [ 'formHeading' ]); ?> </h3>
2026-02-20 21:28:00 -05:00
< 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 " >
2026-02-20 22:46:20 -05:00
< option value = " " > Select a topic & hellip ; </ option >
< option value = " Digital Signage " > Digital Signage Solutions </ option >
< option value = " Content Creation " > Content Creation </ option >
< option value = " Hardware " > Player Devices & amp ; Hardware </ option >
< option value = " Pricing " > Pricing & amp ; Plans </ option >
< option value = " Demo " > Request a Demo </ option >
< option value = " Support " > Technical Support </ option >
2026-02-20 21:28:00 -05:00
< 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 ();
}
2026-02-20 22:06:53 -05:00
/* ── Feature Section (parent - wraps child feature-card blocks) ────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_feature_section ( $a , $content )
{
return oribi_render_card_section ( $a , $content , 'grid' , 3 );
2026-02-20 21:28:00 -05:00
}
2026-02-20 22:06:53 -05:00
/* ── Feature Card (child - renders one card) ───────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_feature_card ( $a )
{
$tag = ! empty ( $a [ 'url' ]) ? 'a' : 'div' ;
$href = ! empty ( $a [ 'url' ]) ? ' href="' . esc_url ( $a [ 'url' ]) . '"' : '' ;
$link_cls = ! empty ( $a [ 'url' ]) ? ' feature-card-link' : '' ;
$center = ! empty ( $a [ 'centered' ]);
$img = oribi_card_image_html ( $a );
$img_cls = $img [ 'card_class' ] ? ' ' . $img [ 'card_class' ] : '' ;
2026-02-20 21:28:00 -05:00
ob_start ();
2026-02-23 06:57:08 -05:00
if ( $img [ 'html' ] && $img [ 'position' ] === 'left' ) : ?>
<< ? php echo $tag . $href ; ?> class="oribi-card<?php echo esc_attr($link_cls . $img_cls); ?>">
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< h3 >< ? php echo wp_kses_post ( $a [ 'title' ]); ?> </h3>
< p >< ? php echo wp_kses_post ( $a [ 'description' ]); ?> </p>
2026-02-20 21:28:00 -05:00
</ div >
</< ? php echo $tag ; ?> >
2026-02-23 06:57:08 -05:00
< ? php
elseif ( $img [ 'html' ] && $img [ 'position' ] === 'background' ) : ?>
<< ? php echo $tag . $href ; ?> class="oribi-card<?php echo esc_attr($link_cls . $img_cls); ?>">
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</< ? php echo $tag ; ?> >
2026-02-23 06:57:08 -05:00
< ? 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' )) : ?>
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
< ? php if (( ! $img [ 'html' ] || $img [ 'position' ] !== 'replace-icon' ) && oribi_has_icon ( $a )) : ?>
< div class = " feature-icon " < ? php echo $center ? ' style="margin-inline:auto;"' : '' ; ?> ><?php echo oribi_render_icon($a); ?></div>
< ? php
endif ; ?>
< h3 >< ? php echo wp_kses_post ( $a [ 'title' ]); ?> </h3>
< p >< ? php echo wp_kses_post ( $a [ 'description' ]); ?> </p>
2026-02-20 21:28:00 -05:00
</< ? php echo $tag ; ?> >
2026-02-23 06:57:08 -05:00
< ? php
endif ;
2026-02-20 21:28:00 -05:00
return ob_get_clean ();
}
/* ── Value Section ─────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_value_section ( $a , $content )
{
return oribi_render_card_section ( $a , $content , 'grid' , 3 );
2026-02-20 21:28:00 -05:00
}
/* ── Value Card ────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_value_card ( $a )
{
$img = oribi_card_image_html ( $a );
2026-02-20 21:28:00 -05:00
$img_cls = $img [ 'card_class' ] ? ' ' . $img [ 'card_class' ] : '' ;
ob_start ();
2026-02-23 06:57:08 -05:00
if ( $img [ 'html' ] && $img [ 'position' ] === 'background' ) : ?>
< div class = " oribi-card value-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? php
elseif ( $img [ 'html' ] && $img [ 'position' ] === 'left' ) : ?>
< div class = " oribi-card value-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< h3 >< ? php echo wp_kses_post ( $a [ 'title' ]); ?> </h3>
< p >< ? php echo wp_kses_post ( $a [ 'description' ]); ?> </p>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ;
2026-02-20 21:28:00 -05:00
return ob_get_clean ();
}
/* ── Addon Section ─────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_addon_section ( $a , $content )
{
return oribi_render_card_section ( $a , $content , 'grid' , 3 );
2026-02-20 21:28:00 -05:00
}
/* ── Addon Card ────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_addon_card ( $a )
{
$img = oribi_card_image_html ( $a );
2026-02-20 21:28:00 -05:00
$img_cls = $img [ 'card_class' ] ? ' ' . $img [ 'card_class' ] : '' ;
ob_start ();
2026-02-23 06:57:08 -05:00
if ( $img [ 'html' ] && $img [ 'position' ] === 'left' ) : ?>
< div class = " oribi-card addon-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? php
elseif ( $img [ 'html' ] && $img [ 'position' ] === 'background' ) : ?>
< div class = " oribi-card addon-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ;
2026-02-20 21:28:00 -05:00
return ob_get_clean ();
}
/* ── Image Section ─────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_image_section ( $a , $content )
{
return oribi_render_card_section ( $a , $content , 'grid' , 3 );
2026-02-20 21:28:00 -05:00
}
/* ── Image Card ────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
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' ] : '' ;
2026-02-20 21:28:00 -05:00
ob_start ();
2026-02-23 06:57:08 -05:00
if ( $img [ 'html' ] && $img [ 'position' ] === 'left' ) : ?>
<< ? php echo $tag . $href ; ?> class="oribi-card image-card<?php echo esc_attr($link_cls . $img_cls); ?>">
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< h3 >< ? php echo wp_kses_post ( $a [ 'title' ]); ?> </h3>
< p >< ? php echo wp_kses_post ( $a [ 'description' ]); ?> </p>
2026-02-20 21:28:00 -05:00
</ div >
</< ? php echo $tag ; ?> >
2026-02-23 06:57:08 -05:00
< ? php
elseif ( $img [ 'html' ] && $img [ 'position' ] === 'background' ) : ?>
<< ? php echo $tag . $href ; ?> class="oribi-card image-card<?php echo esc_attr($link_cls . $img_cls); ?>">
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</< ? php echo $tag ; ?> >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< h3 >< ? php echo wp_kses_post ( $a [ 'title' ]); ?> </h3>
< p >< ? php echo wp_kses_post ( $a [ 'description' ]); ?> </p>
2026-02-20 21:28:00 -05:00
</ div >
</< ? php echo $tag ; ?> >
2026-02-23 06:57:08 -05:00
< ? php
endif ;
2026-02-20 21:28:00 -05:00
return ob_get_clean ();
}
/* ── Stat Section ──────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_stat_section ( $a , $content )
{
return oribi_render_card_section ( $a , $content , 'grid' , 3 );
2026-02-20 21:28:00 -05:00
}
/* ── Stat Card ─────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_stat_card ( $a )
{
$img = oribi_card_image_html ( $a );
2026-02-20 21:28:00 -05:00
$img_cls = $img [ 'card_class' ] ? ' ' . $img [ 'card_class' ] : '' ;
ob_start ();
2026-02-23 06:57:08 -05:00
if ( $img [ 'html' ] && $img [ 'position' ] === 'background' ) : ?>
< div class = " oribi-card stat-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? php
elseif ( $img [ 'html' ] && $img [ 'position' ] === 'left' ) : ?>
< div class = " oribi-card stat-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ;
2026-02-20 21:28:00 -05:00
return ob_get_clean ();
}
/* ── Link Section ──────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_link_section ( $a , $content )
{
return oribi_render_card_section ( $a , $content , 'grid' , 3 );
2026-02-20 21:28:00 -05:00
}
/* ── Link Card ─────────────────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_link_card ( $a )
{
$img = oribi_card_image_html ( $a );
2026-02-20 21:28:00 -05:00
$img_cls = $img [ 'card_class' ] ? ' ' . $img [ 'card_class' ] : '' ;
$cta = '' ;
2026-02-23 06:57:08 -05:00
if ( ! empty ( $a [ 'linkUrl' ])) {
$cta = '<a href="' . esc_url ( $a [ 'linkUrl' ]) . '" class="link-card-cta">'
. esc_html ( $a [ 'linkText' ] ? ? 'Learn More' ) . '</a>' ;
2026-02-20 21:28:00 -05:00
}
ob_start ();
2026-02-23 06:57:08 -05:00
if ( $img [ 'html' ] && $img [ 'position' ] === 'left' ) : ?>
< div class = " oribi-card link-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
< ? php echo $cta ; ?>
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? php
elseif ( $img [ 'html' ] && $img [ 'position' ] === 'background' ) : ?>
< div class = " oribi-card link-card<?php echo esc_attr( $img_cls ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $img [ 'html' ]; ?>
< div class = " oribi-card-body " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
< ? php echo $cta ; ?>
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
< ? php echo $cta ; ?>
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ;
2026-02-20 21:28:00 -05:00
return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Pricing Section (parent - wraps child pricing-card blocks) ────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_pricing_section ( $a , $content , $block )
{
$cls = $a [ 'variant' ] === 'alt' ? 'section section-alt' : 'section' ;
$count = count ( $block -> inner_blocks );
2026-02-20 21:28:00 -05:00
ob_start (); ?>
2026-02-23 06:57:08 -05:00
< section class = " <?php echo esc_attr( $cls ); ?> " >
2026-02-20 21:28:00 -05:00
< div class = " container " >
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< div class = " pricing-grid pricing-grid-<?php echo intval( $count ); ?> " >
2026-02-20 21:28:00 -05:00
< ? php echo $content ; ?>
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Pricing Card (child - renders one pricing tier) ───────────────────────── */
2026-02-23 06:57:08 -05:00
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 ;
2026-02-20 21:28:00 -05:00
$img_html = '' ;
2026-02-23 06:57:08 -05:00
if ( $img_url ) {
2026-02-20 21:28:00 -05:00
$img_style = 'width:' . $img_w . 'px;max-width:100%;height:auto;border-radius:var(--radius-sm);object-fit:contain;display:block;margin-inline:auto;' ;
2026-02-23 06:57:08 -05:00
if ( $img_id ) {
$img_html = wp_get_attachment_image ( $img_id , 'full' , false , [
2026-02-20 21:28:00 -05:00
'class' => 'card-image' ,
'style' => $img_style ,
2026-02-23 06:57:08 -05:00
'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 ) . '">' ;
2026-02-20 21:28:00 -05:00
}
}
ob_start (); ?>
2026-03-22 00:53:37 -04:00
< div class = " pricing-card<?php echo $featured ? ' featured' : ''; ?> " >
2026-02-23 06:57:08 -05:00
< ? php if ( $featured && ! empty ( $a [ 'badge' ])) : ?>
< span class = " pricing-badge " >< ? php echo esc_html ( $a [ 'badge' ]); ?> </span>
< ? php
endif ; ?>
< ? php if ( $img_html ) : ?>
2026-02-20 21:28:00 -05:00
< div class = " card-image-wrap " style = " text-align:center;margin-bottom:1.25rem; " >< ? php echo $img_html ; ?> </div>
2026-02-23 06:57:08 -05:00
< ? 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' ])) : ?>
2026-02-21 00:53:13 -05:00
< div class = " pricing-price " >
2026-02-23 06:57:08 -05:00
< 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 ; ?>
2026-02-21 00:53:13 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
2026-02-20 21:28:00 -05:00
< ul class = " pricing-features " >
2026-02-23 06:57:08 -05:00
< ? php foreach (( $a [ 'features' ] ? ? []) as $f ) : ?>
< li >< span class = " pricing-check " >& #10003;</span> <?php echo wp_kses_post($f); ?></li>
< ? php
endforeach ; ?>
2026-02-20 21:28:00 -05:00
</ ul >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ div >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Platform Section (parent - wraps child platform-row blocks) ───────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_platform_section ( $a , $content )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< section class = " section " >
< div class = " container " >
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
< ? php echo $content ; ?>
</ div >
</ section >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Platform Row (child - renders one service row) ────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_camera_animation ()
{
2026-02-21 17:55:50 -05:00
return <<< 'HTML'
2026-02-21 19:55:47 -05:00
< 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 >
2026-02-21 17:55:50 -05:00
2026-02-21 19:55:47 -05:00
<!-- 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 >
2026-02-27 19:06:27 -05:00
</ svg ></ div >
HTML ;
2026-02-21 17:55:50 -05:00
}
2026-02-27 19:06:27 -05:00
2026-02-23 06:57:08 -05:00
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 ;
2026-02-20 21:28:00 -05:00
2026-02-21 09:43:58 -05:00
// Only render animated dashboard when explicitly flagged
2026-02-23 06:57:08 -05:00
$is_dashboard = ! empty ( $a [ 'isDashboard' ]);
2026-02-21 01:45:51 -05:00
2026-02-23 06:57:08 -05:00
if ( $is_dashboard ) {
2026-02-21 02:08:54 -05:00
// 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
2026-02-21 02:23:06 -05:00
$visual_html = ' < div class = " dashboard-tv " data - dashboard - container = " true " >
< div class = " dashboard-tv__body " >
< div class = " dashboard-tv__screen " >
2026-02-21 02:29:38 -05:00
< svg viewBox = " 0 0 800 450 " xmlns = " http://www.w3.org/2000/svg " class = " dashboard-chart " role = " img " aria - label = " Animated dashboard charts " >
2026-02-21 02:08:54 -05:00
< defs >
< linearGradient id = " barGradient " x1 = " 0% " y1 = " 0% " x2 = " 0% " y2 = " 100% " >
2026-02-21 13:26:59 -05:00
< stop offset = " 0% " stop - color = " #D83302 " stop - opacity = " 1 " />
2026-02-21 02:08:54 -05:00
< 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 >
2026-02-21 02:29:38 -05:00
<!-- ── Top - left : Performance bars ── -->
< g transform = " translate(35,20) " >
2026-02-21 02:08:54 -05:00
< 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) " >
2026-02-21 02:29:38 -05:00
< 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) " />
2026-02-21 02:08:54 -05:00
</ g >
< g transform = " translate(0,152) " >
2026-02-21 02:29:38 -05:00
< 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 >
2026-02-21 02:08:54 -05:00
</ g >
2026-02-21 02:29:38 -05:00
< 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 >
2026-02-21 02:08:54 -05:00
</ g >
</ g >
2026-02-21 02:29:38 -05:00
<!-- ── Top - right : Requests / sec bars ── -->
< g transform = " translate(430,20) " >
2026-02-21 02:08:54 -05:00
< 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) " >
2026-02-21 02:29:38 -05:00
< 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) " />
2026-02-21 02:08:54 -05:00
</ g >
< g transform = " translate(0,152) " >
2026-02-21 02:29:38 -05:00
< 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 >
2026-02-21 02:08:54 -05:00
</ g >
2026-02-21 02:29:38 -05:00
< 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 >
2026-02-21 02:08:54 -05:00
</ g >
</ g >
2026-02-21 02:29:38 -05:00
<!-- ── Bottom - left : Traffic Trend line ── -->
< g id = " line-graph " transform = " translate(35,245) " >
2026-02-21 02:08:54 -05:00
< text class = " ct " x = " 0 " y = " 0 " font - size = " 14 " font - weight = " 600 " fill = " #333 " > Traffic Trend </ text >
< g transform = " translate(0,25) " >
2026-02-21 02:29:38 -05:00
< 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 " />
2026-02-21 02:08:54 -05:00
</ g >
< g transform = " translate(0,25) " >
2026-02-21 02:29:38 -05:00
< 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 " />
2026-02-21 02:08:54 -05:00
</ g >
</ g >
2026-02-21 02:29:38 -05:00
<!-- ── 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) " >
2026-02-21 02:08:54 -05:00
< g class = " pie-segment " transform = " rotate(0) " >
2026-02-21 13:26:59 -05:00
< path d = " M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z " fill = " #D83302 " opacity = " .9 " />
2026-02-21 02:08:54 -05:00
</ g >
< g class = " pie-segment " transform = " rotate(90) " >
2026-02-21 02:29:38 -05:00
< path d = " M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z " fill = " #4CAF50 " opacity = " .8 " />
2026-02-21 02:08:54 -05:00
</ g >
< g class = " pie-segment " transform = " rotate(180) " >
2026-02-21 02:29:38 -05:00
< path d = " M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z " fill = " #f59e0b " opacity = " .7 " />
2026-02-21 02:08:54 -05:00
</ g >
< g class = " pie-segment " transform = " rotate(270) " >
2026-02-21 02:29:38 -05:00
< path d = " M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z " fill = " #ef4444 " opacity = " .7 " />
2026-02-21 02:08:54 -05:00
</ g >
2026-02-21 02:29:38 -05:00
< 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 >
2026-02-21 02:08:54 -05:00
</ g >
2026-02-21 02:29:38 -05:00
< g transform = " translate(30,170) " >
2026-02-21 13:26:59 -05:00
< rect x = " 0 " y = " 0 " width = " 8 " height = " 8 " fill = " #D83302 " />
2026-02-21 02:08:54 -05:00
< 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 >
2026-02-21 02:29:38 -05:00
< 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 >
2026-02-21 02:08:54 -05:00
</ g >
</ g >
</ svg >
2026-02-21 02:23:06 -05:00
</ div ></ div >
< div class = " dashboard-tv__feet " >< div class = " dashboard-tv__foot " ></ div >< div class = " dashboard-tv__foot " ></ div ></ div >
2026-02-21 02:08:54 -05:00
</ div > ' ;
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-dashboard' ;
}
elseif ( $img_url ) {
2026-02-20 21:28:00 -05:00
$img_style = 'width:' . $img_w . 'px;max-width:100%;height:auto;border-radius:var(--radius-sm);object-fit:contain;display:block;margin-inline:auto;' ;
2026-02-23 06:57:08 -05:00
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 ) . '">' ;
2026-02-20 21:28:00 -05:00
}
$visual_cls = 'platform-visual has-img' ;
2026-02-23 06:57:08 -05:00
}
elseif ( ! empty ( $a [ 'deviceAnim' ])) {
2026-02-21 17:53:14 -05:00
$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>' ;
2026-02-23 06:57:08 -05:00
$da = '<div class="da-stage" aria-hidden="true">' ;
2026-02-21 17:53:14 -05:00
$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>' ;
2026-02-21 01:33:52 -05:00
$da .= '</div>' ;
$visual_html = $da ;
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-anim' ;
}
elseif ( ! empty ( $a [ 'tvStick' ])) {
$ts = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">' ;
2026-02-21 09:43:58 -05:00
$ts .= '<div class="ts-tv">' ;
$ts .= '<div class="ts-tv__body">' ;
2026-02-21 12:13:10 -05:00
$ts .= '<div class="ts-tv__screen">' ;
$ts .= '<div class="ts-slides">' ;
2026-02-21 12:18:48 -05:00
// 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>' ;
2026-02-21 12:13:10 -05:00
$ts .= '</div>' ; // ts-slides
$ts .= '</div>' ; // ts-tv__screen
2026-02-21 09:43:58 -05:00
$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 ;
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-tv-stick' ;
}
elseif ( ! empty ( $a [ 'neverGoesDark' ])) {
2026-02-21 12:35:28 -05:00
/* ── Never Goes Dark: player + TV + cloud connection/break animation ── */
2026-02-23 06:57:08 -05:00
$ngd = '<div class="ngd-stage" aria-hidden="true">' ;
2026-02-21 12:35:28 -05:00
/* TV */
$ngd .= '<div class="ngd-tv">' ;
2026-02-23 06:57:08 -05:00
$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>' ;
2026-02-21 12:35:28 -05:00
$ngd .= '</div>' ; /* ngd-tv */
2026-02-21 12:41:45 -05:00
/* Player device (stick style, plugged into TV right-side HDMI port) */
2026-02-21 12:35:28 -05:00
$ngd .= '<div class="ngd-player">' ;
2026-02-23 06:57:08 -05:00
$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>' ;
2026-02-21 12:35:28 -05:00
$ngd .= '</div>' ; /* ngd-player */
2026-02-21 17:30:18 -05:00
/* Signal wrap: vertical line connecting player to globe above */
2026-02-21 12:35:28 -05:00
$ngd .= '<div class="ngd-signal-wrap">' ;
2026-02-23 06:57:08 -05:00
$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 */
2026-02-21 12:35:28 -05:00
$ngd .= '</div>' ; /* ngd-signal-wrap */
$ngd .= '</div>' ; /* ngd-stage */
$visual_html = $ngd ;
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-ngd' ;
}
elseif ( ! empty ( $a [ 'brandedAnim' ])) {
2026-02-21 13:33:53 -05:00
/* ── Custom Display Solutions: branded screens cascade animation ── */
2026-02-23 06:57:08 -05:00
$bd = '<div class="bd-stage" aria-hidden="true">' ;
2026-02-21 13:33:53 -05:00
/* ── Screen 1: Tablet (portrait kiosk) ── */
$bd .= '<div class="bd-device bd-device--tablet">' ;
2026-02-23 06:57:08 -05:00
$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>' ;
2026-02-21 13:33:53 -05:00
$bd .= '</div>' ;
/* ── Screen 2: Wide wall-mount (landscape) ── */
$bd .= '<div class="bd-device bd-device--wall">' ;
2026-02-23 06:57:08 -05:00
$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>' ;
2026-02-21 13:33:53 -05:00
$bd .= '</div>' ;
2026-02-21 13:37:23 -05:00
/* ── Screen 3: Interactive tablet on table ── */
$bd .= '<div class="bd-device bd-device--interactive">' ;
2026-02-23 06:57:08 -05:00
$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>' ;
2026-02-21 13:33:53 -05:00
$bd .= '</div>' ;
$bd .= '</div>' ; /* bd-stage */
$visual_html = $bd ;
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-branded' ;
}
2026-03-16 20:29:15 -04:00
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' ;
}
Add Day-Part Clock Animator and multiple animation options for various displays
- Implemented a new Day-Part Clock Animator in `solutions-animator.js` that updates a clock and badge based on simulated time.
- Updated `index.php` to include new animation options for lobby, conference, day-part, wayfinding, storefront, announcement, campus wayfinding, emergency, enclosure, brightness, cellular, designer, media library, publish, screen groups, monitoring, patient wayfinding, waiting room, multi-zone, and membership displays.
- Each animation option includes HTML structure for respective displays.
2026-03-16 22:32:57 -04:00
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' ;
}
2026-02-23 06:57:08 -05:00
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' ;
}
2026-03-16 23:47:21 -04:00
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' ;
}
2026-02-23 06:57:08 -05:00
elseif ( ! empty ( $a [ 'cameraAnim' ])) {
2026-02-21 17:55:50 -05:00
$visual_html = oribi_render_camera_animation ();
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-video-editor' ;
2026-02-21 13:59:57 -05:00
2026-02-21 14:11:56 -05:00
/* ── Gallery TV Slideshow ───────────────────────────────── */
2026-02-23 06:57:08 -05:00
}
elseif ( ! empty ( $a [ 'galleryIds' ]) && is_array ( $a [ 'galleryIds' ]) && count ( $a [ 'galleryIds' ]) > 0 ) {
2026-02-21 14:11:56 -05:00
$slides = '' ;
2026-02-23 06:57:08 -05:00
$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 ;
2026-02-21 14:11:56 -05:00
$active = $count === 0 ? ' is-active' : '' ;
$slides .= '<div class="gtv-slide' . $active . '">' ;
2026-02-23 06:57:08 -05:00
$slides .= '<img src="' . esc_url ( $url ) . '" alt="' . esc_attr ( $alt ) . '" loading="lazy" />' ;
2026-02-21 14:11:56 -05:00
$slides .= '</div>' ;
$count ++ ;
}
2026-02-23 06:57:08 -05:00
if ( $count > 0 ) {
$visual_html = '<div class="gtv-stage" data-gtv-slideshow aria-hidden="true">' ;
2026-02-21 14:11:56 -05:00
$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
2026-02-23 06:57:08 -05:00
$visual_cls = 'platform-visual has-gallery-tv' ;
}
else {
$visual_html = oribi_render_icon ( $a [ 'visual' ] ? ? '' );
$visual_cls = 'platform-visual' ;
2026-02-21 14:11:56 -05:00
}
2026-02-21 13:59:57 -05:00
2026-02-23 06:57:08 -05:00
}
else {
$visual_html = oribi_render_icon ( $a [ 'visual' ] ? ? '' );
$visual_cls = 'platform-visual' ;
2026-02-20 21:28:00 -05:00
}
ob_start (); ?>
< div class = " platform-row<?php echo $rev ; ?> " >
< div class = " platform-text " >
2026-02-23 06:57:08 -05:00
< 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< div class = " <?php echo esc_attr( $visual_cls ); ?> " >< ? php echo $visual_html ; ?> </div>
2026-02-20 21:28:00 -05:00
</ div >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Trust Section (parent - wraps child trust-item blocks) ────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_trust_section ( $a , $content )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< section class = " section " >
< div class = " container " >
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ 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; " >
2026-02-23 06:57:08 -05:00
< 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Trust Item (child - renders one heading + description pair) ────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_trust_item ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< div class = " trust-item " >
2026-02-23 06:57:08 -05:00
< h3 style = " margin-bottom:1rem; " >< ? php echo wp_kses_post ( $a [ 'heading' ]); ?> </h3>
< p >< ? php echo wp_kses_post ( $a [ 'description' ]); ?> </p>
2026-02-20 21:28:00 -05:00
</ div >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── FAQ Section (parent - wraps child faq-item blocks) ────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_faq_section ( $a , $content )
{
2026-02-20 21:28:00 -05:00
$cls = $a [ 'variant' ] === 'alt' ? 'section section-alt' : 'section' ;
ob_start (); ?>
2026-02-23 06:57:08 -05:00
< section class = " <?php echo esc_attr( $cls ); ?> " >
2026-02-20 21:28:00 -05:00
< div class = " container " >
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
< div class = " faq-list " >
< ? php echo $content ; ?>
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── FAQ Item (child - renders one accordion item) ─────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_faq_item ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< details class = " faq-item " >
2026-02-23 06:57:08 -05:00
< 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>
2026-02-20 21:28:00 -05:00
</ details >
< ? php return ob_get_clean ();
}
2026-02-20 22:06:53 -05:00
/* ── Comparison Table (standalone - renders a feature matrix) ──────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_comparison_table ( $a )
{
$cls = $a [ 'variant' ] === 'alt' ? 'section section-alt' : 'section' ;
2026-02-20 21:28:00 -05:00
$cols = $a [ 'columns' ] ? ? [];
2026-02-23 06:57:08 -05:00
$rows = $a [ 'rows' ] ? ? [];
2026-02-20 21:28:00 -05:00
ob_start (); ?>
2026-02-23 06:57:08 -05:00
< section class = " <?php echo esc_attr( $cls ); ?> " >
2026-02-20 21:28:00 -05:00
< div class = " container " >
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
< div class = " comparison-table-wrap " >
< table class = " comparison-table " >
< thead >
< tr >
< th class = " comparison-feature-col " > Feature </ th >
2026-02-23 06:57:08 -05:00
< ? php foreach ( $cols as $col ) : ?>
< th >< ? php echo esc_html ( $col ); ?> </th>
< ? php
endforeach ; ?>
2026-02-20 21:28:00 -05:00
</ tr >
</ thead >
< tbody >
2026-02-23 06:57:08 -05:00
< ? php foreach ( $rows as $row ) :
$is_group = ! empty ( $row [ 'group' ]);
?>
< ? php if ( $is_group ) : ?>
2026-02-20 21:28:00 -05:00
< tr class = " comparison-group-row " >
2026-02-23 06:57:08 -05:00
< td colspan = " <?php echo count( $cols ) + 1; ?> " >< ? php echo esc_html ( $row [ 'group' ]); ?> </td>
2026-02-20 21:28:00 -05:00
</ tr >
2026-02-23 06:57:08 -05:00
< ? php
else : ?>
2026-02-20 21:28:00 -05:00
< tr >
2026-02-23 06:57:08 -05:00
< td class = " comparison-feature-name " >< ? php echo wp_kses_post ( $row [ 'feature' ] ? ? '' ); ?> </td>
< ? php foreach (( $row [ 'values' ] ? ? []) as $val ) : ?>
2026-02-20 21:28:00 -05:00
< td class = " comparison-cell " >< ? php
2026-02-23 06:57:08 -05:00
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 ; ?>
2026-02-20 21:28:00 -05:00
</ tr >
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
< ? php
endforeach ; ?>
2026-02-20 21:28:00 -05:00
</ tbody >
</ table >
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
/* ══════════════════════════════════════════════════════════════════════════════
2026-02-23 06:57:08 -05:00
ANIMATED HERO BLOCKS ( OTS Signs )
══════════════════════════════════════════════════════════════════════════════ */
2026-02-20 21:28:00 -05:00
/**
* 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 .
*/
2026-02-23 06:57:08 -05:00
function oribi_render_particles ( $count = 12 )
{
2026-02-20 21:28:00 -05:00
$html = '<div class="hero-particles" aria-hidden="true">' ;
2026-02-23 06:57:08 -05:00
for ( $i = 1 ; $i <= $count ; $i ++ ) {
2026-02-20 21:28:00 -05:00
$html .= '<div class="hero-particle hero-particle--' . $i . '"></div>' ;
}
$html .= '</div>' ;
return $html ;
}
/* ── Animated Hero (homepage) ──────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_hero_animated ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start ();
2026-02-23 06:57:08 -05:00
?>
2026-02-20 21:28:00 -05:00
< section class = " hero hero-animated " >
2026-02-23 06:57:08 -05:00
< ? php echo oribi_render_particles ( 12 ); ?>
2026-02-20 21:28:00 -05:00
< div class = " hero-animated__glow " ></ div >
< div class = " container hero-animated__inner " >
< div class = " hero-animated__content " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
< div class = " btn-group " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php if ( $a [ 'stat1Value' ] || $a [ 'stat2Value' ] || $a [ 'stat3Value' ]) : ?>
2026-02-20 21:28:00 -05:00
< div class = " hero-stats hero-stats--three " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-20 21:28:00 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
2026-02-20 21:28:00 -05:00
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
}
/* ── Animated Page Hero (inner pages) ──────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_render_page_hero_animated ( $a )
{
2026-02-20 21:28:00 -05:00
ob_start (); ?>
< section class = " page-hero page-hero-animated " >
2026-02-23 06:57:08 -05:00
< ? php echo oribi_render_particles ( 8 ); ?>
2026-02-20 21:28:00 -05:00
< div class = " hero-animated__glow " ></ div >
< div class = " hero-overlay " ></ div >
< div class = " container " >
2026-02-23 06:57:08 -05:00
< ? 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>
2026-02-20 21:28:00 -05:00
</ div >
</ section >
< ? php return ob_get_clean ();
}
2026-02-21 10:46:40 -05:00
/* ── Use Cases Showcase ────────────────────────────────────────────────── */
2026-02-23 06:57:08 -05:00
function oribi_uc_anim_inner ( $mod )
{
switch ( $mod ) {
2026-02-21 10:46:40 -05:00
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 " >
2026-02-21 13:14:41 -05:00
< div class = " uc-event-cursor " ></ div >
2026-02-21 13:05:58 -05:00
< 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 >
2026-02-21 10:46:40 -05:00
</ 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 '' ;
}
}
2026-02-23 06:57:08 -05:00
function oribi_render_use_cases ( $a )
{
2026-02-21 10:46:40 -05:00
$cases = [
2026-02-23 06:57:08 -05:00
[ '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' ],
2026-02-21 10:46:40 -05:00
];
ob_start (); ?>
< section class = " section use-cases-section " >
< div class = " container " >
2026-02-23 06:57:08 -05:00
< ? php if ( $a [ 'label' ] || $a [ 'heading' ] || $a [ 'lead' ]) : ?>
2026-02-21 10:46:40 -05:00
< div class = " section-header " >
2026-02-23 06:57:08 -05:00
< ? 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 ; ?>
2026-02-21 10:46:40 -05:00
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endif ; ?>
2026-02-21 10:46:40 -05:00
< div class = " uc-track " >
2026-02-23 06:57:08 -05:00
< ? php foreach ( $cases as $c ) : ?>
2026-02-21 10:46:40 -05:00
< div class = " uc-item " >
2026-02-23 06:57:08 -05:00
< div class = " uc-circle uc-anim--<?php echo esc_attr( $c['mod'] ); ?> " >
< ? php echo oribi_uc_anim_inner ( $c [ 'mod' ]); ?>
2026-02-21 10:46:40 -05:00
</ div >
< div class = " uc-item-body " >
2026-02-23 06:57:08 -05:00
< 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 ; ?>
2026-02-21 10:46:40 -05:00
</ div >
</ div >
2026-02-23 06:57:08 -05:00
< ? php
endforeach ; ?>
2026-02-21 10:46:40 -05:00
</ div >
</ div >
</ section >
< ? php return ob_get_clean ();
2026-02-23 06:57:08 -05:00
}