@@ -113,7 +116,7 @@
Learn To Trade
-
+
AI Coach
diff --git a/js/about-us-2-stats.js b/js/about-us-2-stats.js
new file mode 100644
index 0000000..942ffcc
--- /dev/null
+++ b/js/about-us-2-stats.js
@@ -0,0 +1,96 @@
+/**
+ * About Us 2 — achievements stats count-up animation.
+ */
+(function () {
+ var SECTION_SELECTOR = "#about-us-2 .au2-stats";
+ var VALUE_SELECTOR = ".au2-stats__value[data-au2-count]";
+ var DURATION_MS = 1800;
+
+ function easeOutCubic(t) {
+ return 1 - Math.pow(1 - t, 3);
+ }
+
+ function formatValue(value, useGrouping) {
+ if (!useGrouping) return String(value);
+ return value.toLocaleString("en-US");
+ }
+
+ function parseCountOptions(el) {
+ var raw = el.getAttribute("data-au2-count");
+ var to = raw ? Number(raw) : NaN;
+ if (!Number.isFinite(to)) return null;
+
+ return {
+ to: to,
+ prefix: el.getAttribute("data-au2-prefix") || "",
+ suffix: el.getAttribute("data-au2-suffix") || "",
+ grouping: el.getAttribute("data-au2-grouping") === "true",
+ };
+ }
+
+ function renderValue(el, value, options) {
+ el.textContent =
+ options.prefix + formatValue(value, options.grouping) + options.suffix;
+ }
+
+ function animateValue(el, options) {
+ if (el.dataset.au2Counted === "true") return;
+ el.dataset.au2Counted = "true";
+
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
+ renderValue(el, options.to, options);
+ return;
+ }
+
+ var start = performance.now();
+
+ function tick(now) {
+ var progress = Math.min((now - start) / DURATION_MS, 1);
+ var current = Math.round(easeOutCubic(progress) * options.to);
+ renderValue(el, current, options);
+
+ if (progress < 1) {
+ requestAnimationFrame(tick);
+ } else {
+ renderValue(el, options.to, options);
+ }
+ }
+
+ renderValue(el, 0, options);
+ requestAnimationFrame(tick);
+ }
+
+ function initSection(section) {
+ var values = section.querySelectorAll(VALUE_SELECTOR);
+ if (!values.length) return;
+
+ var observer = new IntersectionObserver(
+ function (entries, obs) {
+ entries.forEach(function (entry) {
+ if (!entry.isIntersecting) return;
+
+ values.forEach(function (el) {
+ var options = parseCountOptions(el);
+ if (options) animateValue(el, options);
+ });
+
+ obs.unobserve(entry.target);
+ });
+ },
+ { threshold: 0.35, rootMargin: "0px 0px -40px 0px" }
+ );
+
+ observer.observe(section);
+ }
+
+ function init() {
+ var section = document.querySelector(SECTION_SELECTOR);
+ if (section) initSection(section);
+ }
+
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", init);
+ } else {
+ init();
+ }
+})();
diff --git a/js/au2-testimonials-marquee.js b/js/au2-testimonials-marquee.js
new file mode 100644
index 0000000..05157fd
--- /dev/null
+++ b/js/au2-testimonials-marquee.js
@@ -0,0 +1,80 @@
+/**
+ * Testimonials marquee — same logic as myfundedfutures.com Reviews section:
+ * - Fisher–Yates shuffle, 3 cards per row
+ * - 3 rows × 3 duplicate tracks
+ * - Row speeds: 125s / 75s reverse / 275s (Framer Motion durations → CSS linear)
+ */
+(function () {
+ var ROW_CONFIG = [
+ { duration: 125, reverse: false },
+ { duration: 75, reverse: true },
+ { duration: 275, reverse: false },
+ ];
+ var TRACK_COUNT = 3;
+ var CARDS_PER_ROW = 3;
+
+ function shuffle(list) {
+ var arr = list.slice();
+ for (var i = arr.length - 1; i > 0; i--) {
+ var j = Math.floor(Math.random() * (i + 1));
+ var tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+ return arr;
+ }
+
+ function pickCards(cards, count) {
+ return shuffle(cards).slice(0, Math.min(count, cards.length));
+ }
+
+ function buildTrack(cards, duration, reverse, trackIndex) {
+ var track = document.createElement('div');
+ track.className =
+ 'au2-testimonials__track' + (reverse ? ' au2-testimonials__track--reverse' : '');
+ track.style.setProperty('--duration', duration + 's');
+ if (trackIndex > 0) {
+ track.setAttribute('aria-hidden', 'true');
+ }
+
+ cards.forEach(function (card) {
+ track.appendChild(card.cloneNode(true));
+ });
+
+ return track;
+ }
+
+ function buildRow(cards, config) {
+ var row = document.createElement('div');
+ row.className = 'au2-testimonials__row';
+ var picked = pickCards(cards, CARDS_PER_ROW);
+
+ for (var i = 0; i < TRACK_COUNT; i++) {
+ row.appendChild(buildTrack(picked, config.duration, config.reverse, i));
+ }
+
+ return row;
+ }
+
+ function initAu2TestimonialsMarquee() {
+ var root = document.querySelector('[data-au2-testimonials-marquee]');
+ if (!root) return;
+
+ var source = root.querySelector('.au2-testimonials__source');
+ var rowsEl = root.querySelector('.au2-testimonials__rows');
+ if (!source || !rowsEl) return;
+
+ var cards = Array.prototype.slice.call(source.querySelectorAll('.au2-testimonial'));
+ if (!cards.length) return;
+
+ ROW_CONFIG.forEach(function (config) {
+ rowsEl.appendChild(buildRow(cards, config));
+ });
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initAu2TestimonialsMarquee);
+ } else {
+ initAu2TestimonialsMarquee();
+ }
+})();
diff --git a/js/home-hero-carousel.js b/js/home-hero-carousel.js
index 1c65e60..32d3c2f 100644
--- a/js/home-hero-carousel.js
+++ b/js/home-hero-carousel.js
@@ -1,10 +1,183 @@
/**
- * Home hero carousel — autoplay + dot navigation + mobile swipe
+ * Home hero carousel — autoplay + dot navigation + mobile swipe + layout sync
+ *
+ * Layout contract (extensible per banner):
+ * data-hero-layout-reference — slide that defines carousel height
+ * data-hero-layout-anchor — element whose bottom anchors dot position
+ * --hero-coach-dots-gap — gap between anchor bottom and dots top (default 35px)
+ * Mobile: .is-banner-active fixes dots to viewport bottom while banner is visible
*/
(function () {
var AUTOPLAY_MS = 5000;
var SWIPE_THRESHOLD = 48;
var MOBILE_MQ = '(max-width: 991.98px)';
+ var DESKTOP_MQ = '(min-width: 992px)';
+
+ function readPx(styles, name, fallback) {
+ var value = parseFloat(styles.getPropertyValue(name));
+ return Number.isFinite(value) ? value : fallback;
+ }
+
+ function getLayoutScope(root) {
+ return root.closest('#homepage') || root;
+ }
+
+ function clearMeasuredLayout(scope, root) {
+ [
+ '--hero-reference-content-bottom',
+ '--hero-reference-viewport-height',
+ '--hero-reference-dots-top',
+ '--hero-mobile-dots-reserve',
+ '--hero-dots-y',
+ ].forEach(function (name) {
+ scope.style.removeProperty(name);
+ });
+
+ if (root) {
+ var dots = root.querySelector('.home-hero-carousel__dots');
+ if (dots) {
+ dots.removeAttribute('data-hero-dots-positioned');
+ }
+ }
+ }
+
+ function syncHeroLayout(root) {
+ var inner = root.querySelector('.home-hero-carousel__inner');
+ var viewport = root.querySelector('.home-hero-carousel__viewport');
+ if (!inner || !viewport) return;
+
+ var referenceSlide = root.querySelector('[data-hero-layout-reference]')
+ || root.querySelector('[data-home-hero-slide]');
+ if (!referenceSlide) return;
+
+ var anchor = referenceSlide.querySelector('[data-hero-layout-anchor]')
+ || referenceSlide.querySelector('.home-hero-carousel__ai-coach')
+ || referenceSlide.querySelector('.home-hero-carousel__actions :last-child');
+ if (!anchor) return;
+
+ var scope = getLayoutScope(root);
+ var styles = getComputedStyle(scope);
+ var coachDotsGap = readPx(styles, '--hero-coach-dots-gap', 35);
+ var dotsHeight = readPx(styles, '--hero-dots-height', 10);
+ var innerPaddingBottom = readPx(styles, '--hero-inner-padding-bottom', 40);
+ var isDesktop = window.matchMedia(DESKTOP_MQ).matches;
+
+ if (isDesktop) {
+ var innerRect = inner.getBoundingClientRect();
+ var viewportRect = viewport.getBoundingClientRect();
+ var anchorRect = anchor.getBoundingClientRect();
+
+ var contentBottom = Math.ceil(anchorRect.bottom - viewportRect.top);
+ var viewportHeight = contentBottom + coachDotsGap;
+ var dotsTop = Math.ceil(anchorRect.bottom - innerRect.top + coachDotsGap);
+ var dotsBottomY = dotsTop + dotsHeight + innerPaddingBottom;
+
+ scope.style.setProperty('--hero-reference-content-bottom', contentBottom + 'px');
+ scope.style.setProperty('--hero-reference-viewport-height', viewportHeight + 'px');
+ scope.style.setProperty('--hero-reference-dots-top', dotsTop + 'px');
+ scope.style.setProperty('--hero-dots-y', dotsBottomY + 'px');
+ root.setAttribute('data-hero-layout-synced', 'desktop');
+
+ var dots = root.querySelector('.home-hero-carousel__dots');
+ if (dots) {
+ dots.setAttribute('data-hero-dots-positioned', 'true');
+ }
+ root.classList.remove('is-banner-active');
+ return;
+ }
+
+ clearMeasuredLayout(scope, root);
+
+ var viewportRect = viewport.getBoundingClientRect();
+ var slideGrid = referenceSlide.querySelector('.home-hero-carousel__slide-grid');
+ var visual = referenceSlide.querySelector('.home-hero-carousel__visual');
+ var mobileFixedDotsBottom = readPx(styles, '--hero-mobile-fixed-dots-bottom', 16);
+ var imageScale = readPx(styles, '--hero-visual-image-scale', 1.06);
+
+ if (!slideGrid) return;
+
+ var visualBottom = visual
+ ? visual.getBoundingClientRect().bottom - viewportRect.top
+ : slideGrid.getBoundingClientRect().bottom - viewportRect.top;
+
+ if (visual) {
+ var img = visual.querySelector('img');
+ if (img && imageScale > 1) {
+ var imgHeight = img.getBoundingClientRect().height;
+ visualBottom += Math.ceil((imgHeight * imageScale - imgHeight) / 2);
+ }
+ }
+
+ var viewportHeight = Math.ceil(visualBottom);
+ var dotsReserve = dotsHeight + mobileFixedDotsBottom;
+ var homepageRect = scope.getBoundingClientRect();
+ var dotsBottomY = Math.ceil(
+ viewportRect.top - homepageRect.top + viewportHeight + dotsReserve + innerPaddingBottom
+ );
+
+ scope.style.setProperty('--hero-reference-viewport-height', viewportHeight + 'px');
+ scope.style.setProperty('--hero-mobile-dots-reserve', dotsReserve + 'px');
+ scope.style.setProperty('--hero-dots-y', dotsBottomY + 'px');
+
+ root.setAttribute('data-hero-layout-synced', 'mobile');
+ }
+
+ function bindMobileFixedDots(root) {
+ if (typeof IntersectionObserver === 'undefined') return;
+
+ var mobileMq = window.matchMedia(MOBILE_MQ);
+ var observer = new IntersectionObserver(
+ function (entries) {
+ if (!mobileMq.matches) {
+ root.classList.remove('is-banner-active');
+ return;
+ }
+ root.classList.toggle('is-banner-active', entries[0].isIntersecting);
+ },
+ {
+ threshold: 0,
+ rootMargin: '0px 0px -8% 0px',
+ }
+ );
+
+ observer.observe(root);
+
+ mobileMq.addEventListener('change', function () {
+ if (!mobileMq.matches) {
+ root.classList.remove('is-banner-active');
+ }
+ });
+ }
+
+ function bindHeroLayoutSync(root) {
+ var sync = function () {
+ syncHeroLayout(root);
+ };
+
+ sync();
+
+ if (typeof ResizeObserver !== 'undefined') {
+ var observer = new ResizeObserver(sync);
+ observer.observe(root);
+ var inner = root.querySelector('.home-hero-carousel__inner');
+ var referenceSlide = root.querySelector('[data-hero-layout-reference]')
+ || root.querySelector('[data-home-hero-slide]');
+ if (inner) observer.observe(inner);
+ if (referenceSlide) observer.observe(referenceSlide);
+ var visual = referenceSlide.querySelector('.home-hero-carousel__visual');
+ if (visual) observer.observe(visual);
+ }
+
+ var resizeTimer;
+ window.addEventListener('resize', function () {
+ window.clearTimeout(resizeTimer);
+ resizeTimer = window.setTimeout(sync, 100);
+ });
+
+ if (document.fonts && document.fonts.ready) {
+ document.fonts.ready.then(sync);
+ }
+ }
function initHomeHeroCarousel(root) {
if (root.getAttribute('data-carousel-ready') === 'true') return;
@@ -133,6 +306,8 @@
});
bindTouchSwipe();
+ bindHeroLayoutSync(root);
+ bindMobileFixedDots(root);
setSlide(0);
startAutoplay();
}
@@ -142,6 +317,13 @@
}
window.AifoHomeHeroCarouselInit = initHomeHeroCarousel;
+ window.AifoHomeHeroCarouselSyncLayout = function (root) {
+ if (root) {
+ syncHeroLayout(root);
+ return;
+ }
+ document.querySelectorAll('[data-home-hero-carousel]').forEach(syncHeroLayout);
+ };
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot);
diff --git a/js/layout.js b/js/layout.js
index 99f69a0..9d9269a 100644
--- a/js/layout.js
+++ b/js/layout.js
@@ -6,6 +6,12 @@
var NAV_URL = "/components/nav.html";
var FOOTER_URL = "/components/footer.html";
var FOOT_CSS_ID = "aifo-foot-styles";
+ var NAV_CSS_ID = "aifo-nav-styles";
+ var NAV_CSS_URL = "/assets/css/nav.css";
+ var AIFO_BTN_CSS_ID = "aifo-btn-styles";
+ var AIFO_BTN_CSS_URL = "/assets/css/aifo-btn.css";
+ var ICONFONT_CSS_ID = "aifo-iconfont-styles";
+ var ICONFONT_CSS_URL = "/assets/vendor/icon/iconfont.css";
var FLAG_ICONS_CSS_ID = "aifo-flag-icons-styles";
var FLAG_ICONS_CSS_URL = "/assets/flagicon/css/flag-icons.min.css";
var FOOT_JS_URL = "/js/footer.js";
@@ -114,6 +120,30 @@
document.head.appendChild(link);
}
+ function ensureNavStyles() {
+ if (!document.getElementById(ICONFONT_CSS_ID)) {
+ var iconLink = document.createElement("link");
+ iconLink.id = ICONFONT_CSS_ID;
+ iconLink.rel = "stylesheet";
+ iconLink.href = ICONFONT_CSS_URL;
+ document.head.appendChild(iconLink);
+ }
+ if (!document.getElementById(NAV_CSS_ID)) {
+ var navLink = document.createElement("link");
+ navLink.id = NAV_CSS_ID;
+ navLink.rel = "stylesheet";
+ navLink.href = NAV_CSS_URL;
+ document.head.appendChild(navLink);
+ }
+ if (!document.getElementById(AIFO_BTN_CSS_ID)) {
+ var btnLink = document.createElement("link");
+ btnLink.id = AIFO_BTN_CSS_ID;
+ btnLink.rel = "stylesheet";
+ btnLink.href = AIFO_BTN_CSS_URL;
+ document.head.appendChild(btnLink);
+ }
+ }
+
function loadFooterScript(callback) {
if (footJsLoaded) {
callback();
@@ -139,6 +169,25 @@
document.body.appendChild(script);
}
+ var navIconsJsLoading = false;
+ var navIconsJsLoaded = false;
+
+ function loadNavIconsScript() {
+ if (navIconsJsLoaded || navIconsJsLoading) return;
+ navIconsJsLoading = true;
+ var script = document.createElement("script");
+ script.src = "/js/nav-icons.js";
+ script.onload = function () {
+ navIconsJsLoaded = true;
+ navIconsJsLoading = false;
+ };
+ script.onerror = function () {
+ navIconsJsLoading = false;
+ console.error("[layout.js] Failed to load /js/nav-icons.js");
+ };
+ document.body.appendChild(script);
+ }
+
function initFooterModule(root) {
ensureFooterStyles();
updateCopyrightYear(root);
@@ -165,9 +214,11 @@
var navHtml = parts[0];
var footerHtml = parts[1];
if (navHtml) {
+ ensureNavStyles();
ensureFlagIconsStyles();
var navRoot = injectHtml("nav-container", navHtml);
if (navRoot) highlightActiveNav(navRoot);
+ loadNavIconsScript();
}
if (footerHtml) {
var footerRoot = injectHtml("footer-container", footerHtml);
diff --git a/js/nav-icons.js b/js/nav-icons.js
new file mode 100644
index 0000000..0dcbacc
--- /dev/null
+++ b/js/nav-icons.js
@@ -0,0 +1,36 @@
+/**
+ * Nav submenu iconfont helpers.
+ * Registry: data/nav-icon-registry.json
+ *
+ * After uploading new glyphs to iconfont.cn and replacing iconfont.css:
+ * window.aifoApplyNavIconTargets()
+ * This swaps data-nav-icon-target classes onto each submenu icon.
+ */
+(function () {
+ function applyNavIconTargets(root) {
+ if (!root) return 0;
+ var nodes = root.querySelectorAll("[data-nav-icon-target]");
+ var count = 0;
+ nodes.forEach(function (el) {
+ var target = el.getAttribute("data-nav-icon-target");
+ if (!target) return;
+ el.className = "icon iconfont " + target;
+ count += 1;
+ });
+ return count;
+ }
+
+ window.aifoApplyNavIconTargets = function () {
+ var nav = document.getElementById("nav");
+ var container = document.getElementById("nav-container");
+ var count = applyNavIconTargets(nav) + applyNavIconTargets(container);
+ console.info("[nav-icons] Applied " + count + " target icon class(es).");
+ return count;
+ };
+
+ document.addEventListener("aifo:layout-ready", function () {
+ if (window.AIFO_NAV_USE_TARGET_ICONS === true) {
+ window.aifoApplyNavIconTargets();
+ }
+ });
+})();
diff --git a/js/partnership.js b/js/partnership.js
index 24ea7aa..c079269 100644
--- a/js/partnership.js
+++ b/js/partnership.js
@@ -1,22 +1,22 @@
/**
- * Partnership page — FAQ accordion.
+ * Partnership page — FAQ accordion (Figma export style).
*/
(function () {
function initFaq(root) {
if (!root) return;
- root.querySelectorAll(".faq-header").forEach(function (header) {
+ root.querySelectorAll(".partnership-faq__header").forEach(function (header) {
header.addEventListener("click", function () {
- var item = header.closest(".faq-item");
+ var item = header.closest(".partnership-faq__item");
if (!item) return;
- var isActive = item.classList.contains("active");
- root.querySelectorAll(".faq-item").forEach(function (el) {
- el.classList.remove("active");
+ var isOpen = item.classList.contains("is-open");
+ root.querySelectorAll(".partnership-faq__item").forEach(function (el) {
+ el.classList.remove("is-open");
});
- if (!isActive) {
- item.classList.add("active");
+ if (!isOpen) {
+ item.classList.add("is-open");
}
});
});
diff --git a/js/support-cta-module.js b/js/support-cta-module.js
new file mode 100644
index 0000000..a741824
--- /dev/null
+++ b/js/support-cta-module.js
@@ -0,0 +1,30 @@
+/**
+ * Loads support-cta.section.html into #support-cta-module
+ */
+(function () {
+ var MODULE_URL = '/pages/modules/support-cta.section.html';
+
+ function loadSupportCtaModule() {
+ var container = document.getElementById('support-cta-module');
+ if (!container) return;
+
+ fetch(MODULE_URL, { credentials: 'same-origin' })
+ .then(function (res) {
+ if (!res.ok) throw new Error('Failed to load ' + MODULE_URL);
+ return res.text();
+ })
+ .then(function (html) {
+ container.innerHTML = html;
+ document.dispatchEvent(new CustomEvent('aifo:support-cta-ready'));
+ })
+ .catch(function (err) {
+ console.error('[support-cta-module.js]', err);
+ });
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', loadSupportCtaModule);
+ } else {
+ loadSupportCtaModule();
+ }
+})();
diff --git a/pages/about-us-2.html b/pages/about-us-2.html
index 91cff07..9933b43 100644
--- a/pages/about-us-2.html
+++ b/pages/about-us-2.html
@@ -11,7 +11,8 @@
-
+
+
@@ -30,14 +31,13 @@
-
About AIFO
+
About AIFO
- AIFO is a prop trading firm built to give traders transparent funding, professional tools,
- and a community that supports real growth — from your first challenge to funded success.
+ We are a prop trading platform that focuses on empowering traders through education, community, and innovative support, helping our traders thrive in the financial markets.
@@ -48,15 +48,16 @@
About Us
AIFO was built for traders.
- Here at AIFO, our team consists of experienced traders and financial professionals who truly
- understand the markets. We're committed to supporting your growth with clear rules, practical
- tools, and quality educational resources. Our goal is simple: to help you become a more
- confident and consistent trader.
+
+ Our mission is to empower traders through education, community, and technological innovation. Through our academy, community, and innovative tools, we help traders learn, grow, and navigate the markets with greater confidence.
+
+
Whether you're taking your first steps in trading or returning with renewed determination, AIFO provides support, knowledge, and technology to help you move forward.
+
Because every trader deserves the opportunity to reach their full potential.