Skip to main content

TEST 2

<!DOCTYPE html>

<html lang="en">

<head>

 <meta charset="UTF-8" />

 <meta name="viewport" content="width=device-width, initial-scale=1.0" />

 <title>Build Your Path</title>

 <style>

   :root {

     --bg: #f5f7f9;

     --panel: #ffffff;

     --text: #1f2a37;

     --muted: #5f6b7a;

     --line: #dbe3ea;

     --brand: #156082;

     --brand-soft: #e8f3f7;

     --accent: #5cacd7;

     --success: #1f8a5b;

     --warn: #fff4db;

     --shadow: 0 12px 30px rgba(21, 96, 130, 0.08);

     --radius: 22px;

    }

 

    * { box-sizing: border-box; }

   body {

     margin: 0;

     font-family: Inter, Arial, Helvetica, sans-serif;

     background: linear-gradient(180deg, #f7f9fb 0%, #eef3f6 100%);

     color: var(--text);

     line-height: 1.45;

    }

 

   .wrap {

     max-width: 1280px;

     margin: 0 auto;

     padding: 32px 20px 56px;

    }

 

   .hero {

     background: rgba(255,255,255,0.7);

     backdrop-filter: blur(10px);

     border: 1px solid rgba(255,255,255,0.7);

     border-radius: 30px;

     padding: 28px 28px 18px;

     box-shadow: var(--shadow);

     margin-bottom: 22px;

    }

 

   .eyebrow {

     display: inline-flex;

     align-items: center;

     gap: 8px;

     padding: 8px 12px;

     border-radius: 999px;

     background: var(--brand-soft);

     color: var(--brand);

     font-size: 13px;

     font-weight: 700;

     letter-spacing: 0.02em;

     margin-bottom: 12px;

    }

 

   h1 {

     font-size: clamp(2rem, 4vw, 3rem);

     line-height: 1.05;

     margin: 0 0 10px;

     letter-spacing: -0.03em;

    }

 

   .subtitle {

     max-width: 880px;

     color: var(--muted);

     font-size: 1rem;

     margin: 0;

    }

 

   .layout {

     display: grid;

     grid-template-columns: 360px 1fr;

     gap: 22px;

     align-items: start;

    }

 

   .panel {

     background: var(--panel);

     border: 1px solid var(--line);

     border-radius: var(--radius);

     box-shadow: var(--shadow);

    }

 

   .controls {

     padding: 22px;

     position: sticky;

     top: 20px;

    }

 

   .control-block + .control-block { margin-top: 18px; }

   .control-label {

     display: block;

     font-size: 0.95rem;

     font-weight: 700;

     margin-bottom: 8px;

    }

 

    select {

     width: 100%;

     padding: 14px 16px;

     border-radius: 14px;

     border: 1px solid var(--line);

     background: #fff;

     color: var(--text);

     font-size: 0.98rem;

    }

 

   .note {

     margin-top: 18px;

     padding: 14px 14px;

     border-radius: 16px;

     background: var(--warn);

     color: #6a5220;

     font-size: 0.93rem;

    }

 

   .btn-row {

     display: flex;

     gap: 10px;

     margin-top: 18px;

     flex-wrap: wrap;

    }

 

   button {

     border: 0;

     border-radius: 999px;

     padding: 12px 18px;

     font-weight: 700;

     cursor: pointer;

     transition: transform 0.15s ease, opacity 0.15s ease;

    }

 

   button:hover { transform: translateY(-1px); }

   .btn-primary {

      background: linear-gradient(135deg, var(--brand), var(--accent));

     color: white;

    }

   .btn-secondary {

     background: #eef3f6;

     color: var(--text);

    }

 

   .results {

     padding: 22px;

    }

 

   .summary-card {

     border: 1px solid var(--line);

     border-radius: 18px;

     padding: 18px;

     background: linear-gradient(180deg, #fff 0%, #fbfdff 100%);

     margin-bottom: 18px;

    }

 

   .chips {

     display: flex;

     gap: 8px;

     flex-wrap: wrap;

     margin-bottom: 12px;

    }

 

   .chip {

     display: inline-flex;

     align-items: center;

     border-radius: 999px;

     padding: 7px 12px;

     font-size: 0.84rem;

     font-weight: 700;

    }

 

   .chip.mode { background: #edf7ff; color: #0f5e7e; }

   .chip.award { background: #edf8f1; color: #156c48; }

   .chip.entry { background: #f3efff; color: #5d4ca7; }

 

   .summary-grid {

     display: grid;

     grid-template-columns: repeat(4, minmax(0, 1fr));

     gap: 12px;

     margin-top: 12px;

    }

 

   .metric {

     border: 1px solid var(--line);

     border-radius: 16px;

     padding: 14px;

     background: #fff;

    }

 

   .metric-label {

     font-size: 0.8rem;

     color: var(--muted);

     margin-bottom: 6px;

    }

 

   .metric-value {

     font-size: 1.08rem;

     font-weight: 800;

    }

 

   .path-title {

     display: flex;

     justify-content: space-between;

     gap: 16px;

     align-items: flex-end;

     margin: 10px 0 16px;

     flex-wrap: wrap;

    }

 

   .path-title h2 {

     margin: 0;

     font-size: 1.4rem;

     letter-spacing: -0.02em;

    }

 

   .path-sub {

     color: var(--muted);

     font-size: 0.95rem;

    }

 

   .timeline {

     display: grid;

     gap: 16px;

    }

 

   .term {

     position: relative;

     display: grid;

     grid-template-columns: 190px 1fr;

     gap: 16px;

     padding: 18px;

     border: 1px solid var(--line);

     border-radius: 20px;

     background: #fff;

     overflow: hidden;

    }

 

   .term::before {

     content: "";

     position: absolute;

     left: 0;

     top: 0;

     bottom: 0;

     width: 6px;

     background: linear-gradient(180deg, var(--brand), var(--accent));

    }

 

   .term-meta {

     padding-left: 8px;

    }

 

   .term-kicker {

     color: var(--brand);

     font-size: 0.82rem;

     font-weight: 800;

     text-transform: uppercase;

     letter-spacing: 0.05em;

     margin-bottom: 6px;

    }

 

   .term-name {

     font-size: 1.25rem;

     font-weight: 800;

     margin-bottom: 6px;

    }

 

   .term-desc {

     font-size: 0.93rem;

     color: var(--muted);

    }

 

   .course-grid {

     display: grid;

     grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));

     gap: 12px;

     align-content: start;

    }

 

   .course-card {

     border-radius: 18px;

     padding: 16px;

     min-height: 120px;

     color: white;

     display: flex;

     flex-direction: column;

     justify-content: space-between;

     box-shadow: 0 8px 18px rgba(0,0,0,0.08);

    }

 

   .core { background: linear-gradient(160deg, #156082 0%, #2f86ad 100%); }

   .elective { background: linear-gradient(160deg, #2b7a58 0%, #4aa876 100%); }

   .research { background: linear-gradient(160deg, #6c52c8 0%, #8e73ef 100%); }

   .project { background: linear-gradient(160deg, #bb7a11 0%, #dfaa47 100%); }

 

   .course-top {

     font-size: 0.76rem;

     text-transform: uppercase;

     letter-spacing: 0.08em;

     opacity: 0.9;

     font-weight: 700;

    }

 

   .course-name {

     font-size: 1.18rem;

     font-weight: 800;

     line-height: 1.05;

     margin: 10px 0;

    }

 

   .course-meta {

     font-size: 0.88rem;

     opacity: 0.95;

    }

 

   .milestone-row {

     display: grid;

     grid-template-columns: repeat(3, minmax(0, 1fr));

     gap: 14px;

     margin-top: 18px;

    }

 

   .milestone {

     border: 1px solid var(--line);

     border-radius: 18px;

     padding: 16px;

     background: #f9fbfc;

    }

 

   .milestone h3 {

     margin: 0 0 8px;

     font-size: 1rem;

    }

 

   .milestone p {

     margin: 0;

     color: var(--muted);

     font-size: 0.92rem;

    }

 

   .footer-note {

     margin-top: 18px;

     padding: 14px 16px;

     border-radius: 16px;

     background: #f4f8fb;

     border: 1px dashed #cbd8e2;

     font-size: 0.92rem;

     color: var(--muted);

    }

 

   @media (max-width: 1040px) {

     .layout { grid-template-columns: 1fr; }

     .controls { position: static; }

     .summary-grid, .milestone-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    }

 

   @media (max-width: 720px) {

     .wrap { padding: 18px 14px 40px; }

     .hero, .controls, .results { padding: 18px; }

     .term { grid-template-columns: 1fr; }

     .summary-grid, .milestone-row { grid-template-columns: 1fr; }

     .course-grid { grid-template-columns: 1fr 1fr; }

    }

 

   @media (max-width: 520px) {

     .course-grid { grid-template-columns: 1fr; }

    }

 </style>

</head>

<body>

 <div class="wrap">

   <section class="hero panel">

     <div class="eyebrow">Interactive programme planner</div>

     <h1>Build Your Path</h1>

     <p class="subtitle">

       A student-facing roadmap that lets learners choose their study mode, intended award, and starting point, then instantly see a clear learning path from certificate to diploma to master's.

       <br><br><strong>Disclaimer:</strong> The information in the interactive programme planner is for information purposes only. Please consult the Chief Academic Affairs Officer for tailored academic advising.

     </p>

   </section>

 

   <section class="layout">

     <aside class="panel controls">

       <div class="control-block">

         <label class="control-label" for="mode">1. Select study mode</label>

         <select id="mode">

           <option value="full">Full-time</option>

           <option value="part">Part-time</option>

         </select>

       </div>

 

       <div class="control-block">

         <label class="control-label" for="award">2. Select your intended award</label>

         <select id="award">

           <option value="certificate">Postgraduate Certificate</option>

           <option value="diploma">Postgraduate Diploma</option>

           <option value="masters">Master's (MSc)</option>

         </select>

       </div>

 

       <div class="control-block">

         <label class="control-label" for="entry">3. Confirm your entry point</label>

         <select id="entry">

           <option value="start">I am starting from the beginning</option>

           <option value="certificate_done">I have already completed the certificate</option>

           <option value="diploma_done">I have already completed the diploma</option>

         </select>

       </div>

 

       <div class="note" id="helperText">

         This pathway shows the recommended registration sequence and keeps the learner focused on “what do I register for next?”

       </div>

 

       <div class="btn-row">

         <button class="btn-primary" id="generateBtn">Generate my path</button>

         <button class="btn-secondary" id="resetBtn">Reset</button>

       </div>

     </aside>

 

      <main class="panel results">

       <div class="summary-card">

         <div class="chips" id="chips"></div>

         <div class="path-title">

           <div>

              <h2 id="pathHeading">Your recommended path</h2>

              <div class="path-sub" id="pathSub">Choose your options to view the sequence.</div>

           </div>

         </div>

         <div class="summary-grid" id="summaryGrid"></div>

       </div>

 

       <div class="timeline" id="timeline"></div>

 

       <div class="milestone-row" id="milestones"></div>

 

       <div class="footer-note" id="footerNote"></div>

     </main>

   </section>

 </div>

 

 <script>

   const data = {

     certificate: {

       label: 'Postgraduate Certificate',

       credits: 12,

       fullDuration: '16 weeks',

       partDuration: '32 weeks',

       terms: {

         full: [

           { name: 'Block 1', weeks: '8 weeks', courses: [

              { label: 'Course 1', type: 'core', subtype: 'Core course' },

              { label: 'Course 2', type: 'core', subtype: 'Core course' }

           ]},

           { name: 'Block 2', weeks: '8 weeks', courses: [

              { label: 'Course 3', type: 'core', subtype: 'Core course' },

              { label: 'Course 4', type: 'core', subtype: 'Core course' }

           ]}

         ],

         part: [

           { name: 'Block 1', weeks: '8 weeks', courses: [{ label: 'Course 1', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 2', weeks: '8 weeks', courses: [{ label: 'Course 2', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 3', weeks: '8 weeks', courses: [{ label: 'Course 3', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 4', weeks: '8 weeks', courses: [{ label: 'Course 4', type: 'core', subtype: 'Core course' }]}

         ]

       }

     },

     diploma: {

       label: 'Postgraduate Diploma',

       credits: 21,

       fullDuration: '32 weeks',

       partDuration: '56 weeks',

       terms: {

         full: [

           { name: 'Block 1', weeks: '8 weeks', courses: [

              { label: 'Course 1', type: 'core', subtype: 'Core course' },

              { label: 'Course 2', type: 'core', subtype: 'Core course' }

           ]},

           { name: 'Block 2', weeks: '8 weeks', courses: [

              { label: 'Course 3', type: 'core', subtype: 'Core course' },

              { label: 'Course 4', type: 'core', subtype: 'Core course' }

            ]},

           { name: 'Block 3', weeks: '8 weeks', courses: [

              { label: 'Course 5', type: 'core', subtype: 'Core course' },

              { label: 'Course 6', type: 'elective', subtype: 'Elective' }

           ]},

           { name: 'Block 4', weeks: '8 weeks', courses: [

              { label: 'Course 7', type: 'elective', subtype: 'Elective' }

           ]}

         ],

         part: [

           { name: 'Block 1', weeks: '8 weeks', courses: [{ label: 'Course 1', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 2', weeks: '8 weeks', courses: [{ label: 'Course 2', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 3', weeks: '8 weeks', courses: [{ label: 'Course 3', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 4', weeks: '8 weeks', courses: [{ label: 'Course 4', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 5', weeks: '8 weeks', courses: [{ label: 'Course 5', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 6', weeks: '8 weeks', courses: [{ label: 'Course 6', type: 'elective', subtype: 'Elective' }]},

           { name: 'Block 7', weeks: '8 weeks', courses: [{ label: 'Course 7', type: 'elective', subtype: 'Elective' }]}

         ]

       }

     },

     masters: {

       label: "Master's (MSc)",

       credits: 36,

       fullDuration: '56 weeks',

       partDuration: '96 weeks',

       terms: {

         full: [

           { name: 'Block 1', weeks: '8 weeks', courses: [

              { label: 'Course 1', type: 'core', subtype: 'Core course' },

              { label: 'Course 2', type: 'core', subtype: 'Core course' }

           ]},

           { name: 'Block 2', weeks: '8 weeks', courses: [

              { label: 'Course 3', type: 'core', subtype: 'Core course' },

              { label: 'Course 4', type: 'core', subtype: 'Core course' }

           ]},

           { name: 'Block 3', weeks: '8 weeks', courses: [

              { label: 'Course 5', type: 'core', subtype: 'Core course' },

              { label: 'Course 6', type: 'elective', subtype: 'Elective' }

           ]},

           { name: 'Block 4', weeks: '8 weeks', courses: [

              { label: 'Course 7', type: 'elective', subtype: 'Elective' },

              { label: 'Course 8', type: 'elective', subtype: 'Elective' }

           ]},

           { name: 'Block 5', weeks: '8 weeks', courses: [

              { label: 'Course 9', type: 'research', subtype: 'Research Methods' },

              { label: 'Course 10', type: 'elective', subtype: 'Elective' }

           ]},

           { name: 'Final Project', weeks: '16 weeks', courses: [

              { label: 'Course 11', type: 'project', subtype: 'Final Project' }

           ]}

         ],

         part: [

           { name: 'Block 1', weeks: '8 weeks', courses: [{ label: 'Course 1', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 2', weeks: '8 weeks', courses: [{ label: 'Course 2', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 3', weeks: '8 weeks', courses: [{ label: 'Course 3', type: 'core', subtype: 'Core course' }]},

            { name: 'Block 4', weeks: '8 weeks', courses: [{ label: 'Course 4', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 5', weeks: '8 weeks', courses: [{ label: 'Course 5', type: 'core', subtype: 'Core course' }]},

           { name: 'Block 6', weeks: '8 weeks', courses: [{ label: 'Course 6', type: 'elective', subtype: 'Elective' }]},

           { name: 'Block 7', weeks: '8 weeks', courses: [{ label: 'Course 7', type: 'elective', subtype: 'Elective' }]},

           { name: 'Block 8', weeks: '8 weeks', courses: [{ label: 'Course 8', type: 'elective', subtype: 'Elective' }]},

           { name: 'Block 9', weeks: '8 weeks', courses: [{ label: 'Course 9', type: 'research', subtype: 'Research Methods' }]},

           { name: 'Block 10', weeks: '8 weeks', courses: [{ label: 'Course 10', type: 'elective', subtype: 'Elective' }]},

           { name: 'Final Project', weeks: '16 weeks', courses: [{ label: 'Course 11', type: 'project', subtype: 'Final Project' }]}

         ]

       }

      }

   };

 

   const modeEl = document.getElementById('mode');

   const awardEl = document.getElementById('award');

   const entryEl = document.getElementById('entry');

   const chipsEl = document.getElementById('chips');

   const pathSubEl = document.getElementById('pathSub');

   const summaryGridEl = document.getElementById('summaryGrid');

   const timelineEl = document.getElementById('timeline');

   const milestonesEl = document.getElementById('milestones');

   const helperTextEl = document.getElementById('helperText');

   const footerNoteEl = document.getElementById('footerNote');

 

   function getEntryOptionsForAward(award) {

     if (award === 'certificate') return ['start'];

     if (award === 'diploma') return ['start', 'certificate_done'];

     return ['start', 'certificate_done', 'diploma_done'];

    }

 

   function syncEntryOptions() {

     const award = awardEl.value;

     const allowed = getEntryOptionsForAward(award);

     Array.from(entryEl.options).forEach(opt => {

       opt.hidden = !allowed.includes(opt.value);

     });

     if (!allowed.includes(entryEl.value)) entryEl.value = allowed[0];

    }

 

   function getFilteredTerms(award, entry, mode) {

     const allTerms = data[award].terms[mode];

     if (award === 'certificate') return allTerms;

     if (award === 'diploma' && entry === 'certificate_done') {

       return allTerms.filter(term => !term.courses.some(c => ['Course 1','Course 2','Course 3','Course 4'].includes(c.label)));

     }

     if (award === 'masters') {

       if (entry === 'certificate_done') {

         return allTerms.filter(term => !term.courses.some(c => ['Course 1','Course 2','Course 3','Course 4'].includes(c.label)));

       }

       if (entry === 'diploma_done') {

         if (mode === 'full') {

           return [

              { name: 'Block 5', weeks: '8 weeks', courses: [

                { label: 'Course 8', type: 'elective', subtype: 'Elective' },

                { label: 'Course 9', type: 'research', subtype: 'Research Methods' }

              ]},

              { name: 'Block 6', weeks: '8 weeks', courses: [

                { label: 'Course 10', type: 'elective', subtype: 'Elective' }

              ]},

              { name: 'Final Project', weeks: '16 weeks', courses: [

                { label: 'Course 11', type: 'project', subtype: 'Final Project' }

              ]}

           ];

         }

         return allTerms.filter(term => !term.courses.some(c => ['Course 1','Course 2','Course 3','Course 4','Course 5','Course 6','Course 7'].includes(c.label)));

       }

     }

     return allTerms;

    }

 

   function getEstimatedDuration(termCount, award, mode, entry) {

     const terms = getFilteredTerms(award, entry, mode);

     const weeks = terms.reduce((sum, term) => sum + parseInt(term.weeks, 10), 0);

     return `${weeks} learning weeks`;

    }

 

   function render() {

     syncEntryOptions();

     const mode = modeEl.value;

     const award = awardEl.value;

     const entry = entryEl.value;

     const awardData = data[award];

     const terms = getFilteredTerms(award, entry, mode);

     const totalCourses = terms.flatMap(t => t.courses).length;

     const duration = getEstimatedDuration(terms.length, award, mode, entry);

     const perBlock = mode === 'full' ? '2 courses simultaneously' : '1 course at a time';

 

     const entryLabelMap = {

       start: 'Starting from the beginning',

       certificate_done: 'Certificate already completed',

       diploma_done: 'Diploma already completed'

     };

 

     chipsEl.innerHTML = `

       <span class="chip mode">${mode === 'full' ? 'Full-time' : 'Part-time'}</span>

       <span class="chip award">${awardData.label}</span>

       <span class="chip entry">${entryLabelMap[entry]}</span>

     `;

 

     pathSubEl.textContent = `${awardData.label} · recommended sequence through each 8 weeks learning cycle`;

 

     summaryGridEl.innerHTML = `

       <div class="metric"><div class="metric-label">Estimated duration</div><div class="metric-value">${duration}</div></div>

       <div class="metric"><div class="metric-label">Credits</div><div class="metric-value">${awardData.credits}</div></div>

       <div class="metric"><div class="metric-label">Course progress</div><div class="metric-value">${perBlock}</div></div>

       <div class="metric"><div class="metric-label">Courses to complete</div><div class="metric-value">${totalCourses}</div></div>

     `;

 

     timelineEl.innerHTML = terms.map((term, index) => `

        <section class="term">

         <div class="term-meta">

           <div class="term-kicker">Step ${index + 1}</div>

           <div class="term-name">${term.name}</div>

           <div class="term-desc">${term.weeks} · Access ${term.courses.length} course${term.courses.length > 1 ? 's' : ''}</div>

         </div>

         <div class="course-grid">

           ${term.courses.map(course => `

              <article class="course-card ${course.type}">

                <div>

                  <div class="course-top">${course.subtype}</div>

                  <div class="course-name">${course.label}</div>

                </div>

                <div class="course-meta">${term.weeks}</div>

              </article>

           `).join('')}

         </div>

        </section>

     `).join('');

 

     const certificateDone = ['diploma', 'masters'].includes(award) || entry === 'certificate_done' || entry === 'diploma_done';

     const diplomaDone = award === 'masters' || entry === 'diploma_done';

     const masterUnlocked = award === 'masters';

 

     milestonesEl.innerHTML = `

       <div class="milestone">

         <h3>Certificate milestone</h3>

         <p>Complete Courses 1-4 before progressing to the diploma stage.</p>

       </div>

        <div class="milestone">

         <h3>Diploma milestone</h3>

         <p>Continue with Courses 5-7 before moving to the master’s schedule.</p>

       </div>

       <div class="milestone">

         <h3>Master's milestone</h3>

         <p>Complete Courses 8-10. Course 11 is the final project and is taken after the earlier master's courses are completed.</p>

       </div>

     `;

 

     helperTextEl.textContent = award === 'masters'

       ? 'This view emphasises progression: certificate first, then diploma, then the full master\'s sequence.'

       : award === 'diploma'

         ? 'This view helps learners see the full diploma journey and where the certificate stage fits within it.'

         : 'This view gives prospective students a simple first-step path into the programme.';

 

     footerNoteEl.textContent = mode === 'full'

       ? 'Drupal implementation note: this prototype works well as a single embedded HTML block or a custom Drupal block with inline CSS/JS. The visual cards reduce text load and make the next registration step immediately visible.'

       : 'Accessibility note: the card layout, plain-language labels, and progressive sequencing support mobile users and reduce cognitive load for part-time learners planning one course at a time.';

    }

 

   document.getElementById('generateBtn').addEventListener('click', render);

   document.getElementById('resetBtn').addEventListener('click', () => {

     modeEl.value = 'full';

     awardEl.value = 'certificate';

     entryEl.value = 'start';

     render();

   });

   awardEl.addEventListener('change', render);

   modeEl.addEventListener('change', render);

   entryEl.addEventListener('change', render);

 

   render();

 </script>

</body>

</html>