diff --git a/assets/pasted-20260607-150400-0347d914.png b/assets/pasted-20260607-150400-0347d914.png
new file mode 100644
index 0000000..85223b4
Binary files /dev/null and b/assets/pasted-20260607-150400-0347d914.png differ
diff --git a/assets/pasted-20260607-151405-c8cfdd19.png b/assets/pasted-20260607-151405-c8cfdd19.png
new file mode 100644
index 0000000..2979c4a
Binary files /dev/null and b/assets/pasted-20260607-151405-c8cfdd19.png differ
diff --git a/wp-content/plugins/matthew-lms-mvp/matthew-lms-mvp.php b/wp-content/plugins/matthew-lms-mvp/matthew-lms-mvp.php
index b7f9a1a..a971af0 100644
--- a/wp-content/plugins/matthew-lms-mvp/matthew-lms-mvp.php
+++ b/wp-content/plugins/matthew-lms-mvp/matthew-lms-mvp.php
@@ -2,12 +2,12 @@
/**
* Plugin Name: WAX MVP
* Description: WAX AI-native learning MVP: premium landing styles, profile/course UI helpers, and AI Career Coach submissions.
- * Version: 0.1.6
+ * Version: 0.2.0
*/
if (!defined('ABSPATH')) { exit; }
-define('MATTHEW_LMS_MVP_VERSION', '0.1.6');
+define('MATTHEW_LMS_MVP_VERSION', '0.2.0');
add_action('init', function () {
register_post_type('mlms_coach_request', [
@@ -60,6 +60,12 @@ add_action('wp_head', function () {
add_action('template_redirect', 'matthew_lms_mvp_maybe_handle_login_submission');
add_action('template_redirect', 'matthew_lms_mvp_maybe_handle_google_oauth_callback');
+add_action('template_redirect', 'matthew_lms_mvp_maybe_handle_profile_source_submission');
+add_action('template_redirect', 'matthew_lms_mvp_maybe_render_course_route', 5);
+add_action('wp_ajax_mlms_ai_tutor', 'matthew_lms_mvp_handle_ai_tutor_ajax');
+add_action('wp_ajax_nopriv_mlms_ai_tutor', 'matthew_lms_mvp_handle_ai_tutor_ajax');
+add_action('wp_ajax_mlms_course_progress', 'matthew_lms_mvp_handle_course_progress_ajax');
+add_action('wp_ajax_nopriv_mlms_course_progress', 'matthew_lms_mvp_handle_course_progress_ajax');
add_filter('body_class', function ($classes) {
if (is_page(['home', 'career-coach', 'platform', 'sign-up', 'log-in'])) {
@@ -94,7 +100,8 @@ function matthew_lms_mvp_render_header(): string {
$links = [
'Home' => matthew_lms_mvp_public_url(),
'WAX Coach' => matthew_lms_mvp_public_url('career-coach/'),
- 'Platform' => matthew_lms_mvp_public_url('platform/'),
+ 'Profile' => matthew_lms_mvp_public_url('platform/'),
+ 'Course' => matthew_lms_mvp_course_url('course'),
];
$login_url = add_query_arg('redirect_to', rawurlencode(matthew_lms_mvp_public_url('platform/')), matthew_lms_mvp_public_url('log-in/'));
ob_start();
@@ -120,7 +127,8 @@ function matthew_lms_mvp_render_header(): string {
function matthew_lms_mvp_render_footer(): string {
$links = [
'Career Coach' => matthew_lms_mvp_public_url('career-coach/'),
- 'Platform' => matthew_lms_mvp_public_url('platform/'),
+ 'Profile' => matthew_lms_mvp_public_url('platform/'),
+ 'Course Dashboard' => matthew_lms_mvp_course_url('course'),
'Log In' => matthew_lms_mvp_public_url('log-in/'),
'Sign Up' => matthew_lms_mvp_public_url('sign-up/'),
];
@@ -242,6 +250,20 @@ body.page-id-47 .wp-block-post-title,body.page-id-48 .wp-block-post-title,body.p
@keyframes mlmsPulse{0%,100%{transform:scaleY(.78);opacity:.76}50%{transform:scaleY(1.08);opacity:1}}@keyframes mlmsGlow{0%,100%{filter:saturate(1)}50%{filter:saturate(1.12) brightness(1.04)}}
@media (max-width:900px){.mlms-site-header-inner{min-height:auto;padding-top:16px;padding-bottom:16px;flex-wrap:wrap}.mlms-header-nav{order:3;flex-basis:100%;justify-content:flex-start;gap:18px;overflow-x:auto}.mlms-page:before{height:300px}.mlms-hero{padding:70px 0 46px}.mlms-hero-grid,.mlms-coach-band,.mlms-profile-hero{grid-template-columns:1fr}.mlms-grid-3,.mlms-brand-grid,.mlms-form-grid,.mlms-role-grid{grid-template-columns:1fr}.mlms-ai-card{min-height:auto}.mlms-section-head{display:block}.mlms-h1{font-size:48px}.mlms-course-card{grid-template-columns:1fr}.mlms-shell{padding:0 18px}.mlms-section{padding:46px 0}.mlms-coach-band{padding:28px;border-radius:24px}}
@media (max-width:560px){.mlms-site-header{position:relative}.mlms-header-actions{gap:8px}.mlms-header-login,.mlms-header-signup{padding:10px 12px;font-size:14px}.mlms-site-footer-inner{flex-direction:column;align-items:flex-start}.mlms-footer-links{gap:12px}.mlms-site-footer{padding:30px 0 36px}.mlms-actions{display:grid}.mlms-btn{width:100%}.mlms-h1{font-size:42px}.mlms-h2{font-size:34px}.mlms-ai-card{padding:14px;border-radius:24px}.mlms-dashboard{padding:20px}.mlms-orb{width:46px;height:46px}.mlms-coach-preview{margin:14px 0 0;max-width:none}.mlms-footer-cta{padding-left:0;padding-right:0}}
+
+/* User Profile Page — shareable AI credential card, 5-node skill graph, progress, portfolio, external feed */
+body.page-id-49 #wp--skip-link--target{margin-block-start:0!important}body.page-id-49 #wp--skip-link--target>.wp-block-group{padding-top:0!important}.mlms-profile-page{padding:24px 0 84px}.mlms-profile-page>.mlms-section:first-child{padding-top:38px}.mlms-profile-intro{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:24px;align-items:end;margin-bottom:28px}.mlms-profile-intro .mlms-section-copy{max-width:760px}.mlms-profile-status{display:grid;gap:10px;justify-items:end}.mlms-share-chip{display:inline-flex;align-items:center;gap:9px;border-radius:999px;border:1px solid rgba(33,197,142,.22);background:rgba(33,197,142,.08);color:#08785B;padding:9px 13px;font-weight:900;font-size:13px}.mlms-share-chip:before{content:"";width:9px;height:9px;border-radius:99px;background:var(--mlms-green);box-shadow:0 0 0 6px rgba(33,197,142,.12)}.mlms-profile-dashboard{display:grid;grid-template-columns:minmax(320px,.82fr) minmax(0,1.18fr);gap:24px;align-items:stretch}.mlms-credential-card{position:relative;overflow:hidden;background:linear-gradient(150deg,#07182D 0%,#102C50 52%,#31246E 100%);color:#fff;border-radius:32px;padding:28px;box-shadow:var(--mlms-shadow);min-height:100%}.mlms-credential-card:before{content:"";position:absolute;inset:-70px -60px auto auto;width:220px;height:220px;border-radius:50%;background:radial-gradient(circle,rgba(215,208,255,.42),transparent 64%);animation:mlmsCredentialGlow 4.8s ease-in-out infinite}.mlms-credential-top{position:relative;z-index:1;display:flex;justify-content:space-between;gap:18px;align-items:flex-start;margin-bottom:26px}.mlms-profile-photo{width:96px;height:96px;border-radius:30px;border:1px solid rgba(255,255,255,.20);background:linear-gradient(135deg,#D7D0FF,#635BFF);display:grid;place-items:center;overflow:hidden;color:#fff;font-size:32px;font-weight:950;box-shadow:0 20px 46px rgba(0,0,0,.24)}.mlms-profile-photo img{width:100%;height:100%;object-fit:cover;display:block}.mlms-credential-badge{border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.09);border-radius:18px;padding:10px 12px;color:#E7E3FF;font-size:12px;font-weight:900;text-transform:uppercase;letter-spacing:.1em}.mlms-credential-card h2{position:relative;z-index:1;color:#fff;font-size:clamp(34px,4vw,52px);line-height:.98;letter-spacing:-.06em;margin:0 0 8px}.mlms-profile-title{position:relative;z-index:1;color:#D7E3F1;font-weight:850;margin:0 0 14px}.mlms-profile-bio{position:relative;z-index:1;color:#CEDBEE;margin:0 0 22px;line-height:1.58}.mlms-credential-details{position:relative;z-index:1;display:grid;gap:10px;margin-top:24px}.mlms-credential-details span{display:flex;justify-content:space-between;gap:14px;border-top:1px solid rgba(255,255,255,.12);padding-top:11px;color:#C8D7EA}.mlms-credential-details b{color:#fff}.mlms-credential-actions{position:relative;z-index:1;display:flex;flex-wrap:wrap;gap:10px;margin-top:24px}.mlms-credential-actions .mlms-btn-secondary{background:rgba(255,255,255,.11);border-color:rgba(255,255,255,.16);color:#fff;box-shadow:none}.mlms-profile-main{display:grid;gap:24px}.mlms-profile-module{background:rgba(255,255,255,.9);border:1px solid rgba(10,37,64,.09);border-radius:28px;padding:24px;box-shadow:var(--mlms-shadow-soft);position:relative;overflow:hidden}.mlms-profile-module:before{content:"";position:absolute;top:0;left:24px;right:24px;height:3px;border-radius:0 0 99px 99px;background:linear-gradient(90deg,var(--mlms-primary),#A7B6FF);opacity:.66}.mlms-module-head{display:flex;justify-content:space-between;gap:16px;align-items:flex-start;margin-bottom:18px}.mlms-module-head h3{font-size:24px;line-height:1.08;letter-spacing:-.035em;margin:0;color:var(--mlms-ink)}.mlms-module-head p{margin:6px 0 0;color:var(--mlms-muted);font-size:15px;line-height:1.45}.mlms-skill-network{position:relative;display:grid;grid-template-columns:repeat(5,minmax(74px,1fr));gap:14px;align-items:start;padding:12px 0 4px}.mlms-skill-network:before{content:"";position:absolute;left:7%;right:7%;top:48px;height:2px;background:linear-gradient(90deg,rgba(99,91,255,.55),rgba(99,91,255,.34),rgba(10,37,64,.12));z-index:0}.mlms-skill{position:relative;z-index:1;display:grid;justify-items:center;gap:9px;text-align:center}.mlms-skill-orb{width:76px;height:76px;border-radius:999px;display:grid;place-items:center;background:conic-gradient(var(--mlms-primary) var(--node-progress,0%),#E8EEF6 0);box-shadow:0 10px 26px rgba(50,50,93,.10);padding:5px;animation:mlmsNodeBreathe 3.4s ease-in-out infinite}.mlms-skill-orb span{width:100%;height:100%;border-radius:999px;display:grid;place-items:center;background:#fff;color:var(--mlms-soft);font-weight:950;border:1px solid rgba(10,37,64,.06)}.mlms-skill.earned{--node-progress:100%}.mlms-skill.earned .mlms-skill-orb{background:conic-gradient(var(--mlms-green) 100%,#E8EEF6 0);box-shadow:0 0 0 8px rgba(33,197,142,.08),0 0 28px rgba(33,197,142,.26)}.mlms-skill.earned .mlms-skill-orb span{background:linear-gradient(135deg,#21C58E,#45D6A7);color:#fff}.mlms-skill.current{--node-progress:66%}.mlms-skill.current .mlms-skill-orb{box-shadow:0 0 0 8px rgba(99,91,255,.09),0 0 34px rgba(99,91,255,.32)}.mlms-skill.current .mlms-skill-orb span{background:linear-gradient(135deg,#AFA9FF,var(--mlms-primary));color:#fff}.mlms-skill.external{--node-progress:24%}.mlms-skill.external .mlms-skill-orb span{background:#F8FAFD;color:#4D5F75}.mlms-skill strong{font-size:13px;line-height:1.15;color:var(--mlms-ink)}.mlms-skill small{font-size:12px;line-height:1.25;color:var(--mlms-soft);font-weight:700}.mlms-progress-summary{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:16px}.mlms-progress-stat{border-radius:20px;background:#F7FAFE;border:1px solid #E4EBF3;padding:14px}.mlms-progress-stat b{display:block;font-size:26px;line-height:1;color:var(--mlms-ink);letter-spacing:-.04em}.mlms-progress-stat span{font-size:12px;text-transform:uppercase;letter-spacing:.09em;font-weight:900;color:var(--mlms-soft)}.mlms-phase-tracker{display:grid;gap:12px}.mlms-phase-card{display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;border:1px solid #E2EAF3;background:#fff;border-radius:20px;padding:14px;box-shadow:0 8px 20px rgba(50,50,93,.05)}.mlms-phase-dot{width:44px;height:44px;border-radius:16px;display:grid;place-items:center;background:#EEF3F8;color:#718198;font-weight:950}.mlms-phase-card.completed .mlms-phase-dot{background:rgba(33,197,142,.12);color:#08785B}.mlms-phase-card.current{border-color:rgba(99,91,255,.28);background:#FBFAFF}.mlms-phase-card.current .mlms-phase-dot{background:var(--mlms-primary);color:#fff}.mlms-phase-card h4{margin:0;color:var(--mlms-ink);font-size:17px}.mlms-phase-card p{margin:3px 0 0;color:var(--mlms-muted);font-size:14px;line-height:1.35}.mlms-cert-badge{display:inline-flex;align-items:center;gap:7px;border-radius:999px;background:var(--mlms-primary-soft);color:var(--mlms-primary);padding:8px 10px;font-size:12px;font-weight:950;white-space:nowrap}.mlms-profile-wide{margin-top:24px}.mlms-portfolio-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.mlms-portfolio-card{background:#fff;border:1px solid #E2EAF3;border-radius:24px;padding:20px;box-shadow:0 10px 24px rgba(50,50,93,.07);display:grid;gap:12px}.mlms-portfolio-card h4{font-size:20px;line-height:1.08;letter-spacing:-.03em;margin:0;color:var(--mlms-ink)}.mlms-portfolio-card p{margin:0;color:var(--mlms-muted);font-size:15px;line-height:1.48}.mlms-tool-tags{display:flex;flex-wrap:wrap;gap:8px}.mlms-tool-tags span{border-radius:999px;background:#F0F4FF;color:#4F46E5;padding:6px 9px;font-size:12px;font-weight:900}.mlms-portfolio-link{font-weight:900;color:var(--mlms-primary);font-size:14px}.mlms-external-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:18px;align-items:start}.mlms-feed-list{display:grid;gap:12px}.mlms-feed-item{display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:center;border-radius:18px;border:1px solid #E3EBF4;background:#fff;padding:13px}.mlms-source-icon{width:38px;height:38px;border-radius:14px;display:grid;place-items:center;background:#111827;color:#fff;font-weight:950;font-size:13px}.mlms-source-icon.reddit{background:#FF4500}.mlms-source-icon.ai{background:linear-gradient(135deg,#635BFF,#A7B6FF)}.mlms-feed-item strong{display:block;color:var(--mlms-ink);line-height:1.2}.mlms-feed-item small{display:block;color:var(--mlms-soft);font-weight:700}.mlms-feed-status{font-size:12px;font-weight:950;border-radius:999px;padding:7px 9px;background:#F2F6FA;color:#607086}.mlms-feed-status.connected{background:rgba(33,197,142,.11);color:#08785B}.mlms-source-form{background:#F8FAFD;border:1px dashed rgba(99,91,255,.26);border-radius:22px;padding:18px}.mlms-source-form h4{margin:0 0 8px;font-size:18px;color:var(--mlms-ink)}.mlms-source-form p{margin:0 0 14px;color:var(--mlms-muted);font-size:14px;line-height:1.45}.mlms-source-form .mlms-field{margin-bottom:12px}.mlms-source-form .mlms-btn{width:100%;border:0;cursor:pointer}.mlms-source-form select{width:100%;border:1px solid #DDE6F0;border-radius:14px;padding:12px 14px;background:#fff;color:var(--mlms-ink);font:inherit}.mlms-profile-notice{border-radius:18px;padding:14px 16px;background:#EFFCF7;border:1px solid rgba(33,197,142,.22);color:#0A7458;margin:0 0 18px;font-size:15px;font-weight:750}@keyframes mlmsCredentialGlow{0%,100%{transform:scale(.96);opacity:.8}50%{transform:scale(1.06);opacity:1}}@keyframes mlmsNodeBreathe{0%,100%{transform:translateY(0);filter:saturate(1)}50%{transform:translateY(-3px);filter:saturate(1.12)}}@media (max-width:980px){.mlms-profile-intro,.mlms-profile-dashboard,.mlms-external-grid{grid-template-columns:1fr}.mlms-profile-status{justify-items:start}.mlms-portfolio-grid{grid-template-columns:1fr}.mlms-progress-summary{grid-template-columns:1fr 1fr 1fr}.mlms-skill-network{grid-template-columns:repeat(5,minmax(62px,1fr));overflow-x:auto;padding-bottom:8px}.mlms-skill-network:before{left:38px;right:38px}.mlms-skill-orb{width:66px;height:66px}}@media (max-width:640px){.mlms-profile-page{padding-top:46px}.mlms-profile-module,.mlms-credential-card{border-radius:24px;padding:20px}.mlms-progress-summary{grid-template-columns:1fr}.mlms-phase-card,.mlms-feed-item{grid-template-columns:1fr}.mlms-skill-network{grid-template-columns:repeat(5,74px)}.mlms-credential-top{display:grid}.mlms-credential-details span{display:grid}.mlms-module-head{display:grid}}
+
+
+/* Course dashboard + in-course AI tutor */
+.mlms-course-page .mlms-section{padding-top:42px}.mlms-course-dashboard{position:relative;display:grid;gap:22px;margin:26px 0 34px}.mlms-course-overview{position:relative;overflow:hidden;border-radius:32px;padding:26px;background:linear-gradient(135deg,#07182D 0%,#132747 58%,#251A56 100%);color:#fff;box-shadow:var(--mlms-shadow)}.mlms-course-overview:before{content:"";position:absolute;inset:-80px -120px auto auto;width:320px;height:320px;border-radius:999px;background:rgba(99,91,255,.32);filter:blur(8px)}.mlms-course-overview-head{position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:18px;margin-bottom:22px}.mlms-course-overview h2{margin:0;color:#fff;font-size:clamp(28px,3.5vw,44px);line-height:1.02;letter-spacing:-.05em}.mlms-course-overview p{margin:8px 0 0;color:#C8D5E4;max-width:720px;line-height:1.5}.mlms-course-streak{display:grid;place-items:center;min-width:116px;border-radius:24px;padding:16px;background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.13);text-align:center}.mlms-course-streak b{font-size:32px;line-height:1;color:#fff}.mlms-course-streak span{font-size:12px;text-transform:uppercase;letter-spacing:.12em;color:#C9C4FF;font-weight:950}.mlms-phase-path{position:relative;display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.mlms-dashboard-phase{position:relative;border-radius:24px;padding:18px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.13);min-height:184px;display:grid;gap:14px;align-content:start;transition:transform .18s ease,opacity .18s ease,background .18s ease}.mlms-dashboard-phase:hover{transform:translateY(-2px)}.mlms-dashboard-phase.current{background:rgba(255,255,255,.16);box-shadow:inset 0 0 0 1px rgba(201,196,255,.30)}.mlms-dashboard-phase.locked{opacity:.54;filter:grayscale(.25)}.mlms-dashboard-phase.locked:hover{transform:none}.mlms-dashboard-phase-top{display:flex;justify-content:space-between;gap:10px;align-items:center}.mlms-dashboard-phase-number{width:42px;height:42px;border-radius:15px;display:grid;place-items:center;background:#fff;color:var(--mlms-primary);font-weight:950;box-shadow:0 10px 24px rgba(0,0,0,.18)}.mlms-dashboard-phase.locked .mlms-dashboard-phase-number{background:rgba(255,255,255,.22);color:#E6ECF2}.mlms-dashboard-lock{display:inline-flex;align-items:center;gap:6px;border-radius:999px;background:rgba(255,255,255,.12);color:#E6ECF2;padding:6px 9px;font-size:12px;font-weight:950;white-space:nowrap}.mlms-dashboard-phase h3{margin:0;color:#fff;font-size:20px;letter-spacing:-.03em;line-height:1.1}.mlms-dashboard-phase p{font-size:14px;margin:0;color:#C8D5E4}.mlms-dashboard-meta{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto}.mlms-dashboard-meta span{border-radius:999px;background:rgba(255,255,255,.11);color:#F2F6FA;padding:6px 9px;font-size:12px;font-weight:850}.mlms-dashboard-skill-node{width:14px;height:14px;border-radius:99px;background:#94A3B8;box-shadow:0 0 0 6px rgba(148,163,184,.13);transition:background .25s ease,box-shadow .25s ease,transform .25s ease}.mlms-dashboard-skill-node.current{background:#C9C4FF;box-shadow:0 0 0 6px rgba(201,196,255,.20),0 0 22px rgba(201,196,255,.55)}.mlms-dashboard-skill-node.earned{background:var(--mlms-green);box-shadow:0 0 0 7px rgba(33,197,142,.16),0 0 24px rgba(33,197,142,.50);animation:mlmsCourseEarn .72s ease both}.mlms-lesson-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);gap:22px;align-items:start}.mlms-lesson-reader,.mlms-build-card,.mlms-lesson-side-card{background:rgba(255,255,255,.92);border:1px solid rgba(10,37,64,.09);border-radius:30px;box-shadow:var(--mlms-shadow-soft)}.mlms-lesson-reader{padding:28px;display:grid;gap:22px}.mlms-lesson-topline{display:flex;justify-content:space-between;gap:14px;align-items:flex-start;flex-wrap:wrap}.mlms-lesson-reader h2{margin:0;color:var(--mlms-ink);font-size:clamp(30px,3vw,42px);line-height:1.04;letter-spacing:-.05em}.mlms-lesson-reader p{margin:0;color:var(--mlms-muted);line-height:1.58}.mlms-lesson-progress{min-width:210px}.mlms-lesson-progress-label{display:flex;justify-content:space-between;gap:10px;font-size:13px;color:var(--mlms-soft);font-weight:900;text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px}.mlms-lesson-progress-track{height:10px;border-radius:999px;background:#E6ECF2;overflow:hidden}.mlms-lesson-progress-track span{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,var(--mlms-primary),#A7B6FF);width:42%}.mlms-role-example{border-radius:22px;border:1px solid rgba(99,91,255,.18);background:linear-gradient(135deg,#F8F7FF,#fff);padding:18px;display:grid;gap:8px}.mlms-role-example strong{color:var(--mlms-primary);font-size:14px;text-transform:uppercase;letter-spacing:.12em}.mlms-flowchart{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;align-items:stretch}.mlms-flow-step{position:relative;border-radius:18px;padding:14px;background:#F6F9FC;border:1px solid #E2EAF3;color:var(--mlms-ink);font-weight:850;min-height:86px;display:grid;align-content:center}.mlms-flow-step span{display:block;color:var(--mlms-primary);font-size:12px;text-transform:uppercase;letter-spacing:.1em;margin-bottom:4px}.mlms-flow-step:not(:last-child):after{content:"→";position:absolute;right:-12px;top:50%;transform:translateY(-50%);z-index:2;width:22px;height:22px;border-radius:99px;background:var(--mlms-primary);color:#fff;display:grid;place-items:center;font-size:13px}.mlms-lesson-table{border:1px solid #E2EAF3;border-radius:20px;overflow:hidden;background:#fff}.mlms-lesson-row{display:grid;grid-template-columns:1fr 1.15fr;gap:0}.mlms-lesson-row+ .mlms-lesson-row{border-top:1px solid #E2EAF3}.mlms-lesson-row strong,.mlms-lesson-row span{padding:13px 15px}.mlms-lesson-row strong{background:#F6F9FC;color:var(--mlms-ink)}.mlms-lesson-row span{color:var(--mlms-muted)}.mlms-quiz{border-radius:22px;background:#0A2540;color:#fff;padding:18px}.mlms-quiz h3{margin:0 0 10px;color:#fff;font-size:19px}.mlms-quiz p{color:#C8D5E4}.mlms-quiz-options{display:grid;gap:8px;margin-top:12px}.mlms-quiz-option{display:flex;gap:10px;align-items:flex-start;border:1px solid rgba(255,255,255,.12);border-radius:15px;padding:11px;background:rgba(255,255,255,.07);cursor:pointer;color:#fff}.mlms-quiz-option input{margin-top:4px;accent-color:var(--mlms-primary)}.mlms-quiz-result{display:none;margin-top:12px;border-radius:14px;padding:10px 12px;background:rgba(33,197,142,.14);color:#DAFFF3;font-size:14px;font-weight:760}.mlms-quiz-result.active{display:block}.mlms-lesson-aside{display:grid;gap:16px;position:sticky;top:92px}.mlms-lesson-side-card{padding:20px}.mlms-lesson-side-card h3{margin:0 0 10px;color:var(--mlms-ink);font-size:20px}.mlms-lesson-side-card ul{margin:0;padding:0;list-style:none;display:grid;gap:10px}.mlms-lesson-side-card li{display:flex;gap:10px;color:var(--mlms-muted);font-weight:720;line-height:1.35}.mlms-lesson-side-card li:before{content:"";width:10px;height:10px;flex:0 0 auto;margin-top:6px;border-radius:99px;background:var(--mlms-primary);box-shadow:0 0 0 5px rgba(99,91,255,.10)}.mlms-build-card{padding:24px;display:grid;gap:18px}.mlms-build-card h2{margin:0;color:var(--mlms-ink);font-size:30px;line-height:1.08;letter-spacing:-.04em}.mlms-build-card p{margin:0;color:var(--mlms-muted)}.mlms-build-checklist{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.mlms-build-checklist label{display:flex;gap:9px;align-items:flex-start;border-radius:17px;border:1px solid #E2EAF3;background:#fff;padding:12px;color:var(--mlms-muted);font-weight:760;line-height:1.35}.mlms-build-checklist input{margin-top:4px;accent-color:var(--mlms-primary)}.mlms-build-card textarea{width:100%;min-height:118px;resize:vertical;border:1px solid #DDE6F0;border-radius:18px;padding:14px 16px;background:#fff;color:var(--mlms-ink);font:inherit}.mlms-build-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.mlms-build-actions .mlms-btn{border:0;cursor:pointer}.mlms-build-status{font-size:14px;color:var(--mlms-soft);font-weight:760}.mlms-completion-card{display:none;border-radius:24px;padding:20px;background:linear-gradient(135deg,#ECFFF8,#F7F5FF);border:1px solid rgba(33,197,142,.22);box-shadow:0 18px 34px rgba(33,197,142,.12)}.mlms-completion-card.active{display:grid;gap:10px;animation:mlmsCompletionRise .38s ease both}.mlms-completion-card h3{margin:0;color:#08785B;font-size:22px}.mlms-completion-card p{margin:0;color:#2F4F5F}.mlms-completion-points{display:inline-flex;width:max-content;border-radius:999px;background:#fff;color:#08785B;padding:8px 12px;font-size:13px;font-weight:950;box-shadow:0 8px 20px rgba(33,197,142,.12)}.mlms-tutor-launcher{position:fixed;right:24px;bottom:24px;z-index:80;border:0;border-radius:999px;background:var(--mlms-primary);color:#fff;box-shadow:0 18px 44px rgba(99,91,255,.32);display:flex;align-items:center;gap:10px;padding:13px 17px;font-weight:950;cursor:pointer}.mlms-tutor-launcher span:first-child{width:34px;height:34px;border-radius:99px;background:rgba(255,255,255,.18);display:grid;place-items:center}.mlms-tutor-panel{position:fixed;right:24px;bottom:90px;z-index:81;width:min(410px,calc(100vw - 32px));max-height:min(720px,calc(100vh - 120px));display:grid;grid-template-rows:auto 1fr auto;border-radius:28px;background:#fff;border:1px solid rgba(10,37,64,.10);box-shadow:0 28px 90px rgba(10,37,64,.22);overflow:hidden;opacity:0;pointer-events:none;transform:translateX(28px) translateY(8px);transition:opacity .2s ease,transform .2s ease}.mlms-tutor-panel.open{opacity:1;pointer-events:auto;transform:translateX(0) translateY(0)}.mlms-tutor-head{background:linear-gradient(135deg,#0A2540,#241A56);color:#fff;padding:16px;display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.mlms-tutor-head h3{margin:0;color:#fff;font-size:19px}.mlms-tutor-head p{margin:3px 0 0;color:#C8D5E4;font-size:13px;line-height:1.35}.mlms-tutor-close{width:34px;height:34px;border:0;border-radius:99px;background:rgba(255,255,255,.12);color:#fff;font-size:21px;cursor:pointer}.mlms-tutor-messages{padding:16px;background:#F6F9FC;overflow:auto;display:grid;align-content:start;gap:12px;min-height:220px}.mlms-tutor-msg{max-width:92%;border-radius:18px;padding:12px 13px;font-size:14px;line-height:1.45;white-space:pre-wrap}.mlms-tutor-msg.bot{background:#fff;color:var(--mlms-muted);border:1px solid #E2EAF3;justify-self:start}.mlms-tutor-msg.user{background:var(--mlms-primary);color:#fff;justify-self:end}.mlms-tutor-form{padding:14px;background:#fff;display:grid;gap:10px}.mlms-tutor-mode-row{display:flex;flex-wrap:wrap;gap:8px}.mlms-tutor-chip{border:1px solid #DDE6F0;background:#fff;color:var(--mlms-muted);border-radius:999px;padding:7px 10px;font-size:12px;font-weight:900;cursor:pointer}.mlms-tutor-chip:hover,.mlms-tutor-chip.active{border-color:rgba(99,91,255,.40);background:var(--mlms-primary-soft);color:var(--mlms-primary)}.mlms-tutor-form textarea{width:100%;min-height:76px;resize:vertical;border:1px solid #DDE6F0;border-radius:16px;padding:12px 13px;color:var(--mlms-ink);font:inherit;font-size:14px}.mlms-tutor-file{display:grid;gap:5px;color:var(--mlms-soft);font-size:12px;font-weight:800}.mlms-tutor-file input{font-size:12px}.mlms-tutor-submit{border:0;cursor:pointer;width:100%}.mlms-tutor-help{font-size:12px;color:var(--mlms-soft);line-height:1.35;margin:0}.mlms-ai-note{display:inline-flex;align-items:center;gap:8px;border-radius:999px;background:var(--mlms-primary-soft);color:var(--mlms-primary);padding:8px 11px;font-size:12px;font-weight:950}.mlms-profile-proof-heading{display:flex;align-items:end;justify-content:space-between;gap:14px;margin:34px 0 16px}.mlms-profile-proof-heading h2{margin:0;color:var(--mlms-ink);font-size:28px;letter-spacing:-.04em}.mlms-profile-proof-heading p{margin:4px 0 0;color:var(--mlms-muted)}@keyframes mlmsCourseEarn{0%{transform:scale(.75)}55%{transform:scale(1.28)}100%{transform:scale(1)}}@keyframes mlmsCompletionRise{from{transform:translateY(10px);opacity:0}to{transform:translateY(0);opacity:1}}@media (max-width:980px){.mlms-phase-path,.mlms-lesson-grid{grid-template-columns:1fr}.mlms-lesson-aside{position:relative;top:auto}.mlms-flowchart,.mlms-build-checklist{grid-template-columns:1fr 1fr}.mlms-course-overview-head{display:grid}.mlms-course-streak{width:max-content}}@media (max-width:640px){.mlms-course-overview,.mlms-lesson-reader,.mlms-build-card{border-radius:24px;padding:20px}.mlms-flowchart,.mlms-build-checklist,.mlms-lesson-row{grid-template-columns:1fr}.mlms-flow-step:not(:last-child):after{display:none}.mlms-tutor-launcher{right:16px;bottom:16px}.mlms-tutor-launcher span:last-child{display:none}.mlms-tutor-panel{right:16px;bottom:72px}.mlms-profile-proof-heading{display:grid}}
+
+
+/* Course launch, saved progress, and separate quiz block */
+.mlms-course-actions,.mlms-phase-actions,.mlms-lesson-checkpoint-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.mlms-course-actions{position:relative;margin:18px 0 16px}.mlms-course-actions .mlms-btn,.mlms-phase-actions .mlms-btn,.mlms-lesson-checkpoint-actions .mlms-btn{border:0;cursor:pointer;text-decoration:none}.mlms-course-resume-strip{position:relative;display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;margin:0 0 18px;padding:14px;border-radius:22px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.14)}.mlms-course-resume-strip span{font-size:12px;letter-spacing:.12em;text-transform:uppercase;font-weight:950;color:#C9C4FF}.mlms-course-resume-strip strong{display:block;color:#fff}.mlms-course-resume-strip small{display:block;color:#C8D5E4;margin-top:2px}.mlms-course-mini-meter{width:132px;height:8px;border-radius:999px;background:rgba(255,255,255,.16);overflow:hidden}.mlms-course-mini-meter i{display:block;height:100%;width:42%;border-radius:inherit;background:linear-gradient(90deg,#21C58E,#C9C4FF);transition:width .25s ease}.mlms-phase-actions{margin-top:4px}.mlms-phase-launch{min-height:38px;padding:10px 13px;font-size:13px}.mlms-locked-button{min-height:38px;padding:10px 13px;border-radius:999px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.08);color:#D7E3F1;font-weight:900;cursor:not-allowed}.mlms-course-workspace{display:grid;gap:22px;scroll-margin-top:112px}.mlms-course-workspace.launched{animation:mlmsCourseLaunch .5s ease both}.mlms-course-workspace-head{display:flex;justify-content:space-between;gap:16px;align-items:center;border:1px solid rgba(99,91,255,.14);background:rgba(255,255,255,.88);box-shadow:var(--mlms-shadow-soft);border-radius:26px;padding:18px 20px}.mlms-course-workspace-head h3{margin:0;color:var(--mlms-ink);font-size:24px;letter-spacing:-.035em}.mlms-course-workspace-head p{margin:5px 0 0;color:var(--mlms-muted)}.mlms-course-status-pill{display:inline-flex;align-items:center;gap:8px;white-space:nowrap;border-radius:999px;background:var(--mlms-primary-soft);color:var(--mlms-primary);padding:9px 12px;font-size:12px;font-weight:950;text-transform:uppercase;letter-spacing:.08em}.mlms-course-status-pill:before{content:"";width:8px;height:8px;border-radius:99px;background:var(--mlms-primary);box-shadow:0 0 0 6px rgba(99,91,255,.10)}.mlms-lesson-checkpoint{border-radius:22px;background:#F8FAFD;border:1px solid #E2EAF3;padding:18px;display:grid;gap:10px}.mlms-lesson-checkpoint h3{margin:0;color:var(--mlms-ink);font-size:20px}.mlms-quiz-card{background:rgba(255,255,255,.94);border:1px solid rgba(10,37,64,.09);border-radius:30px;box-shadow:var(--mlms-shadow-soft);padding:28px;display:grid;gap:18px;scroll-margin-top:112px}.mlms-quiz-head{display:flex;justify-content:space-between;gap:18px;align-items:flex-start}.mlms-quiz-head h2{margin:0;color:var(--mlms-ink);font-size:clamp(28px,3vw,38px);letter-spacing:-.045em;line-height:1.04}.mlms-quiz-head p{margin:8px 0 0;color:var(--mlms-muted);max-width:680px}.mlms-quiz-count{border-radius:999px;background:#F2F6FA;border:1px solid #DDE6F0;color:#4D5F75;padding:9px 12px;font-weight:950;font-size:13px;white-space:nowrap}.mlms-quiz-form{display:grid;gap:14px}.mlms-quiz-question{border:1px solid #E2EAF3;border-radius:22px;background:#fff;padding:16px;display:grid;gap:12px}.mlms-quiz-question legend{font-weight:950;color:var(--mlms-ink);padding:0 4px}.mlms-quiz-question.is-correct{border-color:rgba(33,197,142,.34);background:rgba(33,197,142,.05)}.mlms-quiz-question.is-wrong{border-color:rgba(239,68,68,.28);background:rgba(239,68,68,.045)}.mlms-quiz-options{display:grid;gap:10px}.mlms-quiz-option{display:flex;gap:10px;align-items:flex-start;padding:12px;border:1px solid #E2EAF3;background:#F8FAFD;border-radius:16px;color:var(--mlms-muted);font-weight:750;line-height:1.35}.mlms-quiz-option input{margin-top:2px}.mlms-quiz-actions{display:flex;flex-wrap:wrap;gap:12px;align-items:center}.mlms-quiz-actions .mlms-btn{border:0;cursor:pointer}.mlms-quiz-status{color:var(--mlms-soft);font-size:13px;font-weight:850}.mlms-quiz-result{display:none;border-radius:22px;padding:16px;border:1px solid #DDE6F0;background:#F8FAFD;color:var(--mlms-muted);line-height:1.5}.mlms-quiz-result.active{display:block;animation:mlmsCompletionRise .35s ease both}.mlms-quiz-result.pass{border-color:rgba(33,197,142,.30);background:rgba(33,197,142,.07);color:#0B6B52}.mlms-quiz-result.retry{border-color:rgba(245,158,11,.32);background:rgba(245,158,11,.08);color:#7A4B00}.mlms-quiz-result.error{border-color:rgba(239,68,68,.25);background:rgba(239,68,68,.06);color:#8A1F1F}.mlms-quiz-result strong{display:block;color:inherit;margin-bottom:4px}.mlms-profile-course-progress .mlms-module-head{align-items:center}.mlms-profile-resume-card{display:grid;grid-template-columns:1fr auto;gap:16px;align-items:center;border-radius:24px;border:1px solid rgba(99,91,255,.14);background:linear-gradient(135deg,#F8F7FF,#fff);padding:18px;margin-bottom:16px}.mlms-profile-resume-card h4{margin:0;color:var(--mlms-ink);font-size:21px;letter-spacing:-.03em}.mlms-profile-resume-card p{margin:5px 0 0;color:var(--mlms-muted)}.mlms-profile-resume-card .mlms-btn{text-decoration:none}.mlms-profile-progress-bar{height:10px;border-radius:999px;background:#E6ECF2;overflow:hidden;margin:10px 0 16px}.mlms-profile-progress-bar span{display:block;height:100%;width:42%;border-radius:inherit;background:linear-gradient(90deg,var(--mlms-primary),#21C58E);transition:width .25s ease}.mlms-profile-course-progress .mlms-progress-summary{margin-bottom:14px}.mlms-course-dashboard.is-lesson-complete .mlms-dashboard-phase.current{background:rgba(33,197,142,.18)}.mlms-course-dashboard.is-lesson-complete .mlms-course-status-pill{background:rgba(33,197,142,.10);color:#08785B}.mlms-course-dashboard.is-lesson-complete .mlms-course-status-pill:before{background:var(--mlms-green);box-shadow:0 0 0 6px rgba(33,197,142,.12)}@keyframes mlmsCourseLaunch{0%{box-shadow:0 0 0 rgba(99,91,255,0)}45%{box-shadow:0 0 0 8px rgba(99,91,255,.10)}100%{box-shadow:0 0 0 rgba(99,91,255,0)}}@media (max-width:760px){.mlms-course-resume-strip,.mlms-course-workspace-head,.mlms-quiz-head,.mlms-profile-resume-card{grid-template-columns:1fr;display:grid}.mlms-course-mini-meter{width:100%}.mlms-profile-resume-card .mlms-btn{width:max-content}.mlms-quiz-card{padding:20px;border-radius:24px}}
+
+.mlms-course-launch-hub{grid-template-columns:1fr}.mlms-course-page-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.mlms-course-page-card{position:relative;overflow:hidden;border-radius:26px;border:1px solid rgba(10,37,64,.09);background:rgba(255,255,255,.92);box-shadow:var(--mlms-shadow-soft);padding:22px;display:grid;gap:14px;align-content:start}.mlms-course-page-card:before{content:"";position:absolute;inset:0 0 auto 0;height:3px;background:linear-gradient(90deg,var(--mlms-primary),#21C58E);opacity:.75}.mlms-course-page-card h4{margin:0;color:var(--mlms-ink);font-size:22px;letter-spacing:-.035em}.mlms-course-page-card p{margin:0;color:var(--mlms-muted);line-height:1.5}.mlms-course-page-card .mlms-btn{width:max-content;text-decoration:none}.mlms-course-page-meta{display:flex;flex-wrap:wrap;gap:8px}.mlms-course-page-meta span{border-radius:999px;background:#F2F6FA;border:1px solid #DDE6F0;color:#4D5F75;padding:7px 10px;font-size:12px;font-weight:900}.mlms-course-standalone-page{background:var(--mlms-bg)}.mlms-course-standalone{padding:0 0 84px}.mlms-course-standalone-hero{position:relative;overflow:hidden;border-radius:34px;padding:28px;background:linear-gradient(135deg,#07182D 0%,#132747 58%,#251A56 100%);color:#fff;box-shadow:var(--mlms-shadow);margin:28px 0 24px}.mlms-course-standalone-hero h1{margin:0;color:#fff;font-size:clamp(38px,5vw,64px);line-height:.98;letter-spacing:-.06em;max-width:860px}.mlms-course-standalone-hero p{color:#D7E3F1;max-width:760px}.mlms-course-standalone-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}.mlms-course-standalone-actions .mlms-btn-secondary{background:rgba(255,255,255,.11);border-color:rgba(255,255,255,.16);color:#fff;box-shadow:none}.mlms-course-route-shell{display:grid;gap:22px}.mlms-course-backlink{display:inline-flex;align-items:center;gap:8px;color:#C9C4FF!important;font-weight:900;text-decoration:none!important;margin-bottom:14px}.mlms-course-route-pill{display:inline-flex;width:max-content;border-radius:999px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.14);color:#E7E3FF;padding:8px 11px;font-weight:950;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:12px}@media (max-width:900px){.mlms-course-page-grid{grid-template-columns:1fr}.mlms-course-standalone-hero{border-radius:26px;padding:22px}}
+
CSS;
}
@@ -381,6 +403,39 @@ function matthew_lms_mvp_maybe_handle_login_submission(): void {
}
}
+function matthew_lms_mvp_maybe_handle_profile_source_submission(): void {
+ if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST' || !isset($_POST['mlms_profile_source_nonce'])) {
+ return;
+ }
+ if (!is_page('platform')) {
+ return;
+ }
+ $target = matthew_lms_mvp_public_url('platform/') . '#external-skills';
+ if (!is_user_logged_in()) {
+ wp_redirect(add_query_arg('redirect_to', rawurlencode($target), matthew_lms_mvp_public_url('log-in/')));
+ exit;
+ }
+ $nonce = sanitize_text_field(wp_unslash($_POST['mlms_profile_source_nonce'] ?? ''));
+ if (!wp_verify_nonce($nonce, 'mlms_profile_source_submit')) {
+ wp_redirect(add_query_arg('mlms_profile_notice', 'expired', $target));
+ exit;
+ }
+ $source_url = esc_url_raw(wp_unslash($_POST['mlms_profile_source_url'] ?? ''));
+ $source_type = sanitize_text_field(wp_unslash($_POST['mlms_profile_source_type'] ?? 'profile'));
+ $allowed_types = ['github', 'reddit', 'ai-platform', 'linkedin', 'profile'];
+ if (!in_array($source_type, $allowed_types, true)) {
+ $source_type = 'profile';
+ }
+ if ($source_url === '' || !wp_http_validate_url($source_url)) {
+ wp_redirect(add_query_arg('mlms_profile_notice', 'invalid', $target));
+ exit;
+ }
+ update_user_meta(get_current_user_id(), '_mlms_profile_link', $source_url);
+ update_user_meta(get_current_user_id(), '_mlms_external_source_type', $source_type);
+ wp_redirect(add_query_arg('mlms_profile_notice', 'connected', $target));
+ exit;
+}
+
function matthew_lms_mvp_handle_login_submission(): array {
$redirect = matthew_lms_mvp_redirect_url('platform/');
$nonce = sanitize_text_field(wp_unslash($_POST['mlms_login_nonce'] ?? ''));
@@ -638,7 +693,7 @@ function matthew_lms_mvp_render_signup_success(array $result): string {
Email
Role
-
+
AI-generated starter profile
@@ -705,15 +760,1262 @@ function matthew_lms_mvp_js(): string {
syncRoles();
show(current);
}
- if(document.readyState==='loading'){
- document.addEventListener('DOMContentLoaded', initWaxOnboarding);
- } else {
+
+ function mlmsAppendTutorMessage(box, text, who){
+ if(!box){return null;}
+ var msg=document.createElement('div');
+ msg.className='mlms-tutor-msg '+(who||'bot');
+ msg.textContent=text;
+ box.appendChild(msg);
+ box.scrollTop=box.scrollHeight;
+ return msg;
+ }
+
+ function mlmsPostTutor(formData, ajaxUrl){
+ return fetch(ajaxUrl, {method:'POST', credentials:'same-origin', body:formData})
+ .then(function(resp){return resp.json();})
+ .then(function(json){
+ if(json && json.success && json.data){return json.data;}
+ var message=(json && json.data && json.data.message) ? json.data.message : 'The WAX tutor could not respond. Try again with a shorter question.';
+ throw new Error(message);
+ });
+ }
+
+ function initWaxCourseDashboard(){
+ var dashboard=document.querySelector('[data-mlms-course-dashboard]');
+ if(!dashboard){return;}
+ var storageKey='waxCourseProgress:v2';
+ var ajaxUrl=dashboard.getAttribute('data-ajax-url')||'';
+ var progressNonce=dashboard.getAttribute('data-progress-nonce')||'';
+ var defaults={phase:1,lesson:2,step:2,percent:42,status:'in_progress',phase_label:'Phase 1 · AI Workflow Fluency',lesson_title:'Build a practical AI workflow brief',last_block:'Lesson view: role-specific workflow example',next_action:'Continue lesson',quiz_score:0,quiz_total:4,quiz_completed:false,skill_points:0,updated_at:''};
+
+ function clamp(num,min,max){num=parseInt(num,10);if(isNaN(num)){num=min;}return Math.max(min,Math.min(max,num));}
+ function normalizeProgress(raw){
+ var p=Object.assign({},defaults,raw||{});
+ p.phase=clamp(p.phase,1,3);
+ p.lesson=clamp(p.lesson,1,5);
+ p.step=clamp(p.step,1,5);
+ p.percent=clamp(p.percent,0,100);
+ p.quiz_score=clamp(p.quiz_score,0,10);
+ p.quiz_total=clamp(p.quiz_total,1,10);
+ p.skill_points=clamp(p.skill_points,0,999);
+ p.quiz_completed=!!(p.quiz_completed===true || p.quiz_completed==='1' || p.quiz_completed==='true' || p.quiz_completed===1);
+ ['status','phase_label','lesson_title','last_block','next_action','updated_at'].forEach(function(key){p[key]=String(p[key]||defaults[key]||'');});
+ return p;
+ }
+ function parseJsonAttribute(el,attr){
+ try{return JSON.parse(el.getAttribute(attr)||'{}');}catch(error){return {};}
+ }
+ function loadProgress(){
+ var initial=normalizeProgress(parseJsonAttribute(dashboard,'data-initial-progress'));
+ var stored=null;
+ try{stored=JSON.parse(window.localStorage.getItem(storageKey)||'null');}catch(error){stored=null;}
+ if(stored && typeof stored==='object'){
+ var storedProgress=normalizeProgress(stored);
+ var storedTime=Date.parse(storedProgress.updated_at||'');
+ var initialTime=Date.parse(initial.updated_at||'');
+ if(!initial.updated_at || (storedTime && (!initialTime || storedTime>initialTime))){return storedProgress;}
+ }
+ return initial;
+ }
+ var progress=loadProgress();
+
+ function statusLabel(status){
+ if(status==='lesson_complete'){return 'Lesson complete';}
+ if(status==='quiz_completed'){return 'Quiz complete';}
+ if(status==='course_launched'){return 'Course launched';}
+ if(status==='not_started'){return 'Not started';}
+ return 'In progress';
+ }
+ function setText(root,selector,value){
+ if(!root){return;}
+ root.querySelectorAll(selector).forEach(function(el){el.textContent=value;});
+ }
+ function setWidth(root,selector,value){
+ if(!root){return;}
+ root.querySelectorAll(selector).forEach(function(el){el.style.width=value+'%';});
+ }
+ function quizLabel(p){
+ return p.quiz_completed ? (p.quiz_score+'/'+p.quiz_total) : 'Not taken';
+ }
+ function applyProgress(nextProgress){
+ progress=normalizeProgress(nextProgress);
+ dashboard.classList.toggle('is-lesson-complete', progress.status==='lesson_complete');
+ setText(dashboard,'[data-mlms-course-percent]',progress.percent+'%');
+ setText(dashboard,'[data-mlms-course-step]','Step '+progress.step+' of 5');
+ setText(dashboard,'[data-mlms-course-status]',statusLabel(progress.status));
+ setText(dashboard,'[data-mlms-leftoff-title]',progress.lesson_title);
+ setText(dashboard,'[data-mlms-leftoff-meta]',progress.phase_label+' · '+progress.last_block);
+ setWidth(dashboard,'[data-mlms-course-progress-fill]',progress.percent);
+ setWidth(dashboard,'.mlms-lesson-progress-track span',progress.percent);
+ var nodeState=progress.status==='lesson_complete'?'earned':'current';
+ dashboard.querySelectorAll('[data-mlms-skill-node="phase-1"]').forEach(function(node){
+ node.classList.toggle('earned',nodeState==='earned');
+ node.classList.toggle('current',nodeState!=='earned');
+ });
+ var profile=document.querySelector('[data-mlms-profile-progress]');
+ if(profile){
+ setText(profile,'[data-mlms-profile-percent]',progress.percent+'%');
+ setText(profile,'[data-mlms-profile-phase]',progress.phase_label);
+ setText(profile,'[data-mlms-profile-leftoff]',progress.lesson_title);
+ setText(profile,'[data-mlms-profile-last-block]',progress.last_block);
+ setText(profile,'[data-mlms-profile-next-action]',progress.next_action);
+ setText(profile,'[data-mlms-profile-step]','Step '+progress.step+'/5');
+ setText(profile,'[data-mlms-profile-quiz]',quizLabel(progress));
+ setText(profile,'[data-mlms-profile-status]',statusLabel(progress.status));
+ setWidth(profile,'[data-mlms-profile-progress-fill]',progress.percent);
+ }
+ }
+ function persistProgress(patch){
+ progress=normalizeProgress(Object.assign({},progress,patch||{}, {updated_at:(new Date()).toISOString()}));
+ applyProgress(progress);
+ try{window.localStorage.setItem(storageKey,JSON.stringify(progress));}catch(error){}
+ if(!ajaxUrl || !progressNonce){return Promise.resolve(progress);}
+ var data=new FormData();
+ data.append('action','mlms_course_progress');
+ data.append('nonce',progressNonce);
+ ['phase','lesson','step','percent','status','phase_label','lesson_title','last_block','next_action','quiz_score','quiz_total','skill_points','updated_at'].forEach(function(key){data.append(key,progress[key]);});
+ data.append('quiz_completed',progress.quiz_completed?'1':'0');
+ return fetch(ajaxUrl,{method:'POST',credentials:'same-origin',body:data})
+ .then(function(resp){return resp.json();})
+ .then(function(json){
+ if(json && json.success && json.data && json.data.progress){
+ progress=normalizeProgress(json.data.progress);
+ applyProgress(progress);
+ try{window.localStorage.setItem(storageKey,JSON.stringify(progress));}catch(error){}
+ }
+ return progress;
+ })
+ .catch(function(){return progress;});
+ }
+
+ applyProgress(progress);
+ var courseRoute=dashboard.getAttribute('data-course-route')||'';
+ if(courseRoute==='lesson' && progress.status!=='quiz_completed' && progress.status!=='lesson_complete'){
+ persistProgress({status:'course_launched',percent:Math.max(progress.percent,45),last_block:'Lesson page opened',next_action:'Take quiz'});
+ }
+ if(courseRoute==='quiz' && !progress.quiz_completed && progress.status!=='lesson_complete'){
+ persistProgress({status:'in_progress',percent:Math.max(progress.percent,58),step:3,last_block:'Quiz page opened',next_action:'Submit quiz'});
+ }
+
+ document.querySelectorAll('[data-mlms-launch-course]').forEach(function(button){
+ button.addEventListener('click',function(event){
+ var href=button.getAttribute('href')||'';
+ var isHash=href.indexOf('#')===0;
+ var isButton=button.tagName.toLowerCase()==='button';
+ if(isHash || isButton){event.preventDefault();}
+ var workspace=dashboard.querySelector('[data-mlms-course-workspace]')||dashboard.querySelector('.mlms-lesson-grid')||dashboard;
+ if(workspace && workspace.classList){workspace.classList.add('launched');}
+ if(progress.status!=='quiz_completed' && progress.status!=='lesson_complete'){
+ persistProgress({status:'course_launched',percent:Math.max(progress.percent,45),last_block:isHash?'Course workspace opened':'Lesson page launched',next_action:'Continue lesson'});
+ }
+ if((isHash || isButton) && workspace && workspace.scrollIntoView){setTimeout(function(){workspace.scrollIntoView({behavior:'smooth',block:'start'});},40);}
+ });
+ });
+
+ dashboard.querySelectorAll('[data-mlms-open-quiz]').forEach(function(button){
+ button.addEventListener('click',function(event){
+ var href=button.getAttribute('href')||'';
+ var isHash=href.indexOf('#')===0;
+ if(isHash || button.tagName.toLowerCase()==='button'){event.preventDefault();}
+ var quizBlock=dashboard.querySelector('#mlms-quiz-block');
+ if(!progress.quiz_completed && progress.status!=='lesson_complete'){
+ persistProgress({status:'in_progress',percent:Math.max(progress.percent,58),step:3,last_block:isHash?'Quiz block opened':'Quiz page opened',next_action:'Submit quiz'});
+ }
+ if(isHash && quizBlock){quizBlock.scrollIntoView({behavior:'smooth',block:'start'});}
+ });
+ });
+
+ var quiz=dashboard.querySelector('[data-mlms-quiz]');
+ if(quiz){
+ var quizForm=quiz.querySelector('[data-mlms-quiz-form]');
+ var quizResult=quiz.querySelector('[data-mlms-quiz-result]');
+ var quizStatus=quiz.querySelector('[data-mlms-quiz-status]');
+ if(quizForm){
+ quizForm.addEventListener('submit',function(event){
+ event.preventDefault();
+ var questions=[].slice.call(quiz.querySelectorAll('[data-quiz-question]'));
+ var total=questions.length;
+ var score=0;
+ var unanswered=0;
+ questions.forEach(function(question){
+ question.classList.remove('is-correct','is-wrong');
+ var selected=question.querySelector('input[type="radio"]:checked');
+ if(!selected){unanswered++;return;}
+ var isCorrect=selected.getAttribute('data-correct')==='1';
+ if(isCorrect){score++;}
+ question.classList.add(isCorrect?'is-correct':'is-wrong');
+ });
+ if(unanswered){
+ if(quizResult){quizResult.className='mlms-quiz-result active error';quizResult.innerHTML='Almost there. Answer every question before WAX calculates your result.';}
+ if(quizStatus){quizStatus.textContent=unanswered+' question'+(unanswered===1?'':'s')+' still need an answer.';}
+ return;
+ }
+ var passed=score>=Math.ceil(total*0.75);
+ if(quizResult){
+ quizResult.className='mlms-quiz-result active '+(passed?'pass':'retry');
+ quizResult.innerHTML='Result: '+score+'/'+total+' correct. '+(passed?'You passed. The build task is unlocked; continue by submitting your role-specific workflow brief.':'Review the highlighted questions, then resubmit when you are ready. Aim for at least 75% before the build task.');
+ }
+ if(quizStatus){quizStatus.textContent=passed?'Quiz passed — build task unlocked.':'Quiz submitted — review and retry.';}
+ persistProgress({
+ status:'quiz_completed',
+ percent:passed?Math.max(progress.percent,72):Math.max(progress.percent,60),
+ step:passed?4:3,
+ last_block:passed?'Quiz passed — build task unlocked':'Quiz needs review',
+ next_action:passed?'Continue to build task':'Retake quiz',
+ quiz_score:score,
+ quiz_total:total,
+ quiz_completed:true
+ });
+ });
+ }
+ }
+
+ var buildForm=dashboard.querySelector('[data-mlms-build-form]');
+ if(buildForm){
+ buildForm.addEventListener('submit', function(event){
+ event.preventDefault();
+ var status=buildForm.querySelector('[data-mlms-build-status]');
+ var completion=dashboard.querySelector('[data-mlms-completion-card]');
+ var feedback=completion ? completion.querySelector('[data-mlms-validation-feedback]') : null;
+ var submit=buildForm.querySelector('button[type="submit"]');
+ var checks=[].slice.call(buildForm.querySelectorAll('input[type="checkbox"]'));
+ if(checks.length && !checks.every(function(input){return input.checked;})){
+ if(status){status.textContent='Complete each deliverable checklist item before submitting.';}
+ return;
+ }
+ if(status){status.textContent='AI validation is reviewing your build task…';}
+ if(submit){submit.disabled=true;}
+ var data=new FormData(buildForm);
+ data.append('action','mlms_ai_tutor');
+ data.append('mode','build_validation');
+ data.append('nonce',dashboard.getAttribute('data-tutor-nonce')||'');
+ data.append('lesson_context',dashboard.getAttribute('data-lesson-context')||'WAX lesson');
+ function markComplete(message){
+ if(feedback){feedback.textContent=message || 'Validated: your build task is clear enough to earn this lesson skill point.';}
+ if(completion){completion.classList.add('active');}
+ if(status){status.textContent='Skill point earned. Lesson completion confirmed.';}
+ persistProgress({status:'lesson_complete',percent:100,step:5,last_block:'Build task submitted and validated',next_action:'Continue to next lesson',skill_points:20});
+ }
+ mlmsPostTutor(data, dashboard.getAttribute('data-ajax-url')||'')
+ .then(function(payload){markComplete(payload.message);})
+ .catch(function(error){
+ markComplete('Offline validation fallback: your checklist is complete. Review the deliverable once more for clarity, assumptions, and next action.');
+ if(status && error && error.message){status.textContent=error.message;}
+ })
+ .finally(function(){if(submit){submit.disabled=false;}});
+ });
+ }
+ }
+
+ function initWaxTutor(){
+ var root=document.querySelector('[data-mlms-tutor-root]');
+ if(!root){return;}
+ var panel=root.querySelector('.mlms-tutor-panel');
+ var launcher=root.querySelector('.mlms-tutor-launcher');
+ var close=root.querySelector('.mlms-tutor-close');
+ var form=root.querySelector('[data-mlms-tutor-form]');
+ var messages=root.querySelector('.mlms-tutor-messages');
+ var textarea=root.querySelector('textarea[name="question"]');
+ var modeInput=root.querySelector('input[name="mode"]');
+ function openPanel(){ if(panel){panel.classList.add('open'); panel.setAttribute('aria-hidden','false');} if(textarea){setTimeout(function(){textarea.focus();},60);} }
+ function closePanel(){ if(panel){panel.classList.remove('open'); panel.setAttribute('aria-hidden','true');} }
+ if(launcher){launcher.addEventListener('click', openPanel);}
+ if(close){close.addEventListener('click', closePanel);}
+ root.querySelectorAll('[data-tutor-prompt]').forEach(function(chip){
+ chip.addEventListener('click', function(){
+ if(textarea){textarea.value=chip.getAttribute('data-tutor-prompt')||'';}
+ if(modeInput){modeInput.value=chip.getAttribute('data-tutor-mode')||'tutor';}
+ root.querySelectorAll('.mlms-tutor-chip').forEach(function(btn){btn.classList.toggle('active', btn===chip);});
+ openPanel();
+ });
+ });
+ if(form){
+ form.addEventListener('submit', function(event){
+ event.preventDefault();
+ var question=(textarea && textarea.value.trim()) || '';
+ var fileInput=form.querySelector('input[type="file"]');
+ if(!question && !(fileInput && fileInput.files && fileInput.files.length)){
+ if(textarea){textarea.focus();}
+ return;
+ }
+ mlmsAppendTutorMessage(messages, question || 'Uploaded a screenshot for roadblock help.', 'user');
+ var pending=mlmsAppendTutorMessage(messages, 'WAX Tutor is thinking…', 'bot');
+ var data=new FormData(form);
+ data.append('action','mlms_ai_tutor');
+ data.append('lesson_context',root.getAttribute('data-lesson-context')||'WAX course lesson');
+ mlmsPostTutor(data, root.getAttribute('data-ajax-url')||'')
+ .then(function(payload){
+ if(pending){pending.textContent=payload.message || 'I could not produce guidance. Try asking again with more detail.';}
+ if(textarea){textarea.value='';}
+ if(fileInput){fileInput.value='';}
+ })
+ .catch(function(error){
+ if(pending){pending.textContent=error.message || 'The tutor is temporarily unavailable. Paste the exact error text and try again.';}
+ });
+ });
+ }
+ }
+
+ function initAll(){
initWaxOnboarding();
+ initWaxCourseDashboard();
+ initWaxTutor();
+ }
+ if(document.readyState==='loading'){
+ document.addEventListener('DOMContentLoaded', initAll);
+ } else {
+ initAll();
}
})();
JS;
}
+
+function matthew_lms_mvp_profile_initials(string $name, string $email = ''): string {
+ $source = trim($name) !== '' ? $name : $email;
+ $parts = preg_split('/\s+/', trim($source));
+ if (!$parts || trim($source) === '') {
+ return 'WX';
+ }
+ $first = strtoupper(substr((string) $parts[0], 0, 1));
+ $last = count($parts) > 1 ? strtoupper(substr((string) end($parts), 0, 1)) : '';
+ return $first . ($last ?: '');
+}
+
+function matthew_lms_mvp_source_label(string $source_type, string $source_url): string {
+ if ($source_type === 'github' || str_contains($source_url, 'github.com')) {
+ return 'GitHub';
+ }
+ if ($source_type === 'reddit' || str_contains($source_url, 'reddit.com')) {
+ return 'Reddit';
+ }
+ if ($source_type === 'ai-platform') {
+ return 'AI platform';
+ }
+ if ($source_type === 'linkedin' || str_contains($source_url, 'linkedin.com')) {
+ return 'LinkedIn';
+ }
+ return 'External profile';
+}
+
+function matthew_lms_mvp_profile_context(): array {
+ $logged_in = is_user_logged_in();
+ $user = $logged_in ? wp_get_current_user() : null;
+ $user_id = ($logged_in && $user) ? (int) $user->ID : 0;
+ $email = $user ? (string) $user->user_email : '';
+ $display_name = $user ? trim((string) $user->display_name) : '';
+ if ($display_name === '' || $display_name === $email) {
+ $display_name = $email ? current(explode('@', $email)) : 'Alex Morgan';
+ }
+ $role = $user_id ? (string) get_user_meta($user_id, '_mlms_functional_role', true) : '';
+ $goal = $user_id ? (string) get_user_meta($user_id, '_mlms_learning_goal', true) : '';
+ $profile = $user_id ? (string) get_user_meta($user_id, '_mlms_ai_profile_bootstrap', true) : '';
+ $profile_link = $user_id ? (string) get_user_meta($user_id, '_mlms_profile_link', true) : '';
+ $source_type = $user_id ? (string) get_user_meta($user_id, '_mlms_external_source_type', true) : '';
+ $photo = $user_id ? (string) get_user_meta($user_id, '_mlms_google_picture', true) : '';
+ if (!$photo && $user_id) {
+ $photo = get_avatar_url($user_id, ['size' => 192]);
+ }
+ $role = $role ?: 'Marketing Director';
+ $goal = $goal ?: 'campaign automation, better briefs, and faster experimentation';
+ $bio = $profile ? wp_trim_words(wp_strip_all_tags($profile), 34, '…') : 'AI-native growth operator building practical workflows with WAX. Focus: ' . $goal . '.';
+ return [
+ 'logged_in' => $logged_in,
+ 'name' => $display_name,
+ 'email' => $email ?: 'preview@wax.example',
+ 'role' => $role,
+ 'goal' => $goal,
+ 'bio' => $bio,
+ 'photo' => $photo,
+ 'initials' => matthew_lms_mvp_profile_initials($display_name, $email),
+ 'profile_link' => $profile_link,
+ 'source_type' => $source_type ?: 'profile',
+ 'source_label' => $profile_link ? matthew_lms_mvp_source_label($source_type ?: 'profile', $profile_link) : 'Manual connection',
+ 'course_progress' => matthew_lms_mvp_get_course_progress($user_id),
+ ];
+}
+
+function matthew_lms_mvp_course_progress_defaults(): array {
+ return [
+ 'phase' => 1,
+ 'lesson' => 2,
+ 'step' => 2,
+ 'percent' => 42,
+ 'status' => 'in_progress',
+ 'phase_label' => 'Phase 1 · AI Workflow Fluency',
+ 'lesson_title' => 'Build a practical AI workflow brief',
+ 'last_block' => 'Lesson view: role-specific workflow example',
+ 'next_action' => 'Continue lesson',
+ 'quiz_score' => 0,
+ 'quiz_total' => 4,
+ 'quiz_completed' => false,
+ 'skill_points' => 0,
+ 'updated_at' => '',
+ ];
+}
+
+function matthew_lms_mvp_normalize_course_progress(array $raw = []): array {
+ $defaults = matthew_lms_mvp_course_progress_defaults();
+ $progress = array_merge($defaults, array_intersect_key($raw, $defaults));
+ $progress['phase'] = max(1, min(3, absint($progress['phase'])));
+ $progress['lesson'] = max(1, min(5, absint($progress['lesson'])));
+ $progress['step'] = max(1, min(5, absint($progress['step'])));
+ $progress['percent'] = max(0, min(100, absint($progress['percent'])));
+ $progress['quiz_score'] = max(0, min(10, absint($progress['quiz_score'])));
+ $progress['quiz_total'] = max(1, min(10, absint($progress['quiz_total'])));
+ $progress['skill_points'] = max(0, min(999, absint($progress['skill_points'])));
+ $allowed_statuses = ['not_started', 'in_progress', 'course_launched', 'quiz_completed', 'lesson_complete'];
+ $progress['status'] = sanitize_key((string) $progress['status']);
+ if (!in_array($progress['status'], $allowed_statuses, true)) {
+ $progress['status'] = $defaults['status'];
+ }
+ foreach (['phase_label', 'lesson_title', 'last_block', 'next_action', 'updated_at'] as $key) {
+ $progress[$key] = sanitize_text_field((string) $progress[$key]);
+ }
+ $progress['quiz_completed'] = filter_var($progress['quiz_completed'], FILTER_VALIDATE_BOOLEAN);
+ return $progress;
+}
+
+function matthew_lms_mvp_get_course_progress(int $user_id = 0): array {
+ if ($user_id <= 0 || !is_user_logged_in()) {
+ return matthew_lms_mvp_course_progress_defaults();
+ }
+ $stored = get_user_meta($user_id, '_mlms_course_progress', true);
+ return matthew_lms_mvp_normalize_course_progress(is_array($stored) ? $stored : []);
+}
+
+function matthew_lms_mvp_handle_course_progress_ajax(): void {
+ if (!check_ajax_referer('mlms_course_progress', 'nonce', false)) {
+ wp_send_json_error(['message' => 'Your course session expired. Refresh the page and continue again.'], 403);
+ }
+ $raw = [];
+ foreach (array_keys(matthew_lms_mvp_course_progress_defaults()) as $key) {
+ if (isset($_POST[$key])) {
+ $raw[$key] = wp_unslash($_POST[$key]);
+ }
+ }
+ $progress = matthew_lms_mvp_normalize_course_progress($raw);
+ $progress['updated_at'] = current_time('mysql');
+ $saved = false;
+ if (is_user_logged_in()) {
+ update_user_meta(get_current_user_id(), '_mlms_course_progress', $progress);
+ $saved = true;
+ }
+ wp_send_json_success(['saved' => $saved, 'progress' => $progress]);
+}
+
+function matthew_lms_mvp_profile_notice(): string {
+ $notice = sanitize_text_field(wp_unslash($_GET['mlms_profile_notice'] ?? ''));
+ if ($notice === 'connected') {
+ return 'External source connected. Your profile link is now shown in the skills feed.
';
+ }
+ if ($notice === 'invalid') {
+ return 'Connection failed. Enter a valid public URL for GitHub, Reddit, LinkedIn, or another AI platform.
';
+ }
+ if ($notice === 'expired') {
+ return 'Session expired. Refresh the profile page and try connecting the source again.
';
+ }
+ return '';
+}
+
+
+function matthew_lms_mvp_role_lesson_context(string $role): array {
+ $normalized = strtolower($role);
+ if (str_contains($normalized, 'product') || $normalized === 'pm') {
+ return [
+ 'role_label' => 'Product Manager',
+ 'workflow' => 'turn roadmap notes and customer signals into a product-ready feature brief',
+ 'artifact' => 'AI-assisted feature brief',
+ 'example' => 'Convert a backlog idea into a one-page PRD with user problem, acceptance criteria, risks, and a human review checklist.',
+ 'source' => 'roadmap notes, support tickets, and customer interview snippets',
+ 'handoff' => 'a Jira-ready brief your design and engineering partners can critique',
+ ];
+ }
+ if (str_contains($normalized, 'sales')) {
+ return [
+ 'role_label' => 'Sales',
+ 'workflow' => 'turn account research into a targeted outreach and follow-up workflow',
+ 'artifact' => 'AI-assisted account plan',
+ 'example' => 'Build a sequence that summarizes the buyer context, drafts the first email, and flags what a human should personalize.',
+ 'source' => 'CRM notes, call summaries, and public account signals',
+ 'handoff' => 'a reviewed account plan and next-best-action list',
+ ];
+ }
+ if (str_contains($normalized, 'operation') || str_contains($normalized, 'ops')) {
+ return [
+ 'role_label' => 'Operations',
+ 'workflow' => 'turn recurring process notes into a repeatable operating workflow',
+ 'artifact' => 'AI-assisted SOP and status update',
+ 'example' => 'Create a weekly ops agent that drafts updates, highlights blockers, and lists what needs human approval.',
+ 'source' => 'SOP notes, Slack updates, and recurring checklist items',
+ 'handoff' => 'a reviewed SOP plus escalation checklist',
+ ];
+ }
+ if (str_contains($normalized, 'executive') || str_contains($normalized, 'founder') || str_contains($normalized, 'leader')) {
+ return [
+ 'role_label' => 'Executive',
+ 'workflow' => 'turn scattered strategic inputs into a decision-ready leadership brief',
+ 'artifact' => 'AI-assisted decision memo',
+ 'example' => 'Summarize options, assumptions, risks, and recommended decision criteria before a leadership meeting.',
+ 'source' => 'meeting notes, metrics, and strategy docs',
+ 'handoff' => 'a decision memo with assumptions marked for executive review',
+ ];
+ }
+ if (str_contains($normalized, 'marketing') || str_contains($normalized, 'growth')) {
+ return [
+ 'role_label' => 'Marketing',
+ 'workflow' => 'turn campaign notes into a launch-ready creative brief and review loop',
+ 'artifact' => 'AI-assisted campaign brief',
+ 'example' => 'Transform messy campaign inputs into audience, message, channel plan, draft assets, and a brand-safety review checklist.',
+ 'source' => 'campaign notes, audience research, and positioning docs',
+ 'handoff' => 'a reviewed campaign brief your team can execute',
+ ];
+ }
+ return [
+ 'role_label' => $role ?: 'Operator',
+ 'workflow' => 'turn one weekly work process into a repeatable AI-assisted workflow',
+ 'artifact' => 'AI-assisted workflow brief',
+ 'example' => 'Choose a recurring task, define the input, draft the AI prompt, and add a human review step before sharing output.',
+ 'source' => 'notes, examples, and recurring work inputs',
+ 'handoff' => 'a reviewed workflow brief with a clear next action',
+ ];
+}
+
+function matthew_lms_mvp_course_status_labels(): array {
+ return [
+ 'not_started' => 'Not started',
+ 'in_progress' => 'In progress',
+ 'course_launched' => 'Course launched',
+ 'quiz_completed' => 'Quiz complete',
+ 'lesson_complete' => 'Lesson complete',
+ ];
+}
+
+function matthew_lms_mvp_course_url(string $view = ''): string {
+ $view = sanitize_key($view);
+ if ($view === 'course' || $view === 'dashboard') {
+ return matthew_lms_mvp_public_url('platform/course/');
+ }
+ if ($view === 'lesson' || $view === 'quiz') {
+ return matthew_lms_mvp_public_url('platform/' . $view . '/');
+ }
+ return matthew_lms_mvp_public_url('platform/');
+}
+
+function matthew_lms_mvp_course_continue_url(array $progress): string {
+ $progress = matthew_lms_mvp_normalize_course_progress($progress);
+ $course_url = matthew_lms_mvp_course_url('course');
+ if ($progress['status'] === 'lesson_complete') {
+ return $course_url . '#mlms-lesson-completion';
+ }
+ if ($progress['status'] === 'quiz_completed' || $progress['step'] >= 4) {
+ return $course_url . '#mlms-build-task';
+ }
+ if ($progress['step'] >= 3 || stripos($progress['last_block'], 'quiz') !== false) {
+ return matthew_lms_mvp_course_url('quiz');
+ }
+ return $course_url . '#mlms-lesson-view';
+}
+
+function matthew_lms_mvp_course_runtime(array $profile): array {
+ $context = matthew_lms_mvp_role_lesson_context((string) ($profile['role'] ?? ''));
+ $lesson_context = sprintf(
+ 'WAX Phase 1 lesson: AI Workflow Fluency for %s. Goal: %s. Build task artifact: %s.',
+ $context['role_label'],
+ (string) ($profile['goal'] ?? 'practical AI workflow fluency'),
+ $context['artifact']
+ );
+ $progress = matthew_lms_mvp_normalize_course_progress(is_array($profile['course_progress'] ?? null) ? $profile['course_progress'] : []);
+ return [
+ 'context' => $context,
+ 'ajax_url' => admin_url('admin-ajax.php'),
+ 'tutor_nonce' => wp_create_nonce('mlms_ai_tutor'),
+ 'progress_nonce' => wp_create_nonce('mlms_course_progress'),
+ 'lesson_context' => $lesson_context,
+ 'progress' => $progress,
+ 'progress_json' => wp_json_encode($progress),
+ 'progress_status' => matthew_lms_mvp_course_status_labels()[$progress['status']] ?? 'In progress',
+ ];
+}
+
+function matthew_lms_mvp_course_dashboard_attrs(array $runtime, string $route = ''): string {
+ $attrs = [
+ 'id' => 'course-dashboard',
+ 'class' => 'mlms-course-dashboard' . ($route ? ' mlms-course-standalone' : ''),
+ 'data-mlms-course-dashboard' => '',
+ 'data-course-route' => $route,
+ 'data-ajax-url' => $runtime['ajax_url'],
+ 'data-tutor-nonce' => $runtime['tutor_nonce'],
+ 'data-progress-nonce' => $runtime['progress_nonce'],
+ 'data-initial-progress' => $runtime['progress_json'] ?: '{}',
+ 'data-lesson-context' => $runtime['lesson_context'],
+ ];
+ $out = [];
+ foreach ($attrs as $key => $value) {
+ if ($value === '') {
+ $out[] = esc_attr($key);
+ } else {
+ $out[] = esc_attr($key) . '="' . esc_attr((string) $value) . '"';
+ }
+ }
+ return implode(' ', $out);
+}
+
+function matthew_lms_mvp_maybe_render_course_route(): void {
+ $path = trim((string) wp_parse_url(wp_unslash($_SERVER['REQUEST_URI'] ?? ''), PHP_URL_PATH), '/');
+ if (!in_array($path, ['platform/course', 'platform/lesson', 'platform/quiz'], true)) {
+ return;
+ }
+ $view = 'course';
+ if (str_ends_with($path, '/quiz')) {
+ $view = 'quiz';
+ } elseif (str_ends_with($path, '/lesson')) {
+ $view = 'lesson';
+ }
+ status_header(200);
+ global $wp_query;
+ if ($wp_query) {
+ $wp_query->is_404 = false;
+ }
+ echo matthew_lms_mvp_render_course_route_page($view);
+ exit;
+}
+
+function matthew_lms_mvp_render_course_route_page(string $view): string {
+ $profile = matthew_lms_mvp_profile_context();
+ $runtime = matthew_lms_mvp_course_runtime($profile);
+ $context = $runtime['context'];
+ $progress = $runtime['progress'];
+ $is_quiz = $view === 'quiz';
+ $is_lesson = $view === 'lesson';
+ $title = 'WAX Course Dashboard · AI Workflow Fluency';
+ if ($is_quiz) {
+ $title = 'WAX Quiz · AI Workflow Fluency';
+ } elseif ($is_lesson) {
+ $title = 'WAX Lesson · AI Workflow Fluency';
+ }
+ ob_start();
+ ?>
+>
+
+
+
+
+
+
+>
+
+
+
+
+
+
+
+
>
+
+ ← Back to course dashboard
+ · %
+
+ Quiz: AI Workflow Fluency
+ Complete the quiz on its own page. Your score is saved to your profile and unlocks the build task when you pass.
+
+
+ Lesson: build a practical AI workflow brief.
+ Read the lesson on a focused page, use the tutor if you get stuck, then move to the quiz page when you’re ready.
+
+
+
+
+
+
+
+
+
+
Lesson page
Focused lesson and build task The quiz opens on a separate page, so this page stays focused on reading, examples, and the final deliverable.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+
+
+
+
Course overview
+
Course Dashboard: AI Workflow Fluency
+
This page is now dedicated to the course experience: overview, lesson view, task/build section, and lesson completion. Your profile lives separately on the profile page.
+
+
+
%
+
+
+
Where you left off
+
+
+
+
+
+ 1 Current
+ Course Overview
+ Phase 1 builds the practical AI workflow pattern: source inputs, prompt structure, review rubric, and human handoff.
+ Lesson 2 of 5 Step of 5 +20 skill points
+
+
+
+ 2 Next
+ Role-Specific Automation
+ Unlocks after Phase 1 — adaptive examples for workflows.
+ Upcoming phase track
+
+
+ 3 Later
+ Portfolio Certification
+ Final build, source proof, review, and AI Expert credential.
+ Capstone Credential review
+
+
+
+
+
+
+
+
Lesson view
+
Lesson View
+
Read the course lesson inside the course dashboard. If you prefer focus mode, open the lesson-only page.
+
+
+
+
+
+
+
+
+
+
+
Task / build section
+
Task / Build Section
+
Complete the practical deliverable after reading the lesson and passing the quiz.
+
+
+
+
+
+
+
+
+
+
Lesson completion
+
Lesson Completion
+
Completion is confirmed when the build task is submitted and validated. Your profile progress, skill node, and portfolio readiness update automatically.
+
+
+
+
+
+ Progress %
+ Saved course state
+
+
+
+ Skill points /20
+ Phase 1 skill node
+ Submitting and validating the build task marks the lesson complete and lights the Phase 1 node.
+
+
+ Next action
+ Return to profile
+ See your profile header, five-node skill indicator, progress, portfolio, and external skills feed.
+ View profile →
+
+
+
+
+
+
+
+
+
+
+
Lesson view
+
Build a practical AI workflow brief for work.
+
+
+
+ Learn the concept, see a role-specific example, then move to the separate quiz page before the build task.
+
+
+
Input
+
Prompt Ask AI for structure, assumptions, and first draft.
+
Review Score accuracy, tone, risks, and missing context.
+
Handoff
+
+
+
Weak workflow One prompt, no review rubric, unclear owner.
+
WAX workflow Prompt + example + review checklist + clear deliverable.
+
+
+
Next checkpoint: quiz page
+
The quiz now opens on its own page with several questions and a final result.
+
+
+
+
+
+
+
Key skills in this lesson
+
+ Write a role-aware prompt with source context.
+ Evaluate AI output before sharing it.
+ Turn the result into a practical deliverable.
+
+
+
+
In-course AI Tutor
+
Available without covering lesson content
+
Use the chat bubble for glossary help, screenshots of errors, or a quick explanation while staying in the lesson.
+
+
+
+
+
+
+
+
Quiz page
+
Check your understanding before the build task.
+
Answer all questions, submit once, then review your result. Passing the quiz updates your profile progress and unlocks the next action.
+
+
4 questions · 75% pass
+
+
+
+
+
+
+
+
Task / build section
+
Finish the lesson with a deliverable.
+
Submit a concise . AI validation gives feedback, confirms completion, and lights up the Phase 1 skill node when earned.
+
+
+
+
+20 skill points · Phase 1 node lit
+
Lesson completion confirmed.
+
AI validation feedback will appear here after submission.
+
+
+
+
+
AI Ask Tutor
+
+ WAX AI Tutor Glossary help, roadblock screenshots, and step-by-step guidance.
×
+ I’m here beside the lesson. Ask “What is CLI?”, request a concise explanation, or upload an error screenshot with Fix My Error.
+
+
+
+
+ What is CLI?
+ Explain API
+ Fix My Error
+
+
+ Roadblock screenshot/image (optional, PNG/JPG/WebP/GIF under 4 MB)
+ Send to tutor →
+ The tutor gives guidance and explanations, not finished deliverables.
+
+
+
+ 'Tutor session expired. Refresh the lesson and try again.'], 403);
+ }
+ $mode = sanitize_key(wp_unslash($_POST['mode'] ?? 'tutor'));
+ if (!in_array($mode, ['tutor', 'glossary', 'roadblock', 'build_validation'], true)) {
+ $mode = 'tutor';
+ }
+ $question = sanitize_textarea_field(wp_unslash($_POST['question'] ?? ''));
+ $lesson_context = sanitize_textarea_field(wp_unslash($_POST['lesson_context'] ?? 'WAX course lesson'));
+ $deliverable = sanitize_textarea_field(wp_unslash($_POST['deliverable_notes'] ?? ''));
+ if ($mode === 'build_validation') {
+ $checklist = isset($_POST['deliverable_checklist']) && is_array($_POST['deliverable_checklist'])
+ ? array_map('sanitize_text_field', wp_unslash($_POST['deliverable_checklist']))
+ : [];
+ $question = trim($question . "\n\nDeliverable summary:\n" . $deliverable . "\n\nChecklist completed: " . implode(', ', $checklist));
+ }
+ $image = matthew_lms_mvp_prepare_tutor_image('roadblock_image');
+ if (!empty($image['error'])) {
+ wp_send_json_error(['message' => $image['error']], 400);
+ }
+ if (trim($question) === '' && empty($image)) {
+ wp_send_json_error(['message' => 'Ask a question or upload a screenshot first.'], 400);
+ }
+ $message = matthew_lms_mvp_generate_ai_tutor_response($mode, $question, $lesson_context, $image);
+ wp_send_json_success(['message' => $message]);
+}
+
+function matthew_lms_mvp_prepare_tutor_image(string $field): array {
+ if (empty($_FILES[$field]) || !is_array($_FILES[$field])) {
+ return [];
+ }
+ $file = $_FILES[$field];
+ $error = (int) ($file['error'] ?? UPLOAD_ERR_NO_FILE);
+ if ($error === UPLOAD_ERR_NO_FILE) {
+ return [];
+ }
+ if ($error !== UPLOAD_ERR_OK) {
+ return ['error' => 'The screenshot upload failed. Try a smaller PNG or JPG.'];
+ }
+ $size = (int) ($file['size'] ?? 0);
+ if ($size <= 0 || $size > 4 * 1024 * 1024) {
+ return ['error' => 'Upload an image under 4 MB so the tutor can review it.'];
+ }
+ $tmp = (string) ($file['tmp_name'] ?? '');
+ if ($tmp === '' || !is_uploaded_file($tmp)) {
+ return ['error' => 'The uploaded image could not be read.'];
+ }
+ $info = @getimagesize($tmp);
+ $mime = is_array($info) ? (string) ($info['mime'] ?? '') : '';
+ $allowed = ['image/png', 'image/jpeg', 'image/webp', 'image/gif'];
+ if (!in_array($mime, $allowed, true)) {
+ return ['error' => 'Upload a PNG, JPG, WebP, or GIF screenshot.'];
+ }
+ $bytes = file_get_contents($tmp);
+ if ($bytes === false) {
+ return ['error' => 'The uploaded image could not be processed.'];
+ }
+ return [
+ 'name' => sanitize_file_name((string) ($file['name'] ?? 'screenshot')),
+ 'mime' => $mime,
+ 'size' => $size,
+ 'data_url' => 'data:' . $mime . ';base64,' . base64_encode($bytes),
+ ];
+}
+
+function matthew_lms_mvp_generate_ai_tutor_response(string $mode, string $question, string $lesson_context, array $image = []): string {
+ $fallback = matthew_lms_mvp_tutor_fallback($mode, $question, !empty($image));
+ $api = dirname(__DIR__, 3) . '/ai/LocalAIApi.php';
+ if (!file_exists($api)) {
+ return $fallback;
+ }
+ require_once $api;
+ if (!class_exists('LocalAIApi')) {
+ return $fallback;
+ }
+ $mode_instruction = match ($mode) {
+ 'glossary' => 'Explain the term quickly, in plain language, with one example connected to the lesson. Keep it concise.',
+ 'roadblock' => 'Act as Fix My Error. If an image is present, inspect it for error text or UI clues. Return step-by-step troubleshooting guidance distinct from general tutoring.',
+ 'build_validation' => 'Validate the submitted build task. Return a tasteful completion confirmation, two specific strengths, one improvement, and whether the skill point is earned.',
+ default => 'Answer as a non-intrusive in-course tutor. Coach the learner through the concept without doing the whole deliverable for them.',
+ };
+ $prompt = "Lesson context:\n{$lesson_context}\n\nTutor mode: {$mode}\nInstruction: {$mode_instruction}\n\nLearner message:\n{$question}\n\nUse calm, premium language. Prefer 3-5 numbered steps or bullets. If information is missing, ask for the exact detail needed. Keep under 180 words.";
+ $system = 'You are WAX AI Tutor, an in-course assistant for non-technical professionals learning AI-powered work. Be practical, clear, encouraging, and role-specific. Do not cover the entire course content, do not complete assignments for the learner, and avoid fluff.';
+
+ $user_content = $prompt;
+ if (!empty($image['data_url'])) {
+ $user_content = [
+ ['type' => 'input_text', 'text' => $prompt . "\n\nScreenshot attached: " . ($image['name'] ?? 'roadblock image') . '.'],
+ ['type' => 'input_image', 'image_url' => $image['data_url']],
+ ];
+ }
+
+ $resp = LocalAIApi::createResponse([
+ 'input' => [
+ ['role' => 'system', 'content' => $system],
+ ['role' => 'user', 'content' => $user_content],
+ ],
+ ], ['poll_interval' => 2, 'poll_timeout' => 25, 'timeout' => 20]);
+ if (!empty($resp['success'])) {
+ $text = LocalAIApi::extractText($resp);
+ if (is_string($text) && trim($text) !== '') {
+ return trim($text);
+ }
+ }
+
+ if (!empty($image['data_url'])) {
+ $retry_prompt = $prompt . "\n\nThe learner uploaded an image named " . ($image['name'] ?? 'screenshot') . ", but if image inspection is unavailable, provide a careful screenshot-troubleshooting checklist and ask them to paste the exact error text.";
+ $retry = LocalAIApi::createResponse([
+ 'input' => [
+ ['role' => 'system', 'content' => $system],
+ ['role' => 'user', 'content' => $retry_prompt],
+ ],
+ ], ['poll_interval' => 2, 'poll_timeout' => 20, 'timeout' => 18]);
+ if (!empty($retry['success'])) {
+ $text = LocalAIApi::extractText($retry);
+ if (is_string($text) && trim($text) !== '') {
+ return trim($text);
+ }
+ }
+ }
+ return $fallback;
+}
+
+function matthew_lms_mvp_tutor_fallback(string $mode, string $question, bool $has_image = false): string {
+ if ($mode === 'build_validation') {
+ return "AI validation fallback:\n1. Your build can earn the skill point if it names the source inputs, includes the prompt/review rubric, and defines the handoff owner.\n2. Strength: you completed the required checklist.\n3. Improve: make the final next action explicit.\nSkill point: earned when the deliverable is specific enough for another person to review.";
+ }
+ if ($mode === 'roadblock' || $has_image) {
+ return "Fix My Error fallback:\n1. Copy the exact error text from the screenshot.\n2. Identify what changed right before the error appeared.\n3. Retry the smallest step in the lesson and compare it to the expected output.\n4. If it still fails, send the error text plus the tool you are using so I can narrow the fix.";
+ }
+ if ($mode === 'glossary' || stripos($question, 'what is') !== false || stripos($question, 'explain') !== false) {
+ return "Glossary explainer:\nIn this lesson, the term means a practical building block you use to move work from input → AI draft → human review → final handoff. If you tell me the exact acronym or word, I can give a one-sentence definition and a role-specific example.";
+ }
+ return "Tutor guidance:\n1. Restate the task in one sentence.\n2. List the inputs you have.\n3. Ask AI for a structured first draft.\n4. Review assumptions, accuracy, and handoff owner before using the output.\nIf you share where you are stuck, I’ll give the next concrete step.";
+}
+
+add_shortcode('matthew_user_profile', function () {
+ $profile = matthew_lms_mvp_profile_context();
+ $connected = !empty($profile['profile_link']);
+ $course_progress = matthew_lms_mvp_normalize_course_progress(is_array($profile['course_progress'] ?? null) ? $profile['course_progress'] : []);
+ $course_status_labels = [
+ 'not_started' => 'Not started',
+ 'in_progress' => 'In progress',
+ 'course_launched' => 'Course launched',
+ 'quiz_completed' => 'Quiz complete',
+ 'lesson_complete' => 'Lesson complete',
+ ];
+ $course_status = $course_status_labels[$course_progress['status']] ?? 'In progress';
+ $quiz_label = !empty($course_progress['quiz_completed']) ? ($course_progress['quiz_score'] . '/' . $course_progress['quiz_total']) : 'Not taken';
+ $course_continue_url = matthew_lms_mvp_course_continue_url($course_progress);
+ ob_start();
+ ?>
+
+
+
+
+
Profile
+
Your WAX profile and skill proof.
+
This page is now profile-only: profile header, five-node skill indicator, course progress, portfolio artifacts, and external skills feed.
+
+
+ Profile layer
+ Course dashboard separated
+
+
+
+
Profile header
Credential evidence and course progress in one profile view. Use the course progress card to jump into the separate course dashboard.
Profile Header · Skills · Progress
+
+
+
+
+
+
+
WAX AI Credential
+
+
+ · AI-native operator
+
+
+ Credential status
+ Current phase
+ External source
+
+
+
+
+
+
+
+
Skill indicator Five circular nodes light up as skills are earned: three WAX course nodes plus two external achievement nodes.
+
5 nodes
+
+
+
1
Workflow fluency Course earned
+
2
Role automation In progress
+
+
+
RD
Community proof Reddit / community
+
+
+
+
+
+
Course progress Your profile now shows exactly where you left off so you can continue without hunting for the lesson.
+
+
+
+
+
+
% Course progress
+
Step /5 Current step
+
Quiz result
+
+
+
1 AI Workflow Fluency Current — lesson 2 progress, quiz result, and build task are saved here.
+
2 Role-Specific Automation Unlocks after Phase 1 — adaptive examples for workflows.
Locked
+
3 Portfolio Certification Unlocks after phase 2 — final build, review, and AI Expert certification.
Locked
+
+
+
+
+
+
+
+
+
+
Portfolio section
Built artifacts A GitHub-contributions-meets-Behance showcase for projects/products built with AI tools.
+
Showcase-ready
+
+
+
AI Brief Builder Turns messy campaign notes into structured briefs, acceptance criteria, and review prompts.
ChatGPT Sheets Notion
Attach proof →
+
Persona Synthesizer Combines research snippets into reusable buyer personas with documented assumptions.
Claude Docs Perplexity
Attach proof →
+
Weekly Ops Agent Automates recurring updates, flags blockers, and drafts stakeholder-ready summaries.
Zapier Gemini Slack
Attach proof →
+
+
+
+
+
+
+
+
External skills feed
Aggregated proof sources Show source icons, automation status, and a manual connection path when accounts are not auto-detected.
+
GitHub · Reddit · AI platforms
+
+
+
+
GH GitHub repositories and commits
+
RD Reddit AI communities Community participation, helpful answers, and learning evidence.
Ready
+
AI Other AI platforms Artifacts from AI builders, marketplaces, notebooks, or portfolios.
Ready
+
+
+ Connect an external source manually
+ Paste a public GitHub, Reddit, LinkedIn, or AI-platform URL. WAX will show it as a source in the credential feed.
+
+ Source type GitHub Reddit AI platform LinkedIn Other profile
+ Public profile or artifact URL
+
+ Connect source →
+
+ Sign up to connect sources →
+
+
+
+
+
+
+
You’re already signed in. Continue as user_email ?: $current_user->display_name); ?>.
-
+
Log in to WAX.
Use Google for one-click access, or log in with your email/username and password.
diff --git a/wp-content/uploads/mlms-course-progress-quiz-verification.png b/wp-content/uploads/mlms-course-progress-quiz-verification.png
new file mode 100644
index 0000000..0897a8d
Binary files /dev/null and b/wp-content/uploads/mlms-course-progress-quiz-verification.png differ