Compare commits
117 Commits
oribi-sync
...
c91975db12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c91975db12 | ||
|
|
5ea06c2332 | ||
|
|
59295b15db | ||
|
|
82d6ecba1e | ||
|
|
e90e644b62 | ||
|
|
afccdca783 | ||
|
|
d88070949c | ||
|
|
2a0b949ea9 | ||
|
|
2c82b2e432 | ||
|
|
97bbe90ed1 | ||
| 668c92aff6 | |||
| a8ba4a1fef | |||
| edacab26b3 | |||
| 0a18e35943 | |||
| b264511d34 | |||
| 6254fff0c0 | |||
| 3c07a4733c | |||
| e54b94222a | |||
| 44b501b4da | |||
| 4f596dbf30 | |||
|
|
a7d6623eec | ||
|
|
985ba72212 | ||
|
|
cfb216f73e | ||
|
|
ce163d25e3 | ||
|
|
6b8b6b2328 | ||
|
|
f9f15708e3 | ||
|
|
80b36032e8 | ||
|
|
7b4caa1267 | ||
| a69521ab25 | |||
| e03b6e150e | |||
| 8eea9d95ce | |||
| 0fd40020b0 | |||
| afd49f2165 | |||
| c476a79cee | |||
| 369da66d4c | |||
| 402804018a | |||
| 93e1c59e29 | |||
| 170f134927 | |||
|
|
5be6eae083 | ||
|
|
7bb9a0bdd3 | ||
|
|
3027f3da40 | ||
|
|
c50087d669 | ||
|
|
8c3c7a1d8a | ||
|
|
4e4549e865 | ||
|
|
25da755378 | ||
|
|
dc89009cfa | ||
|
|
21d41b24d8 | ||
|
|
8f43b6c584 | ||
|
|
66b6b9cbfb | ||
|
|
018928dd9b | ||
|
|
78065e0143 | ||
|
|
131ef8448c | ||
|
|
a89f9067e2 | ||
|
|
8926a9b071 | ||
|
|
1540aa9f13 | ||
|
|
3dcffaeb06 | ||
| 7aee3eab85 | |||
| 20b655d490 | |||
| 3e3578823d | |||
| b96bdfe355 | |||
| dcb8acb1e5 | |||
| a2821b4c2c | |||
| f12928690e | |||
| 6ddd3ba399 | |||
| 4fe3f6e283 | |||
| 4e5ab8b3fa | |||
|
|
48432c1931 | ||
|
|
2826a3ec4a | ||
|
|
2edbf9732b | ||
|
|
82a2dacbef | ||
|
|
75588a5151 | ||
|
|
624a5c2d4e | ||
|
|
61a7070b0f | ||
|
|
bb30f38090 | ||
|
|
d8c12e3f3b | ||
|
|
ebb4b7668c | ||
|
|
5783fa7ebc | ||
|
|
df794be0d8 | ||
|
|
150fe5a291 | ||
|
|
b0167f2505 | ||
|
|
0407269e79 | ||
|
|
ecba27595c | ||
|
|
c4f3d7e881 | ||
|
|
e5c3be6ec5 | ||
|
|
201e4e4606 | ||
|
|
ef0532ef9b | ||
|
|
1d49929ed3 | ||
|
|
c5d5ad33e5 | ||
|
|
c42c7d7dbc | ||
|
|
5d09382d0d | ||
|
|
accdfa9d70 | ||
|
|
a9697dd714 | ||
|
|
ab6f4212bd | ||
|
|
7e0c216e1c | ||
|
|
d68c2c1d31 | ||
|
|
4591578cb2 | ||
|
|
954c418556 | ||
|
|
b37bcfb72b | ||
|
|
0ec0e71d38 | ||
|
|
e1d9b1a402 | ||
|
|
a33a6d62d2 | ||
|
|
38d585e071 | ||
|
|
f8321568ce | ||
|
|
be30e4d59f | ||
|
|
3e211c376f | ||
|
|
618ba6ded4 | ||
| 3100a93d9a | |||
|
|
8ceb81008c | ||
|
|
0420be8bd6 | ||
|
|
01235c2042 | ||
| ea988f09b1 | |||
| 978c63f9b9 | |||
|
|
68a8cc9578 | ||
|
|
bfe2bf8bf1 | ||
|
|
15d1acbb14 | ||
|
|
06b0831a40 | ||
|
|
2c9825b72d |
@@ -1,27 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: About
|
* Title: About
|
||||||
* Slug: ots-signs/page-about
|
* Slug: about
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: about, company, mission, team, digital signage
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"About Us","title":"The Complete Digital Signage Solution","description":"An Oribi Technology Services company, OTS Signs delivers enterprise-grade digital signage solutions that help businesses communicate, engage, and grow."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/intro-section {"variant":"normal","label":"Our Story","heading":"Built by People Who Understand Technology","description":"OTS Signs was born from a simple idea: digital signage should be powerful yet simple. As part of the Oribi Technology Services family, we bring years of IT infrastructure expertise to the signage industry. We understand networks, security, and reliability, and we\u0027ve built a platform that reflects that knowledge. Our team combines deep technical skills with creative vision to deliver signage solutions that truly work for your business.","visual":""} /-->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
|
<!-- wp:oribi/page-hero-animated {"label":"About Us","title":"Digital Signage, Done Properly","description":"OTS Signs is the digital signage arm of Oribi Technology Services. We combine deep IT expertise with creative production to deliver signage that businesses can genuinely rely on."} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/intro-section {"variant":"alt","label":"Our Mission","heading":"Empowering Businesses to Communicate Better","description":"We believe every business deserves access to professional-grade digital signage. Our mission is to make it affordable, reliable, and effortless, so you can focus on what matters most: your customers. Whether you\u0027re a single-location café or a multi-site enterprise, our platform scales to meet your needs without compromising on quality or support.","visual":"","reversed":true} /-->
|
<!-- wp:oribi/intro-section {"label":"Our Story","heading":"Born from Infrastructure, Built for Signage","description":"OTS Signs grew out of a gap we kept seeing: businesses wanted digital signage but were stuck choosing between complex enterprise platforms and unreliable consumer tools. As part of Oribi Technology Services, we already understood networks, uptime, and security at a deep level. We took that foundation and built a signage platform that is powerful enough for large deployments yet simple enough for a single-site café. Every decision we make, from hardware selection to Command Center design, is grounded in real-world infrastructure experience."} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/value-section {"variant":"normal","label":"What Sets Us Apart","heading":"Why Businesses Choose OTS Signs","lead":"We\u0027re not just a software company. We\u0027re a full-service digital signage partner.","columns":3} -->
|
<!-- wp:oribi/intro-section {"variant":"alt","label":"Our Mission","heading":"Making Professional Signage Accessible to Everyone","description":"Too many signage providers lock essential features behind enterprise price tags. We took a different approach. Our platform gives every customer access to the same professional-grade tools: \u003cbr\u003e- Cloud Content Management\u003cbr\u003e- Intelligent Scheduling\u003cbr\u003e- Live Data Integration \u003cbr\u003e- Content that looks outstanding on screen\u003cbr\u003e\u003cbr\u003eWe handle the complexity so you can focus on running your business.","reversed":true} /-->
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-camera","title":"In-House Content Production","description":"Professional photography, video production, and graphic design services to ensure your signage always looks its best."} /-->
|
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-server","title":"Infrastructure Expertise","description":"Built on enterprise-grade cloud infrastructure by the same team that manages IT systems for businesses across the region."} /-->
|
<!-- wp:oribi/value-section {"label":"What Sets Us Apart","heading":"A Full-Service Signage Partner","lead":"Software alone isn't enough. We pair our platform with hands-on services that make the difference."} -->
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Partnership Approach","description":"We work as an extension of your team. Dedicated support, personalised onboarding, and ongoing optimisation."} /-->
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-camera","title":"Studio-Quality Creative","description":"Photography, videography, and motion graphics produced in-house. Your screens always look polished, on-brand, and impossible to ignore."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-server","title":"IT-Grade Infrastructure","description":"Our roots are in enterprise IT. That means proper networking, redundancy, and security baked into every layer of the platform."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Genuine Partnership","description":"Dedicated onboarding, a named point of contact, and ongoing optimisation. We operate as an extension of your own team."} /-->
|
||||||
<!-- /wp:oribi/value-section -->
|
<!-- /wp:oribi/value-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/trust-section {"label":"Our Commitment","heading":"We Stand Behind Every Screen","lead":"Your success is our success. From initial concept to ongoing management, we\u0027re with you every step of the way.","btnText":"Get in Touch","btnUrl":"/contact","btnSub":"Let\u0027s discuss your digital signage needs"} -->
|
<!-- wp:oribi/trust-section {"label":"Our Commitment","heading":"Promises We Actually Keep","lead":"Every screen in your network reflects on your business. We take that responsibility seriously.","btnText":"Start a Conversation","btnUrl":"/contact","btnSub":"Tell us what you need and we'll take it from there"} -->
|
||||||
<!-- wp:oribi/trust-item {"heading":"Reliable Technology","description":"Enterprise-grade security, 99.9% uptime, and intelligent offline playback ensure your message is always on screen."} /-->
|
<!-- wp:oribi/trust-item {"heading":"Uptime You Can Count On","description":"99.9% platform availability, and intelligent offline playback mean your message stays on screen no matter what."} /-->
|
||||||
<!-- wp:oribi/trust-item {"heading":"Continuous Innovation","description":"We\u0027re constantly improving our platform with new features, integrations, and content tools to keep you ahead of the curve."} /-->
|
|
||||||
|
<!-- wp:oribi/trust-item {"heading":"A Platform That Keeps Improving","description":"Regular feature releases, new integrations, and expanded content tools ensure you're always working with the latest capabilities, at no extra cost."} /-->
|
||||||
<!-- /wp:oribi/trust-section -->
|
<!-- /wp:oribi/trust-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Let\u0027s Build Something Together","text":"Whether you\u0027re starting fresh or upgrading an existing setup, we\u0027re ready to help.","btnText":"Contact Us","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"Ready to See What We Can Do?","text":"Whether you're planning your first screen or scaling to hundreds, we'd love to hear about your project.","btnText":"Get in Touch","btnUrl":"/contact"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Contact
|
* Title: Contact
|
||||||
* Slug: ots-signs/page-contact
|
* Slug: contact
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: contact, sales, support, inquiry, get in touch
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Contact Us","title":"Get in Touch","description":"Ready to transform your screens? Whether you\u0027re exploring options or ready to get started, we\u0027re here to help."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/contact-section {"heading":"Let\u0027s Talk","lead":"Tell us about your digital signage needs and we\u0027ll get back to you within one business day.","email":"hello@ots-signs.com","supportUrl":"https://ots-signs.com/support","portalUrl":"https://ots-signs.com/portal","location":"An Oribi Technology Services Company","formHeading":"Send Us a Message"} /-->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
|
<!-- wp:oribi/page-hero-animated {"label":"Contact Us","title":"Let's Start a Conversation","description":"Whether you're researching digital signage for the first time or ready to roll out screens next week, we're here to help you move forward."} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/value-section {"variant":"alt","label":"How We Can Help","heading":"Reach Out For","lead":"Whatever stage you\u0027re at, we have the expertise to guide you.","columns":3} -->
|
<!-- wp:oribi/contact-section {"heading":"Send Us a Message","lead":"Tell us what you're working on. We respond within one business day, usually faster.","email":"hello@ots-signs.com","supportUrl":"https://ots-signs.com/support","portalUrl":"https://ots-signs.com/portal","location":"An Oribi Technology Services Company","formHeading":"How Can We Help?"} /-->
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-comments","title":"Sales Inquiries","description":"Explore our plans, get a custom quote, or learn how digital signage can benefit your business."} /-->
|
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Technical Support","description":"Need help with your existing setup? Our support team is ready to troubleshoot and resolve any issues."} /-->
|
<!-- wp:oribi/value-section {"variant":"alt","label":"How We Can Help","heading":"Whatever You Need, We're Here","lead":"From your first question to ongoing support, our team has you covered."} -->
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Partnerships","description":"Interested in reselling or integrating our platform? Let\u0027s discuss partnership opportunities."} /-->
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-comments","title":"Sales \u0026 Quotes","description":"Talk through your requirements, get a custom quote, or simply learn how digital signage fits your business."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Technical Support","description":"Already a customer? Our support team is ready to troubleshoot, advise, and resolve any issue quickly."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Partnerships","description":"Interested in reselling, white-labelling, or integrating our platform into your own offering? Let's talk."} /-->
|
||||||
<!-- /wp:oribi/value-section -->
|
<!-- /wp:oribi/value-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Prefer a Live Demo?","text":"See our platform in action before you commit. Request access to our live demo instance.","btnText":"Request Demo","btnUrl":"/demo"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"Rather See It First?","text":"Get hands-on with our platform before committing. Request a live demo and explore at your own pace.","btnText":"Request Demo","btnUrl":"/demo"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,25 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Demo
|
* Title: Demo
|
||||||
* Slug: ots-signs/page-demo
|
* Slug: demo
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: demo, trial, try, preview, platform
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Try It","title":"See It in Action","description":"Experience our digital signage platform firsthand. Request access to our live demo instance and explore every feature, no commitment required."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/intro-section {"variant":"normal","label":"Live Demo","heading":"Explore Our Demo Instance","description":"Our demo environment gives you full access to the OTS Signs CMS platform. Create content, schedule displays, explore integrations, and see exactly how your digital signage will look and feel in production. No credit card needed. Just fill in the form below and we\u0027ll send you access within 24 hours.","visual":""} /-->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
|
<!-- wp:oribi/page-hero-animated {"label":"Try It","title":"Hands-On in Minutes, Not Weeks","description":"Skip the slideshow. Request access to a live instance of our platform and explore every feature at your own pace, no sales call required."} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/feature-section {"variant":"alt","label":"What You\u0027ll See","heading":"Full Platform Access","lead":"The demo instance includes all the features available on our Pro plan.","columns":3} -->
|
<!-- wp:oribi/intro-section {"label":"Live Demo","heading":"Your Own Sandbox to Explore","description":"We'll set you up with full access to the OTS Signs Command Center, the same platform our paying customers use. Build playlists, schedule content, connect data feeds, and preview exactly how your signage will look in production. No credit card, no time limit on the trial. Fill in the form below and we'll send you credentials within 24 hours."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-desktop","title":"Content Management","description":"Upload images, videos, and HTML content. Create playlists and manage your media library."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Scheduling","description":"Set up content schedules with day-parting and time-based triggers to see automated playback in action."} /-->
|
<!-- wp:oribi/feature-section {"variant":"alt","label":"What Youu0027ll See","heading":"Full Pro-Tier Access","lead":"The demo includes every feature available, nothing held back."} -->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-line","title":"Live Data Feeds","description":"Connect sample data sources and see how real-time information appears on your digital signage displays."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-desktop","title":"Content Management","description":"Upload images, videos, and HTML. Organize media, create playlists, and preview how content looks on screen."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-th-large","title":"Template Library","description":"Browse our collection of professionally designed templates for menus, promotions, and informational displays."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users-cog","title":"User Management","description":"See how roles and permissions work to manage team access across your signage network."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Smart Scheduling","description":"Build day-parted schedules, set date ranges, and see how automated playback works across multiple screens."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-pie","title":"Analytics Dashboard","description":"View playback analytics and screen health metrics to understand how your content is performing."} /-->
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-line","title":"Live Data Feeds","description":"Connect sample data sources to experience real-time information flowing directly onto display layouts."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-th-large","title":"Template Library","description":"Browse and customize professional templates for menus, promotions, announcements, and informational displays."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users-cog","title":"Team \u0026 Permissions","description":"Test role-based access, invite collaborators, and see how multi-user management works across your network."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-pie","title":"Playback Analytics","description":"Explore screen health monitoring, content playback logs, and performance dashboards."} /-->
|
||||||
<!-- /wp:oribi/feature-section -->
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/contact-section {"heading":"Request Demo Access","lead":"Fill in your details and we\u0027ll send you credentials for our demo instance within 24 hours.","email":"hello@ots-signs.com","supportUrl":"https://demo.ots-signs.com/","portalUrl":"https://demo.ots-signs.com/","location":"Online Demo Available 24/7","formHeading":"Get Your Demo Access"} /-->
|
<!-- wp:oribi/contact-section {"heading":"Request Demo Access","lead":"Fill in your details below. We'll have your login credentials ready within 24 hours.","email":"hello@ots-signs.com","supportUrl":"https://demo.ots-signs.com/","portalUrl":"https://demo.ots-signs.com/","location":"Online Demo Available 24/7","formHeading":"Get Your Demo Login"} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Ready to Skip the Demo?","text":"If you already know what you need, let\u0027s get started right away.","btnText":"View Pricing","btnUrl":"/pricing"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"Already Convinced?","text":"If you've seen enough and want to get started, jump straight to our plans.","btnText":"View Pricing","btnUrl":"/pricing"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
46
pages/design.php
Normal file
46
pages/design.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Title: Design
|
||||||
|
* Slug: design
|
||||||
|
* Post Type: page
|
||||||
|
*/
|
||||||
|
|
||||||
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
|
<!-- wp:oribi/page-hero-animated {"label":"Creative Services","title":"Content That Demands Attention","description":"Great signage starts with great content. Our in-house creative team produces photography, video, motion graphics, and branded layouts — so every screen in your network looks polished, professional, and impossible to ignore."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-section {"label":"What We Create","heading":"Professional Content for Every Screen","lead":"We handle the entire creative process — from concept to screen-ready assets — so you can focus on running your business."} -->
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Photography That Sells","description":"Our photographers capture your products, venues, and team in the best possible light. Whether it's plated dishes for a digital menu board, hero shots for a retail promotion, or environmental photography for a hotel lobby — every image is composed, lit, and retouched specifically for screen display. No stock photos, no compromises.","btnText":"Get a Quote","btnUrl":"/contact","cameraAnim":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Video \u0026amp; Motion Graphics","description":"Short-form video content grabs attention like nothing else. We produce promotional videos, product loops, animated backgrounds, and kinetic typography — all optimised for digital signage playback. From scripting and shooting to editing and export, we deliver files ready to drop straight into your CMS.","btnText":"See Examples","btnUrl":"/contact","reversed":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Branded Layout Design","description":"Your screens should feel like a natural extension of your brand. We design custom layouts that match your visual identity — fonts, colours, logo placement, and spacing — across every display format. Whether you need a single hero layout or a full library of templates for your team to reuse, we build it to your spec.","btnUrl":"/features"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Digital Menu Boards","description":"Menu boards that update in seconds, not hours. We design structured menu layouts with clear categories, pricing, and imagery — then connect them to the platform so you can change a price, swap a photo, or add a seasonal item without touching the design. One update, every screen, instantly.","btnText":"View Platform","btnUrl":"/features","reversed":true} /-->
|
||||||
|
<!-- /wp:oribi/platform-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-section {"variant":"alt","label":"How We Work","heading":"From Brief to Screen in Days, Not Weeks","lead":"A straightforward process that gets professional content onto your displays quickly — with revisions built in and no surprises on cost.","columns":3} -->
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-comments","title":"1. Discovery \u0026amp; Brief","description":"We learn about your brand, your audience, and your goals. You tell us what you need — we'll recommend what works best on screen and scope the project."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-pencil","title":"2. Create \u0026amp; Review","description":"We produce your content — photography, video, layouts, or all three — and share drafts for your feedback. Revisions are included until you're completely happy."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"3. Publish \u0026amp; Go Live","description":"Approved content goes straight into your CMS, scheduled and ready to play. We handle the upload so you don't have to lift a finger."} /-->
|
||||||
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-section {"label":"Why In-House","heading":"The Advantage of a Single Partner","lead":"When your creative team and your signage platform are under the same roof, everything moves faster and fits better."} -->
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-display","title":"Designed for Screen","description":"Every asset is created specifically for digital display — correct resolutions, aspect ratios, colour profiles, and file formats. No guesswork, no re-exporting."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-layer-group","title":"Platform-Native Layouts","description":"We design directly within the CMS layout engine, so what you approve in the draft is exactly what plays on screen. No design-to-development handoff."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-arrows-rotate","title":"Ongoing Content Refresh","description":"Screens that never change get ignored. We offer ongoing content packages — monthly or quarterly — to keep your displays fresh, seasonal, and relevant."} /-->
|
||||||
|
<!-- /wp:oribi/value-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/stat-section {"variant":"alt","label":"Content Impact","heading":"Why Content Quality Matters","lead":"The difference between signage that works and signage that gets ignored almost always comes down to the content on screen."} -->
|
||||||
|
<!-- wp:oribi/stat-card {"value":"400%","label":"More Views","description":"Digital displays capture 400% more eyeballs than static signage — but only when the content is worth looking at."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/stat-card {"value":"80%","label":"Content Recall","description":"Eight out of ten people remember what they see on a digital display. Professional visuals make that memory count."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/stat-card {"value":"30%","label":"Sales Uplift","description":"Retail locations with well-designed digital signage report up to 30% higher in-store sales."} /-->
|
||||||
|
<!-- /wp:oribi/stat-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/cta-banner {"heading":"Let's Make Your Screens Look Outstanding","text":"Tell us about your brand, your locations, and what you want your screens to do. We'll put together a creative plan and a clear quote — no obligation.","btnText":"Start a Project","btnUrl":"/contact"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
@@ -1,29 +1,47 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Page: Devices
|
* Title: Devices
|
||||||
* Slug: devices
|
* Slug: devices
|
||||||
* Pushed by Oribi Tech Sync on 2026-02-20 22:07:33.
|
* Post Type: page
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return <<<'ORIBI_SYNC_CONTENT'
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Hardware","title":"Player Devices Built for Reliability","description":"Our digital signage players are engineered for performance, security, and simplicity. Plug in, connect, and start displaying. Itu0027s that easy."} /-->
|
<!-- wp:oribi/page-hero-animated {"label":"Hardware","title":"Signage Players Engineered for the Real World","description":"Compact, silent, and built for 24/7 operation. Plug into any HDMI screen, connect to your network, and your content is live in minutes."} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/platform-section {"label":"Our Devices","heading":"Hardware That Just Works","lead":"Purpose-built player devices designed for 24/7 commercial use with zero maintenance."} -->
|
<!-- wp:oribi/platform-section {"label":"Our Devices","heading":"Commercial-Grade Hardware, Consumer-Level Simplicity","lead":"Our players are designed to be set up in minutes and forgotten about for years. No IT degree required. "} -->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Use Existing Screens","description":"Our digital signage players work on any screen with HDMI, so you can easily integrate them into your current setup. No need to replace your existing displays. Just plug in our player and start broadcasting. If you need a complete solution, we also offer bundled packages that include both the player and a high-quality commercial-grade display.","btnText":"Get a Quote","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/platform-row {"heading":"Works With Your Existing Screens","description":"Our player devices connect to any screen with an HDMI port, no proprietary hardware required. Already have displays? Plug in and go. Need a full setup? We offer bundled player-and-display packages too.","btnText":"Get a Quote","btnUrl":"/contact","deviceAnim":true} /-->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Intelligent Offline Playback","description":"Our player devices are engineered to keep your message on screen, even when the internet isnu0027t available. Content is cached locally so your displays continue running seamlessly. When connectivity returns, new content syncs automatically, no manual intervention needed.","btnText":"See Features","btnUrl":"/features","reversed":true} /-->
|
|
||||||
<!-- wp:oribi/platform-row {"heading":"Enterprise-Grade Security","description":"Every device is hardened with enterprise-grade security protocols. Encrypted communications, secure boot, and remote management capabilities ensure your signage network stays protected. Automatic firmware updates keep your devices current without any downtime.","btnText":"Learn More","btnUrl":"/about"} /-->
|
<!-- wp:oribi/platform-row {"heading":"Never Goes Dark","description":"Every player caches content locally. If your internet connection drops, your displays continue running seamlessly with the latest synced content. When connectivity returns, new content pulls down automatically. No manual steps, no reboots.","btnText":"See Features","btnUrl":"/features","reversed":true,"neverGoesDark":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Custom Display Solutions","description":"Create a polished, on-brand experience with our Custom Display Platform. Seamlessly integrated with your interactive signage, it ensures your logo and branding appear consistently across every screen, reinforcing recognition at every touchpoint. Ideal for businesses looking to elevate their presence and deliver a professional, cohesive visual identity.","btnText":"Get a Quote","btnUrl":"/contact","brandedAnim":true} /-->
|
||||||
<!-- /wp:oribi/platform-section -->
|
<!-- /wp:oribi/platform-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/feature-section {"variant":"alt","label":"Device Specifications","heading":"Whatu0027s Inside Every Player","lead":"Commercial-grade components designed for continuous operation in any environment.","columns":3} -->
|
<!-- wp:oribi/feature-section {"variant":"alt","label":"Device Specifications","heading":"What's Inside Every Player","lead":"Purpose-built components selected for reliability, performance, and silent operation in any environment."} -->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-display","title":"4K Output","description":"Crystal-clear 4K resolution output via HDMI for stunning visual quality on any display."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-display","title":"4K Output","description":"Crisp 4K resolution over HDMI for stunning visuals on any display size, from 32-inch panels to 75-inch video walls."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Dual Connectivity","description":"Built-in Wi-Fi and Ethernet for flexible network connectivity options in any installation."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-hard-drive","title":"Local Storage","description":"On-device storage caches your content for seamless offline playback and instant startup."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Dual Connectivity","description":"We offer players with Wi-Fi and Ethernet connectivity. Choose the connection that suits your environment, or use both for redundancy."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-shield-halved","title":"Secure Boot","description":"Hardware-level security with encrypted storage and secure boot ensures tamper-proof operation."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rotate","title":"Auto Updates","description":"Over-the-air firmware updates keep your devices current without manual intervention or downtime."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-hard-drive","title":"Local Storage","description":"On-device storage caches your full content library for instant startup and uninterrupted offline playback."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-temperature-low","title":"Silent Operation","description":"Fanless design means zero noise, making our players perfect for quiet environments like lobbies and restaurants."} /-->
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rotate","title":"Over-the-Air Updates","description":"Firmware updates deploy remotely and automatically. Your devices stay current without site visits or manual intervention."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-temperature-low","title":"Silent \u0026amp; Fanless","description":"Passive cooling means zero noise. Ideal for quiet spaces like hotel lobbies, meeting rooms, and restaurants."} /-->
|
||||||
<!-- /wp:oribi/feature-section -->
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/intro-section {"variant":"normal","label":"Bundles Available","heading":"Complete Display Solutions","description":"Need screens too? We offer bundled packages that include our player device paired with a commercial-grade display, rated for 24/7 operation with enhanced brightness and durability. Available in a range of sizes from 32" to 75". Contact us for custom configurations and volume pricing.","visual":""} /-->
|
<!-- wp:html -->
|
||||||
|
<section class="section">
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Need Help Choosing?","text":"Our team can recommend the right device and display combination for your specific environment and use case.","btnText":"Request a Quote","btnUrl":"/contact"} /-->
|
<div class="container">
|
||||||
|
<div class="devices-split-card">
|
||||||
|
<div class="devices-split-card__panel">
|
||||||
|
<h3>Pre-Configured OTS Players</h3>
|
||||||
|
<p>Every player device ordered through OTS arrives pre-configured and already paired with your Command Center. Plug in power and HDMI, connect to your network, and your screens are ready to publish.</p>
|
||||||
|
</div>
|
||||||
|
<div class="devices-split-card__panel devices-split-card__panel--brand">
|
||||||
|
<h3>Bring Your Own Player (BYO)</h3>
|
||||||
|
<p>Already have compatible media players? We can onboard BYO hardware and connect it to your Command Center. Our team will confirm compatibility requirements and provide setup guidance before rollout.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- /wp:html -->
|
||||||
ORIBI_SYNC_CONTENT;
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,33 +1,42 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: FAQ
|
* Title: Faq
|
||||||
* Slug: ots-signs/page-faq
|
* Slug: faq
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: faq, questions, answers, support, help
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"FAQ","title":"Frequently Asked Questions","description":"Got questions? We\u0027ve got answers. Find everything you need to know about our digital signage platform, pricing, and support."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/faq-section {"label":"Platform \u0026 Pricing","heading":"Plans, Pricing \u0026 Platform","lead":"Common questions about our plans, what\u0027s included, and how pricing works."} -->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/faq-item {"question":"What\u0027s included in the Essentials plan?","answer":"The Essentials plan includes up to 20 screens, a custom subdomain, shared CMS server, content scheduling with day-parting, integration with live data sources, unlimited user seats, and the ability to publish content to your signs in minutes. It\u0027s $7 per screen per month, or $70 per screen annually."} /-->
|
<!-- wp:oribi/page-hero-animated {"label":"FAQ","title":"Your Questions, Answered","description":"Everything you need to know about our platform, pricing, setup, and support, in plain language."} /-->
|
||||||
<!-- wp:oribi/faq-item {"question":"What does the Pro plan include?","answer":"The Pro plan supports 500+ screens with a custom domain, dedicated CMS server, custom live data integrations, priority support, advanced analytics, SSO and role-based access, SLA guarantee, and a dedicated account manager. Contact us for pricing tailored to your needs."} /-->
|
|
||||||
<!-- wp:oribi/faq-item {"question":"Are there any hidden fees?","answer":"No. Our pricing is fully transparent. The per-screen monthly or annual fee covers everything. CMS access, software updates, cloud hosting, and standard support. Content creation services and hardware are quoted separately."} /-->
|
<!-- wp:oribi/faq-section {"label":"Platform u0026 Pricing","heading":"Plans, Pricing \u0026amp; What's Included","lead":"Straightforward answers about what you get and what it costs."} -->
|
||||||
<!-- wp:oribi/faq-item {"question":"Can I switch plans later?","answer":"Absolutely. You can upgrade from Essentials to Pro at any time as your business grows. We\u0027ll handle the migration seamlessly with no disruption to your displays."} /-->
|
<!-- wp:oribi/faq-item {"question":"What's included in the Essentials plan?","answer":"Essentials gives you up to 50 screens on a shared CMS instance with a custom subdomain. You get full content scheduling with day-parting, DataSets, RSS feeds, social widgets, embedded HTML, menu boards, interactive layouts, Canva integration, offline playback, Proof of Play analytics with 30-day retention, unlimited users with standard roles, and two-factor authentication. Pricing is $7 per screen per month, or $70 per screen if you pay annually."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"What extra do I get with Pro?","answer":"Pro gives you unlimited screens on a dedicated CMS instance with a custom domain. On top of everything in Essentials, you get geo-location and weather-triggered scheduling, video wall support, ad campaigns with SSP monetisation, Dashboard Connector and custom API integrations, Audience Reporting with scheduled PDF reports, Proof of Play with 12+ month retention, SSO via SAML or CAS, custom user roles, extended audit trails, display map view, shell commands, in-house creative services, white-glove onboarding, priority support with a 4-hour SLA, a dedicated account manager, and a contractual SLA guarantee. Contact us for a tailored quote."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"Are there any hidden fees?","answer":"None. Your per-screen fee covers the CMS, cloud hosting, software updates, and standard support. Content creation services and hardware are quoted separately and always upfront."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"Can I upgrade later?","answer":"Yes, at any time. Moving from Essentials to Pro is seamless. We handle the migration behind the scenes with no disruption to your live displays."} /-->
|
||||||
<!-- /wp:oribi/faq-section -->
|
<!-- /wp:oribi/faq-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/faq-section {"variant":"alt","label":"Setup \u0026 Integration","heading":"Getting Started","lead":"Everything about setup, installation, and integrating with your existing systems."} -->
|
<!-- wp:oribi/faq-section {"variant":"alt","label":"Setup \u0026 Integration","heading":"Getting Up and Running","lead":"What to expect when you set up your first screen and connect your systems."} -->
|
||||||
<!-- wp:oribi/faq-item {"question":"How long does setup take?","answer":"Most installations are up and running within a day. Plug in our player device, connect to your network, and your content appears on screen. Our team handles the CMS configuration and can have your first content ready to display immediately."} /-->
|
<!-- wp:oribi/faq-item {"question":"How quickly can I be up and running?","answer":"Most installations go live within a day. Plug in the player device, connect it to your network, and your content appears on screen. We configure your CMS in advance and can have your first content loaded and ready before the hardware arrives."} /-->
|
||||||
<!-- wp:oribi/faq-item {"question":"Can I use my existing screens?","answer":"Yes! Our players work with any screen that has an HDMI input. TVs, commercial displays, or monitors. If it has HDMI, our player works with it. No need to replace your existing hardware."} /-->
|
|
||||||
<!-- wp:oribi/faq-item {"question":"How do live data integrations work?","answer":"We can connect your existing web dashboards, APIs, RSS feeds, social media accounts, and other data sources to your digital signage. Data updates are reflected in real-time on your displays. The Essentials plan supports standard integrations, while Pro includes custom integration development."} /-->
|
<!-- wp:oribi/faq-item {"question":"Do I need to buy new screens?","answer":"No. Our players work with any display that has an HDMI port, consumer TVs, commercial panels, or monitors you already own. If you do need screens, we offer bundled player-and-display packages built for commercial use."} /-->
|
||||||
<!-- wp:oribi/faq-item {"question":"Do I need special internet bandwidth?","answer":"Our players are designed to be bandwidth-efficient. Content is cached locally and synced incrementally. A standard business internet connection is more than sufficient. For locations with limited connectivity, our offline playback ensures your content keeps running."} /-->
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"How do live data integrations work?","answer":"Every plan includes DataSets, RSS feeds, social widgets, and embedded HTML, data updates appear on screen in real time. Pro adds the Dashboard Connector for secure third-party service connections, custom API integrations for bespoke data sources, and the SSP Connector for ad monetisation."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"What kind of internet connection do I need?","answer":"A standard business broadband connection is more than enough. Our players sync content incrementally and cache everything locally, so bandwidth usage is minimal. For locations with unreliable connectivity, offline playback ensures your displays never go dark."} /-->
|
||||||
<!-- /wp:oribi/faq-section -->
|
<!-- /wp:oribi/faq-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/faq-section {"label":"Support \u0026 Security","heading":"Support, Security \u0026 Reliability","lead":"How we keep your signage network secure, reliable, and fully supported."} -->
|
<!-- wp:oribi/faq-section {"label":"Support u0026 Security","heading":"Keeping Your Network Secure and Supported","lead":"How we protect your content, keep your screens online, and support you when you need us."} -->
|
||||||
<!-- wp:oribi/faq-item {"question":"What happens if my internet goes down?","answer":"Our intelligent player devices continue playing cached content even when offline. When connectivity returns, new content syncs automatically. Your displays never go dark."} /-->
|
<!-- wp:oribi/faq-item {"question":"What happens if the internet goes down?","answer":"Your displays carry on. Every player caches content locally and keeps playing even without a connection. When the internet returns, new content syncs automatically. Your screens will never go dark because of a network blip."} /-->
|
||||||
<!-- wp:oribi/faq-item {"question":"How secure is the platform?","answer":"We use enterprise-grade security throughout our stack: end-to-end encryption for all communications, secure boot on player devices, role-based access control in the CMS, and SOC 2-aligned cloud infrastructure. Your content and network are always protected."} /-->
|
|
||||||
<!-- wp:oribi/faq-item {"question":"What kind of support do you offer?","answer":"Essentials plans include email support with a 24-hour response time. Pro plans include priority support with a dedicated account manager, phone support, and guaranteed SLA response times."} /-->
|
<!-- wp:oribi/faq-item {"question":"How secure is the platform?","answer":"Security runs through every layer: end-to-end encryption for all communications, secure boot and encrypted storage on player devices, role-based access control in the CMS, and SOC 2-aligned cloud infrastructure. Your content and your network stay protected."} /-->
|
||||||
<!-- wp:oribi/faq-item {"question":"Can I create content myself, or do you do it for me?","answer":"Both! Our CMS is designed for self-service content creation with drag-and-drop simplicity. We also offer professional content creation services: photography, video production, and graphic design, to make your signage look its absolute best."} /-->
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"What support is available?","answer":"Essentials customers get email support with next-business-day response. Pro customers get priority support, a dedicated account manager, phone access, and guaranteed SLA response times."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/faq-item {"question":"Can I create my own content or do you handle it?","answer":"Both. The CMS is designed for self-service content creation with drag-and-drop simplicity. If you'd prefer polished visuals, our in-house creative team offers professional photography, video production, and graphic design services."} /-->
|
||||||
<!-- /wp:oribi/faq-section -->
|
<!-- /wp:oribi/faq-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Still Have Questions?","text":"Our team is happy to answer anything not covered here. Get in touch and we\u0027ll help.","btnText":"Contact Us","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"Something Not Covered Here?","text":"Drop us a message and we'll get back to you with a clear answer, usually within one business day.","btnText":"Contact Us","btnUrl":"/contact"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,34 +1,72 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Features
|
* Title: Features
|
||||||
* Slug: ots-signs/page-features
|
* Slug: features
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: features, platform, content scheduling, cloud CMS, real-time data
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Platform","title":"Technology Designed to Work for You","description":"Our application platform lets you publish content instantly across any network, with built-in real-time analytics. Its secure, cloud-native architecture scales effortlessly while keeping deployments fast and maintenance minimal."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/platform-section {"label":"Core Features","heading":"Powerful Tools, Simple Experience","lead":"Everything you need to create, schedule, and manage stunning digital signage content, from a single dashboard."} -->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/platform-row {"heading":"Manage All Your Screens in One Place","description":"Our cloud CMS offers the power and flexibility to manage digital displays for businesses of all sizes. Whether you\u0027re a single location or a multi-site enterprise, our digital signage network is built to grow with you.","btnText":"Get Started","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/page-hero-animated {"label":"Platform Features","title":"Create It. Schedule It. Forget It.","description":"Design content in minutes, automate your schedule, and let your screens run themselves. One cloud dashboard for every display in your network — with live data, real-time analytics, and the tools your whole team can use from day one."} /-->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Dynamic Content Scheduling","description":"Effortlessly schedule your content for maximum impact. Plan ahead by setting content to play at specific times, daypart, or even trigger based on real-world events. Automate your messaging to ensure the right information is displayed at the right time.","btnText":"See Pricing","btnUrl":"/pricing","reversed":true} /-->
|
|
||||||
<!-- wp:oribi/platform-row {"heading":"Use Existing Screens","description":"Our digital signage players work on any screen with HDMI, so you can easily integrate them into your current setup. If you need a complete solution, we also offer bundled packages that include both the player and a high-quality commercial-grade display.","btnText":"View Devices","btnUrl":"/devices"} /-->
|
<!-- wp:oribi/platform-section {"label":"Create \u0026amp; Publish","heading":"From Idea to Screen in Minutes","lead":"A drag-and-drop layout designer, a built-in media library, and instant publishing — so your content goes live the moment it's ready."} -->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Secure \u0026 Reliable","description":"Enterprise-grade security safeguards your content and network, while our advanced hosting platform guarantees rock-solid reliability. Plus, our intelligent player devices are designed to continue playing content even when offline.","btnText":"Learn More","btnUrl":"/about","reversed":true} /-->
|
<!-- wp:oribi/platform-row {"heading":"Design for Any Screen","description":"Build layouts visually with a drag-and-drop editor that works in any browser. Use ready-made stencils or start from scratch. Layer text, images, video, tickers, and data widgets across multiple zones — then preview exactly how it will look on screen before you publish. Save any layout as a reusable template for your team.","btnText":"Request Demo","btnUrl":"/demo"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Every Media Type, One Library","description":"Upload images, video (including H.265 and HLS streams), PDFs, PowerPoint files, and audio to a centralised media library. Tag, organise, and reuse assets across layouts and playlists. Set expiration dates on media so outdated content removes itself automatically. Need polished creative? Our in-house team handles photography, video production, and graphic design.","btnText":"Creative Services","btnUrl":"/design","reversed":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Publish Without the Wait","description":"Content goes live the moment you hit publish. A draft/publish workflow lets you edit layouts safely without affecting what's already on screen — then push updates across your entire network in one click. Schedule a layout to auto-publish at a specific date and time, or push it immediately. No queues, no approval chains, no delays.","btnUrl":"/pricing"} /-->
|
||||||
<!-- /wp:oribi/platform-section -->
|
<!-- /wp:oribi/platform-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/feature-section {"variant":"alt","label":"Capabilities","heading":"Built for Modern Business","lead":"From content creation to analytics, our platform covers every step of your digital signage journey.","columns":3} -->
|
<!-- wp:oribi/feature-section {"variant":"alt","label":"Smart Scheduling","heading":"Automate Your Entire Schedule","lead":"Set it once and let the platform handle the rest. Day-parting, recurring events, location-based triggers, and weather-driven rules keep the right content on the right screen at the right time."} -->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-cloud","title":"Cloud-Native CMS","description":"Access your content management system from anywhere. No software to install. Just log in and start publishing."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Day-Part Scheduling","description":"Assign content to specific times of day — breakfast menus in the morning, happy hour promos in the evening. Set it once and it repeats automatically."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Content Scheduling","description":"Set content to play at specific times with day-parting. Automate your messaging for maximum impact."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-line","title":"Live Data Integration","description":"Connect your existing web dashboards, social feeds, and real-time data sources directly to your displays."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-arrows-rotate","title":"Recurring Campaigns","description":"Schedule campaigns with daily, weekly, or custom recurrence patterns. Plan weeks of content ahead and let the platform execute on time, every time."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Offline Playback","description":"Content keeps playing even when the internet goes down. Our players cache content locally for uninterrupted display."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited User Seats","description":"Add as many team members as you need. No per-user fees or access restrictions on any plan."} /-->
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-location-dot","title":"Location \u0026amp; Weather Triggers","description":"Show region-specific promotions based on player location. Trigger content automatically when weather conditions change — sunscreen ads when it's sunny, hot drinks when it rains."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-shield-halved","title":"Enterprise Security","description":"End-to-end encryption, role-based access control, and secure cloud infrastructure protect your content and network."} /-->
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-bolt","title":"Interrupt \u0026amp; Priority Content","description":"Push emergency alerts or time-sensitive content to any screen instantly. Interrupt layouts override the schedule without disrupting your planned campaigns."} /-->
|
||||||
<!-- /wp:oribi/feature-section -->
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/value-section {"variant":"normal","label":"Why Choose Us","heading":"The OTS Signs Advantage","lead":"We don\u0027t just provide software. We deliver a complete digital signage experience.","columns":3} -->
|
<!-- wp:oribi/platform-section {"label":"Display Management","heading":"One Dashboard for Every Screen","lead":"Group, monitor, and control your entire display network — whether that's three screens in one venue or three hundred across the country."} -->
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-camera","title":"Professional Content","description":"Our in-house photography and video production team creates stunning visuals that make your signage stand out."} /-->
|
<!-- wp:oribi/platform-row {"heading":"Group, Target, Update","description":"Organise displays into groups by location, department, or purpose. Use dynamic groups that auto-populate based on tags or criteria. Push a content update to one screen, a group, or your whole network — all from one place. Nested groups let you build multi-level hierarchies that mirror your real-world structure.","btnText":"View Devices","btnUrl":"/devices"} /-->
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"Publish in Minutes","description":"Upload content and push it to your screens instantly. No waiting, no complex workflows. Just fast deployment."} /-->
|
|
||||||
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Dedicated Support","description":"Our team is always available to help with setup, content creation, troubleshooting, and ongoing optimisation."} /-->
|
<!-- wp:oribi/platform-row {"heading":"Monitor \u0026amp; Control Remotely","description":"See which screens are online at a glance. Take on-demand or periodic screenshots to verify content is playing correctly. Control screen power, volume, and brightness remotely. Get email alerts the moment a player goes offline. Map view shows every display's location so you always know what's where.","btnUrl":"/contact","reversed":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Runs on Your Hardware","description":"Our player software runs on Android, Windows, Linux, Samsung Tizen, LG webOS, and Chrome OS. Portrait or landscape. Single screen or synchronised video wall. Content is cached locally, so your displays keep running seamlessly even when the internet drops. Not sure which hardware to choose? We'll recommend and configure the right player for your setup.","btnText":"See Devices","btnUrl":"/devices"} /-->
|
||||||
|
<!-- /wp:oribi/platform-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-section {"variant":"alt","label":"Content Toolkit","heading":"Connect Your World to Screen","lead":"Pull in live data, social feeds, menus, dashboards, and third-party content. Everything updates automatically — no manual refreshing, no extra steps.","columns":3} -->
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-database","title":"Live Data Feeds","description":"Connect DataSets, remote JSON sources, and CSV imports directly to your layouts. Data refreshes automatically so your screens always show the latest information."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-utensils","title":"Digital Menu Boards","description":"Build product categories and pricing lists that update across every location. Change a price once and it's live everywhere — no screen-by-screen editing."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-code","title":"Web Pages \u0026amp; Dashboards","description":"Embed any web page, internal dashboard, or HTML content directly on screen. Show operational KPIs, analytics dashboards, or custom web apps in real time."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rss","title":"Tickers \u0026amp; Social Feeds","description":"Display RSS news tickers, social media feeds, and live notifications. Keep your audience informed with auto-updating content streams."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-palette","title":"Canva \u0026amp; Stock Images","description":"Design in Canva and publish straight to your displays — no export/import steps. Browse Pixabay's stock image library directly from the CMS."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-hand-pointer","title":"Interactive Touchscreens","description":"Add buttons, navigation, and actions to your layouts. Let your audience browse products, find directions, or explore content on touch-enabled displays."} /-->
|
||||||
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-section {"label":"Analytics \u0026amp; Reporting","heading":"Prove Every Play","lead":"Know exactly what's playing, where, and when. Export reports, automate delivery, and monitor the health of every screen in your network."} -->
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-pie","title":"Proof of Play","description":"Track every piece of content at the layout, media, and widget level. Configurable retention depth lets you store as much history as you need."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-file-pdf","title":"Scheduled Reports","description":"Set up automated PDF reports and have them emailed to stakeholders on your schedule. Export raw data as CSV for deeper analysis."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-heart-pulse","title":"Display Health","description":"Monitor connection status, storage usage, and player performance in real time. Spot issues before they affect your audience."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-box-archive","title":"Content Usage","description":"See which media is assigned to layouts and which is unused. Library usage reports by user help you manage storage and keep your library clean."} /-->
|
||||||
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-section {"variant":"alt","label":"Secure \u0026amp; Scalable","heading":"Enterprise Trust, Simple Setup","lead":"Every plan includes the security foundations your business needs. Scale your team and your network without worrying about per-user fees or access limits.","columns":4} -->
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-lock","title":"Two-Factor Auth","description":"Secure every login with 2FA on every plan. TLS/HTTPS encryption protects all connections between your CMS and player devices."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-user-shield","title":"Roles \u0026amp; Permissions","description":"Predefined admin, editor, and viewer roles on every plan. Pro adds SSO via SAML or CAS, custom role definitions, and feature-level access control."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-clipboard-list","title":"Audit Trail","description":"Full activity logging with configurable retention. Know who changed what, when — for compliance, accountability, and peace of mind."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited Users","description":"Invite your entire team at no extra cost. No per-seat charges, no access restrictions, no gatekeeping — on any plan."} /-->
|
||||||
<!-- /wp:oribi/value-section -->
|
<!-- /wp:oribi/value-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"See It in Action","text":"Request access to our live demo instance and experience the platform for yourself.","btnText":"Request Demo","btnUrl":"/demo"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"More Than Just Software","text":"Our in-house creative team produces professional photography, video, and graphic design for your screens. Our support team is available when you need us — not hidden behind a ticket queue. Get hands-on access to a live demo and see every feature in action.","btnText":"Request Demo","btnUrl":"/demo"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Home Page
|
* Title: Home
|
||||||
* Slug: ots-signs/page-home
|
* Slug: home
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: home, digital signage, landing, hero
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/hero-animated {"label":"● Digital Signage Solutions","title":"Turn any screen into a dynamic communication tool.","highlightWord":"dynamic","description":"Digital signage is the modern way to connect with your audience. From eye-catching retail displays to dynamic informational screens, we craft tailored solutions that capture attention and deliver your message.","primaryBtnText":"Get Started","primaryBtnUrl":"/contact","secondaryBtnText":"Request Demo","secondaryBtnUrl":"/demo","stat1Value":"6+","stat1Label":"Industries Served","stat2Value":"500+","stat2Label":"Screens Supported","stat3Value":"99.9%","stat3Label":"Uptime"} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/feature-section {"variant":"normal","label":"The Complete Package","heading":"Everything You Need for Engaging Digital Signage","lead":"High-quality visuals, real-time data, and reliable playback, all managed from one powerful platform.","columns":4} -->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-camera","title":"Showcase Your Products","description":"Professional photography and video production services to showcase your products, services, or environment with polished, engaging content.","url":"/features"} /-->
|
<!-- wp:oribi/hero-animated {"label":"● Digital Signage Solutions","title":"Turn any screen into a dynamic communication tool.","highlightWord":"dynamic","description":"Digital signage is the modern way to connect with your audience. From eye-catching retail displays to dynamic informational screens, we craft tailored solutions that capture attention and deliver your message.","secondaryBtnText":"Request Demo","secondaryBtnUrl":"/demo","stat1Value":"4K","stat1Label":"Resolution Supported","stat2Value":"500+","stat2Label":"Screens Supported","stat3Value":"99.9%","stat3Label":"Uptime"} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-line","title":"Live Data Integrations","description":"Integrate your existing web dashboards and real-time data with our platform to bring your most important information to life on digital signage.","url":"/features"} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-utensils","title":"Digital Menu Boards","description":"Make your menu as appealing as your product. We incorporate your branding and include high-quality photography to showcase your offerings.","url":"/solutions"} /-->
|
<!-- wp:oribi/use-cases /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Offline Playback Support","description":"Our intelligent player devices keep your message on screen even when the internet isn\u0027t available, ensuring reliability in any location.","url":"/devices"} /-->
|
|
||||||
|
<!-- wp:oribi/platform-section {"label":"The Complete Package","heading":"Everything You Need for Engaging Digital Signage","lead":"High-quality visuals, real-time data, and reliable playback, all managed from one powerful platform."} -->
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Professional Content Creation","description":"Our in-house photography and video production services showcase your products, services, and environment with polished, engaging visuals. From digital menu boards to branded promotions, we create content that captures attention.","btnText":"Creative Services","btnUrl":"/design","cameraAnim":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Live Data \u0026amp; Web Dashboards","description":"Integrate your existing web dashboards, social feeds, and real-time data sources directly to your displays. Bring your most important information to life on screen, automatically and effortlessly.","btnUrl":"/features","reversed":true,"isDashboard":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Reliable on Any Screen","description":"Our intelligent player devices work on any screen with HDMI, and keep your message running even when the internet goes down. Enterprise-grade hardware designed for uninterrupted, always-on signage.","btnText":"View Devices","btnUrl":"/devices","tvStick":true} /-->
|
||||||
|
<!-- /wp:oribi/platform-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-section {"variant":"alt","label":"Who It's For","heading":"Solutions for Every Industry","lead":"Modern businesses need real-time communication. Digital signage helps you connect, inform, and engage.","columns":4} -->
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-hotel","title":"Hospitality","description":"Showcase menus, promotions, and special events while guiding guests through lobbies, restaurants, and bars.","url":"/solutions"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-store","title":"Retail","description":"Drive product upsells, announce flash-sales, and offer in-store navigation with fresh, eye-catching displays.","url":"/solutions"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-building","title":"Corporate","description":"Enhance meeting experiences with Teams integration. Communicate schedules, company news, and employee alerts.","url":"/solutions"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-graduation-cap","title":"Education","description":"Broadcast class schedules, announcements, and interactive learning content in campuses and auditoriums.","url":"/solutions"} /-->
|
||||||
<!-- /wp:oribi/feature-section -->
|
<!-- /wp:oribi/feature-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/image-section {"variant":"alt","label":"Who It's For","heading":"Solutions for Every Industry","lead":"Modern businesses need real-time communication. Digital signage helps you connect, inform, and engage.","columns":4} -->
|
<!-- wp:oribi/cta-banner {"heading":"Ready to Transform Your Screens?","text":"See our plans, explore player devices, or request a live demo. No pressure, just a conversation about how we can help.","btnText":"Get Started","btnUrl":"/contact"} /-->
|
||||||
<!-- wp:oribi/image-card {"iconType":"fontawesome","faIcon":"fas fa-hotel","title":"Hospitality","description":"Showcase menus, promotions, and special events while guiding guests through lobbies, restaurants, and bars.","url":"/solutions"} /-->
|
ORIBI_SYNC_CONTENT;
|
||||||
<!-- wp:oribi/image-card {"iconType":"fontawesome","faIcon":"fas fa-store","title":"Retail","description":"Drive product upsells, announce flash-sales, and offer in-store navigation with fresh, eye-catching displays.","url":"/solutions"} /-->
|
|
||||||
<!-- wp:oribi/image-card {"iconType":"fontawesome","faIcon":"fas fa-building","title":"Corporate","description":"Enhance meeting experiences with Teams integration. Communicate schedules, company news, and employee alerts.","url":"/solutions"} /-->
|
|
||||||
<!-- wp:oribi/image-card {"iconType":"fontawesome","faIcon":"fas fa-graduation-cap","title":"Education","description":"Broadcast class schedules, announcements, and interactive learning content in campuses and auditoriums.","url":"/solutions"} /-->
|
|
||||||
<!-- /wp:oribi/image-section -->
|
|
||||||
|
|
||||||
<!-- wp:oribi/link-section {"label":"Explore","heading":"Take the Next Step","lead":"See our plans, explore devices, or request a demo.","columns":3} -->
|
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-tags","title":"Pricing Plans","description":"Affordable, scalable options for businesses of all sizes. See what\u0027s included at every level.","linkText":"View Pricing","linkUrl":"/pricing"} /-->
|
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-microchip","title":"Player Devices","description":"Enterprise-grade hardware designed for reliability, with offline playback and HDMI compatibility.","linkText":"See Devices","linkUrl":"/devices"} /-->
|
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-play-circle","title":"Request a Demo","description":"See our platform in action. Request access to our live demo instance.","linkText":"Try It Out","linkUrl":"/demo"} /-->
|
|
||||||
<!-- /wp:oribi/link-section -->
|
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Ready to Transform Your Screens?","text":"Get in touch to discuss your digital signage needs. No pressure, no jargon. Just a conversation about how we can help.","btnText":"Get Started Today","btnUrl":"/contact"} /-->
|
|
||||||
|
|||||||
@@ -1,26 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Pricing
|
* Title: Pricing
|
||||||
* Slug: ots-signs/page-pricing
|
* Slug: pricing
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: pricing, plans, affordable, scalable, essentials, pro
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Pricing","title":"Affordable Solutions, Scalable Options","description":"Simple, transparent pricing designed to grow with your business. Every plan includes our core platform features, no hidden fees, no surprises."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/feature-section {"variant":"normal","label":"All Plans Include","heading":"Core Features on Every Plan","lead":"No matter which plan you choose, you get the full power of our digital signage platform.","columns":4} -->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Content Scheduling","description":"Day-parting, time-based triggers, and automated content rotation included on every plan."} /-->
|
<!-- wp:oribi/page-hero-animated {"label":"Pricing","title":"Straightforward Pricing, No Surprises","description":"Every plan includes the full content engine. Scale your infrastructure, integrations, and support as you grow. No hidden fees, no per-user charges."} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-line","title":"Live Data Integration","description":"Connect your web dashboards and real-time data sources directly to your digital signage."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited User Seats","description":"Add your entire team, no per-user charges or access limitations."} /-->
|
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"Publish in Minutes","description":"Upload content and push it to your screens instantly across your entire network."} /-->
|
|
||||||
<!-- /wp:oribi/feature-section -->
|
|
||||||
|
|
||||||
<!-- wp:oribi/pricing-section {"variant":"alt","label":"Choose Your Plan","heading":"Plans That Fit Your Business","lead":"Start small and scale as you grow. All plans come with our full-featured cloud CMS."} -->
|
<!-- wp:oribi/value-section {"label":"Included on Every Plan","heading":"The Full Content Engine, From Day One","lead":"Whether you choose Essentials or Pro, your team gets the same powerful tools to create, schedule, and publish.","columns":4} -->
|
||||||
<!-- wp:oribi/pricing-card {"name":"Essentials","tagline":"$7/Screen Monthly · $70/Screen Annually","features":["Up to 20 screens","Custom subdomain","Shared CMS server","Content scheduling & day-parting","Integration with live data sources","Unlimited user seats","Publish content in minutes","Offline playback support","Email support"],"btnText":"Get Started","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Automated Scheduling","description":"Day-parting, date ranges, and recurring schedules. Your content plays at exactly the right time, automatically."} /-->
|
||||||
<!-- wp:oribi/pricing-card {"name":"Pro","tagline":"Contact us for more information","features":["500+ screens","Custom domain","Dedicated CMS server","Custom live data integrations","Priority support","Advanced analytics","SSO & role-based access","SLA guarantee","Dedicated account manager"],"btnText":"Contact Sales","btnUrl":"/contact","featured":true,"badge":"Enterprise"} /-->
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rss","title":"Live Data to Screen","description":"Pull DataSets, RSS feeds, social widgets, and embedded HTML directly to your displays, updated in real time."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited Team Access","description":"Invite everyone who needs access. No per-user fees, no seat limits, no gatekeeping."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"Instant Publishing","description":"Upload content and push it live across your network in seconds, not hours."} /-->
|
||||||
|
<!-- /wp:oribi/value-section -->
|
||||||
|
|
||||||
|
<!-- wp:oribi/pricing-section {"variant":"alt","label":"Choose Your Plan","heading":"Scale When You're Ready","lead":"Start with Essentials and upgrade seamlessly as your network grows. No disruption, no data loss."} -->
|
||||||
|
<!-- wp:oribi/pricing-card {"name":"Essentials","tagline":"The full content engine for growing networks","price":"$7","pricePer":"per screen / month · or $70/screen annually","features":["Up to 50 screens","Custom subdomain","Shared CMS instance","Content scheduling \u0026amp; day-parting","DataSets, RSS, social embedded widgets","Menu boards \u0026amp; interactive layouts","Unlimited users with standard roles","Canva integration","Offline playback","Proof of Play analytics (30-day retention)","Email support (next-business-day)"]} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/pricing-card {"name":"Pro","tagline":"Dedicated infrastructure, enterprise integrations u0026 white-glove service","price":"Custom","pricePer":"tailored to your network size","features":["Unlimited screens","Custom domain","Dedicated CMS instance","Geo-location \u0026amp; weather-triggered scheduling","Dashboard Connector \u0026amp; custom API integrations","Video wall support","Ad campaigns \u0026amp; SSP monetisation","SSO (SAML/CAS) \u0026amp; custom user roles","Proof of Play analytics (12+ month retention)","Audience Reporting \u0026amp; scheduled PDF reports","Priority support (4-hour SLA)","Contractual SLA guarantee","Custom Live Data Integrations"],"btnText":"Contact Sales","featured":true,"badge":"Enterprise"} /-->
|
||||||
<!-- /wp:oribi/pricing-section -->
|
<!-- /wp:oribi/pricing-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/intro-section {"variant":"normal","label":"Try Before You Buy","heading":"Want to See How Our Platform Works?","description":"Request access to our demo instance and explore the full platform, no commitment required. See how easy it is to create, schedule, and publish digital signage content.","visual":""} /-->
|
<!-- wp:oribi/comparison-table {"label":"Plan Comparison","heading":"See Exactly What's Included","lead":"A full breakdown of what you get on each plan — so there are no surprises.","columns":["Essentials","Pro"],"rows":[{"group":"Scale u0026 Infrastructure"},{"feature":"Screen limit","values":["Up to 50","Unlimited"]},{"feature":"CMS instance","values":["Shared","Dedicated"]},{"feature":"Custom subdomain","values":[true,true]},{"feature":"Custom domain","values":[false,true]},{"group":"Content u0026 Scheduling"},{"feature":"Day-parting u0026 date scheduling","values":[true,true]},{"feature":"Playlists u0026 campaigns","values":[true,true]},{"feature":"Menu boards","values":[true,true]},{"feature":"Interactive touchscreen actions","values":[true,true]},{"feature":"Overlay layouts","values":[true,true]},{"feature":"Geo-location scheduling","values":[false,true]},{"feature":"Weather-triggered scheduling","values":[false,true]},{"feature":"Video wall","values":[false,true]},{"feature":"Ad campaigns u0026 plays-per-hour control","values":[false,true]},{"group":"Data u0026 Integrations"},{"feature":"DataSets, RSS u0026 tickers","values":[true,true]},{"feature":"Embedded HTML u0026 web pages","values":[true,true]},{"feature":"Social feeds","values":[true,true]},{"feature":"Canva integration","values":[true,true]},{"feature":"Dashboard Connector","values":[false,true]},{"feature":"Custom API integrations","values":[false,true]},{"feature":"SSP Connector (ad monetisation)","values":[false,true]},{"feature":"Custom Live Data Integrations","values":[false,true]},{"group":"Analytics u0026 Reporting"},{"feature":"Proof of Play reporting","values":["30-day retention","12+ month retention"]},{"feature":"Scheduled PDF reports","values":[false,true]},{"feature":"Audience Reporting","values":[false,true]},{"feature":"Display health monitoring","values":[true,true]},{"group":"Users u0026 Security"},{"feature":"Unlimited user seats","values":[true,true]},{"feature":"Predefined roles (admin/editor/viewer)","values":[true,true]},{"feature":"Custom user roles u0026 feature access","values":[false,true]},{"feature":"Two-factor authentication","values":[true,true]},{"feature":"SSO (SAML / CAS)","values":[false,true]},{"feature":"Audit trail","values":["7-day retention","Extended retention"]},{"group":"Display Management"},{"feature":"Screen power on/off control","values":[true,true]},{"feature":"Offline playback","values":[true,true]},{"feature":"Portrait / landscape","values":[true,true]},{"feature":"Email alerts (player offline)","values":[true,true]},{"feature":"Periodic screenshots","values":[false,true]},{"feature":"Display map view","values":[false,true]},{"feature":"Shell commands u0026 RS232","values":[false,true]},{"group":"Support u0026 Services"},{"feature":"Email support","values":["Next-business-day",true]},{"feature":"Priority support","values":[false,"4-hour SLA"]},{"feature":"Dedicated account manager","values":[false,true]},{"feature":"In-house creative services","values":[false,"Included hours"]},{"feature":"White-glove onboarding","values":[false,true]},{"feature":"Contractual SLA guarantee","values":[false,true]}]} /-->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Ready to Get Started?","text":"Contact us to find the right plan for your business, or request a demo to see the platform in action.","btnText":"Get in Touch","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/intro-section {"label":"Try Before You Commit","heading":"Want to Explore the Platform First?","description":"Request access to our live demo instance and take the full CMS for a spin — create content, set up schedules, and see exactly how it works. No credit card, no obligation."} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/cta-banner {"heading":"Questions About Pricing?","text":"We're happy to walk you through the plans, build a custom quote, or set up a demo so you can see the value firsthand.","btnText":"Get in Touch","btnUrl":"/contact"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Resources
|
* Title: Resources
|
||||||
* Slug: ots-signs/page-resources
|
* Slug: resources
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: resources, documentation, guides, knowledge base, support
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Resources","title":"Knowledge \u0026 Support Resources","description":"Guides, documentation, and tools to help you get the most out of your digital signage platform."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/link-section {"variant":"normal","label":"Getting Started","heading":"Essential Resources","lead":"Everything you need to set up, manage, and optimise your digital signage network.","columns":3} -->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-book","title":"Getting Started Guide","description":"Step-by-step instructions to set up your first screen, configure your CMS, and publish your first content.","linkText":"Read the Guide","linkUrl":"/contact"} /-->
|
<!-- wp:oribi/page-hero-animated {"label":"Resources","title":"Guides, Docs u0026 Tools","description":"Everything you need to set up, manage, and get the most out of your digital signage — all in one place."} /-->
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-code","title":"API Documentation","description":"Developer resources for integrating your systems with our digital signage platform via REST API.","linkText":"View API Docs","linkUrl":"/contact"} /-->
|
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-plug","title":"Integration Guides","description":"How to connect live data sources, social media feeds, POS systems, and web dashboards to your displays.","linkText":"See Integrations","linkUrl":"/contact"} /-->
|
<!-- wp:oribi/link-section {"variant":"normal","label":"Getting Started","heading":"Hit the Ground Running","lead":"From first login to first screen, these resources walk you through every step.","columns":3} -->
|
||||||
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-book","title":"Quick Start Guide","description":"Set up your first screen, configure your CMS, and publish content — step by step, start to finish.","linkText":"Read the Guide","linkUrl":"/contact"} /-->
|
||||||
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-code","title":"API Documentation","description":"REST API reference for developers integrating their own systems, data sources, or workflows with OTS Signs.","linkText":"View API Docs","linkUrl":"/contact"} /-->
|
||||||
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-plug","title":"Integration Guides","description":"Connect POS systems, social feeds, web dashboards, and third-party APIs to your signage displays.","linkText":"See Integrations","linkUrl":"/contact"} /-->
|
||||||
<!-- /wp:oribi/link-section -->
|
<!-- /wp:oribi/link-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/link-section {"variant":"alt","label":"Support","heading":"Help \u0026 Support","lead":"Get assistance with setup, troubleshooting, or any questions about the platform.","columns":3} -->
|
<!-- wp:oribi/link-section {"variant":"alt","label":"Support","heading":"Get Help When You Need It","lead":"Troubleshooting, video walkthroughs, and answers to common questions.","columns":3} -->
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Support Portal","description":"Submit support tickets, track issue resolution, and access our knowledge base for common troubleshooting steps.","linkText":"Open Support Portal","linkUrl":"/contact"} /-->
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Support Portal","description":"Submit tickets, track resolutions, and search our knowledge base for step-by-step troubleshooting.","linkText":"Open Support Portal","linkUrl":"/contact"} /-->
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-video","title":"Video Tutorials","description":"Watch step-by-step video guides on content creation, scheduling, device management, and platform features.","linkText":"Watch Tutorials","linkUrl":"/contact"} /-->
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-video","title":"Video Tutorials","description":"Short, focused videos covering content creation, scheduling, device setup, and platform features.","linkText":"Watch Tutorials","linkUrl":"/contact"} /-->
|
||||||
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-question-circle","title":"FAQ","description":"Find answers to the most common questions about our platform, pricing, setup, and support options.","linkText":"Browse FAQ","linkUrl":"/faq"} /-->
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-question-circle","title":"FAQ","description":"Quick answers to the most common questions about pricing, setup, security, and support.","linkText":"Browse FAQ","linkUrl":"/faq"} /-->
|
||||||
<!-- /wp:oribi/link-section -->
|
<!-- /wp:oribi/link-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/feature-section {"variant":"normal","label":"Content Tools","heading":"Create Better Content","lead":"Tools and templates to help you create engaging digital signage content.","columns":3} -->
|
<!-- wp:oribi/link-section {"variant":"normal","label":"Content Tools","heading":"Make Your Screens Look Great","lead":"Templates, guidelines, and strategy tips to elevate the content on your displays.","columns":3} -->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-palette","title":"Template Library","description":"Browse our collection of professionally designed templates for menus, promotions, wayfinding, and informational displays.","url":"/contact"} /-->
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-palette","title":"Template Library","description":"Professionally designed, ready-to-use templates for menus, promotions, wayfinding, and informational layouts.","linkText":"Browse Templates","linkUrl":"/contact"} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-image","title":"Media Best Practices","description":"Guidelines for image resolution, video formats, file sizes, and aspect ratios optimised for digital signage.","url":"/contact"} /-->
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-image","title":"Media Specifications","description":"Recommended resolutions, video formats, file sizes, and aspect ratios for crisp, optimised signage content.","linkText":"View Specs","linkUrl":"/contact"} /-->
|
||||||
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-lightbulb","title":"Content Strategy Tips","description":"Learn how to structure your content rotation, day-parting schedules, and messaging for maximum audience impact.","url":"/contact"} /-->
|
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-lightbulb","title":"Content Strategy Tips","description":"Practical advice on content rotation, day-parting schedules, and messaging that keeps your audience engaged.","linkText":"Read Tips","linkUrl":"/contact"} /-->
|
||||||
<!-- /wp:oribi/feature-section -->
|
<!-- /wp:oribi/link-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Need Personalised Help?","text":"Our team is available to walk you through any aspect of the platform or help with content creation.","btnText":"Contact Support","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"Need a Hand?","text":"Our team is happy to walk you through any part of the platform, help with content, or answer questions one-on-one.","btnText":"Contact Us","btnUrl":"/contact"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
@@ -1,28 +1,36 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* Title: Industry Solutions
|
* Title: Solutions
|
||||||
* Slug: ots-signs/page-solutions
|
* Slug: solutions
|
||||||
* Categories: oribi-pages
|
* Post Type: page
|
||||||
* Keywords: solutions, industries, hospitality, retail, corporate, education, marketplace
|
|
||||||
* Post Types: page
|
|
||||||
*/
|
*/
|
||||||
?>
|
|
||||||
<!-- wp:oribi/page-hero-animated {"label":"Industry Solutions","title":"Solutions for Every Industry","description":"From hospitality to education, our digital signage platform adapts to the unique needs of your industry. Discover how we can transform your customer experience."} /-->
|
|
||||||
|
|
||||||
<!-- wp:oribi/platform-section {"label":"Industries We Serve","heading":"Tailored Solutions for Your Sector","lead":"Every industry has unique communication challenges. Our platform is built to address them all."} -->
|
return <<<'ORIBI_SYNC_CONTENT'
|
||||||
<!-- wp:oribi/platform-row {"heading":"Hospitality","description":"Showcase menus, promotions, and special events while guiding guests through lobbies, restaurants, and bars. Digital signage creates a premium guest experience, drives upsells, and keeps your visitors informed, from check-in to checkout. Integrate with your POS for real-time menu updates and pricing changes.","btnText":"Get Started","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/page-hero-animated {"label":"Industry Solutions","title":"Built for the Way You Work","description":"Every industry communicates differently. Our platform adapts to your environment — whether that's a hotel lobby, a shop floor, a boardroom, or a lecture hall."} /-->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Retail","description":"Drive product upsells, announce flash-sales, and offer in-store navigation with fresh, eye-catching displays. Digital signage in retail has been shown to increase sales by up to 30%. Our platform makes it easy to update promotions across all locations instantly with targeted, data-driven content.","btnText":"See Pricing","btnUrl":"/pricing","reversed":true} /-->
|
|
||||||
<!-- wp:oribi/platform-row {"heading":"Corporate Office","description":"Enhance your meeting experience with Microsoft Teams room integration. Communicate meeting schedules, company news, KPIs, and employee alerts with interactive dashboards. Transform your lobby and common areas into dynamic communication hubs that keep your workforce informed and engaged.","btnText":"Learn More","btnUrl":"/features"} /-->
|
<!-- wp:oribi/platform-section {"label":"Industries We Serve","heading":"One Platform, Tailored to Your Sector","lead":"We've worked with businesses across six key industries. Here's how our platform fits into each one."} -->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Education","description":"Broadcast class schedules, announcements, campus wayfinding, and interactive learning content in campuses and auditoriums. Digital signage helps educational institutions communicate effectively with students, faculty, and visitors across multiple buildings and campuses.","btnText":"Contact Us","btnUrl":"/contact","reversed":true} /-->
|
<!-- wp:oribi/platform-row {"heading":"Hospitality","description":"Digital menu boards that update with your POS, lobby displays that guide guests, and promotional screens that drive upsells in bars and restaurants. Create a polished guest experience from the moment they walk in — and keep it fresh without touching a single printed sign.","btnText":"Get Started","btnUrl":"/contact","galleryIds":[418,417]} /-->
|
||||||
<!-- wp:oribi/platform-row {"heading":"Outdoor Marketplace","description":"Whether it\u0027s a weekly farmers market or seasonal fairs, digital signage adds a modern, professional touch without losing the charm of the market experience. Weather-resistant display options and offline playback ensure your signage works reliably in any outdoor environment.","btnText":"Get a Quote","btnUrl":"/contact"} /-->
|
|
||||||
<!-- wp:oribi/platform-row {"heading":"Live Data Displays","description":"Connect your existing web dashboards and real-time data to our platform for customised digital signage displays that bring your key metrics and insights to life. Perfect for operations centres, trading floors, and management dashboards that need to be visible to entire teams.","btnText":"See Features","btnUrl":"/features","reversed":true} /-->
|
<!-- wp:oribi/platform-row {"heading":"Retail","description":"Launch promotions across every store instantly, spotlight seasonal products, and guide shoppers with in-store wayfinding. Retailers using digital signage see up to 30% more sales. Our platform makes it simple to keep content current, targeted, and data-driven across every location.","btnText":"See Pricing","btnUrl":"/pricing","reversed":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Corporate Office","description":"Meeting room displays with native Microsoft Teams integration, company-wide announcement boards, and live KPI dashboards in common areas. Turn your office into a connected, well-informed workplace where important information is always visible.","btnUrl":"/features"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Education","description":"Timetable displays, campus wayfinding, emergency alerts, and event boards — all managed centrally. Keep students, faculty, and visitors informed across multiple buildings without the overhead of maintaining individual screens.","btnText":"Contact Us","btnUrl":"/contact","reversed":true} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Outdoor Marketplace","description":"From farmers' markets to seasonal fairs, digital signage adds a professional edge without losing the character of your venue. Weather-resistant display options and built-in offline playback ensure your screens perform reliably, rain or shine.","btnText":"Get a Quote","btnUrl":"/contact"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/platform-row {"heading":"Live Data Displays","description":"Bring your web dashboards, real-time KPIs, and operational data to large-format screens. Ideal for operations centres, trading floors, and management war rooms where critical information needs to be visible to the entire team at a glance.","btnText":"See Features","btnUrl":"/features","reversed":true} /-->
|
||||||
<!-- /wp:oribi/platform-section -->
|
<!-- /wp:oribi/platform-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/stat-section {"variant":"alt","label":"By the Numbers","heading":"Impact Across Industries","lead":"Digital signage delivers measurable results for businesses of all sizes.","columns":4} -->
|
<!-- wp:oribi/stat-section {"variant":"alt","label":"By the Numbers","heading":"The Results Speak for Themselves","lead":"Businesses that invest in digital signage see measurable returns across every metric that matters.","columns":4} -->
|
||||||
<!-- wp:oribi/stat-card {"value":"400%","label":"Increase in Views","description":"Digital displays capture 400% more views than static signs."} /-->
|
<!-- wp:oribi/stat-card {"value":"400%","label":"More Views","description":"Digital displays capture 400% more attention than traditional static signage. <a href='https://mvix.com/blog/digital-signage-statistics/' target='_blank' rel='noopener'>Mvix Research →</a>"} /-->
|
||||||
<!-- wp:oribi/stat-card {"value":"30%","label":"Sales Uplift","description":"Retail digital signage drives up to 30% increase in sales."} /-->
|
|
||||||
<!-- wp:oribi/stat-card {"value":"80%","label":"Brand Awareness","description":"Customers recall digital signage content 80% of the time."} /-->
|
<!-- wp:oribi/stat-card {"value":"30%","label":"Revenue Uplift","description":"Retail locations with digital signage report up to 30% higher in-store sales. <a href='https://www.digitalsignagetoday.com/news/nielsen-study-dooh-increases-revenue-at-the-point-of-sale-2/' target='_blank' rel='noopener'>Nielsen DOOH Study →</a>"} /-->
|
||||||
<!-- wp:oribi/stat-card {"value":"50%","label":"Wait Time Perception","description":"Perceived wait times drop by 50% with engaging displays."} /-->
|
|
||||||
|
<!-- wp:oribi/stat-card {"value":"80%","label":"Content Recall","description":"Eight out of ten customers remember what they see on a digital display. <a href='https://www.databeat.net/databeatblog/15-surprising-statistics-about-digital-signage' target='_blank' rel='noopener'>Databeat Research →</a>"} /-->
|
||||||
|
|
||||||
|
<!-- wp:oribi/stat-card {"value":"50%","label":"Shorter Perceived Waits","description":"Engaging displays cut perceived wait times in half for customers in queues. <a href='https://www.digitalsignagetoday.com/articles/the-business-case-for-digital-signage-in-the-waiting-line/' target='_blank' rel='noopener'>Digital Signage Today →</a>"} /-->
|
||||||
<!-- /wp:oribi/stat-section -->
|
<!-- /wp:oribi/stat-section -->
|
||||||
|
|
||||||
<!-- wp:oribi/cta-banner {"heading":"Not Sure Which Solution Fits?","text":"Tell us about your industry and use case, and we\u0027ll recommend the perfect setup.","btnText":"Talk to an Expert","btnUrl":"/contact"} /-->
|
<!-- wp:oribi/cta-banner {"heading":"Let Us Match You to the Right Setup","text":"Tell us about your industry, your locations, and what you want your screens to do. We'll recommend the ideal configuration.","btnText":"Talk to an Expert","btnUrl":"/contact"} /-->
|
||||||
|
ORIBI_SYNC_CONTENT;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
157
theme/assets/js/dashboard-animator.js
Normal file
157
theme/assets/js/dashboard-animator.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* Dashboard Chart Animator
|
||||||
|
* Gently animates SVG bar charts, line graph, and pie chart.
|
||||||
|
* Pauses off-screen via IntersectionObserver for performance.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var SPEED = 0.002; // phase increment per frame
|
||||||
|
var BAR_H = 120; // max bar height (SVG units)
|
||||||
|
var BAR_MIN = 0.15; // min bar ratio
|
||||||
|
var LINE_PTS = 8;
|
||||||
|
var LINE_W = 340; // line graph width in SVG units
|
||||||
|
var PIE_R = 55; // pie chart radius
|
||||||
|
|
||||||
|
var DARK = { text: '#E0E0E0', muted: '#9E9E9E', border: '#333', center: '#1A1A1A' };
|
||||||
|
var LIGHT = { text: '#333333', muted: '#666666', border: '#E0E0E0', center: '#fff' };
|
||||||
|
|
||||||
|
function isDark() { return document.documentElement.getAttribute('data-theme') === 'dark'; }
|
||||||
|
function pal() { return isDark() ? DARK : LIGHT; }
|
||||||
|
|
||||||
|
function wave(t, off) {
|
||||||
|
return Math.max(0, Math.min(1,
|
||||||
|
0.55 +
|
||||||
|
Math.sin(t + off) * 0.25 +
|
||||||
|
Math.sin(t * 1.8 + off * 1.3) * 0.15
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeState(svg) {
|
||||||
|
return {
|
||||||
|
svg: svg,
|
||||||
|
bars1: svg.querySelectorAll('#bars-group-1 .bar'),
|
||||||
|
bars2: svg.querySelectorAll('#bars-group-2 .bar'),
|
||||||
|
vals1: svg.querySelectorAll('#values-group-1 text'),
|
||||||
|
vals2: svg.querySelectorAll('#values-group-2 text'),
|
||||||
|
linePath: svg.querySelector('#line-path'),
|
||||||
|
lineFill: svg.querySelector('#line-fill'),
|
||||||
|
pieSegs: svg.querySelectorAll('.pie-segment'),
|
||||||
|
phase: Math.random() * Math.PI * 2,
|
||||||
|
paused: false,
|
||||||
|
themeN: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBars(bars, vals, st, pct) {
|
||||||
|
for (var i = 0; i < bars.length; i++) {
|
||||||
|
var v = Math.max(BAR_MIN, wave(st.phase, i * 1.1));
|
||||||
|
var h = v * BAR_H;
|
||||||
|
bars[i].setAttribute('height', h);
|
||||||
|
bars[i].setAttribute('y', BAR_H - h);
|
||||||
|
}
|
||||||
|
for (var j = 0; j < Math.min(bars.length, vals.length); j++) {
|
||||||
|
var val = Math.max(BAR_MIN, wave(st.phase, j * 1.1));
|
||||||
|
vals[j].textContent = pct ? Math.round(val * 100) + '%' : Math.round(val * 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLine(st) {
|
||||||
|
if (!st.linePath) return;
|
||||||
|
var d = 'M';
|
||||||
|
for (var i = 0; i < LINE_PTS; i++) {
|
||||||
|
var x = (i / (LINE_PTS - 1)) * LINE_W;
|
||||||
|
var y = 25 + (1 - wave(st.phase * 0.8, i * 0.9)) * 110;
|
||||||
|
d += (i ? ' L' : '') + x.toFixed(1) + ',' + y.toFixed(1);
|
||||||
|
}
|
||||||
|
st.linePath.setAttribute('d', d);
|
||||||
|
if (st.lineFill) st.lineFill.setAttribute('d', d + ' L' + LINE_W + ',145 L0,145 Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pie: each segment gently shifts its slice size, no spinning */
|
||||||
|
function updatePie(st) {
|
||||||
|
if (!st.pieSegs.length) return;
|
||||||
|
var n = st.pieSegs.length;
|
||||||
|
// Generate proportional weights that shift over time
|
||||||
|
var weights = [], total = 0;
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
var w = 0.5 + wave(st.phase * 0.4, i * 2.0) * 0.5;
|
||||||
|
weights.push(w);
|
||||||
|
total += w;
|
||||||
|
}
|
||||||
|
// Convert to cumulative angles
|
||||||
|
var angle = 0;
|
||||||
|
for (var j = 0; j < n; j++) {
|
||||||
|
var sweep = (weights[j] / total) * 360;
|
||||||
|
var startA = angle * Math.PI / 180;
|
||||||
|
var endA = (angle + sweep) * Math.PI / 180;
|
||||||
|
// Large-arc flag needed when sweep > 180
|
||||||
|
var large = sweep > 180 ? 1 : 0;
|
||||||
|
var r = PIE_R;
|
||||||
|
var x1 = Math.sin(startA) * r, y1 = -Math.cos(startA) * r;
|
||||||
|
var x2 = Math.sin(endA) * r, y2 = -Math.cos(endA) * r;
|
||||||
|
var path = st.pieSegs[j].querySelector('path');
|
||||||
|
if (path) {
|
||||||
|
path.setAttribute('d',
|
||||||
|
'M0,0 L' + x1.toFixed(2) + ',' + y1.toFixed(2) +
|
||||||
|
' A' + r + ',' + r + ' 0 ' + large + ',1 ' +
|
||||||
|
x2.toFixed(2) + ',' + y2.toFixed(2) + ' Z'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Remove any rotation transform — segments are positioned by path geometry
|
||||||
|
st.pieSegs[j].removeAttribute('transform');
|
||||||
|
angle += sweep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTheme(st) {
|
||||||
|
var c = pal(), q = st.svg.querySelectorAll.bind(st.svg), all, k;
|
||||||
|
all = q('.ct'); for (k = 0; k < all.length; k++) all[k].setAttribute('fill', c.text);
|
||||||
|
all = q('.cl'); for (k = 0; k < all.length; k++) all[k].setAttribute('fill', c.muted);
|
||||||
|
all = q('.cv'); for (k = 0; k < all.length; k++) all[k].setAttribute('fill', c.text);
|
||||||
|
all = q('.grid-line'); for (k = 0; k < all.length; k++) all[k].setAttribute('stroke', c.border);
|
||||||
|
var cc = st.svg.querySelector('#pie-center');
|
||||||
|
if (cc) { cc.setAttribute('fill', c.center); cc.setAttribute('stroke', c.border); }
|
||||||
|
var pt = st.svg.querySelector('#pie-center-text');
|
||||||
|
if (pt) pt.setAttribute('fill', c.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tick(st) {
|
||||||
|
if (!st.paused) {
|
||||||
|
st.phase += SPEED * 16;
|
||||||
|
updateBars(st.bars1, st.vals1, st, true);
|
||||||
|
updateBars(st.bars2, st.vals2, st, false);
|
||||||
|
updateLine(st);
|
||||||
|
updatePie(st);
|
||||||
|
if (++st.themeN > 30) { st.themeN = 0; applyTheme(st); }
|
||||||
|
}
|
||||||
|
requestAnimationFrame(function () { tick(st); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function observe(st) {
|
||||||
|
if (!('IntersectionObserver' in window)) return;
|
||||||
|
new IntersectionObserver(function (entries) {
|
||||||
|
for (var i = 0; i < entries.length; i++) st.paused = !entries[i].isIntersecting;
|
||||||
|
}, { rootMargin: '200px', threshold: 0.05 }).observe(st.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function boot() {
|
||||||
|
var svgs = document.querySelectorAll('.dashboard-chart');
|
||||||
|
if (!svgs.length) return;
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
|
for (var i = 0; i < svgs.length; i++) {
|
||||||
|
if (svgs[i]._dbAnim) continue;
|
||||||
|
var st = makeState(svgs[i]);
|
||||||
|
svgs[i]._dbAnim = st;
|
||||||
|
applyTheme(st);
|
||||||
|
tick(st);
|
||||||
|
observe(st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', boot);
|
||||||
|
} else {
|
||||||
|
boot();
|
||||||
|
}
|
||||||
|
})();
|
||||||
61
theme/assets/js/industry-animator.js
Normal file
61
theme/assets/js/industry-animator.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Gallery TV Slideshow
|
||||||
|
* Cycles through images inside gallery-TV blocks.
|
||||||
|
* Pauses off-screen via IntersectionObserver for performance.
|
||||||
|
* Respects prefers-reduced-motion.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var INTERVAL = 4000; // ms between slides
|
||||||
|
|
||||||
|
function boot() {
|
||||||
|
var stages = document.querySelectorAll('[data-gtv-slideshow]');
|
||||||
|
if (!stages.length) return;
|
||||||
|
|
||||||
|
/* Honour reduced-motion – show first slide only */
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
|
|
||||||
|
for (var i = 0; i < stages.length; i++) {
|
||||||
|
initSlideshow(stages[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSlideshow(stage) {
|
||||||
|
var slides = stage.querySelectorAll('.gtv-slide');
|
||||||
|
if (slides.length < 2) return;
|
||||||
|
|
||||||
|
var state = { current: 0, paused: false, timer: null };
|
||||||
|
|
||||||
|
/* IntersectionObserver – pause when off-screen */
|
||||||
|
if ('IntersectionObserver' in window) {
|
||||||
|
new IntersectionObserver(function (entries) {
|
||||||
|
for (var j = 0; j < entries.length; j++) {
|
||||||
|
state.paused = !entries[j].isIntersecting;
|
||||||
|
}
|
||||||
|
if (!state.paused && !state.timer) {
|
||||||
|
state.timer = setInterval(function () { advance(slides, state); }, INTERVAL);
|
||||||
|
} else if (state.paused && state.timer) {
|
||||||
|
clearInterval(state.timer);
|
||||||
|
state.timer = null;
|
||||||
|
}
|
||||||
|
}, { rootMargin: '200px', threshold: 0.05 }).observe(stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start cycling */
|
||||||
|
state.timer = setInterval(function () { advance(slides, state); }, INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function advance(slides, state) {
|
||||||
|
if (state.paused) return;
|
||||||
|
slides[state.current].classList.remove('is-active');
|
||||||
|
state.current = (state.current + 1) % slides.length;
|
||||||
|
slides[state.current].classList.add('is-active');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', boot);
|
||||||
|
} else {
|
||||||
|
boot();
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -17,6 +17,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
window.addEventListener('scroll', () => {
|
window.addEventListener('scroll', () => {
|
||||||
header.classList.toggle('scrolled', window.scrollY > 40);
|
header.classList.toggle('scrolled', window.scrollY > 40);
|
||||||
}, { passive: true });
|
}, { passive: true });
|
||||||
|
|
||||||
|
/* Detect whether the hero beneath the header has a light background.
|
||||||
|
.hero (homepage) is white in light mode; .page-hero stays dark.
|
||||||
|
Re-evaluate when the theme toggle changes data-theme. */
|
||||||
|
function updateHeroContrast() {
|
||||||
|
const isLight = document.documentElement.getAttribute('data-theme') !== 'dark';
|
||||||
|
const hasLightHero = isLight && document.querySelector('.hero') && !document.querySelector('.page-hero');
|
||||||
|
header.classList.toggle('over-light-hero', !!hasLightHero);
|
||||||
|
}
|
||||||
|
updateHeroContrast();
|
||||||
|
new MutationObserver(updateHeroContrast).observe(document.documentElement, {
|
||||||
|
attributes: true, attributeFilter: ['data-theme']
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Mobile nav toggle ──────────────────────────────────── */
|
/* ── Mobile nav toggle ──────────────────────────────────── */
|
||||||
@@ -26,6 +39,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
toggle.addEventListener('click', () => {
|
toggle.addEventListener('click', () => {
|
||||||
toggle.classList.toggle('open');
|
toggle.classList.toggle('open');
|
||||||
nav.classList.toggle('open');
|
nav.classList.toggle('open');
|
||||||
|
document.body.classList.toggle('menu-open');
|
||||||
const expanded = toggle.getAttribute('aria-expanded') === 'true';
|
const expanded = toggle.getAttribute('aria-expanded') === 'true';
|
||||||
toggle.setAttribute('aria-expanded', !expanded);
|
toggle.setAttribute('aria-expanded', !expanded);
|
||||||
});
|
});
|
||||||
@@ -119,18 +133,33 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
/* ── Animate cards on scroll ────────────────────────────── */
|
/* ── Animate cards on scroll ────────────────────────────── */
|
||||||
const cards = document.querySelectorAll('.oribi-card, .feature-card, .industry-card, .pricing-card, .value-card, .platform-row');
|
const cards = document.querySelectorAll('.oribi-card, .feature-card, .industry-card, .pricing-card, .value-card, .platform-row');
|
||||||
if (cards.length && 'IntersectionObserver' in window) {
|
if (cards.length && 'IntersectionObserver' in window &&
|
||||||
cards.forEach(c => { c.style.opacity = '0'; c.style.transform = 'translateY(24px)'; c.style.transition = 'opacity .5s ease, transform .5s ease'; });
|
!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||||
|
cards.forEach(c => c.classList.add('scroll-hidden'));
|
||||||
|
/* Use rAF to ensure the class is applied before observing – avoids
|
||||||
|
Safari quirk where elements already in-viewport don't fire. */
|
||||||
|
requestAnimationFrame(() => {
|
||||||
const io = new IntersectionObserver((entries) => {
|
const io = new IntersectionObserver((entries) => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
entry.target.style.opacity = '1';
|
entry.target.classList.remove('scroll-hidden');
|
||||||
entry.target.style.transform = 'translateY(0)';
|
entry.target.classList.add('scroll-visible');
|
||||||
io.unobserve(entry.target);
|
io.unobserve(entry.target);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, { threshold: 0.1 });
|
}, { threshold: 0.05, rootMargin: '0px 0px 80px 0px' });
|
||||||
cards.forEach(c => io.observe(c));
|
cards.forEach(c => io.observe(c));
|
||||||
|
});
|
||||||
|
/* Safety net: reveal any still-hidden elements after 4 s so content
|
||||||
|
is never permanently invisible (e.g. iOS Safari edge-cases). */
|
||||||
|
setTimeout(() => {
|
||||||
|
cards.forEach(c => {
|
||||||
|
if (c.classList.contains('scroll-hidden')) {
|
||||||
|
c.classList.remove('scroll-hidden');
|
||||||
|
c.classList.add('scroll-visible');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 4000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -610,3 +639,117 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
paintBg();
|
paintBg();
|
||||||
start();
|
start();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
/* ── Device Animator ──────────────────────────────────────────────────────── */
|
||||||
|
(function () {
|
||||||
|
const DEVICES = [
|
||||||
|
'da-tablet', 'da-monitor-sm', 'da-monitor-lg',
|
||||||
|
'da-tv', 'da-projector', 'da-vwall'
|
||||||
|
];
|
||||||
|
const DWELL = 2500; // ms each device is shown
|
||||||
|
|
||||||
|
document.querySelectorAll('.da-stage').forEach(function (stage) {
|
||||||
|
let current = 0;
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
// Collect the 6 device panels
|
||||||
|
const panels = DEVICES.map(function (cls) {
|
||||||
|
return stage.querySelector('.' + cls);
|
||||||
|
});
|
||||||
|
|
||||||
|
function show(idx) {
|
||||||
|
panels.forEach(function (el, i) {
|
||||||
|
if (!el) return;
|
||||||
|
el.classList.toggle('is-active', i === idx);
|
||||||
|
el.classList.remove('is-leaving');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function advance() {
|
||||||
|
const leaving = current;
|
||||||
|
current = (current + 1) % DEVICES.length;
|
||||||
|
if (panels[leaving]) panels[leaving].classList.add('is-leaving');
|
||||||
|
show(current);
|
||||||
|
setTimeout(function () {
|
||||||
|
if (panels[leaving]) panels[leaving].classList.remove('is-leaving');
|
||||||
|
}, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startCycle() {
|
||||||
|
if (timer) return;
|
||||||
|
timer = setInterval(advance, DWELL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopCycle() {
|
||||||
|
clearInterval(timer);
|
||||||
|
timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Honour reduced-motion preference: show first device statically
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||||
|
show(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
show(0);
|
||||||
|
startCycle();
|
||||||
|
|
||||||
|
// Pause when scrolled out of view to save resources
|
||||||
|
if ('IntersectionObserver' in window) {
|
||||||
|
new IntersectionObserver(function (entries) {
|
||||||
|
entries.forEach(function (e) {
|
||||||
|
e.isIntersecting ? startCycle() : stopCycle();
|
||||||
|
});
|
||||||
|
}, { threshold: 0.2 }).observe(stage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* ── TV Stick Plug Animation ─────────────────────────────────────────────── */
|
||||||
|
(function () {
|
||||||
|
var stages = document.querySelectorAll('[data-tv-stick-anim]');
|
||||||
|
if (!stages.length) return;
|
||||||
|
|
||||||
|
// Honour reduced-motion: show plugged-in state immediately
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||||
|
stages.forEach(function (stage) {
|
||||||
|
stage.classList.add('is-plugged');
|
||||||
|
startTsSlides(stage);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('IntersectionObserver' in window) {
|
||||||
|
var io = new IntersectionObserver(function (entries) {
|
||||||
|
entries.forEach(function (e) {
|
||||||
|
if (e.isIntersecting) {
|
||||||
|
var stage = e.target;
|
||||||
|
stage.classList.add('is-animating');
|
||||||
|
// Add plugged state after slide-in completes (1.4s)
|
||||||
|
setTimeout(function () {
|
||||||
|
stage.classList.add('is-plugged');
|
||||||
|
// Start promotional slide cycling after screen glow (0.9s)
|
||||||
|
setTimeout(function () {
|
||||||
|
startTsSlides(stage);
|
||||||
|
}, 900);
|
||||||
|
}, 1400);
|
||||||
|
io.unobserve(stage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, { threshold: 0.3 });
|
||||||
|
stages.forEach(function (stage) { io.observe(stage); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTsSlides(stage) {
|
||||||
|
var slides = stage.querySelectorAll('.ts-slide');
|
||||||
|
if (!slides.length) return;
|
||||||
|
var current = 0;
|
||||||
|
slides[0].classList.add('is-active');
|
||||||
|
stage.classList.add('is-playing');
|
||||||
|
setInterval(function () {
|
||||||
|
slides[current].classList.remove('is-active');
|
||||||
|
current = (current + 1) % slides.length;
|
||||||
|
slides[current].classList.add('is-active');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|||||||
110
theme/assets/js/video-editor-animator.js
Normal file
110
theme/assets/js/video-editor-animator.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* Video Editor Timeline Animator
|
||||||
|
* Animates playhead scrubbing across the timeline and video preview crossfades.
|
||||||
|
* Mirrors the structure and conventions of dashboard-animator.js.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var DURATION = 10000; // ms for one full playhead sweep (left → right, then loop)
|
||||||
|
var X_MIN = 104; // leftmost playhead centre (SVG units)
|
||||||
|
var X_MAX = 504; // rightmost playhead centre (end of clip area)
|
||||||
|
|
||||||
|
function makeState(svg) {
|
||||||
|
return {
|
||||||
|
svg: svg,
|
||||||
|
playheadLine: svg.querySelector('#ve-playhead-line'),
|
||||||
|
playheadHead: svg.querySelector('#ve-playhead-head'),
|
||||||
|
scene1: svg.querySelector('#ve-scene-1'),
|
||||||
|
scene2: svg.querySelector('#ve-scene-2'),
|
||||||
|
scene3: svg.querySelector('#ve-scene-3'),
|
||||||
|
innerScreen: svg.querySelector('#ve-inner-screen'),
|
||||||
|
timecode: svg.querySelector('#ve-timecode'),
|
||||||
|
scrubPct: 0,
|
||||||
|
lastTime: performance.now(),
|
||||||
|
paused: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function lerp(a, b, t) { return a + (b - a) * t; }
|
||||||
|
|
||||||
|
function updatePlayhead(st) {
|
||||||
|
var xC = lerp(X_MIN, X_MAX, st.scrubPct);
|
||||||
|
if (st.playheadLine) st.playheadLine.setAttribute('x', (xC - 1).toFixed(1));
|
||||||
|
if (st.playheadHead) st.playheadHead.setAttribute('transform', 'translate(' + xC.toFixed(1) + ',234)');
|
||||||
|
if (st.timecode) {
|
||||||
|
var s = Math.floor(st.scrubPct * 10);
|
||||||
|
st.timecode.textContent = '0:' + (s < 10 ? '0' + s : s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateScenes(st) {
|
||||||
|
var p = st.scrubPct;
|
||||||
|
var o1, o2, o3, fade;
|
||||||
|
if (p < 0.30) {
|
||||||
|
o1 = 1; o2 = 0; o3 = 0;
|
||||||
|
} else if (p < 0.40) {
|
||||||
|
fade = (p - 0.30) / 0.10; o1 = 1 - fade; o2 = fade; o3 = 0;
|
||||||
|
} else if (p < 0.65) {
|
||||||
|
o1 = 0; o2 = 1; o3 = 0;
|
||||||
|
} else if (p < 0.75) {
|
||||||
|
fade = (p - 0.65) / 0.10; o1 = 0; o2 = 1 - fade; o3 = fade;
|
||||||
|
} else {
|
||||||
|
o1 = 0; o2 = 0; o3 = 1;
|
||||||
|
}
|
||||||
|
if (st.scene1) st.scene1.setAttribute('opacity', o1.toFixed(3));
|
||||||
|
if (st.scene2) st.scene2.setAttribute('opacity', o2.toFixed(3));
|
||||||
|
if (st.scene3) st.scene3.setAttribute('opacity', o3.toFixed(3));
|
||||||
|
if (st.innerScreen) {
|
||||||
|
st.innerScreen.setAttribute('fill',
|
||||||
|
p < 0.38 ? 'url(#ve-scr-warm)' :
|
||||||
|
p < 0.72 ? 'url(#ve-scr-cold)' :
|
||||||
|
'url(#ve-scr-go)'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loop(st, now) {
|
||||||
|
if (!st.paused) {
|
||||||
|
var delta = now - st.lastTime;
|
||||||
|
st.lastTime = now;
|
||||||
|
st.scrubPct += delta / DURATION;
|
||||||
|
if (st.scrubPct >= 1) st.scrubPct -= 1;
|
||||||
|
updatePlayhead(st);
|
||||||
|
updateScenes(st);
|
||||||
|
} else {
|
||||||
|
st.lastTime = now; // keep fresh so there is no jump on resume
|
||||||
|
}
|
||||||
|
requestAnimationFrame(function (t) { loop(st, t); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function observe(st) {
|
||||||
|
if (!('IntersectionObserver' in window)) return;
|
||||||
|
new IntersectionObserver(function (entries) {
|
||||||
|
for (var i = 0; i < entries.length; i++) {
|
||||||
|
st.paused = !entries[i].isIntersecting;
|
||||||
|
}
|
||||||
|
}, { rootMargin: '200px', threshold: 0.05 }).observe(st.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function boot() {
|
||||||
|
var svgs = document.querySelectorAll('.ve-svg');
|
||||||
|
if (!svgs.length) return;
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
|
for (var i = 0; i < svgs.length; i++) {
|
||||||
|
(function (svg) {
|
||||||
|
if (svg._veAnim) return;
|
||||||
|
var st = makeState(svg);
|
||||||
|
svg._veAnim = st;
|
||||||
|
observe(st);
|
||||||
|
requestAnimationFrame(function (t) { loop(st, t); });
|
||||||
|
})(svgs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', boot);
|
||||||
|
} else {
|
||||||
|
boot();
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -1067,6 +1067,8 @@ reg('oribi/pricing-card', {
|
|||||||
faIcon: { type: 'string', default: '' },
|
faIcon: { type: 'string', default: '' },
|
||||||
name: { type: 'string', default: '' },
|
name: { type: 'string', default: '' },
|
||||||
tagline: { type: 'string', default: '' },
|
tagline: { type: 'string', default: '' },
|
||||||
|
price: { type: 'string', default: '' },
|
||||||
|
pricePer: { type: 'string', default: '' },
|
||||||
features: { type: 'array', default: [] },
|
features: { type: 'array', default: [] },
|
||||||
btnText: { type: 'string', default: 'Get Started' },
|
btnText: { type: 'string', default: 'Get Started' },
|
||||||
btnUrl: { type: 'string', default: '/contact' },
|
btnUrl: { type: 'string', default: '/contact' },
|
||||||
@@ -1122,6 +1124,17 @@ reg('oribi/pricing-card', {
|
|||||||
onChange: function(v){s({name:v});}, placeholder: 'Plan name...' }),
|
onChange: function(v){s({name:v});}, placeholder: 'Plan name...' }),
|
||||||
el(RT, { tagName: 'p', className: 'pricing-tagline', value: a.tagline,
|
el(RT, { tagName: 'p', className: 'pricing-tagline', value: a.tagline,
|
||||||
onChange: function(v){s({tagline:v});}, placeholder: 'Tagline...' }),
|
onChange: function(v){s({tagline:v});}, placeholder: 'Tagline...' }),
|
||||||
|
a.price || a.pricePer ? el('div', { className: 'pricing-price' },
|
||||||
|
el(RT, { tagName: 'div', className: 'pricing-amount', value: a.price || '',
|
||||||
|
onChange: function(v){s({price:v});}, placeholder: '$0' }),
|
||||||
|
el(RT, { tagName: 'div', className: 'pricing-per', value: a.pricePer || '',
|
||||||
|
onChange: function(v){s({pricePer:v});}, placeholder: 'per screen / month' })
|
||||||
|
) : el('div', { className: 'pricing-price' },
|
||||||
|
el(RT, { tagName: 'div', className: 'pricing-amount', value: '',
|
||||||
|
onChange: function(v){s({price:v});}, placeholder: '$0' }),
|
||||||
|
el(RT, { tagName: 'div', className: 'pricing-per', value: '',
|
||||||
|
onChange: function(v){s({pricePer:v});}, placeholder: 'per screen / month' })
|
||||||
|
),
|
||||||
el('ul', { className: 'pricing-features' },
|
el('ul', { className: 'pricing-features' },
|
||||||
features.map(function (f, fi) {
|
features.map(function (f, fi) {
|
||||||
return el('li', { key: fi, style: { display: 'flex', alignItems: 'center', gap: '4px' } },
|
return el('li', { key: fi, style: { display: 'flex', alignItems: 'center', gap: '4px' } },
|
||||||
@@ -1167,16 +1180,95 @@ reg('oribi/platform-row', {
|
|||||||
imgUrl: { type: 'string', default: '' },
|
imgUrl: { type: 'string', default: '' },
|
||||||
imgAlt: { type: 'string', default: '' },
|
imgAlt: { type: 'string', default: '' },
|
||||||
imgWidth: { type: 'number', default: 300 },
|
imgWidth: { type: 'number', default: 300 },
|
||||||
|
isDashboard: { type: 'boolean', default: false },
|
||||||
|
deviceAnim: { type: 'boolean', default: false },
|
||||||
|
tvStick: { type: 'boolean', default: false },
|
||||||
|
cameraAnim: { type: 'boolean', default: false },
|
||||||
|
neverGoesDark: { type: 'boolean', default: false },
|
||||||
|
brandedAnim: { type: 'boolean', default: false },
|
||||||
|
galleryIds: { type: 'array', default: [] },
|
||||||
},
|
},
|
||||||
edit: function (props) {
|
edit: function (props) {
|
||||||
var a = props.attributes, s = props.setAttributes;
|
var a = props.attributes, s = props.setAttributes;
|
||||||
var imgW = a.imgWidth || 300;
|
var imgW = a.imgWidth || 300;
|
||||||
|
|
||||||
|
/* ── Animation HTML strings (mirror PHP render, used via dangerouslySetInnerHTML) ── */
|
||||||
|
var 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>';
|
||||||
|
var DA_HTML = '<div class="da-stage" aria-hidden="true">' +
|
||||||
|
'<div class="da-device da-tablet"><div class="da-body">' + DA_SCREEN + '</div><span class="da-label">Tablet</span></div>' +
|
||||||
|
'<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>' +
|
||||||
|
'<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>' +
|
||||||
|
'<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>' +
|
||||||
|
'<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>' +
|
||||||
|
'<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>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
var TS_MI = '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
var TS_COL = '<div class="ts-menu__col"><div class="ts-menu__cat"></div>' + TS_MI + TS_MI + TS_MI + '</div>';
|
||||||
|
var TS_HTML = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">' +
|
||||||
|
'<div class="ts-tv"><div class="ts-tv__body"><div class="ts-tv__screen"><div class="ts-slides">' +
|
||||||
|
'<div class="ts-slide ts-slide--menu"><div class="ts-menu"><div class="ts-menu__header"><div class="ts-menu__logo"></div><div class="ts-menu__title"></div></div><div class="ts-menu__cols">' + TS_COL + TS_COL + '</div></div></div>' +
|
||||||
|
'<div class="ts-slide ts-slide--wayfind"><div class="ts-wf"><div class="ts-wf__header"><div class="ts-wf__building"></div></div><div class="ts-wf__rows"><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><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><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><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></div></div></div>' +
|
||||||
|
'<div class="ts-slide ts-slide--sched"><div class="ts-sched"><div class="ts-sched__header"><div class="ts-sched__title"></div><div class="ts-sched__date"></div></div><div class="ts-sched__table"><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><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><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><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><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></div></div></div>' +
|
||||||
|
'</div></div><div class="ts-tv__port"></div></div><div class="ts-tv__feet"><div class="ts-tv__foot"></div><div class="ts-tv__foot"></div></div></div>' +
|
||||||
|
'<div class="ts-stick"><div class="ts-stick__body"><div class="ts-stick__led"></div></div><div class="ts-stick__connector"></div></div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
var NGD_ROW = '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
var NGD_ROWH = '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
var NGD_HTML = '<div class="ngd-stage" aria-hidden="true">' +
|
||||||
|
'<div class="ngd-tv"><div class="ngd-tv__body"><div class="ngd-tv__screen"><div class="ngd-menu"><div class="ngd-menu__hd"><div class="ngd-menu__logo"></div><div class="ngd-menu__ttl"></div></div><div class="ngd-menu__cols"><div class="ngd-menu__col"><div class="ngd-menu__cat"></div>' + NGD_ROW + NGD_ROWH + NGD_ROW + '</div><div class="ngd-menu__col"><div class="ngd-menu__cat"></div>' + NGD_ROW + NGD_ROW + NGD_ROWH + '</div></div><div class="ngd-menu__ticker"><div class="ngd-menu__ticker-inner"></div></div></div></div><div class="ngd-tv__port"></div></div><div class="ngd-tv__feet"><div class="ngd-tv__foot"></div><div class="ngd-tv__foot"></div></div></div>' +
|
||||||
|
'<div class="ngd-player"><div class="ngd-player__connector"></div><div class="ngd-player__body"><div class="ngd-player__led"></div></div><div class="ngd-player__check"><svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="11" cy="11" r="10" stroke="#4CAF50" stroke-width="1.5"/><polyline points="6,11 9.5,14.5 16,7.5" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div></div>' +
|
||||||
|
'<div class="ngd-signal-wrap"><div class="ngd-cloud"><svg class="ngd-cloud__svg" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg"><circle class="ngd-cloud__path" cx="32" cy="23" r="14" stroke-width="2.2" fill="none"/><path class="ngd-cloud__path" d="M18.5 23C23 20 41 20 45.5 23" stroke-width="1.9" stroke-linecap="round" fill="none"/><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"/><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"/><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"/></svg></div><div class="ngd-signal-line"><div class="ngd-signal__dots"><div class="ngd-signal__dot ngd-signal__dot--1"></div><div class="ngd-signal__dot ngd-signal__dot--2"></div><div class="ngd-signal__dot ngd-signal__dot--3"></div></div><div class="ngd-signal__break"><svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="9" cy="9" r="8" fill="rgba(239,68,68,0.12)" stroke="#ef4444" stroke-width="1.2"/><line x1="5.5" y1="5.5" x2="12.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/><line x1="12.5" y1="5.5" x2="5.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/></svg></div></div></div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
var BD_SPLASH = '<div class="bd-splash"><div class="bd-splash__logo"></div></div>';
|
||||||
|
var BD_HDR = '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
||||||
|
var BD_HTML = '<div class="bd-stage" aria-hidden="true">' +
|
||||||
|
'<div class="bd-device bd-device--tablet"><span class="bd-device__label">Kiosk</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--welcome"><div class="bd-promo__hero"></div><div class="bd-promo__heading"></div><div class="bd-promo__text"></div><div class="bd-promo__btn"></div></div></div></div></div></div></div>' +
|
||||||
|
'<div class="bd-device bd-device--wall"><span class="bd-device__label">Wall Display</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--sale"><div class="bd-promo__cols"><div class="bd-promo__visual"></div><div class="bd-promo__info"><div class="bd-promo__badge"></div><div class="bd-promo__heading"></div><div class="bd-promo__text"></div><div class="bd-promo__text bd-promo__text--short"></div><div class="bd-promo__price"></div></div></div></div></div></div></div></div><div class="bd-mount"></div></div>' +
|
||||||
|
'<div class="bd-device bd-device--interactive"><span class="bd-device__label">Interactive</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--menu"><div class="bd-promo__heading"></div><div class="bd-promo__grid"><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div></div></div></div></div></div></div><div class="bd-table"></div></div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
var DB_HTML = '<div class="dashboard-tv" data-dashboard-container="true"><div class="dashboard-tv__body"><div class="dashboard-tv__screen"><svg viewBox="0 0 800 450" xmlns="http://www.w3.org/2000/svg" class="dashboard-chart" role="img" aria-label="Animated dashboard charts"><defs><linearGradient id="dbe-barGrad" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#D83302" stop-opacity="1"/><stop offset="100%" stop-color="#4CAF50" stop-opacity=".8"/></linearGradient><linearGradient id="dbe-lineGrad" 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><g transform="translate(35,20)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Performance</text><g id="dbe-bars1" transform="translate(0,25)"><rect x="0" y="60" width="28" height="60" fill="url(#dbe-barGrad)"/><rect x="40" y="80" width="28" height="40" fill="url(#dbe-barGrad)"/><rect x="80" y="40" width="28" height="80" fill="url(#dbe-barGrad)"/><rect x="120" y="70" width="28" height="50" fill="url(#dbe-barGrad)"/><rect x="160" y="50" width="28" height="70" fill="url(#dbe-barGrad)"/></g><g transform="translate(0,152)"><text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#aaa">API</text><text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#aaa">Cache</text><text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#aaa">DB</text><text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#aaa">Queue</text><text class="cl" x="174" y="0" font-size="10" text-anchor="middle" fill="#aaa">Worker</text></g></g><g transform="translate(430,20)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Requests/sec</text><g transform="translate(0,25)"><rect x="0" y="50" width="28" height="70" fill="url(#dbe-barGrad)"/><rect x="40" y="30" width="28" height="90" fill="url(#dbe-barGrad)"/><rect x="80" y="65" width="28" height="55" fill="url(#dbe-barGrad)"/><rect x="120" y="45" width="28" height="75" fill="url(#dbe-barGrad)"/></g><g transform="translate(0,152)"><text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#aaa">Read</text><text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#aaa">Write</text><text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#aaa">Update</text><text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#aaa">Delete</text></g></g><g transform="translate(35,245)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Traffic Trend</text><g transform="translate(0,25)"><line class="grid-line" x1="0" y1="0" x2="340" y2="0" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="40" x2="340" y2="40" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="80" x2="340" y2="80" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="120" x2="340" y2="120" stroke="#ddd" stroke-width=".5"/><path d="M0,90 L42,70 L85,50 L127,80 L170,45 L212,65 L255,55 L297,75 L340,60 L340,145 L0,145 Z" fill="url(#dbe-lineGrad)"/><path d="M0,90 L42,70 L85,50 L127,80 L170,45 L212,65 L255,55 L297,75 L340,60" stroke="#4CAF50" stroke-width="2.5" fill="none" stroke-linecap="round"/></g></g><g transform="translate(490,245)"><text class="ct" x="100" y="0" font-size="14" font-weight="600" text-anchor="middle" fill="#888">Distribution</text><g transform="translate(100,90)"><path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#D83302" opacity=".9"/><path d="M0,0 L38.89,-38.89 A55,55 0 0,1 55,0 Z" fill="#4CAF50" opacity=".8"/><path d="M0,0 L55,0 A55,55 0 0,1 0,55 Z" fill="#f59e0b" opacity=".7"/><path d="M0,0 L0,55 A55,55 0 1,1 0,-55 Z" fill="#ef4444" opacity=".7"/><circle cx="0" cy="0" r="22" fill="#f5f5f5" stroke="#ddd" stroke-width="1"/></g></g></svg></div></div><div class="dashboard-tv__feet"><div class="dashboard-tv__foot"></div><div class="dashboard-tv__foot"></div></div></div>';
|
||||||
|
|
||||||
return el(Frag, null,
|
return el(Frag, null,
|
||||||
el(IC, null,
|
el(IC, null,
|
||||||
el(PB, { title: 'Row Settings' },
|
el(PB, { title: 'Row Settings' },
|
||||||
el(TC, { label: 'Visual (emoji)', value: a.visual, onChange: function(v){s({visual:v});} }),
|
el(TC, { label: 'Visual (emoji)', value: a.visual, onChange: function(v){s({visual:v});} }),
|
||||||
el(TC, { label: 'Button URL', value: a.btnUrl, onChange: function(v){s({btnUrl:v});} }),
|
el(TC, { label: 'Button URL', value: a.btnUrl, onChange: function(v){s({btnUrl:v});} }),
|
||||||
el(TG, { label: 'Reversed', checked: !!a.reversed, onChange: function(v){s({reversed:v});} })
|
el(TG, { label: 'Reversed', checked: !!a.reversed, onChange: function(v){s({reversed:v});} }),
|
||||||
|
el(TG, { label: 'Dashboard Animation', checked: !!a.isDashboard, onChange: function(v){s({isDashboard:v});} }),
|
||||||
|
el(TG, { label: 'Device Animation', checked: !!a.deviceAnim, onChange: function(v){s({deviceAnim:v});} }),
|
||||||
|
el(TG, { label: 'TV Stick Animation', checked: !!a.tvStick, onChange: function(v){s({tvStick:v});} }),
|
||||||
|
el(TG, { label: 'Camera Animation', checked: !!a.cameraAnim, onChange: function(v){s({cameraAnim:v});} }),
|
||||||
|
el(TG, { label: 'Never Goes Dark', checked: !!a.neverGoesDark, onChange: function(v){s({neverGoesDark:v});} }),
|
||||||
|
el(TG, { label: 'Branded Display', checked: !!a.brandedAnim, onChange: function(v){s({brandedAnim:v});} })
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Gallery TV Slideshow', initialOpen: false },
|
||||||
|
el(MUC, null,
|
||||||
|
el(MU, {
|
||||||
|
onSelect: function(media) {
|
||||||
|
s({ galleryIds: media.map(function(m){ return m.id; }) });
|
||||||
|
},
|
||||||
|
allowedTypes: ['image'],
|
||||||
|
gallery: true,
|
||||||
|
multiple: true,
|
||||||
|
value: a.galleryIds || [],
|
||||||
|
render: function(ref) {
|
||||||
|
return el(Frag, null,
|
||||||
|
a.galleryIds && a.galleryIds.length
|
||||||
|
? el('div', { style: { marginBottom: '8px' } },
|
||||||
|
el('p', { style: { margin: '0 0 4px' } }, a.galleryIds.length + ' image(s) selected'),
|
||||||
|
el(Btn, { variant: 'link', isDestructive: true, onClick: function(){ s({ galleryIds: [] }); } }, 'Clear gallery')
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
el(Btn, { onClick: ref.open, variant: 'secondary', __next40pxDefaultSize: true },
|
||||||
|
a.galleryIds && a.galleryIds.length ? 'Edit gallery' : 'Select images for TV slideshow')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
),
|
),
|
||||||
el(PB, { title: 'Visual Image', initialOpen: false },
|
el(PB, { title: 'Visual Image', initialOpen: false },
|
||||||
el(MUC, null,
|
el(MUC, null,
|
||||||
@@ -1207,7 +1299,77 @@ reg('oribi/platform-row', {
|
|||||||
a.btnUrl ? el(RT, { tagName: 'span', className: 'btn btn-outline mt-3',
|
a.btnUrl ? el(RT, { tagName: 'span', className: 'btn btn-outline mt-3',
|
||||||
value: a.btnText, onChange: function(v){s({btnText:v});}, placeholder: 'Button...' }) : null
|
value: a.btnText, onChange: function(v){s({btnText:v});}, placeholder: 'Button...' }) : null
|
||||||
),
|
),
|
||||||
a.imgUrl
|
a.isDashboard
|
||||||
|
? el('div', { className: 'platform-visual has-dashboard', dangerouslySetInnerHTML: { __html: DB_HTML } })
|
||||||
|
: a.cameraAnim
|
||||||
|
? el('div', { className: 'platform-visual has-camera' },
|
||||||
|
el('div', { className: 'cam-stage', 'aria-hidden': 'true' },
|
||||||
|
// Photo camera (left)
|
||||||
|
el('div', { className: 'pc-wrap' },
|
||||||
|
el('div', { className: 'pc-body' },
|
||||||
|
el('div', { className: 'pc-flash-unit' }),
|
||||||
|
el('div', { className: 'pc-top' },
|
||||||
|
el('div', { className: 'pc-shutter-btn' }),
|
||||||
|
el('div', { className: 'pc-viewfinder' })
|
||||||
|
),
|
||||||
|
el('div', { className: 'pc-front' },
|
||||||
|
el('div', { className: 'pc-lens-ring' },
|
||||||
|
el('div', { className: 'pc-lens-glass' },
|
||||||
|
el('div', { className: 'pc-lens-reflex' })
|
||||||
|
)
|
||||||
|
),
|
||||||
|
el('div', { className: 'pc-grip' })
|
||||||
|
)
|
||||||
|
),
|
||||||
|
el('div', { className: 'pc-prints' },
|
||||||
|
el('div', { className: 'pc-print pc-print--1', style: { opacity: '1', transform: 'rotate(-12deg) translateY(0)' } },
|
||||||
|
el('div', { className: 'pc-print__img' })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// Centre scene
|
||||||
|
el('div', { className: 'cam-scene' },
|
||||||
|
el('div', { className: 'cam-subject cam-subject--1' }),
|
||||||
|
el('div', { className: 'cam-flash-overlay' }),
|
||||||
|
el('div', { className: 'cam-vid-overlay' })
|
||||||
|
),
|
||||||
|
// Video camera on tripod (right)
|
||||||
|
el('div', { className: 'vc-wrap' },
|
||||||
|
el('div', { className: 'vc-camera' },
|
||||||
|
el('div', { className: 'vc-handle' }),
|
||||||
|
el('div', { className: 'vc-body' },
|
||||||
|
el('div', { className: 'vc-lens-barrel' },
|
||||||
|
el('div', { className: 'vc-lens-tip' },
|
||||||
|
el('div', { className: 'vc-lens-glass' },
|
||||||
|
el('div', { className: 'vc-lens-reflex' })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
el('div', { className: 'vc-top-rail' }),
|
||||||
|
el('div', { className: 'vc-rec-light' }),
|
||||||
|
el('div', { className: 'vc-eyepiece' })
|
||||||
|
)
|
||||||
|
),
|
||||||
|
el('div', { className: 'vc-tripod' },
|
||||||
|
el('div', { className: 'vc-stem' }),
|
||||||
|
el('div', { className: 'vc-legs' },
|
||||||
|
el('div', { className: 'vc-leg vc-leg--l' }),
|
||||||
|
el('div', { className: 'vc-leg vc-leg--c' }),
|
||||||
|
el('div', { className: 'vc-leg vc-leg--r' })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: a.deviceAnim
|
||||||
|
? el('div', { className: 'platform-visual has-anim', dangerouslySetInnerHTML: { __html: DA_HTML } })
|
||||||
|
: a.tvStick
|
||||||
|
? el('div', { className: 'platform-visual has-tv-stick', dangerouslySetInnerHTML: { __html: TS_HTML } })
|
||||||
|
: a.neverGoesDark
|
||||||
|
? el('div', { className: 'platform-visual has-ngd', dangerouslySetInnerHTML: { __html: NGD_HTML } })
|
||||||
|
: a.brandedAnim
|
||||||
|
? el('div', { className: 'platform-visual has-branded', dangerouslySetInnerHTML: { __html: BD_HTML } })
|
||||||
|
: a.imgUrl
|
||||||
? el('div', { className: 'platform-visual has-img' },
|
? el('div', { className: 'platform-visual has-img' },
|
||||||
el('img', { src: a.imgUrl, style: { width: imgW + 'px', maxWidth: '100%', height: 'auto', borderRadius: '4px', objectFit: 'contain', display: 'block', marginInline: 'auto' } })
|
el('img', { src: a.imgUrl, style: { width: imgW + 'px', maxWidth: '100%', height: 'auto', borderRadius: '4px', objectFit: 'contain', display: 'block', marginInline: 'auto' } })
|
||||||
)
|
)
|
||||||
@@ -1543,6 +1705,74 @@ reg('oribi/comparison-table', {
|
|||||||
var a = props.attributes, s = props.setAttributes;
|
var a = props.attributes, s = props.setAttributes;
|
||||||
var cols = a.columns || [];
|
var cols = a.columns || [];
|
||||||
var rows = a.rows || [];
|
var rows = a.rows || [];
|
||||||
|
|
||||||
|
/* ── Column helpers ─────────────────────────────────────── */
|
||||||
|
function updateCol(idx, val) {
|
||||||
|
var c = cols.slice(); c[idx] = val; s({ columns: c });
|
||||||
|
}
|
||||||
|
function addCol() {
|
||||||
|
var newRows = rows.map(function(r) {
|
||||||
|
if (r.group) return r;
|
||||||
|
return Object.assign({}, r, { values: (r.values || []).concat([false]) });
|
||||||
|
});
|
||||||
|
s({ columns: cols.concat(['Plan']), rows: newRows });
|
||||||
|
}
|
||||||
|
function removeCol(idx) {
|
||||||
|
var c = cols.slice(); c.splice(idx, 1);
|
||||||
|
var newRows = rows.map(function(r) {
|
||||||
|
if (r.group) return r;
|
||||||
|
var v = (r.values || []).slice(); v.splice(idx, 1);
|
||||||
|
return Object.assign({}, r, { values: v });
|
||||||
|
});
|
||||||
|
s({ columns: c, rows: newRows });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Row helpers ────────────────────────────────────────── */
|
||||||
|
function updateRow(idx, key, val) {
|
||||||
|
var r = rows.slice();
|
||||||
|
r[idx] = Object.assign({}, r[idx]);
|
||||||
|
r[idx][key] = val;
|
||||||
|
s({ rows: r });
|
||||||
|
}
|
||||||
|
function updateCell(ri, ci, val) {
|
||||||
|
var r = rows.slice();
|
||||||
|
r[ri] = Object.assign({}, r[ri]);
|
||||||
|
var v = (r[ri].values || []).slice();
|
||||||
|
v[ci] = val;
|
||||||
|
r[ri].values = v;
|
||||||
|
s({ rows: r });
|
||||||
|
}
|
||||||
|
function toggleCell(ri, ci) {
|
||||||
|
var val = (rows[ri].values || [])[ci];
|
||||||
|
updateCell(ri, ci, val === true ? false : val === false ? true : true);
|
||||||
|
}
|
||||||
|
function switchCellToText(ri, ci) { updateCell(ri, ci, ''); }
|
||||||
|
function addFeatureRow() {
|
||||||
|
var vals = cols.map(function() { return false; });
|
||||||
|
s({ rows: rows.concat([{ feature: 'New feature', values: vals }]) });
|
||||||
|
}
|
||||||
|
function addGroupRow() {
|
||||||
|
s({ rows: rows.concat([{ group: 'New Group' }]) });
|
||||||
|
}
|
||||||
|
function removeRow(idx) {
|
||||||
|
var r = rows.slice(); r.splice(idx, 1); s({ rows: r });
|
||||||
|
}
|
||||||
|
function moveRow(idx, dir) {
|
||||||
|
var t = idx + dir;
|
||||||
|
if (t < 0 || t >= rows.length) return;
|
||||||
|
var r = rows.slice();
|
||||||
|
var tmp = r[idx]; r[idx] = r[t]; r[t] = tmp;
|
||||||
|
s({ rows: r });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Inline styles for editor controls ──────────────────── */
|
||||||
|
var inputStyle = { width: '100%', padding: '4px 6px', border: '1px solid #ddd', borderRadius: '3px', fontSize: '13px', background: 'transparent', boxSizing: 'border-box' };
|
||||||
|
var thInputStyle = Object.assign({}, inputStyle, { fontWeight: 600, textAlign: 'center' });
|
||||||
|
var smallBtnStyle = { background: 'none', border: 'none', cursor: 'pointer', padding: '2px 4px', fontSize: '11px', lineHeight: 1, opacity: 0.6, verticalAlign: 'middle' };
|
||||||
|
var rowCtrlStyle = { whiteSpace: 'nowrap', width: '1%', padding: '4px', verticalAlign: 'middle', border: 'none', background: 'transparent' };
|
||||||
|
var cellBtnStyle = { background: 'none', border: '1px solid #ddd', borderRadius: '3px', cursor: 'pointer', padding: '2px 6px', fontSize: '13px', lineHeight: '1.4', margin: '0 1px' };
|
||||||
|
|
||||||
|
/* ── Render ─────────────────────────────────────────────── */
|
||||||
return el(Frag, null,
|
return el(Frag, null,
|
||||||
el(IC, null,
|
el(IC, null,
|
||||||
el(PB, { title: 'Table Settings' },
|
el(PB, { title: 'Table Settings' },
|
||||||
@@ -1550,6 +1780,21 @@ reg('oribi/comparison-table', {
|
|||||||
{ label: 'Normal', value: 'normal' }, { label: 'Alternate', value: 'alt' }
|
{ label: 'Normal', value: 'normal' }, { label: 'Alternate', value: 'alt' }
|
||||||
], onChange: function(v){s({variant:v});} }),
|
], onChange: function(v){s({variant:v});} }),
|
||||||
el(TC, { label: 'Label', value: a.label, onChange: function(v){s({label:v});} })
|
el(TC, { label: 'Label', value: a.label, onChange: function(v){s({label:v});} })
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Columns', initialOpen: false },
|
||||||
|
cols.map(function(col, i) {
|
||||||
|
return el('div', { key: i, style: { display: 'flex', gap: '4px', marginBottom: '8px', alignItems: 'center' } },
|
||||||
|
el(TC, { label: '', value: col, onChange: function(v){ updateCol(i, v); }, style: { flex: 1 } }),
|
||||||
|
el(Btn, { isDestructive: true, isSmall: true, onClick: function(){ removeCol(i); } }, '\u2715')
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
el(Btn, { isSecondary: true, isSmall: true, onClick: addCol }, '+ Add Column')
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Add Rows', initialOpen: false },
|
||||||
|
el('div', { style: { display: 'flex', gap: '8px' } },
|
||||||
|
el(Btn, { isSecondary: true, isSmall: true, onClick: addFeatureRow }, '+ Feature Row'),
|
||||||
|
el(Btn, { isSecondary: true, isSmall: true, onClick: addGroupRow }, '+ Group Row')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
el('section', { className: a.variant === 'alt' ? 'section section-alt' : 'section' },
|
el('section', { className: a.variant === 'alt' ? 'section section-alt' : 'section' },
|
||||||
@@ -1564,26 +1809,62 @@ reg('oribi/comparison-table', {
|
|||||||
el('thead', null,
|
el('thead', null,
|
||||||
el('tr', null,
|
el('tr', null,
|
||||||
el('th', { className: 'comparison-feature-col' }, 'Feature'),
|
el('th', { className: 'comparison-feature-col' }, 'Feature'),
|
||||||
cols.map(function(col, i) { return el('th', { key: i }, col); })
|
cols.map(function(col, i) {
|
||||||
|
return el('th', { key: i },
|
||||||
|
el('input', { type: 'text', value: col, style: thInputStyle, onChange: function(e){ updateCol(i, e.target.value); } })
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
el('th', { style: rowCtrlStyle })
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
el('tbody', null,
|
el('tbody', null,
|
||||||
rows.map(function(row, i) {
|
rows.map(function(row, ri) {
|
||||||
if (row.group) {
|
if (row.group) {
|
||||||
return el('tr', { key: i, className: 'comparison-group-row' },
|
return el('tr', { key: ri, className: 'comparison-group-row' },
|
||||||
el('td', { colSpan: cols.length + 1 }, row.group)
|
el('td', { colSpan: cols.length + 1 },
|
||||||
|
el('input', { type: 'text', value: row.group, style: Object.assign({}, inputStyle, { fontWeight: 700 }), onChange: function(e){ updateRow(ri, 'group', e.target.value); } })
|
||||||
|
),
|
||||||
|
el('td', { style: rowCtrlStyle },
|
||||||
|
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, -1); }, title: 'Move up' }, '\u25B2'),
|
||||||
|
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, 1); }, title: 'Move down' }, '\u25BC'),
|
||||||
|
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#b00' }), onClick: function(){ removeRow(ri); }, title: 'Remove row' }, '\u2715')
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return el('tr', { key: i },
|
return el('tr', { key: ri },
|
||||||
el('td', { className: 'comparison-feature-name' }, row.feature || ''),
|
el('td', { className: 'comparison-feature-name' },
|
||||||
(row.values || []).map(function(val, j) {
|
el('input', { type: 'text', value: row.feature || '', style: inputStyle, placeholder: 'Feature name\u2026', onChange: function(e){ updateRow(ri, 'feature', e.target.value); } })
|
||||||
return el('td', { key: j, className: 'comparison-cell' },
|
),
|
||||||
val === true ? '\u2713' : val === false ? '\u2014' : String(val)
|
(row.values || []).map(function(val, ci) {
|
||||||
|
if (typeof val === 'boolean') {
|
||||||
|
return el('td', { key: ci, className: 'comparison-cell', style: { textAlign: 'center' } },
|
||||||
|
el('button', { style: Object.assign({}, cellBtnStyle, { color: val ? '#2e7d32' : '#c62828' }), onClick: function(){ toggleCell(ri, ci); }, title: 'Toggle \u2713/\u2717' },
|
||||||
|
val ? '\u2713' : '\u2717'
|
||||||
|
),
|
||||||
|
el('button', { style: Object.assign({}, smallBtnStyle, { fontSize: '10px' }), onClick: function(){ switchCellToText(ri, ci); }, title: 'Switch to text' }, 'Aa')
|
||||||
);
|
);
|
||||||
})
|
}
|
||||||
|
return el('td', { key: ci, className: 'comparison-cell' },
|
||||||
|
el('div', { style: { display: 'flex', alignItems: 'center', gap: '2px' } },
|
||||||
|
el('input', { type: 'text', value: String(val), style: Object.assign({}, inputStyle, { flex: 1, minWidth: '60px' }), placeholder: 'Value\u2026', onChange: function(e){ updateCell(ri, ci, e.target.value); } }),
|
||||||
|
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#2e7d32' }), onClick: function(){ updateCell(ri, ci, true); }, title: 'Set as \u2713' }, '\u2713'),
|
||||||
|
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#c62828' }), onClick: function(){ updateCell(ri, ci, false); }, title: 'Set as \u2717' }, '\u2717')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
el('td', { style: rowCtrlStyle },
|
||||||
|
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, -1); }, title: 'Move up' }, '\u25B2'),
|
||||||
|
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, 1); }, title: 'Move down' }, '\u25BC'),
|
||||||
|
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#b00' }), onClick: function(){ removeRow(ri); }, title: 'Remove row' }, '\u2715')
|
||||||
|
)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
),
|
||||||
|
el('div', { style: { display: 'flex', gap: '8px', marginTop: '12px', justifyContent: 'center' } },
|
||||||
|
el(Btn, { isSecondary: true, isSmall: true, onClick: addFeatureRow }, '+ Feature Row'),
|
||||||
|
el(Btn, { isSecondary: true, isSmall: true, onClick: addGroupRow }, '+ Group Row'),
|
||||||
|
el(Btn, { isSecondary: true, isSmall: true, onClick: addCol }, '+ Column')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1688,7 +1969,6 @@ reg('oribi/hero-animated', {
|
|||||||
save: function () { return null; }
|
save: function () { return null; }
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ANIMATED PAGE HERO ──────────────────────────────────────────────────── */
|
|
||||||
reg('oribi/page-hero-animated', {
|
reg('oribi/page-hero-animated', {
|
||||||
title: 'Animated Page Hero',
|
title: 'Animated Page Hero',
|
||||||
icon: 'flag',
|
icon: 'flag',
|
||||||
@@ -1771,4 +2051,81 @@ reg('oribi/site-footer', {
|
|||||||
save: function () { return null; }
|
save: function () { return null; }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* USE CASES SHOWCASE ──────────────────────────────────────────────────── */
|
||||||
|
reg('oribi/use-cases', {
|
||||||
|
title: 'Use Cases Showcase',
|
||||||
|
icon: 'grid-view',
|
||||||
|
category: 'oribi',
|
||||||
|
supports: { html: false },
|
||||||
|
attributes: {
|
||||||
|
label: { type: 'string', default: '\u25cf Use Cases' },
|
||||||
|
heading: { type: 'string', default: 'Built for Every Scenario' },
|
||||||
|
lead: { type: 'string', default: 'From menus to meeting-room dashboards, digital signage adapts to your environment.' },
|
||||||
|
case1Title: { type: 'string', default: 'Menu Boards' },
|
||||||
|
case1Desc: { type: 'string', default: 'Showcase food, drinks, and daily specials with dynamic, always-current displays.' },
|
||||||
|
case2Title: { type: 'string', default: 'Event Displays' },
|
||||||
|
case2Desc: { type: 'string', default: 'Promote schedules, speakers, and live countdowns across lobbies and venues.' },
|
||||||
|
case3Title: { type: 'string', default: 'Office Dashboards' },
|
||||||
|
case3Desc: { type: 'string', default: 'Surface KPIs, occupancy data, and team alerts on screens throughout your workspace.' },
|
||||||
|
case4Title: { type: 'string', default: 'Wayfinding' },
|
||||||
|
case4Desc: { type: 'string', default: 'Guide visitors through complex buildings with interactive maps and directional signs.' },
|
||||||
|
},
|
||||||
|
edit: function (props) {
|
||||||
|
var a = props.attributes, s = props.setAttributes;
|
||||||
|
return el(Frag, null,
|
||||||
|
el(IC, null,
|
||||||
|
el(PB, { title: 'Section Header' },
|
||||||
|
el(TC, { label: 'Label', value: a.label, onChange: function(v){s({label:v});} }),
|
||||||
|
el(TC, { label: 'Heading', value: a.heading, onChange: function(v){s({heading:v});} }),
|
||||||
|
el(TA, { label: 'Lead', value: a.lead, onChange: function(v){s({lead:v});} })
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Use Case 1 – Menu Boards', initialOpen: false },
|
||||||
|
el(TC, { label: 'Title', value: a.case1Title, onChange: function(v){s({case1Title:v});} }),
|
||||||
|
el(TA, { label: 'Description', value: a.case1Desc, onChange: function(v){s({case1Desc:v});} })
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Use Case 2 – Events', initialOpen: false },
|
||||||
|
el(TC, { label: 'Title', value: a.case2Title, onChange: function(v){s({case2Title:v});} }),
|
||||||
|
el(TA, { label: 'Description', value: a.case2Desc, onChange: function(v){s({case2Desc:v});} })
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Use Case 3 – Dashboards', initialOpen: false },
|
||||||
|
el(TC, { label: 'Title', value: a.case3Title, onChange: function(v){s({case3Title:v});} }),
|
||||||
|
el(TA, { label: 'Description', value: a.case3Desc, onChange: function(v){s({case3Desc:v});} })
|
||||||
|
),
|
||||||
|
el(PB, { title: 'Use Case 4 – Wayfinding', initialOpen: false },
|
||||||
|
el(TC, { label: 'Title', value: a.case4Title, onChange: function(v){s({case4Title:v});} }),
|
||||||
|
el(TA, { label: 'Description', value: a.case4Desc, onChange: function(v){s({case4Desc:v});} })
|
||||||
|
)
|
||||||
|
),
|
||||||
|
el('section', { className: 'section use-cases-section' },
|
||||||
|
el('div', { className: 'container' },
|
||||||
|
el('div', { className: 'section-header' },
|
||||||
|
a.label ? el('span', { className: 'section-label' }, a.label) : null,
|
||||||
|
a.heading ? el('h2', null, a.heading) : null,
|
||||||
|
a.lead ? el('p', { className: 'lead' }, a.lead) : null
|
||||||
|
),
|
||||||
|
el('div', { className: 'uc-track' },
|
||||||
|
['menu', 'event', 'dashboard', 'wayfinding'].map(function (mod, i) {
|
||||||
|
var n = i + 1;
|
||||||
|
var title = a['case' + n + 'Title'];
|
||||||
|
var desc = a['case' + n + 'Desc'];
|
||||||
|
return el('div', { key: mod, className: 'uc-item' },
|
||||||
|
el('div', { className: 'uc-circle uc-anim--' + mod,
|
||||||
|
style: { display:'flex', alignItems:'center', justifyContent:'center',
|
||||||
|
fontSize:'.7rem', color:'var(--color-muted)', textAlign:'center', padding:'8px' } },
|
||||||
|
mod
|
||||||
|
),
|
||||||
|
el('div', { className: 'uc-item-body' },
|
||||||
|
el('div', { className: 'uc-item-title' }, title),
|
||||||
|
desc ? el('p', { className: 'uc-item-desc' }, desc) : null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
save: function () { return null; }
|
||||||
|
});
|
||||||
|
|
||||||
})(window.wp);
|
})(window.wp);
|
||||||
|
|||||||
@@ -513,6 +513,8 @@ add_action( 'init', function () {
|
|||||||
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
'faIcon' => [ 'type' => 'string', 'default' => '' ],
|
||||||
'name' => [ 'type' => 'string', 'default' => '' ],
|
'name' => [ 'type' => 'string', 'default' => '' ],
|
||||||
'tagline' => [ 'type' => 'string', 'default' => '' ],
|
'tagline' => [ 'type' => 'string', 'default' => '' ],
|
||||||
|
'price' => [ 'type' => 'string', 'default' => '' ],
|
||||||
|
'pricePer' => [ 'type' => 'string', 'default' => '' ],
|
||||||
'features' => [ 'type' => 'array', 'default' => [] ],
|
'features' => [ 'type' => 'array', 'default' => [] ],
|
||||||
'btnText' => [ 'type' => 'string', 'default' => 'Get Started' ],
|
'btnText' => [ 'type' => 'string', 'default' => 'Get Started' ],
|
||||||
'btnUrl' => [ 'type' => 'string', 'default' => '/contact' ],
|
'btnUrl' => [ 'type' => 'string', 'default' => '/contact' ],
|
||||||
@@ -551,6 +553,13 @@ add_action( 'init', function () {
|
|||||||
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
|
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
|
||||||
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
|
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
|
||||||
'imgWidth' => [ 'type' => 'number', 'default' => 300 ],
|
'imgWidth' => [ 'type' => 'number', 'default' => 300 ],
|
||||||
|
'isDashboard' => [ 'type' => 'boolean', 'default' => false ],
|
||||||
|
'deviceAnim' => [ 'type' => 'boolean', 'default' => false ],
|
||||||
|
'tvStick' => [ 'type' => 'boolean', 'default' => false ],
|
||||||
|
'cameraAnim' => [ 'type' => 'boolean', 'default' => false ],
|
||||||
|
'neverGoesDark'=> [ 'type' => 'boolean', 'default' => false ],
|
||||||
|
'brandedAnim' => [ 'type' => 'boolean', 'default' => false ],
|
||||||
|
'galleryIds' => [ 'type' => 'array', 'default' => [], 'items' => [ 'type' => 'number' ] ],
|
||||||
],
|
],
|
||||||
'supports' => $block_supports,
|
'supports' => $block_supports,
|
||||||
'render_callback' => 'oribi_render_platform_row',
|
'render_callback' => 'oribi_render_platform_row',
|
||||||
@@ -651,6 +660,25 @@ add_action( 'init', function () {
|
|||||||
'render_callback' => 'oribi_render_page_hero_animated',
|
'render_callback' => 'oribi_render_page_hero_animated',
|
||||||
] );
|
] );
|
||||||
|
|
||||||
|
/* Use Cases Showcase - 4 animated circles beneath the homepage hero */
|
||||||
|
register_block_type( 'oribi/use-cases', [
|
||||||
|
'attributes' => [
|
||||||
|
'label' => [ 'type' => 'string', 'default' => '● Use Cases' ],
|
||||||
|
'heading' => [ 'type' => 'string', 'default' => 'Built for Every Scenario' ],
|
||||||
|
'lead' => [ 'type' => 'string', 'default' => 'From menus to meeting-room dashboards, digital signage adapts to your environment.' ],
|
||||||
|
'case1Title' => [ 'type' => 'string', 'default' => 'Menu Boards' ],
|
||||||
|
'case1Desc' => [ 'type' => 'string', 'default' => 'Showcase food, drinks, and daily specials with dynamic, always-current displays.' ],
|
||||||
|
'case2Title' => [ 'type' => 'string', 'default' => 'Event Displays' ],
|
||||||
|
'case2Desc' => [ 'type' => 'string', 'default' => 'Promote schedules, speakers, and live countdowns across lobbies and venues.' ],
|
||||||
|
'case3Title' => [ 'type' => 'string', 'default' => 'Office Dashboards' ],
|
||||||
|
'case3Desc' => [ 'type' => 'string', 'default' => 'Surface KPIs, occupancy data, and team alerts on screens throughout your workspace.' ],
|
||||||
|
'case4Title' => [ 'type' => 'string', 'default' => 'Wayfinding' ],
|
||||||
|
'case4Desc' => [ 'type' => 'string', 'default' => 'Guide visitors through complex buildings with interactive maps and directional signs.' ],
|
||||||
|
],
|
||||||
|
'supports' => $block_supports,
|
||||||
|
'render_callback' => 'oribi_render_use_cases',
|
||||||
|
] );
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
/* ══════════════════════════════════════════════════════════════════════════════
|
/* ══════════════════════════════════════════════════════════════════════════════
|
||||||
@@ -666,9 +694,8 @@ function oribi_render_site_header() {
|
|||||||
<div class="site-logo">
|
<div class="site-logo">
|
||||||
<?php if ( $has_logo ) : ?>
|
<?php if ( $has_logo ) : ?>
|
||||||
<?php the_custom_logo(); ?>
|
<?php the_custom_logo(); ?>
|
||||||
<?php else : ?>
|
|
||||||
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="logo-text"><strong>Oribi</strong> Tech</a>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="logo-text"><strong>OTS</strong> Signs</a>
|
||||||
</div>
|
</div>
|
||||||
<button class="nav-toggle" id="nav-toggle" aria-expanded="false" aria-label="<?php esc_attr_e( 'Toggle navigation', 'ots-theme' ); ?>">
|
<button class="nav-toggle" id="nav-toggle" aria-expanded="false" aria-label="<?php esc_attr_e( 'Toggle navigation', 'ots-theme' ); ?>">
|
||||||
<span></span><span></span><span></span>
|
<span></span><span></span><span></span>
|
||||||
@@ -698,9 +725,10 @@ function oribi_render_site_header() {
|
|||||||
/** Fallback menu when no WP menu is assigned. */
|
/** Fallback menu when no WP menu is assigned. */
|
||||||
function oribi_fallback_menu() {
|
function oribi_fallback_menu() {
|
||||||
echo '<ul class="nav-menu">';
|
echo '<ul class="nav-menu">';
|
||||||
echo '<li><a href="' . esc_url( home_url( '/managed-it' ) ) . '">Services</a></li>';
|
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( '/about' ) ) . '">About</a></li>';
|
echo '<li><a href="' . esc_url( home_url( '/about' ) ) . '">About</a></li>';
|
||||||
echo '<li><a href="' . esc_url( home_url( '/faq' ) ) . '">FAQ</a></li>';
|
|
||||||
echo '<li><a href="' . esc_url( home_url( '/contact' ) ) . '">Contact</a></li>';
|
echo '<li><a href="' . esc_url( home_url( '/contact' ) ) . '">Contact</a></li>';
|
||||||
echo '</ul>';
|
echo '</ul>';
|
||||||
}
|
}
|
||||||
@@ -718,25 +746,25 @@ function oribi_render_site_footer() {
|
|||||||
<?php else : ?>
|
<?php else : ?>
|
||||||
<div class="logo-text"><strong>Oribi</strong> Tech</div>
|
<div class="logo-text"><strong>Oribi</strong> Tech</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<p class="footer-tagline">IT solutions tailored for your business.</p>
|
<p class="footer-tagline">Digital signage solutions that communicate, engage, and grow your business.</p>
|
||||||
<p class="footer-location">Saratoga Springs, Upstate New York</p>
|
<p class="footer-location">An Oribi Technology Services Company</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<div class="footer-col">
|
<div class="footer-col">
|
||||||
<h4>Services</h4>
|
<h4>Platform</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/365care' ) ); ?>">365Care</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/features' ) ); ?>">Features</a></li>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/endpointcare' ) ); ?>">EndpointCare</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/pricing' ) ); ?>">Pricing</a></li>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/netcare' ) ); ?>">NetCare</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/devices' ) ); ?>">Devices</a></li>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/servercare' ) ); ?>">ServerCare</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/demo' ) ); ?>">Demo</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-col">
|
<div class="footer-col">
|
||||||
<h4>Company</h4>
|
<h4>Company</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/about' ) ); ?>">About</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/about' ) ); ?>">About</a></li>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/managed-it' ) ); ?>">Managed IT</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/solutions' ) ); ?>">Solutions</a></li>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/services-comparison' ) ); ?>">Compare</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>
|
<li><a href="<?php echo esc_url( home_url( '/faq' ) ); ?>">FAQ</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -744,14 +772,14 @@ function oribi_render_site_footer() {
|
|||||||
<h4>Connect</h4>
|
<h4>Connect</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="<?php echo esc_url( home_url( '/contact' ) ); ?>">Contact</a></li>
|
<li><a href="<?php echo esc_url( home_url( '/contact' ) ); ?>">Contact</a></li>
|
||||||
<li><a href="https://portal.oribi-tech.com/" target="_blank" rel="noopener">Client Portal</a></li>
|
<li><a href="https://ots-signs.com/portal" target="_blank" rel="noopener">Client Portal</a></li>
|
||||||
<li><a href="mailto:solutions@oribi-tech.com">Email Us</a></li>
|
<li><a href="mailto:hello@ots-signs.com">Email Us</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-bottom">
|
<div class="footer-bottom">
|
||||||
<p>© <?php echo esc_html( $year ); ?> OTS Themenology Services. All rights reserved.</p>
|
<p>© <?php echo esc_html( $year ); ?> Oribi Technology Services. All rights reserved.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -950,12 +978,13 @@ function oribi_render_contact_section( $a ) {
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cf-interest">Interested In</label>
|
<label for="cf-interest">Interested In</label>
|
||||||
<select id="cf-interest" name="interest">
|
<select id="cf-interest" name="interest">
|
||||||
<option value="">Select a service…</option>
|
<option value="">Select a topic…</option>
|
||||||
<option value="365Care">365Care</option>
|
<option value="Digital Signage">Digital Signage Solutions</option>
|
||||||
<option value="EndpointCare">EndpointCare</option>
|
<option value="Content Creation">Content Creation</option>
|
||||||
<option value="NetCare">NetCare</option>
|
<option value="Hardware">Player Devices & Hardware</option>
|
||||||
<option value="ServerCare">ServerCare</option>
|
<option value="Pricing">Pricing & Plans</option>
|
||||||
<option value="Full Managed IT">Full Managed IT</option>
|
<option value="Demo">Request a Demo</option>
|
||||||
|
<option value="Support">Technical Support</option>
|
||||||
<option value="Other">Other / Not sure</option>
|
<option value="Other">Other / Not sure</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -1294,6 +1323,12 @@ function oribi_render_pricing_card( $a ) {
|
|||||||
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon" style="margin-inline:auto;"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
<?php if ( oribi_has_icon( $a ) ) : ?><div class="feature-icon" style="margin-inline:auto;"><?php echo oribi_render_icon( $a ); ?></div><?php endif; ?>
|
||||||
<div class="pricing-name"><?php echo esc_html( $a['name'] ); ?></div>
|
<div class="pricing-name"><?php echo esc_html( $a['name'] ); ?></div>
|
||||||
<p class="pricing-tagline"><?php echo wp_kses_post( $a['tagline'] ); ?></p>
|
<p class="pricing-tagline"><?php echo wp_kses_post( $a['tagline'] ); ?></p>
|
||||||
|
<?php if ( ! empty( $a['price'] ) ) : ?>
|
||||||
|
<div class="pricing-price">
|
||||||
|
<div class="pricing-amount"><?php echo wp_kses_post( $a['price'] ); ?></div>
|
||||||
|
<?php if ( ! empty( $a['pricePer'] ) ) : ?><div class="pricing-per"><?php echo wp_kses_post( $a['pricePer'] ); ?></div><?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<ul class="pricing-features">
|
<ul class="pricing-features">
|
||||||
<?php foreach ( ( $a['features'] ?? [] ) as $f ) : ?>
|
<?php foreach ( ( $a['features'] ?? [] ) as $f ) : ?>
|
||||||
<li><span class="pricing-check">✓</span> <?php echo wp_kses_post( $f ); ?></li>
|
<li><span class="pricing-check">✓</span> <?php echo wp_kses_post( $f ); ?></li>
|
||||||
@@ -1321,6 +1356,208 @@ function oribi_render_platform_section( $a, $content ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── Platform Row (child - renders one service row) ────────────────────────── */
|
/* ── Platform Row (child - renders one service row) ────────────────────────── */
|
||||||
|
function oribi_render_camera_animation() {
|
||||||
|
return <<<'HTML'
|
||||||
|
<div class="ve-stage" aria-hidden="true"><svg viewBox="0 0 540 360" xmlns="http://www.w3.org/2000/svg" class="ve-svg" role="img" aria-label="Animated video editor timeline">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="ve-preview-clip">
|
||||||
|
<rect x="54" y="36" width="256" height="184"/>
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient id="ve-sg-warm" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#3d0800"/>
|
||||||
|
<stop offset="50%" stop-color="#a02500"/>
|
||||||
|
<stop offset="100%" stop-color="#1d0400"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ve-sg-cold" x1="100%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#0a1f3d"/>
|
||||||
|
<stop offset="50%" stop-color="#0e3d6e"/>
|
||||||
|
<stop offset="100%" stop-color="#06111e"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ve-sg-go" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#07180d"/>
|
||||||
|
<stop offset="50%" stop-color="#1c6038"/>
|
||||||
|
<stop offset="100%" stop-color="#040e07"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ve-scr-warm" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#ff9500"/>
|
||||||
|
<stop offset="100%" stop-color="#ff4500"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ve-scr-cold" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#1a8aff"/>
|
||||||
|
<stop offset="100%" stop-color="#0055cc"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="ve-scr-go" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#00cc66"/>
|
||||||
|
<stop offset="100%" stop-color="#008844"/>
|
||||||
|
</linearGradient>
|
||||||
|
<pattern id="ve-scanlines" x="0" y="0" width="1" height="3" patternUnits="userSpaceOnUse">
|
||||||
|
<rect width="1" height="1" fill="rgba(0,0,0,0.18)"/>
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Laptop lid outer shell -->
|
||||||
|
<rect x="20" y="5" width="500" height="300" rx="12" fill="#d2d2d0" stroke="#b0aca8" stroke-width="1.5"/>
|
||||||
|
<rect x="28" y="12" width="484" height="280" rx="8" fill="#1c1c1c"/>
|
||||||
|
<rect x="32" y="16" width="476" height="272" rx="5" fill="#0e1117"/>
|
||||||
|
<!-- Laptop base -->
|
||||||
|
<rect x="10" y="305" width="520" height="26" rx="5" fill="#c8c8c8" stroke="#b0ada8" stroke-width="0.8"/>
|
||||||
|
<rect x="80" y="301" width="380" height="5" rx="2" fill="#a8a6a2"/>
|
||||||
|
<rect x="205" y="311" width="130" height="13" rx="5" fill="#b8b5b0" stroke="#a0a09a" stroke-width="0.7"/>
|
||||||
|
<rect x="38" y="306" width="155" height="18" rx="2" fill="#bcbab6" opacity="0.45"/>
|
||||||
|
<rect x="347" y="306" width="155" height="18" rx="2" fill="#bcbab6" opacity="0.45"/>
|
||||||
|
|
||||||
|
<!-- Editor title bar -->
|
||||||
|
<rect x="32" y="16" width="476" height="20" rx="4" fill="#1e2229"/>
|
||||||
|
<circle cx="50" cy="26" r="5" fill="#FF5F56"/>
|
||||||
|
<circle cx="66" cy="26" r="5" fill="#FFBD2E"/>
|
||||||
|
<circle cx="82" cy="26" r="5" fill="#27C93F"/>
|
||||||
|
<rect x="180" y="21" width="180" height="10" rx="3" fill="#3a3f48"/>
|
||||||
|
<rect x="100" y="22" width="28" height="8" rx="2" fill="#2e333c"/>
|
||||||
|
<rect x="132" y="22" width="24" height="8" rx="2" fill="#2e333c"/>
|
||||||
|
<rect x="160" y="22" width="16" height="8" rx="2" fill="#2e333c"/>
|
||||||
|
|
||||||
|
<!-- Left toolbar -->
|
||||||
|
<rect x="32" y="36" width="22" height="184" fill="#181c22"/>
|
||||||
|
<line x1="54" y1="36" x2="54" y2="220" stroke="#2a2e38" stroke-width="1"/>
|
||||||
|
<rect x="36" y="46" width="14" height="14" rx="2" fill="#3a4152"/>
|
||||||
|
<rect x="36" y="66" width="14" height="14" rx="2" fill="#3a4152"/>
|
||||||
|
<rect x="36" y="86" width="14" height="14" rx="2" fill="#3a4152"/>
|
||||||
|
<rect x="36" y="106" width="14" height="14" rx="2" fill="#3a4152"/>
|
||||||
|
<rect x="36" y="126" width="14" height="14" rx="2" fill="#3a4152"/>
|
||||||
|
<rect x="33" y="46" width="3" height="14" rx="1" fill="#D83302"/>
|
||||||
|
|
||||||
|
<!-- Preview pane -->
|
||||||
|
<rect x="54" y="36" width="256" height="184" fill="#0a0b0e"/>
|
||||||
|
<g clip-path="url(#ve-preview-clip)">
|
||||||
|
<rect id="ve-scene-1" x="54" y="36" width="256" height="184" fill="url(#ve-sg-warm)" opacity="1"/>
|
||||||
|
<rect id="ve-scene-2" x="54" y="36" width="256" height="184" fill="url(#ve-sg-cold)" opacity="0"/>
|
||||||
|
<rect id="ve-scene-3" x="54" y="36" width="256" height="184" fill="url(#ve-sg-go)" opacity="0"/>
|
||||||
|
<!-- Laptop in the preview video -->
|
||||||
|
<rect x="102" y="52" width="156" height="106" rx="5" fill="#1c1c1c" stroke="#2e2e2e" stroke-width="1"/>
|
||||||
|
<rect x="106" y="56" width="148" height="98" rx="3" fill="#111111"/>
|
||||||
|
<rect id="ve-inner-screen" x="108" y="58" width="144" height="94" rx="1" fill="url(#ve-scr-warm)"/>
|
||||||
|
<polygon points="108,58 160,58 108,88" fill="white" opacity="0.04"/>
|
||||||
|
<rect x="108" y="58" width="144" height="94" fill="url(#ve-scanlines)" opacity="0.45"/>
|
||||||
|
<circle cx="180" cy="55" r="2.5" fill="#232323" stroke="#2e2e2e" stroke-width="0.5"/>
|
||||||
|
<rect x="92" y="158" width="176" height="17" rx="2" fill="#222222" stroke="#2d2d2d" stroke-width="0.5"/>
|
||||||
|
<rect x="150" y="162" width="60" height="9" rx="3" fill="#2a2a2a" stroke="#353535" stroke-width="0.5"/>
|
||||||
|
<rect x="97" y="159" width="166" height="1" fill="#2c2c2c"/>
|
||||||
|
<line x1="54" y1="175" x2="310" y2="175" stroke="#1c1c1c" stroke-width="2"/>
|
||||||
|
<rect x="54" y="175" width="256" height="45" fill="#040507" opacity="0.75"/>
|
||||||
|
<rect x="54" y="36" width="256" height="184" fill="url(#ve-scanlines)" opacity="0.25"/>
|
||||||
|
</g>
|
||||||
|
<rect x="54" y="36" width="256" height="184" fill="none" stroke="#2a2e38" stroke-width="0.5"/>
|
||||||
|
<line x1="310" y1="36" x2="310" y2="220" stroke="#2a2e38" stroke-width="1"/>
|
||||||
|
|
||||||
|
<!-- Inspector / Properties panel -->
|
||||||
|
<rect x="310" y="36" width="198" height="184" fill="#141619"/>
|
||||||
|
<rect x="310" y="36" width="198" height="20" fill="#1a1e25"/>
|
||||||
|
<rect x="318" y="42" width="80" height="8" rx="2" fill="#3a3f48"/>
|
||||||
|
<rect x="318" y="64" width="50" height="7" rx="2" fill="#2a2e38"/>
|
||||||
|
<rect x="378" y="64" width="82" height="7" rx="2" fill="#333a45"/>
|
||||||
|
<rect x="318" y="78" width="45" height="7" rx="2" fill="#2a2e38"/>
|
||||||
|
<rect x="378" y="78" width="96" height="7" rx="2" fill="#333a45"/>
|
||||||
|
<rect x="318" y="92" width="35" height="7" rx="2" fill="#2a2e38"/>
|
||||||
|
<rect x="378" y="92" width="62" height="7" rx="2" fill="#333a45"/>
|
||||||
|
<rect x="318" y="106" width="55" height="7" rx="2" fill="#2a2e38"/>
|
||||||
|
<rect x="378" y="106" width="72" height="7" rx="2" fill="#333a45"/>
|
||||||
|
<rect x="318" y="120" width="40" height="7" rx="2" fill="#2a2e38"/>
|
||||||
|
<rect x="378" y="120" width="54" height="7" rx="2" fill="#333a45"/>
|
||||||
|
<line x1="318" y1="136" x2="498" y2="136" stroke="#2a2e38" stroke-width="0.5"/>
|
||||||
|
<rect x="310" y="136" width="198" height="12" fill="#1a1e25"/>
|
||||||
|
<rect x="318" y="140" width="60" height="6" rx="2" fill="#2a2e38"/>
|
||||||
|
<rect x="318" y="150" width="32" height="24" rx="1" fill="#C0390A" opacity="0.8"/>
|
||||||
|
<rect x="354" y="150" width="32" height="24" rx="1" fill="#1a52c8" opacity="0.8"/>
|
||||||
|
<rect x="390" y="150" width="32" height="24" rx="1" fill="#1a7a3d" opacity="0.8"/>
|
||||||
|
<rect x="426" y="150" width="32" height="24" rx="1" fill="#c07800" opacity="0.8"/>
|
||||||
|
<rect x="462" y="150" width="32" height="24" rx="1" fill="#7030d0" opacity="0.8"/>
|
||||||
|
|
||||||
|
<!-- Timeline section -->
|
||||||
|
<rect x="32" y="220" width="476" height="68" fill="#161616"/>
|
||||||
|
<line x1="32" y1="220" x2="508" y2="220" stroke="#2a2e38" stroke-width="1"/>
|
||||||
|
<rect x="32" y="220" width="476" height="14" fill="#1a1e24"/>
|
||||||
|
<rect x="32" y="220" width="72" height="68" fill="#1a1e24"/>
|
||||||
|
<line x1="104" y1="220" x2="104" y2="288" stroke="#2a2e38" stroke-width="1"/>
|
||||||
|
<!-- Ruler ticks and labels -->
|
||||||
|
<line x1="104" y1="220" x2="104" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
||||||
|
<text x="105" y="231" fill="#565a64" font-size="8" font-family="monospace">0:00</text>
|
||||||
|
<line x1="184" y1="220" x2="184" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
||||||
|
<text x="185" y="231" fill="#565a64" font-size="8" font-family="monospace">0:02</text>
|
||||||
|
<line x1="264" y1="220" x2="264" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
||||||
|
<text x="265" y="231" fill="#565a64" font-size="8" font-family="monospace">0:04</text>
|
||||||
|
<line x1="344" y1="220" x2="344" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
||||||
|
<text x="345" y="231" fill="#565a64" font-size="8" font-family="monospace">0:06</text>
|
||||||
|
<line x1="424" y1="220" x2="424" y2="232" stroke="#4a4e58" stroke-width="1"/>
|
||||||
|
<text x="425" y="231" fill="#565a64" font-size="8" font-family="monospace">0:08</text>
|
||||||
|
<line x1="144" y1="220" x2="144" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
||||||
|
<line x1="224" y1="220" x2="224" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
||||||
|
<line x1="304" y1="220" x2="304" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
||||||
|
<line x1="384" y1="220" x2="384" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
||||||
|
<line x1="464" y1="220" x2="464" y2="226" stroke="#2e3240" stroke-width="0.5"/>
|
||||||
|
<!-- Track label colour strips -->
|
||||||
|
<rect x="36" y="237" width="56" height="14" rx="2" fill="#283040"/>
|
||||||
|
<rect x="36" y="255" width="56" height="14" rx="2" fill="#203020"/>
|
||||||
|
<rect x="36" y="273" width="56" height="14" rx="2" fill="#302818"/>
|
||||||
|
|
||||||
|
<!-- Track 1: VIDEO clips -->
|
||||||
|
<rect x="104" y="234" width="404" height="18" fill="#1a1a22"/>
|
||||||
|
<rect x="104" y="235" width="88" height="16" rx="2" fill="#2563EB"/>
|
||||||
|
<rect x="104" y="235" width="88" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
<rect x="196" y="235" width="66" height="16" rx="2" fill="#1D4ED8"/>
|
||||||
|
<rect x="196" y="235" width="66" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
<rect x="266" y="235" width="106" height="16" rx="2" fill="#2563EB"/>
|
||||||
|
<rect x="266" y="235" width="106" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
<rect x="376" y="235" width="88" height="16" rx="2" fill="#1E40AF"/>
|
||||||
|
<rect x="376" y="235" width="88" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
|
||||||
|
<!-- Track 2: AUDIO/MUSIC clips -->
|
||||||
|
<rect x="104" y="252" width="404" height="18" fill="#141c12"/>
|
||||||
|
<rect x="104" y="253" width="178" height="16" rx="2" fill="#15803D"/>
|
||||||
|
<rect x="104" y="253" width="178" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
|
||||||
|
<!-- Inline waveform bars -->
|
||||||
|
<rect x="108" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="112" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="116" y="260" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="120" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="124" y="260" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="128" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="132" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="136" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="140" y="260" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="144" y="258" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="148" y="261" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="152" y="258" width="2" height="6" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="156" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="160" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="164" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="168" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="172" y="261" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="176" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
|
||||||
|
<rect x="286" y="253" width="148" height="16" rx="2" fill="#166534"/>
|
||||||
|
<rect x="286" y="253" width="148" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
|
||||||
|
<rect x="438" y="253" width="66" height="16" rx="2" fill="#15803D"/>
|
||||||
|
<rect x="438" y="253" width="66" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
|
||||||
|
|
||||||
|
<!-- Track 3: GFX / TEXT clips -->
|
||||||
|
<rect x="104" y="270" width="404" height="18" fill="#181710"/>
|
||||||
|
<rect x="120" y="271" width="60" height="16" rx="2" fill="#D97706"/>
|
||||||
|
<rect x="120" y="271" width="60" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
<rect x="226" y="271" width="52" height="16" rx="2" fill="#B45309"/>
|
||||||
|
<rect x="226" y="271" width="52" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
<rect x="334" y="271" width="78" height="16" rx="2" fill="#D97706"/>
|
||||||
|
<rect x="334" y="271" width="78" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
<rect x="452" y="271" width="50" height="16" rx="2" fill="#B45309"/>
|
||||||
|
<rect x="452" y="271" width="50" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
|
||||||
|
|
||||||
|
<!-- Animated playhead -->
|
||||||
|
<polygon id="ve-playhead-head" points="0,-8 -6,-2 6,-2" transform="translate(104,234)" fill="#FF4500"/>
|
||||||
|
<rect id="ve-playhead-line" x="103" y="220" width="2" height="68" fill="#FF4500" opacity="0.92"/>
|
||||||
|
<!-- Timecode display -->
|
||||||
|
<text id="ve-timecode" x="36" y="230" fill="#8a8e98" font-size="8" font-family="monospace">0:00</text>
|
||||||
|
</svg></div>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
|
|
||||||
function oribi_render_platform_row( $a ) {
|
function oribi_render_platform_row( $a ) {
|
||||||
$rev = ! empty( $a['reversed'] ) ? ' reverse' : '';
|
$rev = ! empty( $a['reversed'] ) ? ' reverse' : '';
|
||||||
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
|
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
|
||||||
@@ -1328,7 +1565,128 @@ function oribi_render_platform_row( $a ) {
|
|||||||
$img_alt = ! empty( $a['imgAlt'] ) ? $a['imgAlt'] : '';
|
$img_alt = ! empty( $a['imgAlt'] ) ? $a['imgAlt'] : '';
|
||||||
$img_w = ! empty( $a['imgWidth'] ) ? intval( $a['imgWidth'] ) : 300;
|
$img_w = ! empty( $a['imgWidth'] ) ? intval( $a['imgWidth'] ) : 300;
|
||||||
|
|
||||||
if ( $img_url ) {
|
// Only render animated dashboard when explicitly flagged
|
||||||
|
$is_dashboard = ! empty( $a['isDashboard'] );
|
||||||
|
|
||||||
|
if ( $is_dashboard ) {
|
||||||
|
// Render animated dashboard chart SVG
|
||||||
|
// Text uses class hooks: .ct = title, .cl = label, .cv = value
|
||||||
|
// JS will dynamically set fill colours based on data-theme
|
||||||
|
$visual_html = '<div class="dashboard-tv" data-dashboard-container="true">
|
||||||
|
<div class="dashboard-tv__body">
|
||||||
|
<div class="dashboard-tv__screen">
|
||||||
|
<svg viewBox="0 0 800 450" xmlns="http://www.w3.org/2000/svg" class="dashboard-chart" role="img" aria-label="Animated dashboard charts">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="barGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#D83302" stop-opacity="1"/>
|
||||||
|
<stop offset="100%" stop-color="#4CAF50" stop-opacity=".8"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#4CAF50" stop-opacity=".3"/>
|
||||||
|
<stop offset="100%" stop-color="#4CAF50" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- ── Top-left: Performance bars ── -->
|
||||||
|
<g transform="translate(35,20)">
|
||||||
|
<text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#333">Performance</text>
|
||||||
|
<g id="bars-group-1" transform="translate(0,25)">
|
||||||
|
<rect class="bar" x="0" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="40" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="80" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="120" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="160" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(0,152)">
|
||||||
|
<text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#666">API</text>
|
||||||
|
<text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#666">Cache</text>
|
||||||
|
<text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#666">DB</text>
|
||||||
|
<text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#666">Queue</text>
|
||||||
|
<text class="cl" x="174" y="0" font-size="10" text-anchor="middle" fill="#666">Worker</text>
|
||||||
|
</g>
|
||||||
|
<g id="values-group-1" transform="translate(0,168)">
|
||||||
|
<text class="cv" x="14" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
||||||
|
<text class="cv" x="54" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
||||||
|
<text class="cv" x="94" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
||||||
|
<text class="cv" x="134" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
||||||
|
<text class="cv" x="174" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0%</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- ── Top-right: Requests/sec bars ── -->
|
||||||
|
<g transform="translate(430,20)">
|
||||||
|
<text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#333">Requests/sec</text>
|
||||||
|
<g id="bars-group-2" transform="translate(0,25)">
|
||||||
|
<rect class="bar" x="0" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="40" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="80" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
<rect class="bar" x="120" y="120" width="28" height="0" fill="url(#barGradient)"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(0,152)">
|
||||||
|
<text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#666">Read</text>
|
||||||
|
<text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#666">Write</text>
|
||||||
|
<text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#666">Update</text>
|
||||||
|
<text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#666">Delete</text>
|
||||||
|
</g>
|
||||||
|
<g id="values-group-2" transform="translate(0,168)">
|
||||||
|
<text class="cv" x="14" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
||||||
|
<text class="cv" x="54" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
||||||
|
<text class="cv" x="94" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
||||||
|
<text class="cv" x="134" y="0" font-size="11" font-weight="600" text-anchor="middle" fill="#333">0</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- ── Bottom-left: Traffic Trend line ── -->
|
||||||
|
<g id="line-graph" transform="translate(35,245)">
|
||||||
|
<text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#333">Traffic Trend</text>
|
||||||
|
<g transform="translate(0,25)">
|
||||||
|
<line class="grid-line" x1="0" y1="0" x2="340" y2="0" stroke="#E0E0E0" stroke-width=".5"/>
|
||||||
|
<line class="grid-line" x1="0" y1="40" x2="340" y2="40" stroke="#E0E0E0" stroke-width=".5"/>
|
||||||
|
<line class="grid-line" x1="0" y1="80" x2="340" y2="80" stroke="#E0E0E0" stroke-width=".5"/>
|
||||||
|
<line class="grid-line" x1="0" y1="120" x2="340" y2="120" stroke="#E0E0E0" stroke-width=".5"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(0,25)">
|
||||||
|
<path id="line-fill" d="M0,80 L340,80 L340,145 L0,145 Z" fill="url(#lineGradient)"/>
|
||||||
|
<path id="line-path" d="M0,80 L340,80" stroke="#4CAF50" stroke-width="2.5" fill="none" stroke-linecap="round"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- ── Bottom-right: Distribution pie ── -->
|
||||||
|
<g transform="translate(490,245)">
|
||||||
|
<text class="ct" x="100" y="0" font-size="14" font-weight="600" text-anchor="middle" fill="#333">Distribution</text>
|
||||||
|
<g transform="translate(100,90)">
|
||||||
|
<g class="pie-segment" transform="rotate(0)">
|
||||||
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#D83302" opacity=".9"/>
|
||||||
|
</g>
|
||||||
|
<g class="pie-segment" transform="rotate(90)">
|
||||||
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#4CAF50" opacity=".8"/>
|
||||||
|
</g>
|
||||||
|
<g class="pie-segment" transform="rotate(180)">
|
||||||
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#f59e0b" opacity=".7"/>
|
||||||
|
</g>
|
||||||
|
<g class="pie-segment" transform="rotate(270)">
|
||||||
|
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#ef4444" opacity=".7"/>
|
||||||
|
</g>
|
||||||
|
<circle id="pie-center" cx="0" cy="0" r="22" fill="#fff" stroke="#E0E0E0" stroke-width="1"/>
|
||||||
|
<text id="pie-center-text" x="0" y="5" text-anchor="middle" font-size="13" font-weight="600" fill="#333">100%</text>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(30,170)">
|
||||||
|
<rect x="0" y="0" width="8" height="8" fill="#D83302"/>
|
||||||
|
<text class="cl" x="12" y="8" font-size="11" fill="#666">Service A</text>
|
||||||
|
<rect x="0" y="15" width="8" height="8" fill="#4CAF50"/>
|
||||||
|
<text class="cl" x="12" y="23" font-size="11" fill="#666">Service B</text>
|
||||||
|
<rect x="100" y="0" width="8" height="8" fill="#f59e0b"/>
|
||||||
|
<text class="cl" x="112" y="8" font-size="11" fill="#666">Service C</text>
|
||||||
|
<rect x="100" y="15" width="8" height="8" fill="#ef4444"/>
|
||||||
|
<text class="cl" x="112" y="23" font-size="11" fill="#666">Service D</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div></div>
|
||||||
|
<div class="dashboard-tv__feet"><div class="dashboard-tv__foot"></div><div class="dashboard-tv__foot"></div></div>
|
||||||
|
</div>';
|
||||||
|
$visual_cls = 'platform-visual has-dashboard';
|
||||||
|
} elseif ( $img_url ) {
|
||||||
$img_style = 'width:' . $img_w . 'px;max-width:100%;height:auto;border-radius:var(--radius-sm);object-fit:contain;display:block;margin-inline:auto;';
|
$img_style = 'width:' . $img_w . 'px;max-width:100%;height:auto;border-radius:var(--radius-sm);object-fit:contain;display:block;margin-inline:auto;';
|
||||||
if ( $img_id ) {
|
if ( $img_id ) {
|
||||||
$visual_html = wp_get_attachment_image( $img_id, 'full', false, [ 'style' => $img_style, 'alt' => $img_alt ] );
|
$visual_html = wp_get_attachment_image( $img_id, 'full', false, [ 'style' => $img_style, 'alt' => $img_alt ] );
|
||||||
@@ -1336,6 +1694,292 @@ function oribi_render_platform_row( $a ) {
|
|||||||
$visual_html = '<img src="' . esc_url( $img_url ) . '" alt="' . esc_attr( $img_alt ) . '" style="' . esc_attr( $img_style ) . '">';
|
$visual_html = '<img src="' . esc_url( $img_url ) . '" alt="' . esc_attr( $img_alt ) . '" style="' . esc_attr( $img_style ) . '">';
|
||||||
}
|
}
|
||||||
$visual_cls = 'platform-visual has-img';
|
$visual_cls = 'platform-visual has-img';
|
||||||
|
} elseif ( ! empty( $a['deviceAnim'] ) ) {
|
||||||
|
$da_screen = '<div class="da-screen"><div class="da-promo"><div class="da-promo__top"><span class="da-promo__dot"></span><span class="da-promo__brand"></span></div><div class="da-promo__hero"></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--lg"></span><span class="da-promo__line da-promo__line--sm"></span></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--md"></span><span class="da-promo__line da-promo__line--xs"></span></div><div class="da-promo__ticker"><span class="da-promo__chip"></span><span class="da-promo__chip"></span><span class="da-promo__chip"></span></div></div></div>';
|
||||||
|
$da = '<div class="da-stage" aria-hidden="true">';
|
||||||
|
$da .= '<div class="da-device da-tablet"><div class="da-body">' . $da_screen . '</div><span class="da-label">Tablet</span></div>';
|
||||||
|
$da .= '<div class="da-device da-monitor-sm"><div class="da-body">' . $da_screen . '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Small Monitor</span></div>';
|
||||||
|
$da .= '<div class="da-device da-monitor-lg"><div class="da-body">' . $da_screen . '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Large Monitor</span></div>';
|
||||||
|
$da .= '<div class="da-device da-tv"><div class="da-body">' . $da_screen . '</div><div class="da-feet"><div class="da-foot"></div><div class="da-foot"></div></div><span class="da-label">TV</span></div>';
|
||||||
|
$da .= '<div class="da-device da-projector"><div class="da-proj-layout"><div class="da-proj-body"><div class="da-lens"></div></div><div class="da-beam"></div><div class="da-proj-screen">' . $da_screen . '</div></div><span class="da-label">Projector</span></div>';
|
||||||
|
$da .= '<div class="da-device da-vwall"><div class="da-vwall-grid"><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div></div><span class="da-label">Video Wall</span></div>';
|
||||||
|
$da .= '</div>';
|
||||||
|
$visual_html = $da;
|
||||||
|
$visual_cls = 'platform-visual has-anim';
|
||||||
|
} elseif ( ! empty( $a['tvStick'] ) ) {
|
||||||
|
$ts = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">';
|
||||||
|
$ts .= '<div class="ts-tv">';
|
||||||
|
$ts .= '<div class="ts-tv__body">';
|
||||||
|
$ts .= '<div class="ts-tv__screen">';
|
||||||
|
$ts .= '<div class="ts-slides">';
|
||||||
|
|
||||||
|
// Slide 1 — Menu Board
|
||||||
|
$ts .= '<div class="ts-slide ts-slide--menu">';
|
||||||
|
$ts .= '<div class="ts-menu">';
|
||||||
|
$ts .= '<div class="ts-menu__header"><div class="ts-menu__logo"></div><div class="ts-menu__title"></div></div>';
|
||||||
|
$ts .= '<div class="ts-menu__cols">';
|
||||||
|
$ts .= '<div class="ts-menu__col">';
|
||||||
|
$ts .= '<div class="ts-menu__cat"></div>';
|
||||||
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '<div class="ts-menu__col">';
|
||||||
|
$ts .= '<div class="ts-menu__cat"></div>';
|
||||||
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
|
||||||
|
// Slide 2 — Wayfinding Sign
|
||||||
|
$ts .= '<div class="ts-slide ts-slide--wayfind">';
|
||||||
|
$ts .= '<div class="ts-wf">';
|
||||||
|
$ts .= '<div class="ts-wf__header"><div class="ts-wf__building"></div></div>';
|
||||||
|
$ts .= '<div class="ts-wf__rows">';
|
||||||
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w1"></span><span class="ts-wf__floor"></span></div>';
|
||||||
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--right"></span><span class="ts-wf__label ts-wf__label--w2"></span><span class="ts-wf__floor"></span></div>';
|
||||||
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--up"></span><span class="ts-wf__label ts-wf__label--w3"></span><span class="ts-wf__floor"></span></div>';
|
||||||
|
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w4"></span><span class="ts-wf__floor"></span></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
|
||||||
|
// Slide 3 — Schedule / Timetable
|
||||||
|
$ts .= '<div class="ts-slide ts-slide--sched">';
|
||||||
|
$ts .= '<div class="ts-sched">';
|
||||||
|
$ts .= '<div class="ts-sched__header"><div class="ts-sched__title"></div><div class="ts-sched__date"></div></div>';
|
||||||
|
$ts .= '<div class="ts-sched__table">';
|
||||||
|
$ts .= '<div class="ts-sched__hrow"><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span></div>';
|
||||||
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span></div>';
|
||||||
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div>';
|
||||||
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--c"></span></div>';
|
||||||
|
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
|
||||||
|
$ts .= '</div>'; // ts-slides
|
||||||
|
$ts .= '</div>'; // ts-tv__screen
|
||||||
|
$ts .= '<div class="ts-tv__port"></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '<div class="ts-tv__feet"><div class="ts-tv__foot"></div><div class="ts-tv__foot"></div></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '<div class="ts-stick">';
|
||||||
|
$ts .= '<div class="ts-stick__body">';
|
||||||
|
$ts .= '<div class="ts-stick__led"></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '<div class="ts-stick__connector"></div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$ts .= '</div>';
|
||||||
|
$visual_html = $ts;
|
||||||
|
$visual_cls = 'platform-visual has-tv-stick';
|
||||||
|
} elseif ( ! empty( $a['neverGoesDark'] ) ) {
|
||||||
|
/* ── Never Goes Dark: player + TV + cloud connection/break animation ── */
|
||||||
|
$ngd = '<div class="ngd-stage" aria-hidden="true">';
|
||||||
|
|
||||||
|
/* TV */
|
||||||
|
$ngd .= '<div class="ngd-tv">';
|
||||||
|
$ngd .= '<div class="ngd-tv__body">';
|
||||||
|
$ngd .= '<div class="ngd-tv__screen">';
|
||||||
|
$ngd .= '<div class="ngd-menu">';
|
||||||
|
$ngd .= '<div class="ngd-menu__hd">';
|
||||||
|
$ngd .= '<div class="ngd-menu__logo"></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__ttl"></div>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__cols">';
|
||||||
|
$ngd .= '<div class="ngd-menu__col">';
|
||||||
|
$ngd .= '<div class="ngd-menu__cat"></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__col">';
|
||||||
|
$ngd .= '<div class="ngd-menu__cat"></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
$ngd .= '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '</div>'; /* cols */
|
||||||
|
$ngd .= '<div class="ngd-menu__ticker"><div class="ngd-menu__ticker-inner"></div></div>';
|
||||||
|
$ngd .= '</div>'; /* ngd-menu */
|
||||||
|
$ngd .= '</div>'; /* ngd-tv__screen */
|
||||||
|
$ngd .= '<div class="ngd-tv__port"></div>';
|
||||||
|
$ngd .= '</div>'; /* ngd-tv__body */
|
||||||
|
$ngd .= '<div class="ngd-tv__feet"><div class="ngd-tv__foot"></div><div class="ngd-tv__foot"></div></div>';
|
||||||
|
$ngd .= '</div>'; /* ngd-tv */
|
||||||
|
|
||||||
|
/* Player device (stick style, plugged into TV right-side HDMI port) */
|
||||||
|
$ngd .= '<div class="ngd-player">';
|
||||||
|
$ngd .= '<div class="ngd-player__connector"></div>';
|
||||||
|
$ngd .= '<div class="ngd-player__body">';
|
||||||
|
$ngd .= '<div class="ngd-player__led"></div>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '<div class="ngd-player__check">';
|
||||||
|
$ngd .= '<svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
||||||
|
$ngd .= '<circle cx="11" cy="11" r="10" stroke="#4CAF50" stroke-width="1.5"/>';
|
||||||
|
$ngd .= '<polyline points="6,11 9.5,14.5 16,7.5" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
|
||||||
|
$ngd .= '</svg>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '</div>'; /* ngd-player */
|
||||||
|
|
||||||
|
/* Signal wrap: vertical line connecting player to globe above */
|
||||||
|
$ngd .= '<div class="ngd-signal-wrap">';
|
||||||
|
$ngd .= '<div class="ngd-cloud">';
|
||||||
|
$ngd .= '<svg class="ngd-cloud__svg" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
||||||
|
$ngd .= '<circle class="ngd-cloud__path" cx="32" cy="23" r="14" stroke-width="2.2" fill="none"/>';
|
||||||
|
$ngd .= '<path class="ngd-cloud__path" d="M18.5 23C23 20 41 20 45.5 23" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
||||||
|
$ngd .= '<path class="ngd-cloud__path" d="M20.5 29C25.5 31 38.5 31 43.5 29" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
||||||
|
$ngd .= '<path class="ngd-cloud__path" d="M24.5 12C21.5 16.5 21.5 29.5 24.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
||||||
|
$ngd .= '<path class="ngd-cloud__path" d="M39.5 12C42.5 16.5 42.5 29.5 39.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
|
||||||
|
$ngd .= '</svg>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '<div class="ngd-signal-line">';
|
||||||
|
$ngd .= '<div class="ngd-signal__dots">';
|
||||||
|
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--1"></div>';
|
||||||
|
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--2"></div>';
|
||||||
|
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--3"></div>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '<div class="ngd-signal__break">';
|
||||||
|
$ngd .= '<svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">';
|
||||||
|
$ngd .= '<circle cx="9" cy="9" r="8" fill="rgba(239,68,68,0.12)" stroke="#ef4444" stroke-width="1.2"/>';
|
||||||
|
$ngd .= '<line x1="5.5" y1="5.5" x2="12.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>';
|
||||||
|
$ngd .= '<line x1="12.5" y1="5.5" x2="5.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>';
|
||||||
|
$ngd .= '</svg>';
|
||||||
|
$ngd .= '</div>';
|
||||||
|
$ngd .= '</div>'; /* ngd-signal-line */
|
||||||
|
$ngd .= '</div>'; /* ngd-signal-wrap */
|
||||||
|
|
||||||
|
$ngd .= '</div>'; /* ngd-stage */
|
||||||
|
|
||||||
|
$visual_html = $ngd;
|
||||||
|
$visual_cls = 'platform-visual has-ngd';
|
||||||
|
} elseif ( ! empty( $a['brandedAnim'] ) ) {
|
||||||
|
/* ── Custom Display Solutions: branded screens cascade animation ── */
|
||||||
|
$bd = '<div class="bd-stage" aria-hidden="true">';
|
||||||
|
|
||||||
|
/* ── Screen 1: Tablet (portrait kiosk) ── */
|
||||||
|
$bd .= '<div class="bd-device bd-device--tablet">';
|
||||||
|
$bd .= '<span class="bd-device__label">Kiosk</span>';
|
||||||
|
$bd .= '<div class="bd-device__body">';
|
||||||
|
$bd .= '<div class="bd-device__screen">';
|
||||||
|
$bd .= '<div class="bd-splash">';
|
||||||
|
$bd .= '<div class="bd-splash__logo"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '<div class="bd-ui">';
|
||||||
|
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
||||||
|
$bd .= '<div class="bd-ui__content">';
|
||||||
|
$bd .= '<div class="bd-promo bd-promo--welcome">';
|
||||||
|
$bd .= '<div class="bd-promo__hero"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__heading"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__text"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__btn"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
|
||||||
|
/* ── Screen 2: Wide wall-mount (landscape) ── */
|
||||||
|
$bd .= '<div class="bd-device bd-device--wall">';
|
||||||
|
$bd .= '<span class="bd-device__label">Wall Display</span>';
|
||||||
|
$bd .= '<div class="bd-device__body">';
|
||||||
|
$bd .= '<div class="bd-device__screen">';
|
||||||
|
$bd .= '<div class="bd-splash">';
|
||||||
|
$bd .= '<div class="bd-splash__logo"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '<div class="bd-ui">';
|
||||||
|
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
||||||
|
$bd .= '<div class="bd-ui__content">';
|
||||||
|
$bd .= '<div class="bd-promo bd-promo--sale">';
|
||||||
|
$bd .= '<div class="bd-promo__cols">';
|
||||||
|
$bd .= '<div class="bd-promo__visual"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__info">';
|
||||||
|
$bd .= '<div class="bd-promo__badge"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__heading"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__text"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__text bd-promo__text--short"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__price"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '<div class="bd-mount"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
|
||||||
|
/* ── Screen 3: Interactive tablet on table ── */
|
||||||
|
$bd .= '<div class="bd-device bd-device--interactive">';
|
||||||
|
$bd .= '<span class="bd-device__label">Interactive</span>';
|
||||||
|
$bd .= '<div class="bd-device__body">';
|
||||||
|
$bd .= '<div class="bd-device__screen">';
|
||||||
|
$bd .= '<div class="bd-splash">';
|
||||||
|
$bd .= '<div class="bd-splash__logo"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '<div class="bd-ui">';
|
||||||
|
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
||||||
|
$bd .= '<div class="bd-ui__content">';
|
||||||
|
$bd .= '<div class="bd-promo bd-promo--menu">';
|
||||||
|
$bd .= '<div class="bd-promo__heading"></div>';
|
||||||
|
$bd .= '<div class="bd-promo__grid">';
|
||||||
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
||||||
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
||||||
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
||||||
|
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
$bd .= '<div class="bd-table"></div>';
|
||||||
|
$bd .= '</div>';
|
||||||
|
|
||||||
|
$bd .= '</div>'; /* bd-stage */
|
||||||
|
$visual_html = $bd;
|
||||||
|
$visual_cls = 'platform-visual has-branded';
|
||||||
|
} elseif ( ! empty( $a['cameraAnim'] ) ) {
|
||||||
|
$visual_html = oribi_render_camera_animation();
|
||||||
|
$visual_cls = 'platform-visual has-video-editor';
|
||||||
|
|
||||||
|
/* ── Gallery TV Slideshow ───────────────────────────────── */
|
||||||
|
} elseif ( ! empty( $a['galleryIds'] ) && is_array( $a['galleryIds'] ) && count( $a['galleryIds'] ) > 0 ) {
|
||||||
|
$slides = '';
|
||||||
|
$count = 0;
|
||||||
|
foreach ( $a['galleryIds'] as $gid ) {
|
||||||
|
$gid = intval( $gid );
|
||||||
|
if ( ! $gid ) continue;
|
||||||
|
$url = wp_get_attachment_url( $gid );
|
||||||
|
$alt = get_post_meta( $gid, '_wp_attachment_image_alt', true );
|
||||||
|
if ( ! $url ) continue;
|
||||||
|
$active = $count === 0 ? ' is-active' : '';
|
||||||
|
$slides .= '<div class="gtv-slide' . $active . '">';
|
||||||
|
$slides .= '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt ) . '" loading="lazy" />';
|
||||||
|
$slides .= '</div>';
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
if ( $count > 0 ) {
|
||||||
|
$visual_html = '<div class="gtv-stage" data-gtv-slideshow aria-hidden="true">';
|
||||||
|
$visual_html .= '<div class="gtv-tv">';
|
||||||
|
$visual_html .= '<div class="gtv-tv__body">';
|
||||||
|
$visual_html .= '<div class="gtv-tv__screen">';
|
||||||
|
$visual_html .= '<div class="gtv-slides">' . $slides . '</div>';
|
||||||
|
$visual_html .= '</div>'; // screen
|
||||||
|
$visual_html .= '</div>'; // body
|
||||||
|
$visual_html .= '<div class="gtv-tv__feet"><div class="gtv-tv__foot"></div><div class="gtv-tv__foot"></div></div>';
|
||||||
|
$visual_html .= '</div>'; // tv
|
||||||
|
$visual_html .= '</div>'; // stage
|
||||||
|
$visual_cls = 'platform-visual has-gallery-tv';
|
||||||
|
} else {
|
||||||
|
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
|
||||||
|
$visual_cls = 'platform-visual';
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
|
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
|
||||||
$visual_cls = 'platform-visual';
|
$visual_cls = 'platform-visual';
|
||||||
@@ -1354,7 +1998,6 @@ function oribi_render_platform_row( $a ) {
|
|||||||
</div>
|
</div>
|
||||||
<?php return ob_get_clean();
|
<?php return ob_get_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Trust Section (parent - wraps child trust-item blocks) ────────────────── */
|
/* ── Trust Section (parent - wraps child trust-item blocks) ────────────────── */
|
||||||
function oribi_render_trust_section( $a, $content ) {
|
function oribi_render_trust_section( $a, $content ) {
|
||||||
ob_start(); ?>
|
ob_start(); ?>
|
||||||
@@ -1546,3 +2189,107 @@ function oribi_render_page_hero_animated( $a ) {
|
|||||||
</section>
|
</section>
|
||||||
<?php return ob_get_clean();
|
<?php return ob_get_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Use Cases Showcase ────────────────────────────────────────────────── */
|
||||||
|
function oribi_uc_anim_inner( $mod ) {
|
||||||
|
switch ( $mod ) {
|
||||||
|
case 'menu':
|
||||||
|
return '
|
||||||
|
<div class="uc-inner uc-inner--menu" aria-hidden="true">
|
||||||
|
<div class="uc-menu-header"></div>
|
||||||
|
<div class="uc-menu-row"><span class="uc-menu-name"></span><span class="uc-menu-price"></span></div>
|
||||||
|
<div class="uc-menu-row uc-menu-row--highlight"><span class="uc-menu-name"></span><span class="uc-menu-price"></span></div>
|
||||||
|
<div class="uc-menu-row"><span class="uc-menu-name uc-menu-name--sm"></span><span class="uc-menu-price"></span></div>
|
||||||
|
<div class="uc-menu-row"><span class="uc-menu-name"></span><span class="uc-menu-price"></span></div>
|
||||||
|
<div class="uc-menu-divider"></div>
|
||||||
|
<div class="uc-menu-row"><span class="uc-menu-name uc-menu-name--sm"></span><span class="uc-menu-price"></span></div>
|
||||||
|
</div>';
|
||||||
|
case 'event':
|
||||||
|
return '
|
||||||
|
<div class="uc-inner uc-inner--event" aria-hidden="true">
|
||||||
|
<div class="uc-event-cursor"></div>
|
||||||
|
<div class="uc-event-header">Schedule</div>
|
||||||
|
<div class="uc-event-row">
|
||||||
|
<div class="uc-event-time">9:00</div>
|
||||||
|
<div class="uc-event-title uc-event-title--active">Keynote Speech</div>
|
||||||
|
</div>
|
||||||
|
<div class="uc-event-row">
|
||||||
|
<div class="uc-event-time">10:30</div>
|
||||||
|
<div class="uc-event-title">Panel Discussion</div>
|
||||||
|
</div>
|
||||||
|
<div class="uc-event-row">
|
||||||
|
<div class="uc-event-time">11:45</div>
|
||||||
|
<div class="uc-event-title uc-event-title--accent">Coffee Break</div>
|
||||||
|
</div>
|
||||||
|
<div class="uc-event-row">
|
||||||
|
<div class="uc-event-time">12:30</div>
|
||||||
|
<div class="uc-event-title">Networking Lunch</div>
|
||||||
|
</div>
|
||||||
|
</div>';
|
||||||
|
case 'dashboard':
|
||||||
|
return '
|
||||||
|
<div class="uc-inner uc-inner--dashboard" aria-hidden="true">
|
||||||
|
<div class="uc-db-bars">
|
||||||
|
<div class="uc-db-bar uc-db-bar--1"></div>
|
||||||
|
<div class="uc-db-bar uc-db-bar--2"></div>
|
||||||
|
<div class="uc-db-bar uc-db-bar--3"></div>
|
||||||
|
<div class="uc-db-bar uc-db-bar--4"></div>
|
||||||
|
</div>
|
||||||
|
<div class="uc-db-baseline"></div>
|
||||||
|
<div class="uc-db-labels">
|
||||||
|
<div class="uc-db-lbl"></div>
|
||||||
|
<div class="uc-db-lbl"></div>
|
||||||
|
<div class="uc-db-lbl"></div>
|
||||||
|
<div class="uc-db-lbl"></div>
|
||||||
|
</div>
|
||||||
|
</div>';
|
||||||
|
case 'wayfinding':
|
||||||
|
return '
|
||||||
|
<div class="uc-inner uc-inner--wayfinding" aria-hidden="true">
|
||||||
|
<div class="uc-wf-corridor uc-wf-corridor--h"></div>
|
||||||
|
<div class="uc-wf-corridor uc-wf-corridor--v"></div>
|
||||||
|
<div class="uc-wf-room uc-wf-room--1"></div>
|
||||||
|
<div class="uc-wf-room uc-wf-room--2"></div>
|
||||||
|
<div class="uc-wf-room uc-wf-room--3"></div>
|
||||||
|
<div class="uc-wf-dot"></div>
|
||||||
|
<div class="uc-wf-arrow"></div>
|
||||||
|
</div>';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function oribi_render_use_cases( $a ) {
|
||||||
|
$cases = [
|
||||||
|
[ 'title' => $a['case1Title'], 'desc' => $a['case1Desc'], 'mod' => 'menu' ],
|
||||||
|
[ 'title' => $a['case2Title'], 'desc' => $a['case2Desc'], 'mod' => 'event' ],
|
||||||
|
[ 'title' => $a['case3Title'], 'desc' => $a['case3Desc'], 'mod' => 'dashboard' ],
|
||||||
|
[ 'title' => $a['case4Title'], 'desc' => $a['case4Desc'], 'mod' => 'wayfinding' ],
|
||||||
|
];
|
||||||
|
ob_start(); ?>
|
||||||
|
<section class="section use-cases-section">
|
||||||
|
<div class="container">
|
||||||
|
<?php if ( $a['label'] || $a['heading'] || $a['lead'] ) : ?>
|
||||||
|
<div class="section-header">
|
||||||
|
<?php if ( $a['label'] ) : ?><span class="section-label"><?php echo esc_html( $a['label'] ); ?></span><?php endif; ?>
|
||||||
|
<?php if ( $a['heading'] ) : ?><h2><?php echo wp_kses_post( $a['heading'] ); ?></h2><?php endif; ?>
|
||||||
|
<?php if ( $a['lead'] ) : ?><p class="lead"><?php echo wp_kses_post( $a['lead'] ); ?></p><?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<div class="uc-track">
|
||||||
|
<?php foreach ( $cases as $c ) : ?>
|
||||||
|
<div class="uc-item">
|
||||||
|
<div class="uc-circle uc-anim--<?php echo esc_attr( $c['mod'] ); ?>">
|
||||||
|
<?php echo oribi_uc_anim_inner( $c['mod'] ); ?>
|
||||||
|
</div>
|
||||||
|
<div class="uc-item-body">
|
||||||
|
<div class="uc-item-title"><?php echo esc_html( $c['title'] ); ?></div>
|
||||||
|
<?php if ( $c['desc'] ) : ?><p class="uc-item-desc"><?php echo esc_html( $c['desc'] ); ?></p><?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php return ob_get_clean();
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,6 +29,33 @@ add_action( 'wp_enqueue_scripts', function () {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Dashboard chart animator - smooth continuous animations for dashboard cards
|
||||||
|
wp_enqueue_script(
|
||||||
|
'oribi-dashboard-animator',
|
||||||
|
ORIBI_URI . '/assets/js/dashboard-animator.js',
|
||||||
|
[],
|
||||||
|
ORIBI_VERSION . '.' . filemtime( ORIBI_DIR . '/assets/js/dashboard-animator.js' ),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Gallery TV slideshow - cycles images in TV-frame cards
|
||||||
|
wp_enqueue_script(
|
||||||
|
'oribi-gallery-tv',
|
||||||
|
ORIBI_URI . '/assets/js/industry-animator.js',
|
||||||
|
[],
|
||||||
|
ORIBI_VERSION . '.' . filemtime( ORIBI_DIR . '/assets/js/industry-animator.js' ),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Video editor timeline animator - animated playhead and preview crossfades
|
||||||
|
wp_enqueue_script(
|
||||||
|
'oribi-video-editor-animator',
|
||||||
|
ORIBI_URI . '/assets/js/video-editor-animator.js',
|
||||||
|
[],
|
||||||
|
ORIBI_VERSION . '.' . filemtime( ORIBI_DIR . '/assets/js/video-editor-animator.js' ),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
// Localize AJAX endpoint for the contact form
|
// Localize AJAX endpoint for the contact form
|
||||||
wp_localize_script( 'oribi-main', 'oribiAjax', [
|
wp_localize_script( 'oribi-main', 'oribiAjax', [
|
||||||
'url' => admin_url( 'admin-ajax.php' ),
|
'url' => admin_url( 'admin-ajax.php' ),
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ function oribi_get_theme_defaults() {
|
|||||||
return [
|
return [
|
||||||
|
|
||||||
/* ── Light-mode colour palette ──────────────────────── */
|
/* ── Light-mode colour palette ──────────────────────── */
|
||||||
'color_primary' => '#004225',
|
'color_primary' => '#D83302',
|
||||||
'color_primary_dk' => '#002E1A',
|
'color_primary_dk' => '#A22702',
|
||||||
'color_primary_lt' => '#E8F5E9',
|
'color_primary_lt' => '#FFF0EB',
|
||||||
'color_accent' => '#4CAF50',
|
'color_accent' => '#4CAF50',
|
||||||
'color_accent_dk' => '#388E3C',
|
'color_accent_dk' => '#388E3C',
|
||||||
'color_accent_lt' => '#E8F5E9',
|
'color_accent_lt' => '#E8F5E9',
|
||||||
@@ -39,9 +39,9 @@ function oribi_get_theme_defaults() {
|
|||||||
'color_bg_alt' => '#F5F5F5',
|
'color_bg_alt' => '#F5F5F5',
|
||||||
|
|
||||||
/* ── Dark-mode colour palette ───────────────────────── */
|
/* ── Dark-mode colour palette ───────────────────────── */
|
||||||
'dark_primary' => '#4CAF50',
|
'dark_primary' => '#FF6B3D',
|
||||||
'dark_primary_dk' => '#004225',
|
'dark_primary_dk' => '#D83302',
|
||||||
'dark_primary_lt' => 'rgba(0,66,37,0.15)',
|
'dark_primary_lt' => 'rgba(216,51,2,0.15)',
|
||||||
'dark_accent' => '#66BB6A',
|
'dark_accent' => '#66BB6A',
|
||||||
'dark_accent_dk' => '#4CAF50',
|
'dark_accent_dk' => '#4CAF50',
|
||||||
'dark_accent_lt' => 'rgba(76,175,80,0.15)',
|
'dark_accent_lt' => 'rgba(76,175,80,0.15)',
|
||||||
@@ -94,18 +94,21 @@ function oribi_get_setting( $key ) {
|
|||||||
*/
|
*/
|
||||||
function oribi_maybe_seed_defaults() {
|
function oribi_maybe_seed_defaults() {
|
||||||
|
|
||||||
if ( get_theme_mod( 'oribi_defaults_seeded' ) ) {
|
$defaults = oribi_get_theme_defaults();
|
||||||
|
$hash = md5( wp_json_encode( $defaults ) );
|
||||||
|
$stored = get_theme_mod( 'oribi_defaults_hash', '' );
|
||||||
|
|
||||||
|
if ( $stored === $hash ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaults = oribi_get_theme_defaults();
|
|
||||||
|
|
||||||
foreach ( $defaults as $key => $value ) {
|
foreach ( $defaults as $key => $value ) {
|
||||||
// Only set if the user hasn't already saved a value.
|
|
||||||
if ( false === get_theme_mod( 'oribi_' . $key, false ) ) {
|
|
||||||
set_theme_mod( 'oribi_' . $key, $value );
|
set_theme_mod( 'oribi_' . $key, $value );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
set_theme_mod( 'oribi_defaults_hash', $hash );
|
||||||
set_theme_mod( 'oribi_defaults_seeded', true );
|
set_theme_mod( 'oribi_defaults_seeded', true );
|
||||||
|
|
||||||
|
// Force CSS regeneration on next check.
|
||||||
|
set_theme_mod( 'oribi_css_theme_version', '' );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,11 +227,11 @@ function oribi_build_css() {
|
|||||||
--color-bg-alt: {$dk_bg_alt};
|
--color-bg-alt: {$dk_bg_alt};
|
||||||
--color-bg-dark: {$dk_bg_dark};
|
--color-bg-dark: {$dk_bg_dark};
|
||||||
--color-heading: {$dk_heading};
|
--color-heading: {$dk_heading};
|
||||||
--header-scrolled-bg: rgba(15,23,36,.97);
|
--header-scrolled-bg: rgba(26,26,26,.97);
|
||||||
--header-scrolled-text: {$dk_text};
|
--header-scrolled-text: {$dk_text};
|
||||||
--card-bg: {$dk_card_bg};
|
--card-bg: {$dk_card_bg};
|
||||||
--form-bg: {$dk_card_bg};
|
--form-bg: {$dk_card_bg};
|
||||||
--form-bg-focus: #1A2538;
|
--form-bg-focus: {$dk_card_bg};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Typography application ────────────────────────────────────── */
|
/* ── Typography application ────────────────────────────────────── */
|
||||||
@@ -295,12 +295,32 @@ function oribi_write_generated_css() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regenerate the CSS file if it doesn't exist yet (e.g. first page load).
|
* Regenerate the CSS file when it is missing or the theme version has changed.
|
||||||
*
|
*
|
||||||
* Hooked early so the file is ready before wp_enqueue_scripts fires.
|
* Hooked early so the file is ready before wp_enqueue_scripts fires.
|
||||||
|
* Also re-seeds defaults if the palette has changed, so the generated
|
||||||
|
* CSS always reflects the current default values.
|
||||||
*/
|
*/
|
||||||
add_action( 'init', function () {
|
add_action( 'init', function () {
|
||||||
if ( ! file_exists( oribi_generated_css_path() ) ) {
|
|
||||||
|
// Re-seed defaults if the defaults array has changed (e.g. new palette).
|
||||||
|
if ( function_exists( 'oribi_maybe_seed_defaults' ) ) {
|
||||||
|
oribi_maybe_seed_defaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
$needs_regen = ! file_exists( oribi_generated_css_path() );
|
||||||
|
|
||||||
|
if ( ! $needs_regen && defined( 'ORIBI_VERSION' ) ) {
|
||||||
|
$stored = get_theme_mod( 'oribi_css_theme_version', '' );
|
||||||
|
if ( $stored !== ORIBI_VERSION ) {
|
||||||
|
$needs_regen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $needs_regen ) {
|
||||||
oribi_write_generated_css();
|
oribi_write_generated_css();
|
||||||
|
if ( defined( 'ORIBI_VERSION' ) ) {
|
||||||
|
set_theme_mod( 'oribi_css_theme_version', ORIBI_VERSION );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|||||||
@@ -636,7 +636,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
if (heroText) heroText.style.color = 'rgba(255,255,255,.8)';
|
if (heroText) heroText.style.color = 'rgba(255,255,255,.8)';
|
||||||
}
|
}
|
||||||
if (btnP) {
|
if (btnP) {
|
||||||
btnP.style.backgroundColor = get('oribi_color_primary') || '#004225';
|
btnP.style.backgroundColor = get('oribi_color_primary') || '#D83302';
|
||||||
btnP.style.borderRadius = (get('oribi_radius_sm') || '6') + 'px';
|
btnP.style.borderRadius = (get('oribi_radius_sm') || '6') + 'px';
|
||||||
}
|
}
|
||||||
if (btnA) {
|
if (btnA) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Theme URI: https://oribi-tech.com
|
|||||||
Author: Oribi Technology Services
|
Author: Oribi Technology Services
|
||||||
Author URI: https://oribi-tech.com
|
Author URI: https://oribi-tech.com
|
||||||
Description: Custom marketing theme for Oribi Technology Services - Managed IT, 365Care, EndpointCare, NetCare, ServerCare.
|
Description: Custom marketing theme for Oribi Technology Services - Managed IT, 365Care, EndpointCare, NetCare, ServerCare.
|
||||||
Version: 1.0.0
|
Version: 1.1.0
|
||||||
Requires at least: 6.4
|
Requires at least: 6.4
|
||||||
Tested up to: 6.7
|
Tested up to: 6.7
|
||||||
Requires PHP: 7.4
|
Requires PHP: 7.4
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
"customDuotone": false,
|
"customDuotone": false,
|
||||||
"customGradient": false,
|
"customGradient": false,
|
||||||
"palette": [
|
"palette": [
|
||||||
{ "slug": "primary", "color": "#004225", "name": "Primary" },
|
{ "slug": "primary", "color": "#D83302", "name": "Primary" },
|
||||||
{ "slug": "primary-dk", "color": "#002E1A", "name": "Primary Dark" },
|
{ "slug": "primary-dk", "color": "#A22702", "name": "Primary Dark" },
|
||||||
{ "slug": "primary-lt", "color": "#E8F5E9", "name": "Primary Light" },
|
{ "slug": "primary-lt", "color": "#FFF0EB", "name": "Primary Light" },
|
||||||
{ "slug": "accent", "color": "#4CAF50", "name": "Accent" },
|
{ "slug": "accent", "color": "#4CAF50", "name": "Accent" },
|
||||||
{ "slug": "accent-dk", "color": "#388E3C", "name": "Accent Dark" },
|
{ "slug": "accent-dk", "color": "#388E3C", "name": "Accent Dark" },
|
||||||
{ "slug": "accent-lt", "color": "#E8F5E9", "name": "Accent Light" },
|
{ "slug": "accent-lt", "color": "#E8F5E9", "name": "Accent Light" },
|
||||||
@@ -85,9 +85,9 @@
|
|||||||
},
|
},
|
||||||
"custom": {
|
"custom": {
|
||||||
"dark": {
|
"dark": {
|
||||||
"primary": "#4CAF50",
|
"primary": "#FF6B3D",
|
||||||
"primary-dk": "#004225",
|
"primary-dk": "#D83302",
|
||||||
"primary-lt": "rgba(0,66,37,0.15)",
|
"primary-lt": "rgba(216,51,2,0.15)",
|
||||||
"accent": "#66BB6A",
|
"accent": "#66BB6A",
|
||||||
"accent-dk": "#388E3C",
|
"accent-dk": "#388E3C",
|
||||||
"accent-lt": "rgba(76,175,80,0.12)",
|
"accent-lt": "rgba(76,175,80,0.12)",
|
||||||
|
|||||||
Reference in New Issue
Block a user