1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> 6 <link rel="apple-touch-icon" sizes="76x76" href="https://static.studyladder.co.uk/cdn/site/2e/fb7b4b5af2aa.png" /> 7 <link rel="apple-touch-icon" sizes="120x120" href="https://static.studyladder.co.uk/cdn/site/c5/21378bb6616f.png" /> 8 <link rel="apple-touch-icon" sizes="152x152" href="https://static.studyladder.co.uk/cdn/site/67/2d9c8f4113ad.png" /> 9 <link rel="apple-touch-icon" sizes="180x180" href="https://static.studyladder.co.uk/cdn/site/f0/67c0f8d932e1.png" /> 10 <link rel="shortcut icon" sizes="192x192" href="https://static.studyladder.co.uk/cdn/site/d5/5ccd0010bcfa.png"> 11 <meta name="description" content="Used by over 70,000 teachers & 1 million students at home and school. Studyladder is an online english literacy & mathematics learning tool. Kids activity games, worksheets and lesson plans for Primary and Junior High School students in United Kingdom." /> 12 <meta name="keywords" content="studyladder, smartkiddies, study ladder, english, literacy, maths, mathematics, kids games, worksheets, lesson plans, kids activities, algebra, multiplication, geometry, comprehension, United Kingdom." /> 13 <meta name="rating" content="General" /> 14 <meta name="robots" content="all" /> 15 <meta name="google-site-verification" content="D8IxNaFFb30mlpk1W9ckC7yBm3szytFOoXiHyo2Cpm8" /> 16 <meta name="author" content="Studyladder" /> 17 <meta name="geo.position" content="51;-0"> 18 <meta name="geo.country" content="GB"> 19 <meta name="geo.placename" content="Studyladder UK"> 20 <meta http-equiv="content-type" content="text/html;charset=utf-8" /> 21 <meta http-equiv="X-UA-Compatible" content="IE=edge; text/html; charset=utf-8" /> 22 <meta charset="utf-8"> 23 <!-- Google Tag Manager --> 24
24<script>
vendor: 387 bytes, lines 24-28
24 25 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'}); 26 var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:''; 27 j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl; f.parentNode.insertBefore(j,f); 28 })(window,document,'script','dataLayer','
28GTM-MRVSQXKH
vendor: 12 bytes, lines 28-29
28'); 29
29</script>
29 30 31 32
32<script> 33 window.dataLayer = window.dataLayer || []; 34 function gtag(){dataLayer.push(arguments);} 35 gtag('config', 'AW-1071699385'); 36 </script>
36 37 38 <!-- End Google Tag Manager --> 39 40 <title>Studyladder, online english literacy & mathematics. Kids activity games, worksheets and lesson plans.</title> 41 42
42<script type="text/javascript" src="/cdn/lib/vendor/jquery/jquery-3.7.1-v1.min.js"></script>
42 43
43<script type="text/javascript" src="/cdn/lib/vendor/bootstrap/4.6.2/js/bootstrap.bundle.min.js"></script>
43 44
44<script type="module"> 45 import { DotLottie } from "https://static.studyladder.co.uk/cdn/site/94/e40a4cda63bc.js";//"https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/+esm"; 46 window.DotLottie = DotLottie; // Attach DotLottie to the window object for global access 47 </script>
47 48
48<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/2f/978ac60cd6ed.js"></script>
48 49 50
50<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/0a/24d5b043bd4d.js"></script>
50 51
51<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/6b/6f6a16f17ffa.js"></script>
51 52
52<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/85/8149e1190b9d.js"></script>
52 53 <link rel="preconnect" href="https://fonts.gstatic.com"> 54 <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@800&display=swap" rel="stylesheet"> 55 <link href="https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap" rel="stylesheet"> 56 <link href='https://fonts.googleapis.com/css?family=ABeeZee:400,400italic' rel='stylesheet' type='text/css'> 57 <link href="https://fonts.googleapis.com/css?family=Muli|Quicksand:400,500,700" rel="stylesheet"> 58 <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"> 59 <link rel="stylesheet" type="text/css" href="/cdn/lib/vendor/font-awesome/pro-5.5.00-web/css/fontawesome-solid-regular.min.css"/> 60 <link rel="stylesheet" href="https://static.studyladder.co.uk/cdn/dist/scss/ad0326d857b829a3/scss/bootstrap.min.css"/> 61 62 <link rel="stylesheet" type="text/css" href="https://static.studyladder.co.uk/cdn/dist/scss/b0d969d290c3b536/global.min.css"/> 63 <link rel="stylesheet" type="text/css" href="https://static.studyladder.co.uk/cdn/site/8a/72f4b89544ba.css"/> 64 <link rel="stylesheet" type="text/css" href="https://static.studyladder.co.uk/cdn/dist/scss/909e79e5b57df6af/scss/public.min.css"/> 65 <link rel="stylesheet" type="text/css" href="https://static.studyladder.co.uk/cdn/dist/scss/5c15ee88194d2866/account/register.min.css"/> 66
66<script type="text/javascript" src="https://www.studyladder.co.uk/secure/stripe-purchase-client?v=20260925-1"></script>
vendor: 85 bytes, lines 66-68
66 67 68 <script src='https://www.google.com/recaptcha/api.js'></script>
68<style>.grecaptcha-badge{z-index:999999;background-color:#fff}</style> 69
69<script> gtag('event', 'conversion', {'send_to': 'AW-1071699385/DQ0SCL-pjO0ZELmrg_8D'}); </script>
69 70
70<script> 71 window.MathJax = { 72 loader: { 73 paths: { 74 mathjax: "\/lib\/vendor\/mathjax\/3.2.2\/es5" } 75 }, 76 tex: { 77 inlineMath: [['\\(', '\\)']], 78 }, 79 svg: { 80 fontCache: 'global' 81 } 82 }; 83 </script>
83 84 85
85<script src="https://static.studyladder.co.uk/cdn/site/cf/b8e18acf40a7.js" async></script>
85 86 87 </head> 88 <body style="" class=""> 89
89<script>var animation; var swalAnimation; var cacheVersion = 0.01</script>
89 90 91 <!-- Google Tag Manager (noscript) -->
vendor: 89 bytes, lines 91-93
91 92 <noscript> 93 <iframe src="https://www.googletagmanager.com/ns.html?id=
93GTM-MRVSQXKH
vendor: 92 bytes, lines 93-94
93" height="0" width="0" style="display:none;visibility:hidden"></iframe> 94 </noscript>
94<!-- End Google Tag Manager (noscript) --> 95 <header id="site-header" class="site-header-container public "> 96 <nav class="site-header"> 97 <div class="">
98<script> 99 // Set data-locale on <html> as early as possible so .au-only / .intl-only 100 // spans render correctly without a flash of wrong content. 101 (function(){ 102 try { document.documentElement.setAttribute('data-locale', "intl"); } catch(e){} 103 })(); 104</script>
104 105 106<style> 107/* âââ Country bar (top strip) ââââââââââââââââââââââââââââââââââââââ */ 108.country-bar { 109 background: #F8FAFC; 110 border-bottom: 1px solid #E2E8F0; 111 padding: 2px 0; 112 font-size: 12px; 113 color: #475569; 114 line-height: 1.2; 115} 116.country-bar-inner { 117 max-width: 1280px; 118 margin: 0 auto; 119 padding: 0 20px; 120 display: flex; 121 align-items: center; 122 justify-content: flex-end; 123 gap: 12px; 124} 125.country-selector { 126 display: inline-flex; 127 align-items: center; 128 gap: 6px; 129 position: relative; 130} 131.country-flag { 132 display: inline-flex; 133 align-items: center; 134 justify-content: center; 135 width: 18px; 136 height: 12px; 137 overflow: hidden; 138 border-radius: 2px; 139 flex: 0 0 auto; 140} 141.country-flag img { 142 width: 18px !important; 143 height: auto !important; 144 max-width: 18px !important; 145 display: block; 146} 147.country-select { 148 background: transparent; 149 border: 0; 150 padding: 2px 20px 2px 6px; 151 font: inherit; 152 font-size: 12px; 153 color: #0F172A; 154 cursor: pointer; 155 -webkit-appearance: none; 156 appearance: none; 157 background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'><path d='M1 1l4 4 4-4' stroke='%2364748B' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"); 158 background-repeat: no-repeat; 159 background-position: right 4px center; 160 line-height: 1.2; 161} 162.country-select:hover { color: #2D5BFF; } 163.country-caret { display: none; } /* selector renders its own arrow */ 164 165/* âââ Main nav âââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 166nav.top { 167 background: #FFFFFF; 168 border-bottom: 1px solid #E2E8F0; 169 position: relative; 170 z-index: 100; 171} 172nav.top .nav-inner { 173 max-width: 1280px; 174 margin: 0 auto; 175 padding: 8px 20px; 176 display: flex; 177 align-items: center; 178 gap: 24px; 179} 180nav.top .logo { 181 display: inline-flex; 182 align-items: center; 183 flex: 0 0 auto; 184} 185nav.top .logo img { 186 height: 36px; 187 width: auto; 188 display: block; 189} 190nav.top .nav-links { 191 list-style: none; 192 margin: 0; 193 padding: 0; 194 display: flex; 195 align-items: center; 196 gap: 4px; 197 flex: 1 1 auto; 198} 199nav.top .nav-links > li { position: relative; } 200nav.top .nav-links > li > a, 201nav.top .nav-links > li > .nav-dropdown-trigger { 202 display: inline-flex; 203 align-items: center; 204 gap: 4px; 205 padding: 10px 14px; 206 font-size: 14px; 207 font-weight: 500; 208 color: #475569; 209 text-decoration: none; 210 border-radius: 8px; 211 transition: background .15s ease, color .15s ease;
212 cursor: pointer; 213} 214nav.top .nav-links > li > a:hover, 215nav.top .nav-links > li > .nav-dropdown-trigger:hover { 216 color: #0F172A; 217 background: #F8FAFC; 218} 219nav.top .nav-caret { 220 font-size: 14px; 221 opacity: 0.8; 222 margin-left: 2px; 223 display: inline-block; 224 line-height: 1; 225 transition: transform .15s ease; 226} 227nav.top .nav-dropdown:hover .nav-caret { transform: rotate(180deg); } 228nav.top .nav-dropdown-menu { 229 display: none; 230 position: absolute !important; 231 top: 100% !important; 232 left: 50% !important; 233 transform: translateX(-50%) !important; 234 margin-top: 5px !important; 235 min-width: 220px; 236 background: #FFFFFF; 237 border: 1px solid #E2E8F0; 238 border-radius: 12px; 239 box-shadow: 0 12px 32px -8px rgba(15,23,42,0.18), 0 2px 6px rgba(15,23,42,0.06); 240 padding: 8px; 241 z-index: 200; 242} 243/* Hover-bridge so mouse can travel from trigger to dropdown without losing hover */ 244nav.top .nav-dropdown::after { 245 content: ""; 246 position: absolute; 247 top: 100%; 248 left: 0; 249 right: 0; 250 height: 8px; 251 pointer-events: auto; 252} 253nav.top .nav-dropdown:hover .nav-dropdown-menu, 254nav.top .nav-dropdown:focus-within .nav-dropdown-menu { display: block; } 255nav.top .nav-dropdown-menu a { 256 display: flex; 257 align-items: center; 258 gap: 10px; 259 padding: 10px 12px; 260 border-radius: 8px; 261 font-size: 14px; 262 color: #0F172A; 263 text-decoration: none; 264 transition: background .15s ease; 265} 266nav.top .nav-dropdown-menu a:hover { background: #F1F5F9; } 267nav.top .nav-dropdown-icon { 268 display: inline-flex !important; 269 align-items: center !important; 270 justify-content: center !important; 271 width: 28px !important; 272 height: 28px !important; 273 min-width: 28px !important; 274 border-radius: 6px !important; 275 font-size: 14px !important; 276 font-weight: 700 !important; 277 flex: 0 0 28px !important; 278 line-height: 1 !important; 279 text-transform: none !important; 280 font-family: inherit !important; 281} 282/* Soft pastel backgrounds with deep coloured letters â matches subject-page topic-card-icon style */ 283nav.top .nav-dropdown-icon.maths { background: #DBE6FF !important; color: #2D5BFF !important; } /* blue */ 284nav.top .nav-dropdown-icon.english { background: #D1FAE5 !important; color: #059669 !important; } /* green */ 285nav.top .nav-dropdown-icon.science { background: #FED7AA !important; color: #EA580C !important; } /* orange */ 286nav.top .nav-dropdown-icon.parent { background: #FED7AA !important; color: #EA580C !important; } /* orange */ 287nav.top .nav-dropdown-icon.teacher { background: #DBE6FF !important; color: #2D5BFF !important; } /* blue */ 288nav.top .nav-dropdown-icon.school { background: #D1FAE5 !important; color: #059669 !important; } /* green */ 289 290nav.top .nav-cta { 291 display: flex; 292 align-items: center; 293 gap: 8px; 294 flex: 0 0 auto; 295} 296nav.top .nav-cta .btn { 297 font-size: 14px; 298 padding: 8px 16px; 299 border-radius: 999px; 300 font-weight: 600; 301 text-decoration: none; 302 display: inline-flex; 303 align-items: center; 304} 305nav.top .nav-cta .btn-ghost { 306 background: transparent; 307 color: #0F172A; 308 border: 1px solid transparent; 309} 310nav.top .nav-cta .btn-ghost:hover { background: #F1F5F9; } 311nav.top .nav-cta .btn-primary { 312 background: #2D5BFF; 313 color: #FFFFFF; 314 border: 1px solid #2D5BFF; 315} 316nav.top .nav-cta .btn-primary:hover { background: #1E40AF; border-color: #1E40AF; } 317 318nav.top .nav-menu-toggle { 319 display: none; 320 background: transparent; 321 border: 0; 322 width: 40px; 323 height: 40px; 324 padding: 8px; 325 cursor: pointer; 326 flex-direction: column; 327 justify-content: space-between; 328 align-items: stretch; 329} 330nav.top .nav-menu-toggle span { 331 display: block; 332 height: 2px; 333 width: 100%; 334 background: #0F172A; 335 border-radius: 2px; 336 transition: transform .2s ease, opacity .2s ease; 337} 338 339.nav-mobile-only { display: none; } 340 341/* Force white text on the mobile Join Now button, regardless of viewport width. 342 sl-marketing.scss's mobile nav kicks in at â¤1024px and its `.sl-marketing a { color: blue }` 343 base rule would otherwise leave the button reading blue-on-blue. */ 344nav.top .nav-mobile-only .nav-mobile-join, 345nav.top .nav-mobile-only .nav-mobile-join:link, 346nav.top .nav-mobile-only .nav-mobile-join:visited, 347nav.top .nav-mobile-only .nav-mobile-join:hover, 348nav.top .nav-mobile-only .nav-mobile-join:focus, 349nav.top .nav-mobile-only .nav-mobile-join:active { 350 color: #FFFFFF !important; 351 background: #2D5BFF !important; 352} 353 354/* âââ Mobile breakpoint ââââââââââââââââââââââââââââââââââââââââââââ */ 355/* Aligned to sl-marketing.scss's own 1024px nav breakpoint so both stylesheets 356 flip to mobile at the same viewport width. Also toggles on `.open` (the 357 class name sl-marketing already targets) instead of a bespoke `.is-open`. */ 358@media (max-width: 1024px) { 359 nav.top .nav-links { 360 display: none; 361 position: absolute; 362 top: 100%; 363 left: 0; 364 right: 0; 365 flex-direction: column; 366 align-items: stretch; 367 background: #FFFFFF; 368 border-bottom: 1px solid #E2E8F0; 369 padding: 12px 16px; 370 gap: 4px; 371 box-shadow: 0 12px 24px -10px rgba(15,23,42,0.15); 372 max-height: calc(100vh - 80px); 373 overflow-y: auto; 374 } 375 nav.top .nav-links.open, 376 nav.top .nav-links.is-open { display: flex; } 377 nav.top .nav-links > li > a, 378 nav.top .nav-links > li > .nav-dropdown-trigger { padding: 12px 10px; font-size: 16px; } 379 nav.top .nav-dropdown-menu { 380 display: none !important; 381 position: static !important; 382 top: auto !important; 383 left: auto !important; 384 right: auto !important; 385 transform: none !important; 386 margin: 0 !important; 387 box-shadow: none !important; 388 border: 0 !important; 389 border-radius: 0 !important; 390 padding: 4px 0 8px 24px !important; 391 background: transparent !important; 392 min-width: 0 !important; 393 width: 100% !important; 394 } 395 /* Kill desktop hover/focus reveal on mobile (touch devices shouldn't use hover) */ 396 nav.top .nav-dropdown:hover > .nav-dropdown-menu, 397 nav.top .nav-dropdown:focus-within > .nav-dropdown-menu, 398 nav.top .nav-dropdown:hover .nav-dropdown-menu, 399 nav.top .nav-dropdown:focus-within .nav-dropdown-menu { display: none !important; } 400 /* .open wins via source order over the hover/focus block above */ 401 nav.top .nav-dropdown.open > .nav-dropdown-menu, 402 nav.top .nav-dropdown.open:hover > .nav-dropdown-menu, 403 nav.top .nav-dropdown.open:focus-within > .nav-dropdown-menu { display: block !important; } 404 nav.top .nav-dropdown.open > .nav-dropdown-trigger .nav-caret { transform: rotate(180deg); } 405 nav.top .nav-dropdown::after { display: none; } 406 nav.top .nav-dropdown { position: static !important; } 407 .nav-mobile-only .nav-mobile-join, 408 .nav-mobile-only .nav-mobile-join:hover, 409 .nav-mobile-only .nav-mobile-join:focus, 410 .nav-mobile-only .nav-mobile-join:active { color: #FFFFFF !important; background: #2D5BFF !important; } 411 nav.top .nav-menu-toggle { display: flex; } 412 nav.top .nav-cta .btn-ghost, 413 nav.top .nav-cta .btn-primary { display: none; } 414 .nav-mobile-only { display: block; margin-top: 10px; padding-top: 10px; border-top: 1px solid #E2E8F0; } 415 .nav-mobile-only .btn { display: block; width: 100%; text-align: center; margin: 6px 0; font-size: 15px; padding: 12px 16px; border-radius: 10px; text-decoration: none; } 416 .nav-mobile-only .nav-mobile-join { background: #2D5BFF; color: #FFFFFF; } 417 .nav-mobile-only .nav-mobile-login { background: #FFFFFF; color: #0F172A; border: 1px solid #E2E8F0; }
418 body.nav-open { overflow: hidden; } 419} 420 421/* âââ Short viewports â pin Join Now / Login to the top of the menu ââââ 422 On landscape phones / small laptops (Nest Hub etc.) the CTA row at the 423 bottom of the menu can fall below the fold. Flex `order` moves it to 424 the top of the column without touching the DOM. */ 425@media (max-width: 1024px) and (max-height: 650px) { 426 nav.top .nav-links .nav-mobile-cta { 427 order: -1; 428 margin-top: 0; 429 padding-top: 0; 430 border-top: 0; 431 margin-bottom: 10px; 432 padding-bottom: 10px; 433 border-bottom: 1px solid #E2E8F0; 434 } 435} 436</style> 437 438<!-- COUNTRY BAR â thin strip at the top, replaces the old dark navbar --> 439<div class="country-bar"> 440 <div class="country-bar-inner"> 441 <form class="country-selector" id="lcForm"> 442 <span class="country-flag" aria-hidden="true"> 443 <img src="https://static.studyladder.co.uk/cdn/site/66/a8cfb86cfc1b.png" alt=""> 444 </span> 445 <select id="lc_select" name="lc_set" class="country-select" aria-label="Change country"> 446 <option value="https://www.studyladder.com.au/account/teacher">Australia</option> 447 <option value="https://www.studyladder.ca/account/teacher">Canada</option> 448 <option value="https://www.studyladder.co.nz/account/teacher">New Zealand</option> 449 <option value="https://www.studyladder.co.uk/account/teacher" selected="selected">United Kingdom</option> 450 <option value="https://www.studyladder.com/account/teacher">United States</option> 451 </select> 452 <span class="country-caret" aria-hidden="true">▾</span> 453 </form> 454 </div> 455</div> 456
457<script> 458 // Locale switcher â submit to the selected URL 459 document.getElementById('lc_select').addEventListener('change', function(){ 460 var u = this.value; 461 var f = document.getElementById('lcForm'); 462 f.setAttribute('action', u); 463 f.submit(); 464 }); 465</script>
465 466 467<!-- MAIN NAV â new marketing design --> 468<nav class="top"> 469 <div class="nav-inner"> 470 <a href="/" class="logo"> 471 <img src="https://static.studyladder.co.uk/cdn/site/13/6f597fea9532.png" alt="Studyladder"> 472 </a> 473 474 <ul class="nav-links" id="primaryNav"> 475 <li><a href="/about/parent">Parents</a></li> 476 <li><a href="/about/teacher">Teachers</a></li> 477 <li><a href="/about/schools">Schools</a></li> 478 479 <li class="nav-dropdown"> 480 <a href="/about/subjects" class="nav-dropdown-trigger">Subjects <span class="nav-caret">▾</span></a> 481 <div class="nav-dropdown-menu"> 482 <a href="/about/subjects-mathematics"><span class="nav-dropdown-icon maths">M</span>Mathematics</a> 483 <a href="/about/subjects-english"><span class="nav-dropdown-icon english">E</span>English</a> 484 <a href="/about/subjects-science"><span class="nav-dropdown-icon science">S</span>Science</a> 485 </div> 486 </li> 487 488 <li><a href="/info/curriculum-aligned?jurisdiction=gb">Curriculum</a></li> 489 490 <li class="nav-dropdown"> 491 <a href="#pricing" class="nav-dropdown-trigger">Pricing <span class="nav-caret">▾</span></a> 492 <div class="nav-dropdown-menu"> 493 <a href="/account/parent-pricing"><span class="nav-dropdown-icon parent">P</span>For parents</a> 494 <a href="/about/teacher-school-pricing?t=t"><span class="nav-dropdown-icon teacher">T</span>For teachers</a> 495 <a href="/about/teacher-school-pricing?t=s"><span class="nav-dropdown-icon school">S</span>For schools</a> 496 </div> 497 </li> 498 499 <li><a href="/about/contact-us">Support</a></li> 500 501 <!-- Mobile-only CTAs (collapse into the menu when open on small screens) --> 502 <li class="nav-mobile-only nav-mobile-cta"> 503 <a href="#joinNow" data-toggle="modal" class="btn btn-primary nav-mobile-join">Join Now</a> 504 <a href="/login/account" class="btn btn-secondary nav-mobile-login">Login</a> 505 </li> 506 </ul> 507 508 <div class="nav-cta"> 509 <a href="/login/account" class="btn btn-ghost">Login</a> 510 <a href="#joinNow" data-toggle="modal" class="btn btn-primary nav-join-btn">Join Now</a> 511 <button type="button" class="nav-menu-toggle" aria-label="Open menu" aria-expanded="false" aria-controls="primaryNav"> 512 <span></span> 513 <span></span> 514 <span></span> 515 </button> 516 </div> 517 </div> 518</nav> 519
520<script> 521 // Mobile menu toggle â opens / closes the primary nav on small screens 522 (function(){ 523 var toggle = document.querySelector('.nav-menu-toggle'); 524 var nav = document.getElementById('primaryNav'); 525 if (!toggle || !nav) return; 526 toggle.addEventListener('click', function(){ 527 var open = nav.classList.toggle('is-open'); 528 nav.classList.toggle('open', open); // matches sl-marketing.scss's `.nav-links.open` rule 529 toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); 530 document.body.classList.toggle('nav-open', open); 531 }); 532 533 // Mobile = the burger button is currently rendered 534 function isMobileNav(){ 535 return toggle && toggle.offsetParent !== null; 536 } 537 538 // Bind tap-to-toggle directly on each dropdown trigger so it runs before any 539 // delegated handlers and we can stopPropagation reliably. 540 nav.querySelectorAll('.nav-dropdown-trigger').forEach(function(trig){ 541 trig.addEventListener('click', function(e){ 542 if (!isMobileNav()) return; // desktop: link navigates as normal 543 e.preventDefault(); 544 e.stopPropagation(); 545 var parent = trig.parentElement; 546 if (!parent || !parent.classList.contains('nav-dropdown')) return; 547 // Close other open dropdowns (accordion behaviour) 548 nav.querySelectorAll('.nav-dropdown.open').forEach(function(d){ 549 if (d !== parent) d.classList.remove('open'); 550 }); 551 parent.classList.toggle('open'); 552 }); 553 }); 554 555 // Close burger menu when a child link inside a submenu is clicked 556 nav.addEventListener('click', function(e){ 557 var t = e.target; 558 if (!t || !t.closest) return; 559 if (t.closest('.nav-dropdown-trigger')) return; // handled above 560 var link = t.closest('a'); 561 if (!link) return; 562 nav.classList.remove('is-open'); 563 nav.classList.remove('open'); 564 toggle.setAttribute('aria-expanded', 'false'); 565 document.body.classList.remove('nav-open'); 566 nav.querySelectorAll('.nav-dropdown.open').forEach(function(d){ d.classList.remove('open'); }); 567 }); 568 })(); 569 570 // Clear stale dashboard localStorage flags (preserved from original) 571 try { 572 localStorage.removeItem('liveClassroomOpen'); 573 localStorage.removeItem('teacherDashboardOpen'); 574 } catch (e) {} 575</script>
575 576 <style> 577 main p, 578 main b, 579 main span, 580 main label, 581 main li, 582 main h1, 583 main h2, 584 main h3, 585 main h4, 586 main h5, 587 main h6, 588 main small { 589 opacity: 0; 590 transition: opacity 0.2s ease-in; 591 } 592 </style> 593 594 595
596<script> 597document.addEventListener("DOMContentLoaded", function () { 598 // Idempotency guard â the copy-localisation partial can end up rendered twice 599 // via the header include chain, which would swap the same text twice 600 // (e.g. "English" â "English Language Arts" â "English Language Arts Language Arts"). 601 if (window.__slLocalisationRan) return; 602 window.__slLocalisationRan = true; 603 604 const country = "GB"; // AU, US, GB, NZ, CA 605//if(country=="GB"){country="UK";} 606 607console.log("country="+country); 608 if (country !== "AU") { 609const terms = { 610 "Foundation / Prep": { US: "Kindergarten", GB: "Reception", CA: "Kindergarten", NZ: "Year 1" }, 611 "Foundation": { US: "Kindergarten", GB: "Reception", CA: "Kindergarten", NZ: "Year 1" }, 612 "Year": { US: "Grade", GB: "Year", CA: "Grade", NZ: "Year" }, 613 "Kindergarten â Year 6": { US: "Kindergarten â Grade 6",GB: "Reception â Year 6",CA: "Kindergarten â Grade 6",NZ: "Year 1 â Year 6" }, 614 "K-6": { US: "Kâ6",GB: "Râ6",CA: "Kâ6",NZ: "1â6" }, 615 "FâYr 6": { US: "Kâ6",GB: "Râ6",CA: "Kâ6",NZ: "Yr1âYr6" }, 616 "Primary School": { US: "Elementary School", GB: "Primary School", CA: "Elementary School", NZ: "Primary School" }, 617 "High School": { US: "High School", GB: "Secondary School", CA: "High School", NZ: "Secondary School" }, 618 //"Year 12": { US: "Grade 12", GB: "Year 13 / Sixth Form", CA: "Grade 12", NZ: "Year 13" }, 619 "Principal": { US: "Principal", GB: "Headteacher", CA: "Principal", NZ: "Principal" }, 620 "Deputy Principal": { US: "Vice Principal", GB: "Deputy Headteacher", CA: "Vice Principal", NZ: "Deputy Principal" }, 621 "Student": { US: "Student", GB: "Student", CA: "Student", NZ: "Student" }, 622 //"Class": { US: "Class", GB: "Class", CA: "Homeroom", NZ: "Class" }, 623 "Class Teacher": { US: "Homeroom Teacher", GB: "Form Tutor", CA: "Homeroom Teacher", NZ: "Class Teacher" }, 624 "Marking": { US: "Grading", GB: "Marking", CA: "Grading", NZ: "Marking" }, 625 "Mark": { US: "Grade", GB: "Mark", CA: "Grade", NZ: "Mark" }, 626 "School Report": { US: "Report Card", GB: "School Report", CA: "Report Card", NZ: "School Report" }, 627 "Revision": { US: "Review", GB: "Revision", CA: "Studying", NZ: "Revision" }, 628 // "Exam": { US: "Test / Exam", GB: "Exam", CA: "Exam", NZ: "Exam" }, 629 "Maths": { US: "Math", GB: "Maths", CA: "Math", NZ: "Maths" }, 630 "Digital Technologies": { US: "Computer Class", GB: "ICT", CA: "Tech Ed / ICT", NZ: "Digital Technologies" },
631 "English": { US: "English Language Arts", GB: "English", CA: "English", NZ: "English" }, 632 "History": { US: "Social Studies", GB: "History", CA: "Social Studies", NZ: "Social Studies" }, 633 "School Holidays": { US: "Vacation", GB: "School Holidays", CA: "School Holidays", NZ: "School Holidays" }, 634 635 "Programme": { US: "Program", GB: "Programme", CA: "Programme", NZ: "Programme" }, 636 "Centre": { US: "Center", GB: "Centre", CA: "Centre", NZ: "Centre" }, 637 "Practice": { US: "Practice", GB: "Practice", CA: "Practice", NZ: "Practice" }, 638 "practising": { US: "practicing", GB: "practising", CA: "practicing", NZ: "practising" }, 639 "Honours": { US: "Honors", GB: "Honours", CA: "Honours", NZ: "Honours" }, 640 "Colour": { US: "Color", GB: "Colour", CA: "Colour", NZ: "Colour" }, 641 "Judgement": { US: "Judgment", GB: "Judgement", CA: "Judgement", NZ: "Judgement" }, 642 "Learnt": { US: "Learned", GB: "Learnt", CA: "Learnt", NZ: "Learnt" }, 643 644 "Customise": { US: "Customize", GB: "Customise", CA: "Customise", NZ: "Customise" }, 645 "Personalise": { US: "Personalize", GB: "Personalise", CA: "Personalise", NZ: "Personalise" }, 646 "Personalised": { US: "Personalized", GB: "Personalised", CA: "Personalised", NZ: "Personalised" }, 647 "Behaviour": { US: "Behavior", GB: "Behaviour", CA: "Behaviour", NZ: "Behaviour" }, 648 "Organisation": { US: "Organization", GB: "Organisation", CA: "Organisation", NZ: "Organisation" }, 649 "Analyse": { US: "Analyze", GB: "Analyse", CA: "Analyse", NZ: "Analyse" }, 650 "Specialisation": { US: "Specialization", GB: "Specialisation", CA: "Specialisation", NZ: "Specialisation" }, 651 "Recognise": { US: "Recognize", GB: "Recognise", CA: "Recognise", NZ: "Recognise" }, 652 "Utilise": { US: "Utilize", GB: "Utilise", CA: "Utilise", NZ: "Utilise" }, 653 "Utilising": { US: "Utilizing", GB: "Utilising", CA: "Utilising", NZ: "Utilising" }, 654 "Authorisation": { US: "Authorization", GB: "Authorisation", CA: "Authorisation", NZ: "Authorisation" }, 655 "Authorise": { US: "Authorize", GB: "Authorise", CA: "Authorise", NZ: "Authorise" }, 656 "Memorise": { US: "Memorize", GB: "Memorise", CA: "Memorise", NZ: "Memorise" }, 657 "Optimise": { US: "Optimize", GB: "Optimise", CA: "Optimise", NZ: "Optimise" }, 658 "Realise": { US: "Realize", GB: "Realise", CA: "Realise", NZ: "Realise" }, 659 "Initialise": { US: "Initialize", GB: "Initialise", CA: "Initialise", NZ: "Initialise" }, 660 661 "Defence": { US: "Defense", GB: "Defence", CA: "Defence", NZ: "Defence" }, 662 "Organising": { US: "Organizing", GB: "Organising", CA: "Organizing", NZ: "Organising" }, 663 "Organisational": { US: "Organizational",GB: "Organisational",CA: "Organizational",NZ: "Organisational" }, 664 "Analysed": { US: "Analyzed", GB: "Analysed", CA: "Analyzed", NZ: "Analysed" }, 665 "Apologise": { US: "Apologize", GB: "Apologise", CA: "Apologize", NZ: "Apologise" }, 666 "Dialogue": { US: "Dialog", GB: "Dialogue", CA: "Dialogue", NZ: "Dialogue" }, 667 "Catalogue": { US: "Catalog", GB: "Catalogue", CA: "Catalogue", NZ: "Catalogue" }, 668 "Aluminium": { US: "Aluminum", GB: "Aluminium", CA: "Aluminium", NZ: "Aluminium" }, 669 "Traveller": { US: "Traveler", GB: "Traveller", CA: "Traveller", NZ: "Traveller" }, 670 "Travelling": { US: "Traveling", GB: "Travelling", CA: "Travelling", NZ: "Travelling" }, 671 "Cancelled": { US: "Canceled", GB: "Cancelled", CA: "Cancelled", NZ: "Cancelled" }, 672 "Cancelling": { US: "Canceling", GB: "Cancelling", CA: "Cancelling", NZ: "Cancelling" }, 673 "Fuelled": { US: "Fueled", GB: "Fuelled", CA: "Fuelled", NZ: "Fuelled" }, 674 "Enrol": { US: "Enroll", GB: "Enrol", CA: "Enrol", NZ: "Enrol" }, 675 "Fulfil": { US: "Fulfill", GB: "Fulfil", CA: "Fulfill", NZ: "Fulfil" }, 676 "Instalment": { US: "Installment", GB: "Instalment", CA: "Instalment", NZ: "Instalment" }, 677 "Practise": { US: "Practice", GB: "Practise", CA: "Practise", NZ: "Practise" }, 678 "Acknowledgement":{ US: "Acknowledgment",GB: "Acknowledgement",CA: "Acknowledgment",NZ: "Acknowledgement" }, 679 "Manoeuvre": { US: "Maneuver", GB: "Manoeuvre", CA: "Manoeuvre", NZ: "Manoeuvre" }, 680 "Paediatric": { US: "Pediatric", GB: "Paediatric", CA: "Paediatric", NZ: "Paediatric" } 681 682/* 683 "Recess / Break": { US: "Recess", GB: "Break Time", CA: "Recess", NZ: "Morning Tea /
683Lunch" }, 684 "Relief Teacher": { US: "Substitute Teacher", GB: "Supply Teacher", CA: "Substitute Teacher", NZ: "Relief Teacher" }, 685 "PE": { US: "PE / Gym", GB: "PE", CA: "PE", NZ: "PE" }, 686 "Timetable": { US: "Schedule", GB: "Timetable", CA: "Schedule", NZ: "Timetable" }, 687 "Learning Support": { US: "SPED", GB: "SEN", CA: "Special Education", NZ: "SEN / Learning Support"}, 688 "Gifted & Talented": { US: "Gifted and Talented", GB: "More Able / G&T", CA: "Gifted", NZ: "Extension / Gifted" }, 689 "Enrolment": { US: "Enrollment", GB: "Enrolment", CA: "Enrolment", NZ: "Enrolment" }, 690 "Labour": { US: "Labor", GB: "Labour", CA: "Labour", NZ: "Labour" }, 691 "Licence": { US: "License", GB: "Licence", CA: "Licence", NZ: "Licence" }, 692 "Ageing": { US: "Aging", GB: "Ageing", CA: "Ageing", NZ: "Ageing" }, 693 "Tonne": { US: "Ton", GB: "Tonne", CA: "Tonne", NZ: "Tonne" }, 694 "Modelled": { US: "Modeled", GB: "Modelled", CA: "Modelled", NZ: "Modelled" }, 695 "Fulfil": { US: "Fulfill", GB: "Fulfil", CA: "Fulfil", NZ: "Fulfil" }, 696 "Counsellor": { US: "Counselor", GB: "Counsellor", CA: "Counsellor", NZ: "Counsellor" }, 697 "Dialogue": { US: "Dialog", GB: "Dialogue", CA: "Dialogue", NZ: "Dialogue" } 698 */ 699 700}; 701 702 703 704 function preserveCase(from, to) { 705 if (from === from.toUpperCase()) return to.toUpperCase(); 706 if (from === from.toLowerCase()) return to.toLowerCase(); 707 if (from[0] === from[0].toUpperCase()) return to[0].toUpperCase() + to.slice(1); 708 return to; 709 } 710 711 function replaceTerms(countryCode) { 712 // Walk every text node in the document body once. Skip nodes inside site chrome 713 // (nav/header/footer/country-bar/modals/dropdowns), script/style/noscript, and anything opted out via .no-change. 714 // This captures text directly inside any element â including <div> wrappers that don't use <p>/<span>. 715 const EXCLUDE_SEL = "nav, header, footer, script, style, noscript, .no-change, .country-bar, .modal, .nav-dropdown-menu, .nav-links"; 716 717 const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, { 718 acceptNode: (node) => { 719 if (!node.parentElement) return NodeFilter.FILTER_REJECT; 720 if (!node.nodeValue || !node.nodeValue.trim()) return NodeFilter.FILTER_REJECT; 721 if (node.parentElement.closest(EXCLUDE_SEL)) return NodeFilter.FILTER_REJECT; 722 return NodeFilter.FILTER_ACCEPT; 723 } 724 }); 725 726 const textNodes = []; 727 while (walker.nextNode()) { 728 textNodes.push(walker.currentNode); 729 } 730 731 textNodes.forEach(node => { 732 let text = node.nodeValue; 733 const originalText = text; 734 735 Object.entries(terms).forEach(([key, translations]) => { 736 const target = translations[countryCode]; 737 if (!target || target === "Either") return; 738 739 // Escape regex metacharacters in the key (handles dots, parens, etc.) 740 const safeKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 741 const pattern = new RegExp(`\\b(${safeKey})(s?)\\b`, "gi"); 742 743 text = text.replace(pattern, (match, word, plural) => { 744 let replaced = preserveCase(word, target); 745 if (plural && !replaced.endsWith('s')) replaced += 's'; 746 return replaced; 747 }); 748 }); 749 750 if (text !== originalText) { 751 node.nodeValue = text; 752 const el = node.parentElement; 753 if (el) { 754 el.style.visibility = "visible"; 755 el.style.transition = "opacity 0.4s ease"; 756 el.style.opacity = 1; 757 } 758 } 759 }); 760 761 762 763 } 764 765 replaceTerms(country); 766 767 document.querySelectorAll("p, b, span, label, li, h1, h2, h3, h4, h5, h6") 768 .forEach(el => { 769 el.style.opacity = "1"; 770 771 }); 772 } 773if (country !== "AU") { 774$('<style>') 775 .prop('type', 'text/css') 776 .html('p, b, span, label, li, h1, h2, h3, h4, h5, h6 { opacity: 1!important; }') 777 .appendTo('head'); 778} 779}); 780 781</script>
781 782 </div> 783 </nav> 784 </header> 785 <main> 786<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400&display=swap"> 787<style id="sl-signup-theme"> 788/* Do not apply marketing's global reset to Bootstrap, Google or Stripe iframes. */ 789.sl-signup-root, .sl-signup-supplement, body.sl-signup-page .swal2-container, body.sl-signup-page .modal { 790 --blue: #2D5BFF; --blue-dark: #1E40C8; --blue-soft: #EEF2FF; 791 --ink: #0F172A; --ink-2: #334155; --muted: #64748B; 792 --line: #E2E8F0; --bg: #FFFFFF; --bg-2: #F8FAFC; 793 --yellow: #FEF3C7; --yellow-deep: #F59E0B; 794 --green: #D1FAE5; --green-deep: #059669; 795 --pink: #FCE7F3; --pink-deep: #DB2777; 796 --purple: #EDE9FE; --purple-deep: #7C3AED; 797 --orange: #FFEDD5; --orange-deep: #EA580C; 798 --radius: 16px; --radius-sm: 10px; 799 --shadow-sm: 0 1px 2px rgba(15,23,42,.04), 0 1px 3px rgba(15,23,42,.06); 800 --shadow-md: 0 4px 6px -1px rgba(15,23,42,.06), 0 2px 4px -1px rgba(15,23,42,.04); 801 --shadow-lg: 0 20px 40px -15px rgba(15,23,42,.15), 0 8px 16px -8px rgba(15,23,42,.08); 802 --danger: #B91C1C; --danger-soft: #FEF2F2; 803 font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 804 color: var(--ink-2); font-size: 16px; line-height: 1.55; 805} 806.sl-signup-root *, .sl-signup-supplement * { box-sizing: border-box; } 807.sl-signup-root.sl-signup-flow { max-width: 1180px; width: 100%; padding: 40px 24px 24px !important; margin: 0 auto; } 808.sl-signup-root.sl-signup-flow[data-signup-step="10"] { padding-top: 0 !important; } 809.sl-signup-root h1, .sl-signup-root h2, .sl-signup-root h3, .sl-signup-root h4, 810.sl-signup-supplement h2, .sl-signup-supplement h3 { color: var(--ink); font-family: inherit; letter-spacing: -.02em; } 811.sl-signup-root h1, .sl-signup-root .hero-text { font-size: clamp(28px, 3.5vw, 40px) !important; font-weight: 800; line-height: 1.15; } 812.sl-signup-root h2, .sl-signup-root > .row h3 { font-size: clamp(26px, 3vw, 36px); font-weight: 800; line-height: 1.2; } 813.sl-signup-root h3, .sl-signup-supplement h3 { font-size: 22px; font-weight: 700; line-height: 1.25; } 814.sl-signup-root h4 { font-size: 20px; font-weight: 700; line-height: 1.3; } 815.sl-signup-root h5 { color: var(--ink-2); font-size: 16px; font-weight: 400; line-height: 1.55; } 816.sl-signup-root p { line-height: 1.55; } 817.sl-signup-root a:not(.btn), .sl-signup-supplement a:not(.btn) { color: var(--blue); } 818.sl-signup-root .sl-signup-eyebrow { display: inline-block; padding: 6px 14px; margin-bottom: 14px; border-radius: 999px; background: var(--blue-soft); color: var(--blue); font-size: 12px; font-weight: 700; line-height: 1.5; letter-spacing: .08em; text-transform: uppercase; } 819.sl-signup-root.sl-signup-parent .sl-signup-eyebrow { background: var(--orange); color: var(--orange-deep); } 820.sl-signup-root.sl-signup-school .sl-signup-eyebrow { background: var(--green); color: var(--green-deep); } 821.sl-signup-root .sl-signup-intro { max-width: 640px; margin: 8px auto 24px; color: var(--muted); font-size: 16px; } 822.sl-signup-root.sl-signup-flow:not([data-signup-step="10"]) #registration-content { 823 max-width: 700px !important; width: 100% !important; min-height: 0 !important; 824 border: 1px solid var(--line);
824 border-top: 4px solid var(--blue); border-radius: 20px !important; 825 background: var(--bg); box-shadow: var(--shadow-md) !important; padding: 28px 32px !important; 826} 827.sl-signup-root.sl-signup-parent:not([data-signup-step="10"]) #registration-content { border-top-color: var(--orange-deep); } 828.sl-signup-root.sl-signup-school #registration-content { border-top-color: var(--green-deep); } 829.sl-signup-root.sl-signup-parent[data-signup-step="2"] #registration-content, 830.sl-signup-root.sl-signup-parent[data-signup-step="3"] #registration-content, 831.sl-signup-root.sl-signup-parent[data-signup-step="100"] #registration-content, 832.sl-signup-root.sl-signup-flow[data-signup-step="4"] #registration-content { max-width: 1100px !important; } 833.sl-signup-root form#create-account { margin: 0 !important; } 834.sl-signup-root .form-group { margin-bottom: 20px; } 835.sl-signup-root label:not(.form-check-label), body.sl-signup-page .swal2-popup label:not(.form-check-label) { 836 display: block; font-weight: 600; font-size: 14px; color: var(--ink); margin-bottom: 7px; line-height: 1.5; 837} 838.sl-signup-root .form-control, .sl-signup-root select:not([multiple]), 839body.sl-signup-page .swal2-popup select, body.sl-signup-page .swal2-popup input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]) { 840 font-family: inherit; font-size: 16px; color: var(--ink); background-color: var(--bg); 841 border: 1px solid var(--line); border-radius: var(--radius-sm); width: 100%; 842 min-height: 48px; height: auto; padding: 11px 14px; line-height: 1.5; box-shadow: none; 843 transition: border-color .15s ease, box-shadow .15s ease; 844} 845.sl-signup-root .form-control::placeholder { color: var(--muted); opacity: .9; } 846.sl-signup-root .form-control:focus, .sl-signup-root select:focus, 847body.sl-signup-page .swal2-popup input:focus, body.sl-signup-page .swal2-popup select:focus { 848 border-color: var(--blue); outline: 0; box-shadow: 0 0 0 3px rgba(45,91,255,.14); 849} 850.sl-signup-root .form-control.is-valid, .sl-signup-root .form-control.border-success { border-color: var(--green-deep) !important; } 851.sl-signup-root .form-control.is-invalid, .sl-signup-root .form-control.border-danger { border-color: var(--danger) !important; } 852.sl-signup-root .form-control.is-valid, .sl-signup-root .form-control.is-invalid { padding-right: 38px; } 853.sl-signup-root input[type="checkbox"], .sl-signup-root input[type="radio"] { accent-color: var(--blue); width: 18px; height: 18px; cursor: pointer; } 854.sl-signup-root .form-check { padding-left: 28px; } 855.sl-signup-root .form-check-input { margin-left: -28px; margin-top: 3px; } 856.sl-signup-root .form-check-label { cursor: pointer; color: var(--ink-2); font-size: 14px; line-height: 1.65; } 857.sl-signup-root .terms { margin-left: 0; margin-right: 0; margin-top: 24px !important; padding: 16px; background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius); } 858.sl-signup-root .terms .form-control-plaintext { color: var(--ink); font-size: 14px; font-weight: 600; margin-bottom: 8px; padding: 0; } 859.sl-signup-root .terms > .col-md-12 { padding-left: 0; padding-right: 0; } 860.sl-signup-root small, .sl-signup-root .small { font-size: 13px; line-height: 1.5; } 861.sl-signup-root .form-text, .sl-signup-root .help-block { display: block; color: var(--muted); margin-top: 7px; } 862.sl-signup-root .btn, body.sl-signup-page .swal2-popup .swal2-styled, 863body.sl-signup-page .swal2-popup .btn, body.sl-signup-page .modal .btn { 864 font-family: inherit; display: inline-flex; align-items: center; justify-content: center; gap: 8px; 865 border: 1px solid transparent; border-radius: 999px; font-size: 15px; font-weight: 600; 866 padding: 11px 20px; line-height: 1.5; min-height: 46px; max-height: none !important; 867 text-decoration: none; white-space: normal; cursor: pointer; transition: background .15s ease, transform .15s ease; 868} 869.sl-signup-root .btn-lg { padding: 14px 26px; font-size: 16px; } 870.sl-signup-root .btn-primary, .sl-signup-root .btn-submit, body.sl-signup-page .swal2-popup .swal2-confirm, 871body.sl-signup-page .swal2-popup .btn-primary, body.sl-signup-page .modal .btn-primary { 872 color: var(--bg) !important; background: var(--blue) !important; border-color: var(--blue) !important; 873 box-shadow: 0 4px 14px rgba(45,91,255,.22); 874} 875.sl-signup-root .btn-primary:hover, .sl-signup-root .btn-submit:hover, body.sl-signup-page .swal2-popup .swal2-confirm:hover { background: var(--blue-dark) !important; border-color: var(--blue-dark) !important; } 876.sl-signup-root .btn-secondary, .sl-signup-root .btn-light, .sl-signup-root .btn-outline-primary, 877body.sl-signup-page .swal2-popup .swal2-cancel, body.sl-signup-page .swal2-popup .swal2-deny, body.sl-signup-page .modal .btn-secondary { 878 color: var(--ink) !important; background: var(--bg) !important; border-color: var(--line) !important; box-shadow: none; 879} 880.sl-signup-root .btn-secondary:hover, .sl-signup-root .btn-light:hover { background: var(--bg-2) !important; } 881.sl-signup-root .btn:focus-visible, body.sl-signup-page .swal2-popup button:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; } 882.sl-signup-root .btn.disabled, .sl-signup-root .btn:disabled { opacity: .55;
882 cursor: not-allowed; transform: none; } 883.sl-signup-root .input-group { flex-wrap: nowrap; align-items: stretch; } 884.sl-signup-root .input-group > .form-control { min-width: 0; height: auto !important; border-radius: var(--radius-sm) 0 0 var(--radius-sm); } 885.sl-signup-root .input-group-append { max-height: none !important; } 886.sl-signup-root .input-group-append .btn { border-radius: 0 var(--radius-sm) var(--radius-sm) 0 !important; padding: 8px 15px; box-shadow: none; } 887.sl-signup-root .text-success { color: var(--green-deep) !important; } 888.sl-signup-root .text-danger, .sl-signup-root .error-message { color: var(--danger) !important; } 889.sl-signup-root .text-primary { color: var(--blue) !important; } 890.sl-signup-root .password-feedback:not(:empty) { margin-top: 10px; padding: 12px 14px; background: var(--bg-2); border-radius: var(--radius-sm); } 891.sl-signup-root .password-feedback li { list-style: none; padding: 3px 0; gap: 10px; max-width: none !important; line-height: 1.55; font-size: 13px !important; } 892.sl-signup-root .sl-signup-error-summary { margin: 0 0 20px; padding: 16px 20px; background: var(--danger-soft); color: var(--danger); border: 1px solid var(--danger); border-radius: var(--radius); } 893.sl-signup-root .sl-signup-error-summary ul { margin: 6px 0 0; padding-left: 20px; } 894.sl-signup-root .sl-signup-google-area { margin: 0 0 24px !important; gap: 14px; } 895.sl-signup-root .sl-signup-google-area #buttonDiv { max-width: 100%; min-height: 44px !important; } 896.sl-signup-root .sl-signup-google-area .loading-google { min-height: 44px !important; border-radius: 999px; } 897.sl-signup-root .sl-signup-divider { display: flex; align-items: center; gap: 14px; width: 100%; margin: 4px 0 0 !important; font-size: 13px; color: var(--muted); font-weight: 400; } 898.sl-signup-root .sl-signup-divider::before, .sl-signup-root .sl-signup-divider::after { content: ''; height: 1px; flex: 1; background: var(--line); } 899.sl-signup-root .sl-google-unavailable { max-width: 320px; text-align: center; color: var(--muted); font-size: 13px; } 900.sl-signup-root .sl-signup-progress { transform: none !important; max-width: 700px; margin: 0 auto 24px !important; } 901.sl-signup-root .sl-signup-progress .progress-span { font-size: 12px; font-weight: 500; color: var(--muted); white-space: normal; text-align: left; } 902.sl-signup-root .progress-current, .sl-signup-root .progress-future, .sl-signup-root .progress-past { 903 display: flex; align-items: center; justify-content: center; width: 32px; min-width: 32px; height: 32px; 904 border-radius: 50%; font-size: 14px; font-weight: 600; line-height: 1; border: 0; box-shadow: none; 905 background: var(--bg-2); color: var(--muted); 906} 907.sl-signup-root .progress-current { background: var(--blue); color: var(--bg); } 908.sl-signup-root .progress-past { background: var(--blue-soft); color: var(--blue); } 909.sl-signup-root .sl-signup-progress-line { height: 2px; width: 100%; background: var(--line); } 910.sl-signup-root .back-to-pricing, .sl-signup-root .back-to-search, .sl-signup-root h3 > .cancel-payment { color: var(--muted); font-size: 20px !important; vertical-align: middle; } 911.sl-signup-root .sl-school-form { width: 100%; max-width: 100%; margin: 0; padding: 0; } 912.sl-signup-root .sl-school-search-box { background: var(--blue-soft) !important; border-radius: var(--radius); padding: 16px !important; } 913.sl-signup-root #results .form-check { padding: 14px 14px 14px 42px; margin: 8px 0; border: 1px solid var(--line); border-radius: var(--radius-sm); } 914.sl-signup-root #results .form-check-input { margin-left: -28px; } 915.sl-signup-root .card { border: 1px solid var(--line); border-radius: 20px; background: var(--bg); box-shadow: var(--shadow-sm); } 916.sl-signup-root.sl-signup-invitation { max-width: 740px; width: 100%; padding: 40px 24px 64px; margin: auto; } 917.sl-signup-root.sl-signup-invitation .logo { display: block; width: 180px; max-width: 60%; margin: 0 auto 24px !important; } 918.sl-signup-root .sl-invitation-intro { text-align: center; padding: 0 12px; } 919.sl-signup-root .sl-invitation-intro p { overflow-wrap: anywhere; } 920.sl-signup-root .sl-invitation-form { width: 100%; max-width: 640px; margin: 24px auto 0 !important; padding: 28px 32px !important;
920 border-top: 4px solid var(--blue); } 921.sl-signup-root.sl-signup-legacy { padding: 28px 24px; background: var(--bg); border: 1px solid var(--line); border-top: 4px solid var(--blue); border-radius: 20px; box-shadow: var(--shadow-md); } 922.sl-signup-supplement { max-width: 1180px; margin: 40px auto 0 !important; padding: 32px 24px !important; } 923.sl-signup-supplement .testimonial-inner { height: 100%; margin: 0; border: 1px solid var(--line); background: var(--bg) !important; border-radius: 20px !important; box-shadow: var(--shadow-sm) !important; padding: 24px !important; } 924.sl-signup-supplement .testimonial-inner p.pt-5 { padding-top: 0 !important; } 925.sl-signup-supplement .testimonial-author { color: var(--ink); font-weight: 600; margin-bottom: 0; } 926.sl-signup-supplement .bubble-holder { display: none; } 927.sl-signup-supplement > .px-xl-5, .sl-signup-supplement .row.px-xl-5 { margin-left: 0 !important; margin-right: 0 !important; padding-left: 0 !important; padding-right: 0 !important; } 928.sl-signup-supplement img:not(.logo) { max-width: 100%; height: auto; border-radius: var(--radius); } 929/* Dialogs are appended to body by SweetAlert/Bootstrap, outside the page wrapper. */ 930body.sl-signup-page .swal2-container { z-index: 20000 !important; padding: 20px; } 931body.sl-signup-page .swal2-popup { font-family: inherit; font-size: 16px; color: var(--ink-2); width: min(640px, 100%); max-width: 100%; max-height: calc(100dvh - 40px); overflow-y: auto; border: 1px solid var(--line); border-radius: 20px !important; padding: 24px 28px; box-shadow: var(--shadow-lg); } 932body.sl-signup-page .swal2-title, body.sl-signup-page .swal2-popup h3 { color: var(--ink); font-family: inherit; font-weight: 700; font-size: 24px; line-height: 1.25; letter-spacing: -.02em; padding: 0; } 933body.sl-signup-page .swal2-html-container, body.sl-signup-page .swal2-content { font-size: 16px; line-height: 1.55; color: var(--ink-2); margin: 16px 0 0; padding: 0; overflow-wrap: anywhere; } 934body.sl-signup-page .swal2-popup a { color: var(--blue); } 935body.sl-signup-page .swal2-actions { gap: 10px; margin: 22px 0 0; flex-wrap: wrap; } 936body.sl-signup-page .swal2-popup .swal2-styled { margin: 0; position: static !important; } 937body.sl-signup-page .swal2-popup .swal2-confirm { max-width: 100%; } 938body.sl-signup-page .swal2-validation-message { font-size: 14px; background: var(--danger-soft); color: var(--danger); border-radius: var(--radius-sm); margin: 14px 0 0; padding: 12px; } 939body.sl-signup-page .swal2-popup .verify-input-container { gap: 12px; flex-wrap: wrap; } 940body.sl-signup-page .swal2-popup #v_code { max-width: 220px; letter-spacing: .15em; font-variant-numeric: tabular-nums; } 941body.sl-signup-page .sl-google-intro { margin-bottom: 20px; text-align: left; } 942body.sl-signup-page .sl-google-location { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; text-align: left; } 943body.sl-signup-page .sl-google-region-status { grid-column: 1 / -1; margin: 0; color: var(--muted); font-size: 13px; } 944body.sl-signup-page .sl-google-terms { text-align: left; margin: 18px 0 0; padding: 16px; background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius); font-size: 14px; } 945body.sl-signup-page .sl-google-terms p { margin: 0; } 946body.sl-signup-page .modal { z-index: 20100; } 947body.sl-signup-page .modal-content { border: 1px solid var(--line); border-radius: 20px; box-shadow: var(--shadow-lg); overflow: hidden; } 948body.sl-signup-page .modal-header { background: var(--blue) !important; } 949body.sl-signup-page .modal-body { color: var(--ink-2); font-size: 15px; } 950@media (max-width: 767px) { 951 .sl-signup-root.sl-signup-flow { padding: 28px 16px 20px !important; } 952 .sl-signup-root.sl-signup-flow:not([data-signup-step="10"]) #registration-content { padding: 24px 20px !important; } 953 .sl-signup-root.sl-signup-flow > .row > [class*="col-"] { padding-left: 15px !important; padding-right: 15px !important; } 954 .sl-signup-root .sl-signup-intro { font-size: 14px; margin-bottom: 20px; } 955 .sl-signup-root .terms { margin-left: 0; margin-right: 0; padding: 14px; } 956 .sl-signup-root.sl-signup-invitation { padding: 28px 16px 40px; } 957 .sl-signup-root .sl-invitation-form { padding: 24px 20px !important; } 958 .sl-signup-root .btn-lg { width: 100%; } 959 .sl-signup-root #submit { width: 100%; } 960 .sl-signup-supplement { padding: 24px 16px !important; } 961 body.sl-signup-page .swal2-container { padding: 12px; } 962 body.sl-signup-page .swal2-popup { padding: 24px 18px; max-height: calc(100dvh - 24px); } 963 body.sl-signup-page .sl-google-location { grid-template-columns: 1fr; gap: 14px; } 964 body.sl-signup-page .swal2-actions { width: 100%; } 965 body.sl-signup-page .swal2-popup .swal2-confirm { flex-basis: 100%; } 966} 967@media (prefers-reduced-motion: reduce) { 968 .sl-signup-root .btn, .sl-signup-root .form-control, body.sl-signup-page .swal2-popup { transition: none; } 969} 970</style>
971<script> 972(function () { 973 function markSignupPage() { if (document.body) document.body.classList.add('sl-signup-page'); } 974 if (document.body) markSignupPage(); 975 else document.addEventListener('DOMContentLoaded', markSignupPage); 976}()); 977</script>
977 978 979
979<script> 980 window.dataLayer = window.dataLayer || []; 981 window.dataLayer.push({"event":"Teacher Account","Action":"Creation","Step":"1","Step Name":"Create"}); 982 </script>
982 983 984 985 986 987 988 989<div data-signup-step="1" class="sl-signup-root sl-signup-flow sl-signup-teacher section container mt-0 pb-0" style="padding-top:2.5rem !important;"> 990 991 992 <div class="row"> 993 <div class="offset-xl-2 col-xl-8 pl-0 text-center"> 994 <span class="sl-signup-eyebrow">For teachers</span> 995 <style> 996 .progress-current{ 997 border-radius: 50%; 998 background-color: #a4d0ff; 999 width: 2.75rem; 1000 min-width: 2.75rem; 1001 height: 2.75rem; 1002 line-height: 2.25rem; 1003 font-size: 1.5rem; 1004 font-weight: 500; 1005 color: #418fe7; 1006 border: 0.25rem solid white; 1007 box-shadow: 0 0 5px 5px lightgray; 1008 } 1009 .progress-future, .progress-past { 1010 border-radius: 50%; 1011 background-color: #72b6ff; 1012 width: 2.75rem; 1013 min-width: 2.75rem; 1014 height: 2.75rem; 1015 line-height: 2.75rem; 1016 font-size: 1.5rem; 1017 font-weight: 500; 1018 color: #418fe7; 1019 } 1020 .progress-span{ 1021 font-weight: 500; 1022 color: #2c71ca; 1023 white-space: nowrap; 1024 } 1025 </style> 1026 1027 <h3 class="mt-2 pb-1"><i class="fas fa-arrow-left mr-3 back-to-pricing" style="font-size: 2rem;font-weight: 900;cursor:pointer;"></i>Create a Teacher Account</h3> 1028
1028<script> 1029 $(function(){ 1030 $('.back-to-pricing').on('click', function(){ 1031 window.location.href = `/`; 1032 }) 1033 }) 1034 </script>
1034 1035 1036 <p class="sl-signup-intro">Create your account, then choose your school.</p> 1037 </div> 1038 </div> 1039 <div class="row"> 1040 <div class="offset-xl-2 col-xl-8 pl-0 text-center pb-3"> 1041 <p>Used in schools and homes since 2009 across Australia, New Zealand, USA, UK and Canada<br/> 1042 1043 </div> 1044 </div> 1045 <div class="d-flex w-100 flex-column align-items-center"> 1046 <div id="registration-content" class=" pt-md-0" style=" 1047 max-width: 700px; 1048 width: 95%; 1049 border-radius: 20px; 1050 box-shadow: 0 0 10px #708adb; 1051 min-height: 620px; 1052 "> 1053 1054 1055 <section id="step_1-section"> 1056 1057 1058 1059 <!-- 1060<div class="pb-3 pb-md-4 mb-2"> 1061 <ul id="breadcrumbs" class="d-flex justify-content-around align-items-center bg-info rounded p-0 my-3"> 1062 <li class="curr">1. Create Account</li> 1063 <li class="sep">»</li> 1064 <li class="">2. Select</li> 1065 <li class="sep">»</li> 1066 <li class="">3. Finished !</li> 1067 </ul> 1068 </div> 1069= 1070--> 1071<style> 1072 1073 .refund-badge { 1074 1075 max-width: 7rem; 1076 /* top: -3.8rem; */ 1077 right: -50px !important; 1078 z-index: 1; 1079 float: right; 1080 } 1081 1082 #create-using-email, .parent-sign-in, .loading-google { 1083 -webkit-border-radius: 4px; 1084 border-radius: 4px; 1085 -webkit-box-sizing: border-box; 1086 box-sizing: border-box; 1087 -webkit-transition: background-color .218s, border-color .218s; 1088 transition: background-color .218s, border-color .218s; 1089 background-color: #fff; 1090 border: 1px solid #dadce0; 1091 color: #3c4043; 1092 cursor: pointer; 1093 font-family: "Google Sans", arial, sans-serif; 1094 font-size: 14px; 1095 height: 32px; 1096 letter-spacing: 0.25px; 1097 min-width: 188px; 1098 line-height: 13px; 1099 } 1100 1101 #create-using-email:hover { 1102 -webkit-box-shadow: none; 1103 box-shadow: none; 1104 border-color: #d2e3fc; 1105 outline: none; 1106 background-color: #f7fafe; 1107 } 1108</style> 1109<div style="position:relative"> 1110 <!-- <img class="refund-badge d-none d-md-block" src="https://static.studyladder.co.uk/cdn/site/aa/a6554c9ae7d1.png" alt="14-day money back guarantee">--> 1111 <div class="row"> 1112 1113 <div class="col-12"> 1114 1115
1115<script>/* Shared by the parent and teacher signup forms; included inline by PHP. */ 1116(function (window, document, $) { 1117 'use strict'; 1118 if (window.SLSignupGoogle) return; 1119 1120 var configuration = null; 1121 var initialised = false; 1122 var unavailableTimer = null; 1123 var dialogOpen = false; 1124 1125 function alerts() { return window.Swal || window.swal; } 1126 function escapeHtml(value) { 1127 var element = document.createElement('div'); 1128 element.textContent = String(value == null ? '' : value); 1129 return element.innerHTML; 1130 } 1131 function responseMessage(response) { 1132 if (!response || !response.msg) return 'Your account could not be created. Please try again.'; 1133 if (typeof response.msg === 'string') return response.msg; 1134 if (Array.isArray(response.msg)) { 1135 return response.msg.map(function (error) { 1136 return Array.isArray(error) && error.length === 2 ? String(error[1]) : String(error); 1137 }).join('\n'); 1138 } 1139 return 'Your account could not be created. Please try again.'; 1140 } 1141 function unavailable() { 1142 if (initialised) return; 1143 var target = document.getElementById('buttonDiv'); 1144 if (target) { 1145 target.innerHTML = '<p class="sl-google-unavailable">Google sign-up is unavailable at the moment. You can use the email form below, or reload the page to try Google again.</p>'; 1146 } 1147 } 1148 function initialise() { 1149 if (initialised || !configuration || !document.getElementById('buttonDiv')) return; 1150 if (!window.google || !window.google.accounts || !window.google.accounts.id) return; 1151 try { 1152 var target = document.getElementById('buttonDiv'); 1153 var width = Math.min(320, Math.floor(target.parentElement.clientWidth) || 320); 1154 window.google.accounts.id.initialize({ 1155 client_id: configuration.clientId, 1156 callback: configuration.callback, 1157 context: 'signup' 1158 }); 1159 window.google.accounts.id.disableAutoSelect(); 1160 target.innerHTML = ''; 1161 window.google.accounts.id.renderButton(target, { 1162 theme: 'outline', size: 'large', text: 'signup_with', shape: 'pill', width: width 1163 }); 1164 initialised = true; 1165 window.clearTimeout(unavailableTimer); 1166 } catch (error) { 1167 unavailable(); 1168 } 1169 } 1170 function configure(options) { 1171 configuration = options; 1172 initialise(); 1173 window.clearTimeout(unavailableTimer); 1174 unavailableTimer = window.setTimeout(unavailable, 15000); 1175 } 1176 1177 function signup(response, options) { 1178 var swal = alerts(); 1179 if (dialogOpen) return; 1180 if (!response || typeof response.credential !== 'string' || !response.credential) { 1181 return swal.fire({icon: 'error', title: 'Google sign-up', text: 'Google did not return a sign-up credential. Please try the Google button again.'}); 1182 } 1183 var isParent = options.role === 'parent'; 1184 var form = document.getElementById('create-account'); 1185 var sourceCountry = isParent && form ? form.querySelector('[name="countryId"]') : null; 1186 var sourceRegion = isParent && form ? form.querySelector('[name="regionId"]') : null; 1187 if (isParent && (!sourceCountry || !sourceRegion)) { 1188 return swal.fire({icon: 'error', title: 'Location could not be loaded', text: 'Please reload the signup page and try again.'}); 1189 } 1190 1191 var popup = null; 1192 var countrySelect = null; 1193 var regionSelect = null; 1194 var regionRequest = null; 1195 var regionSequence = 0; 1196 var regionsReadyFor = null; 1197 var active = true; 1198 var submitting = false; 1199 dialogOpen = true; 1200 1201 function isCurrent() { return active && popup && swal.getPopup() === popup; } 1202 function validation(message) { swal.showValidationMessage(escapeHtml(message).replace(/\n/g, '<br>')); } 1203 function setSubmitting(busy) { 1204 submitting = busy; 1205 if (!isCurrent()) return; 1206 swal.getCancelButton().disabled = busy; 1207 if (isParent) { 1208 countrySelect.disabled = busy; 1209 regionSelect.disabled = busy || regionsReadyFor !== countrySelect.value; 1210 } 1211 } 1212 function setRegionStatus(message, retry) { 1213 if (!isCurrent()) return; 1214 var status = popup.querySelector('.sl-google-region-status'); 1215 status.textContent = message; 1216 if (retry) { 1217 var button = document.createElement('button'); 1218 button.type = 'button'; 1219 button.className = 'btn btn-secondary sl-google-retry-regions'; 1220 button.textContent = 'Retry'; 1221 button.addEventListener('click', function () { loadRegions(countrySelect.value, ''); }); 1222 status.appendChild(document.createTextNode(' ')); 1223 status.appendChild(button); 1224 } 1225 } 1226 function loadRegions(countryId, preferredRegion) { 1227 if (submitting) return; 1228 var sequence = ++regionSequence; 1229 if (regionRequest) regionRequest.abort(); 1230 regionsReadyFor = null; 1231 regionSelect.disabled = true; 1232 regionSelect.options.length = 0; 1233 regionSelect.add(new Option(countryId ? 'Loading regionsâ¦' : 'Choose a country first', '')); 1234 swal.getConfirmButton().disabled = true; 1235 swal.resetValidationMessage(); 1236 setRegionStatus(countryId ? 'Loading regionsâ¦' : 'Please choose your country.', false); 1237 if (!countryId) return; 1238 1239 // Reuse the same public endpoint and {code, name} response as school signup. 1240 regionRequest = $.ajax({ 1241 url: '/location/country-regions', method: 'GET', dataType: 'json', timeout: 20000, 1242 data: {country_id: countryId} 1243 }).done(function (result) { 1244 if (!isCurrent() || sequence !== regionSequence || countrySelect.value !== countryId) return; 1245 if (!result || !result.ok || !result.regions) { 1246 setRegionStatus('Regions could not be loaded. Please retry.', true); 1247 return; 1248 } 1249 var regions = $.map(result.regions, function (region) { 1250 if (!region || region.code == null || region.name == null) return null; 1251 return {code: String(region.code), name: String(region.name)}; 1252 }); 1253 regionSelect.options.length = 0; 1254 regionSelect.add(new Option('Choose your state / regi
1254on', '')); 1255 regions.forEach(function (region) { regionSelect.add(new Option(region.name, region.code)); }); 1256 if (!regions.length) { 1257 setRegionStatus('No regions are available for this country. Please check your country or contact support.', true); 1258 return; 1259 } 1260 var hasPreferred = regions.some(function (region) { return region.code === String(preferredRegion); }); 1261 regionSelect.value = hasPreferred ? String(preferredRegion) : (regions.length === 1 ? regions[0].code : ''); 1262 regionSelect.disabled = false; 1263 regionsReadyFor = countryId; 1264 swal.getConfirmButton().disabled = false; 1265 setRegionStatus(regionSelect.value ? '' : 'Please choose your state or region.', false); 1266 }).fail(function (xhr, status) { 1267 if (status === 'abort' || !isCurrent() || sequence !== regionSequence) return; 1268 setRegionStatus('Regions could not be loaded. Please retry.', true); 1269 }); 1270 } 1271 1272 var locationHtml = isParent ? 1273 '<div class="sl-google-location">' + 1274 '<div><label for="sl-google-country">Country</label><select class="form-control" id="sl-google-country" name="google_country"></select></div>' + 1275 '<div><label for="sl-google-region">State / region</label><select class="form-control" id="sl-google-region" name="google_region" disabled></select></div>' + 1276 '<p class="sl-google-region-status" role="status" aria-live="polite"></p>' + 1277 '</div>' : ''; 1278 var terms = isParent ? 'I am 18 years of age or over' : 'I am 18 years of age or over, a qualified teacher or employed by a school'; 1279 1280 return swal.fire({ 1281 title: isParent ? 'Create your parent account' : 'Create your teacher account', 1282 html: '<p class="sl-google-intro">' + (isParent ? 'Check your location, then agree to the terms to finish signing up with Google.' : 'Agree to the terms to finish signing up with Google.') + '</p>' + locationHtml + 1283 '<div class="sl-google-terms"><p>' + terms + ' & agree to the Studyladder <a href="/about/terms" target="_blank" rel="noopener">Terms & Conditions</a>.</p></div>', 1284 footer: '<span>Already have an account? <a href="/login/account">Sign in</a></span>', 1285 width: 640, 1286 confirmButtonText: 'Agree and create account', 1287 cancelButtonText: 'Cancel', 1288 showCancelButton: true, 1289 showLoaderOnConfirm: true, 1290 focusConfirm: !isParent, 1291 allowOutsideClick: function () { return !submitting; }, 1292 allowEscapeKey: function () { return !submitting; }, 1293 customClass: {container: 'sl-signup-google-dialog', popup: 'sl-signup-google-popup'}, 1294 didOpen: function (element) { 1295 popup = element; 1296 if (!isParent) return; 1297 countrySelect = popup.querySelector('#sl-google-country'); 1298 regionSelect = popup.querySelector('#sl-google-region'); 1299 Array.prototype.forEach.call(sourceCountry.options, function (option) { 1300 // Copy option data, not the helper's markup, IDs or event handlers. 1301 countrySelect.add(new Option(option.text, option.value)); 1302 }); 1303 countrySelect.value = sourceCountry.value; 1304 countrySelect.addEventListener('change', function () { loadRegions(countrySelect.value, ''); }); 1305 regionSelect.addEventListener('change', function () { 1306 swal.resetValidationMessage(); 1307 setRegionStatus(regionSelect.value ? '' : 'Please choose your state or region.', false); 1308 }); 1309 loadRegions(countrySelect.value, sourceRegion.value); 1310 }, 1311 preConfirm: function () { 1312 var data = {token: response.credential}; 1313 if (isParent) { 1314 if (!countrySelect.value || !regionSelect.value || regionSelect.disabled || regionsReadyFor !== countrySelect.value) { 1315 validation('Please choose your country and state / regi
1315on before continuing.'); 1316 return false; 1317 } 1318 data.country = countrySelect.value; 1319 data.region = regionSelect.value; 1320 } 1321 setSubmitting(true); 1322 // Return the request: the dialog stays open until creation has really succeeded. 1323 return $.ajax({ 1324 url: isParent ? '/account/parent-signup-google' : '/account/teacher-signup-google', 1325 method: 'POST', dataType: 'json', timeout: 185000, data: data 1326 }).then(function (result) { 1327 setSubmitting(false); 1328 if (!result || result.ok !== true) { 1329 validation(responseMessage(result)); 1330 return false; 1331 } 1332 return result; 1333 }, function () { 1334 setSubmitting(false); 1335 validation('The account request could not be completed. Please try again. If your account was already created, use Sign in below.'); 1336 return false; 1337 }); 1338 }, 1339 willClose: function () { 1340 active = false; 1341 ++regionSequence; 1342 if (regionRequest) regionRequest.abort(); 1343 } 1344 }).then(function (result) { 1345 dialogOpen = false; 1346 active = false; 1347 if (result.isConfirmed && result.value && result.value.ok === true) options.onSuccess(result.value); 1348 return result; 1349 }, function (error) { 1350 dialogOpen = false; 1351 active = false; 1352 throw error; 1353 }); 1354 } 1355 1356 window.SLSignupGoogle = {configure: configure, initialise: initialise, unavailable: unavailable, signup: signup}; 1357 document.addEventListener('DOMContentLoaded', initialise); 1358 window.addEventListener('load', initialise); 1359}(window, document, jQuery)); 1360</script>
1360 1361
1361<script src="https://accounts.google.com/gsi/client" async defer 1362 onload="SLSignupGoogle.initialise()" onerror="SLSignupGoogle.unavailable()"></script>
1362 1363
1363<script> 1364 function handleCredentialResponse(response) { 1365 return SLSignupGoogle.signup(response, {role: 'teacher', onSuccess: doPostPart2}); 1366 } 1367 SLSignupGoogle.configure({ 1368 clientId: '436701450551-qb7rmj3n0i4c4jihgenss78n32bssvg7.apps.googleusercontent.com', 1369 callback: handleCredentialResponse 1370 }); 1371 </script>
1371 1372 <div class="sl-signup-google-area d-flex align-items-center justify-content-center w-100 mb-5 mt-3 flex-column"> 1373 <div id="buttonDiv" style="min-width:180px;min-height:32px;"><div class="w-100 h-100 loading-google d-flex align-items-center justify-content-center" style="min-width:180px;min-height:32px;"><i class="fas fa-circle-notch fa-spin"></i></div></div> 1374 <p class="sl-signup-divider">or sign up with email</p> 1375 <!--div id="emailButtonDiv"><a class='btn btn-light' id='create-using-email'>Sign up using Email</a></div--> 1376 </div> 1377 <form class="m-5" role="form" id="create-account"> 1378 1379 <div class="row"> 1380 <div class="col-md-6"> 1381 <div class="form-group fname-group has-feedback"> 1382 <label for="first-name">First name</label> 1383 <input type="text" class="form-control" placeholder="First name" id="first-name" name="firstname" required=""> 1384 </div> 1385 </div> 1386 1387 <div class="col-md-6"> 1388 <div class="form-group lname-group has-feedback"> 1389 <label for="last-name">Last name</label> 1390 <input type="text" class="form-control" placeholder="Last name" id="last-name" name="surname" required=""> 1391 </div> 1392 </div> 1393 </div> 1394 1395 <div class="form-group email-group has-feedback"> 1396 <label for="email">Email address</label> 1397 <input type="email" class="form-control" placeholder="Email" id="email" name="email" autocomplete="email" required=""> 1398 <small id="emailHelp" class="form-text">Your email address is also your Studyladder 1399 username.</small> 1400 </div> 1401 1402 <div class="form-group pw-group has-feedback"> 1403 <!--input type="password" class="form-control" id="password" name="password" required=""> 1404 <small class="help-block">Password must be at least 4 characters long.</small--> 1405 <label for="password">Password</label> 1406 <div class="input-group"> 1407 <input type="password" class="form-control" id="password" name="password" required="" placeholder="Password" autocomplete="new-password" style="height:38px;"> 1408 <div class="input-group-append" style="max-height:38px;"> 1409 <button class="btn btn-light" type="button" id="togglePassword" aria-label="Show or hide password"><i class="fas fa-eye"></i></button> 1410 </div> 1411 </div> 1412 <div class="password-feedback"></div> 1413 </div> 1414 1415 1416 <div class="form-group row terms has-feedback mt-4"> 1417 <div class="col-md-12"> 1418 <p class="form-control-plaintext">Terms & Conditions.</p> 1419 <div class="form-check"> 1420 <input id="term-check" class="form-check-input" type="checkbox" value=true 1421 name="sasTermsAgreed"> 1422 <label class="form-check-label" for="term-check"> 1423 I am 18 years of age or over, a qualified teacher or employed by a school & agree to the Studyladder <a id="terms-button" 1424 href="#terms-info" 1425 data-toggle="modal">Terms 1426 & Conditions</a>. 1427 </label> 1428 </div> 1429 <small></small> 1430 </div> 1431 </div> 1432 <div class="form-group row mt-4 mb-0"> 1433 <div class="col-md-12 d-flex justify-content-center"> 1434 <input type="hidden" name="user_type" value="teacher"> 1435 <input type="hidden" name="recaptcha" value=""/> 1436 <div class="mt-4 " id="submit"> 1437 <input id="details-submit" type="submit" 1438 class="btn btn-block btn-primary btn-lg px-5 g-recaptcha" 1439 style="border-radius:50px;" 1440 data-sitekey="6LcCpxwUAAAAAGL5imoR7y2uPA28OQBrNs6czsVl" 1441 data-callback="onCreateAccountTeacher" value="Create Account"> 1442 <!-- 1443 <input id="details-submit" type="submit" class="btn btn-block btn-light btn-lg g-recaptcha float-left" style="width:45%" data-sitekey="6LcCpxwUAAAAAGL5imoR7y2uPA28OQBrNs6czsVl" data-callback="onCreateAccountTeacher" value="Free Supervision Account">
1444 <span style="position: absolute; left:50%; margin-left:-10px;padding-top:12px;">OR</span> 1445 <input id="details-submit" type="submit" class="btn btn-block btn-primary btn-lg g-recaptcha float-right" style="width:45%" data-sitekey="6LcCpxwUAAAAAGL5imoR7y2uPA28OQBrNs6czsVl" data-callback="onCreateAccountTeacher" value="Purchase Premium Account">--> 1446 </div> 1447 </div> 1448 </div> 1449 1450 </form> 1451 <!--h4 class="text-center pb-2">I already have an account</h4> 1452 <div class="w-100 d-flex align-items-center justify-content-center"> 1453 <a class='btn btn-light parent-sign-in' href="/login/account?backURL=%2Faccount%2Fteacher%3Ft%3Dteacher">Sign in</a> 1454 </div--> 1455 1456 </div> 1457 1458 <div class="col-12"> 1459 1460 <div id="error-messages-teacher-only" class="alert alert-sl alert-warning collapse"> 1461 <p class="lead"><strong>Teachers Only</strong></p> 1462 <p>This sign up is for a teacher account and is only available to teachers.</p> 1463 <p>If you need any assistance please contact us at <a 1464 href="mailto:[email protected]">[email protected]</a> 1465 </p> 1466 </div> 1467 1468 <div id="error-messages-google" class="alert alert-sl alert-warning collapse"> 1469 <p class="lead"><strong>An account has already been created using the Google account attached to this 1470 email address.</strong></p> 1471 <p>You can only log into this studyladder account using the same Google account that created it.</p> 1472 <p>You can log into your existing account <a href="/login/login">here</a> (use the "sign in to Google" 1473 button at the bottom of the login box).</p> 1474 <p>If you need any assistance getting access to your existing account please contact us at <a 1475 href="mailto:[email protected]">[email protected]</a> 1476 </p> 1477 </div> 1478 1479 <div id="error-messages" class="alert alert-sl alert-warning collapse"> 1480 <p class="lead"><strong>An account for that email already exists.</strong></p> 1481 <p>You can log into your existing account <a href="/login/login">here</a>.</p> 1482 <p>If you have forgotten your password please do a <a href="/login/forgot">password reset</a>.</p> 1483 <p>If you need any assistance getting access to your existing account please contact us at <a 1484 href="mailto:[email protected]">[email protected]</a> 1485 </p> 1486 </div> 1487 1488 <div id="error-messages-confirm" class="alert alert-sl alert-warning collapse"> 1489 <p class="lead"><strong>Confirm email address does not match.</strong></p> 1490 <p>Your 'Email address' and 'Confirm email address' are not the same.</p> 1491 <p>Please recheck they are both correct and the same.</p> 1492 <p>If you need any assistance please contact us at <a 1493 href="mailto:[email protected]">[email protected]</a> 1494 </p> 1495 </div> 1496 1497 1498 <!-- 1499 <div class="card bg-light "> 1500 <div class="card-body"> 1501 <div class="float-right"> 1502 <img class="special-offer-img mt-1" style="width:100px; height:auto" src="/images/info/upgrade-to-premium/sl-premium-logo.jpg"> 1503 </div> 1504 <div> 1505 <h4 class=" pb-1 ">SL Premium</h4> 1506 <span class="price" style="font-size:1.6rem;"> 1507 £4 </span><br class="d-none" /> 1508 <span style="font-size:0.9rem">for 12 months</span> 1509 <br/><span class="pb-3 pt-2 d-block" style="font-size:0.9rem">14 Day money back guarantee</span> 1510 </div> 1511 1512 1513 <h4 class=" pb-1 pt-3 pb-3">OR </h4> 1514 <h4 class="h5" >Free Parent Supervision Account</h4> 1515 <p class="pb-3 " style="font-size:0.9rem">Limited access for student accounts setup by schools</p> 1516 1517 1518 <hr/> 1519 1520 <h4 class="h5 pb-1 pt-3 ">Benefits of Studyladder Premium</h4> 1521 <ul class="check-list pb-3" style="font-size:0.9rem"> 1522 1523 <li>Unlimited activities any time</li> 1524 <li><strong>Up to 5 children</strong> on 1 parent account.</li> 1525 <li>Over 5,000 activities available.</li> 1526 <li>Fun activities & rewards to motivate children.</li> 1527 <li>The same materials used by over 400,000 teachers.</li> 1528 </ul> 1529 1530 1531 </div> 1532 </div> 1533 --> 1534 </div> 1535 1536 </div> 1537</div> 1538<!-- terms info Modal --> 1539<div id="terms-info" class="modal" tabindex="-1" role="dialog" style='z-index:5000;'> 1540 <div class="modal-dialog" role="document" style='min-width:90%;max-width:900px;'> 1541 <div class="modal-content"> 1542 <div class="modal-header bg-medium-dark-blue text-white"> 1543 <h5 class="modal-title">Terms & Conditions</h5> 1544 <button type="button" class="close text-white" data-dismiss="modal"><span class="fa fa-times"></span> 1545 </button> 1546 </div> 1547 <div class="modal-body"> 1548 </div> 1549 <div class="modal-footer"> 1550 <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> 1551 </div> 1552 </div> 1553 </div> 1554</div> 1555
1556<script> 1557 $(document).ready(function () { 1558 const togglePassword = document.querySelector('#togglePassword'); 1559 const password = document.querySelector('#password'); 1560 1561 togglePassword.addEventListener('click', function (e) { 1562 // Toggle the type attribute 1563 const type = password.getAttribute('type') === 'password' ? 'text' : 'password'; 1564 password.setAttribute('type', type); 1565 1566 // Toggle the button text 1567 this.innerHTML = type === 'password' ? '<i class="fas fa-eye"></i>' : '<i class="fas fa-eye-slash"></i>'; 1568 }); 1569 //loads terms from about/terms into modal so users dont have to navigate away from page. 1570 $("#terms-info .modal-body").load("/about/terms #terms-content"); 1571 var emailChecked = false; 1572 $('[name="email"], #email-confirm').on('change', function () { 1573 checkEmail(); 1574 }) 1575 1576 function checkEmail(callback) { 1577 if (!$("#create-account").is(":visible")) { 1578 return; 1579 } 1580 if (!$('[name="email"]').val().length) { 1581 return; 1582 } 1583 $.ajax({ 1584 url: "/secure/check-email-is-new", 1585 method: "POST", 1586 data: {email: $('[name="email"]').val()}, 1587 dataType: "json", 1588 success: function (result) { 1589 if (!result.ok) { 1590 swal.fire({ 1591 html: `<div class="position-relative w-100 mt-4 p-3 alert-danger text-dark border-danger rounded"> 1592 <p>We noticed you already have an account</p> 1593 <p><a href="/login/login">sign in here</a> or <a href="/login/forgot">reset your password</a>.</p> 1594 <small>If you need any assistance getting access to your existing account please contact us at <a 1595 href="mailto:[email protected]">[email protected]</a> 1596 </small> 1597 </div>`, 1598 customClass: { 1599 confirmButton: 'btn btn-primary btn-sm', // Bootstrap 'danger' style for confirm button 1600 }, 1601 buttonsStyling: false 1602 }); 1603 $('[name="email"], #email-confirm').removeClass('border-success').addClass('border-danger'); 1604 } else { 1605 emailChecked = true; 1606 if (callback && typeof callback == "function") { 1607 callback(); 1608 } 1609 } 1610 } 1611 }) 1612 } 1613 1614 $('[name="email"]').on('input', function () { 1615 $(this).removeClass('border-success').removeClass('border-danger'); 1616 emailChecked = false; 1617 }) 1618 $("#email-confirm").on("keyup", function () { 1619 if ($('[name="email"]').val() == $('#email-confirm').val()) { 1620 $('[name="email"], #email-confirm').removeClass('border-danger').addClass('border-success'); 1621 } else { 1622 $('[name="email"], #email-confirm').removeClass('border-success').addClass('border-danger'); 1623 } 1624 }); 1625 $('[name="password"]').on("keyup", function () { 1626 if (checkPassword($('[name="password"]').val()).ok) { 1627 $('[name="password"]').removeClass('border-danger').addClass('border-success'); 1628 $('.password-feedback').html(""); 1629 } else { 1630 $('[name="password"]').removeClass('border-success').addClass('border-danger'); 1631 $('.password-feedback').html(`<ul class="mt-1">${checkPassword($('[name="password"]').val()).desc}</ul>`); 1632 } 1633 }); 1634 1635 }); 1636 1637 function checkPassword(password){ 1638 var minLength = password.length >= 14; 1639 var hasUppercase = /[A-Z]/.test(password); 1640 var hasLowercase = /[a-z]/.test(password); 1641 var hasNumber = /\d/.test(password); 1642 var hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password); 1643 let retVal = ""; 1644 let isOK = true; 1645 if (minLength){ 1646 retVal += `<li class="text-success w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Must be at least 14 characters<i class="far fa-check-circle"></i></li>` 1647 } else { 1648 isOK = false;
1649 retVal += `<li class="text-danger w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Must be at least 14 characters<i class="far fa-times-circle"></i></li>` 1650 } 1651 if (hasUppercase){ 1652 retVal += `<li class="text-success w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 uppercase character<i class="far fa-check-circle"></i></li>` 1653 } else { 1654 isOK = false; 1655 retVal += `<li class="text-danger w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 uppercase character<i class="far fa-times-circle"></i></li>` 1656 } 1657 if (hasLowercase){ 1658 retVal += `<li class="text-success w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 lowercase character<i class="far fa-check-circle"></i></li>` 1659 } else { 1660 isOK = false; 1661 retVal += `<li class="text-danger w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 lowercase character<i class="far fa-times-circle"></i></li>` 1662 } 1663 if (hasNumber){ 1664 retVal += `<li class="text-success w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 number<i class="far fa-check-circle"></i></li>` 1665 } else { 1666 isOK = false; 1667 retVal += `<li class="text-danger w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 number<i class="far fa-times-circle"></i></li>` 1668 } 1669 if (hasSpecialChar){ 1670 retVal += `<li class="text-success w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 special character - !@#$%^&*(),.?":{}|<><i class="far fa-check-circle"></i></li>` 1671 } else { 1672 isOK = false; 1673 retVal += `<li class="text-danger w-100 d-flex align-items-center justify-content-between" style="font-size:12px; max-width:320px; opacity:1;">Has at least 1 special character - !@#$%^&*(),.?":{}|<><i class="far fa-times-circle"></i></li>` 1674 } 1675 return {ok: isOK, desc: retVal}; 1676 } 1677 1678 //jquery chainable function. 1679 $.fn.setFeedback = function(state) { 1680 if (state == 'valid') 1681 this.addClass("is-valid").removeClass('is-invalid'); 1682 if (state == 'invalid') 1683 this.removeClass("is-valid").addClass('is-invalid'); 1684 return this; 1685 } 1686 1687 $("form#create-account").on('change', function() { 1688 //reenable button for submission after fields on form change 1689 $("#details-submit").removeClass('disabled').attr('disabled', false); 1690 //reenable recaptcha after failed submission (tokens are single use) 1691 grecaptcha.reset(); 1692 }); 1693 1694 //Use the stronger page-specific policy when one is supplied (teacher signup), 1695 //otherwise retain the normal account minimum (including parent signup). 1696 $("#password").on('focusout', function() { 1697 var valid = typeof checkPassword === 'function' 1698 ? checkPassword($(this).val()).ok 1699 : $(this).val().length >= 4; 1700 1701 $(this).setFeedback(valid ? 'valid' : 'invalid'); 1702 }); 1703 1704 //trigger error state if password does not meet minimum required character length 1705 $("#email").on('focusout', function() { 1706 if ( !isValidEmailAddress( $(this).val() ) ) { 1707 $(this).setFeedback('invalid'); 1708 msg = "The email address you have entered does not appear to be valid."; 1709 } else if ( $(this).val().match(/^[_a-z0-9-]+([\.\+_a-z0-9-]+)*@studyladder+(\.[a-z0-9-]+)*\.[a-z]+$/i) ) { 1710 $(this).setFeedback('invalid'); 1711 msg = "The email address you have entered is unavailable."; 1712 } else { 1713 $(this).setFeedback('valid'); 1714 } 1715 }); 1716 1717 $("#email-confirm").on('focusout', function() { 1718 if ( !isValidEmailAddress( $(this).val() ) ) { 1719 $(this).setFeedback('invalid'); 1720 msg = "The email address you have entered does not appear to be valid."; 1721 } else if ( $(this).val().match(/^[_a-z0-9-]+([\.\+_a-z0-9-]+)*@studyladder+(\.[a-z0-9-]+)*\.[a-z]+$/i) ) { 1722 $(this).setFeedback('invalid'); 1723 msg = "The email address you have entered is unavailable."; 1724 } else if ( $(this).val() != $("#email").val() ) { 1725 $(this).setFeedback('invalid'); 1726 msg = "Your email address above does not match."; 1727 } else { 1728 $(this).setFeedback('valid'); 1729 } 1730 }); 1731 1732 $("#term-check").on('change', function() { 1733 var termsAccepted = $("#term-check").prop('checked'); 1734 //if check box has been filled, remove error class and message. 1735 if ( termsAccepted ) { 1736 $(this).removeClass('is-invalid'); 1737 $(".terms small").html(''); 1738 } 1739 }); 1740 1741 function isValidEmailAddress(emailAddress) { 1742 var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i; 1743 return pattern.test(emailAddress); 1744 }; 1745 1746 $("#first-name, #last-name").on('focusout', function() { 1747 if ( $(this).val().length > 0 ) { 1748 $(this).setFeedback('valid'); 1749 } else { 1750 $(this).setFeedback('invalid'); 1751 msg = "Please complete this field."; 1752 } 1753 }); 1754 onCreateAccountTeacher = function (token) { 1755 var form = $('form#create-account'); 1756 1757 $('input[type="submit"]').addClass("disabled").val("loading..."); 1758 1759 form.find('input[type=hidden][name=recaptcha]').val(token); 1760 1761 function validateForm() { 1762 let errors = ""; 1763 1764 if (!$('[name="firstname"]').val().length) { 1765 $('[name="firstname"]').removeClass('is-valid').addClass('is-invalid'); 1766 errors += "<li>First name is missing</li>"; 1767 } 1768 1769 if (!$('[name="surname"]').val().length) { 1770 $('[name="surname"]').removeClass('is-valid').addClass('is-invalid'); 1771 errors += "<li>Last name is missing</li>"; 1772 } 1773 1774 if ($('[name="email"]').val().indexOf("@") < 0) { 1775 $('[name="email"]').removeClass('is-valid').addClass('is-invalid'); 1776 errors += "<li>Enter a valid email address</li>"; 1777 } else if ($('[name="email"]').hasClass('border-danger')) { 1778 $('[name="email"]').removeClass('is-valid').addClass('is-invalid'); 1779 errors += "<li>Email address is incorrect or already used on another account</li>"; 1780 } 1781 1782 if (!checkPassword($('[name="password"]').val()).ok) { 1783 $('[name="password"]').removeClass('is-valid').addClass('is-invalid'); 1784 errors += "<li>Password does not meet criteria</li>"; 1785 } 1786 1787 if (!$('#term-check').prop('checked')) { 1788 $('[name="sasTermsAgreed"]').removeClass('is-valid').addClass('is-invalid'); 1789 errors += "<li>You have not indicated that you are over 18 and have agreed to our terms and conditions.</li>" 1790 } 1791 1792 if (errors.length) { 1793 swal.fire({ 1794 html: `<div class="position-relative w-100 mt-4 p-3 alert-danger text-dark border-danger rounded"> 1795 <p>We noticed the following issues. You will need to fix them before we can create an account.</p> 1796 <ul class="text-left">${errors}</ul> 1797 <small>If you need any assistance please contact us at <a 1798 href="mailto:[email protected]">[email protected]</a> 1799 </small> 1800 </div>`, 1801 customClass: { 1802 confirmButton: 'btn btn-primary btn-sm', // Bootstrap 'danger' style for confirm button 1803 }, 1804 buttonsStyling: false 1805 }).then(() => { 1806 $('input[type="submit"]').removeClass("disabled").val("Create Account"); 1807 $("#details-submit").removeClass('disabled').attr('disabled', false); 1808 //reenable recaptcha after failed submission (tokens are single use) 1809 grecaptcha.reset(); 1810 }) 1811 } else { 1812 submitTeacher(); 1813 } 1814 } 1815 1816 function submitTeacher() { 1817 1818 const queryParams = new URLSearchParams(window.location.search); 1819 const parameterValue = queryParams.get('admin_token'); 1820 1821 if (parameterValue) { 1822 $.ajax({ 1823 url: "/secure/verify-admin-token", 1824 method: "POST", 1825 data: {token: parameterValue, email: $('[name="email"]').val(), for: "teacher.email"}, 1826 dataType: "json", 1827 success: function (result) { 1828 if (result.ok) { 1829 doPost(); 1830 } else { 1831 swal.fire({ 1832 icon: "error", 1833 title: "An error occurred", 1834 }).then((value) => { 1835 $('input[type="submit"]').removeClass("disabled").val("Create Account"); 1836 $("#details-submit").removeClass('disabled').attr('disabled', false); 1837 //reenable recaptcha after failed submission (tokens are single use) 1838 grecaptcha.reset(); 1839 1840 }); 1841 if (result.hasOwnProperty("msg")) { 1842 swal.update({html: result.msg}); 1843 } 1844 } 1845 1846 } 1847 }) 1848 } else { 1849 1850 $.ajax({ 1851 url: "/secure/generate-verification-code-email", 1852 method: "POST", 1853 data: { 1854 email: $('[name="email"]').val(), 1855 firstname: $('[name="firstname"]').val(), 1856 surname: $('[name="surname"]').val(), 1857 for: "teacher.email", 1858 is_teacher: true, 1859 is_support: false }, 1860 dataType: "json", 1861 success: function (result) { 1862 if (result.ok) { 1863 swal.fire({ 1864 html: ` 1865 <h3>Verify your email</h3> 1866 <p style="font-size: 0.95rem;">A 6-digit verification code has been sent to your email address.<br>Please enter it below to verify your email.</p> 1867 <p class="text-primary" style="font-size:1.1rem;font-weight:500">Sent to: ${$('[name="email"]').val()}</p> 1868 <div class="d-flex align-items-center justify-content-center verify-input-container"> 1869 <input type="text" id="v_code" data-public="${result.public}" maxlength="6" minlength="6" style="border-color:#333;border-radius:12px;font-size: 1.5rem;padding: 7px 0;text-align: center;"> 1870 </div> 1871 `, 1872 1873 width: '600px', 1874 showCancelButton: true, 1875 showConfirmButton: true, 1876 confirmButtonText: "Verify", 1877 showDenyButton: true, 1878 denyButtonText: "Resend code", 1879 allowOutsideClick: false, 1880 preConfirm: function () { 1881 swal.showLoading(); 1882 $.ajax({ 1883 url: "/secure/verify-email-from-code", 1884 method: "POST", 1885 data: {public: result.public, code: $('#v_code').val(), for: "teacher.email"}, 1886 dataType: "json", 1887 success: function (result) { 1888 if (!result.ok) { 1889 swal.fire({ 1890 icon: "error", 1891 title: "An error occurred", 1892 showCancelButton: true, 1893 confirmButtonText: "Resend validation email" 1894 }).then((value) => { 1895 if (value.isConfirmed) { 1896 submitTeacher(); 1897 } else { 1898 $('input[type="submit"]').removeClass("disabled").val("Create Account"); 1899 $("#details-submit").removeClass('disabled').attr('disabled', false); 1900 //reenable recaptcha after failed submission (tokens are single use) 1901 grecaptcha.reset(); 1902 } 1903 }); 1904 if (result.hasOwnProperty("msg")) { 1905 swal.update({html: result.msg}); 1906 } 1907 } else { 1908 doPost(); 1909 } 1910 } 1911 }); 1912 } 1913 1914 }).then((value) => { 1915 if (value.isDenied) { 1916 submitTeacher(); 1917 } else if (value.isDismissed) { 1918 $('input[type="submit"]').removeClass("disabled").val("Create Account"); 1919 $("#details-submit").removeClass('disabled').attr('disabled', false); 1920 //reenable recaptcha after failed submission (tokens are single use) 1921 grecaptcha.reset(); 1922 } 1923 }) 1924 } 1925 } 1926 }) 1927 } 1928 1929 } 1930 1931 validateForm(); 1932 1933 1934 function doPost() { 1935 form.append(`<input type="hidden" name="email-confirm" value="${$('[name="email"]').val()}">`); 1936 $.post 1937 ( 1938 '/account/teacher-create-account', 1939 form.find('input,select').serialize(), 1940 function (response) { 1941 $('[name="email-confirm"]').remove(); 1942 doPostPart2(response); 1943 }).done(function () { 1944 $('input[type="submit"]').val("Create Account"); 1945 }); 1946 }; 1947 } 1948 1949 function doPostPart2(response) { 1950 1951 if (!response.ok && !response.msg) { 1952 response.ok = false;
1953 $("#error-messages").html("A system error occurred.\n\nPlease try again or contact us at [email protected] for assistance.").collapse("show"); 1954 } 1955 1956 if (!response.ok) { 1957 swal.close(); 1958 if ($.isArray(response.msg)) { 1959 $.each(response.msg, function (idx, e) { 1960 var msg = e.length && e.length == 2 ? e[1] : e; 1961 var error = e.length && e.length == 2 ? e[0] : null; 1962 1963 if (error && error == "email") { 1964 $("#email").setFeedback('invalid'); 1965 $("#email+small").html(msg).addClass("text-danger"); 1966 if (msg == "The email you have entered is already in use by another account.") { 1967 $("#error-messages").collapse('show'); 1968 } else if (msg == "The email you have entered is already in use by another google account.") { 1969 $("#error-messages-google").collapse('show'); 1970 } else if (msg == "This is a parent account, only parents can create parent accounts.") { 1971 $("#error-messages-parent-only").collapse('show'); 1972 } else if (msg == "Your confirm email address does not match.") { 1973 $("#error-messages-confirm").collapse('show'); 1974 } 1975 } 1976 if (error && error == "firstname") { 1977 $("#first-name").setFeedback('invalid'); 1978 } 1979 if (error && error == "surname") { 1980 $("#last-name").setFeedback('invalid'); 1981 } 1982 if (error && error == "password") { 1983 $("#password").setFeedback('invalid'); 1984 } 1985 if (error && error == "sas_terms_agreed") { 1986 $("#term-check").setFeedback('invalid'); 1987 $(".terms small").html(msg).addClass("text-danger"); 1988 } 1989 }); 1990 1991 } 1992 } else { 1993 $('body').append(` 1994 <form id="tmp-sub" action="/account/teacher-onboard" method="POST"> 1995 <input type="hidden" name="source" value="join"> 1996 <input type="hidden" name="step" value="2"> 1997 </form> 1998 `) 1999 $('#tmp-sub')[0].submit() 2000 } 2001 } 2002 2003 2004</script>
2004 2005 2006 </section> 2007 </div><!-- end of #registration-content.row --> 2008 </div> 2009 2010 <div class="row"> 2011 <div class="offset-xl-2 col-xl-8 pl-0 text-center pt-3"> 2012 <p class="small"><strong>Studyladder Pty Ltd</strong>: Registered office: 88 Phillip Street (Ground Floor), Parramatta NSW 2150</p> 2013 </div> 2014 </div> 2015 2016</div> 2017<div class="sl-signup-supplement section container-fluid pt-0 pt-md-3 pt-xl-1 mt-4" > 2018 <div class="" > 2019 <div class="row pb-0 "> 2020 <div class=" col-12 mb-3 text-center"> 2021 <h3 class="pt-4 mt-0 mb-3 " style=""><b>Included in Studyladder</b></h3> 2022 </div> 2023 <div class="col-6 offset-md-2 col-md-4 offset-xl-1 col-xl-2 text-center pb-3 benefit"> 2024 <div class="img-holder"><img class="pb-3" src="https://static.studyladder.co.uk/cdn/site/2b/e6e8cbaebd08.png"></div> 2025 <p >Priority Support</p> 2026 </div> 2027 <div class="col-6 col-md-4 offset-xl-0 col-xl-2 text-center pb-3 benefit"> 2028 <div class="img-holder"><img class="pb-3" src="https://static.studyladder.co.uk/cdn/site/8a/535481955d28.png"></div> 2029 <p >Detailed reports to track progress</p> 2030 </div> 2031 <div class="col-6 offset-md-2 col-md-4 offset-xl-0 col-xl-2 text-center pb-3 benefit"> 2032 <div class="img-holder"><img class="pb-3" src="https://static.studyladder.co.uk/cdn/site/95/c87243f32c82.png"></div> 2033 <p >Unlimited Access to over 17,000 activities, printables and video tutorials</p> 2034 </div> 2035 <div class="col-6 col-md-4 offset-xl-0 col-xl-2 text-center pb-3 benefit d-none d-xl-block"> 2036 <div class="img-holder"><img class="pb-3" src="https://static.studyladder.co.uk/cdn/site/c0/1ec8c8a5ec32.png"></div> 2037 <p >Exam Preparation</p> 2038 </div> 2039 <div class="col-6 col-md-4 offset-xl-0 col-xl-2 text-center pb-3 benefit"> 2040 <div class="img-holder"><img class="pb-3" src="https://static.studyladder.co.uk/cdn/site/82/930e0680c6b5.png"></div> 2041 <p >Monitor your students real-time as they work on the activities assigned by you </p> 2042 </div> 2043 2044 2045 2046 2047 </div> 2048 2049 </div> 2050</div> 2051<div class="sl-signup-supplement section container-fluid pt-0 " > 2052 <div class=" px-xl-5 mx-xl-5" > 2053 <div class="row pb-5 px-xl-5 mx-xl-5"> 2054 <div class=" col-12 mb-3 text-center"> 2055 2056 <h3 class="pt-4 mt-0 mb-3 mb-lg-5 pb-3" style="">What Teachers are saying about Studyladder</b></h3> 2057 2058 </div> 2059 <div class=" col-lg-4 text-left mb-4 testimonial-holder"> 2060 <div class="bubble-holder"><img style="" src="https://static.studyladder.co.uk/cdn/site/50/aeb91a8ce94a.png"></div> 2061 <div class="testimonial-inner px-5"> 2062 <p class="pt-5">âYou guys are fantastic. I definitely find myself taking for granted all the <strong>awesome online and printable resources available for both individual student and whole class use.</strong>â</p> 2063 <p class="testimonial-author">Richard Goodson<br/><strong>Teacher</strong></p> 2064 </div> 2065 </div> 2066 <div class=" col-lg-4 text-left mb-4 testimonial-holder"> 2067 <div class="bubble-holder"><img style="" src="https://static.studyladder.co.uk/cdn/site/50/aeb91a8ce94a.png"></div> 2068 <div class="testimonial-inner px-5"> 2069 <p class="pt-5">â<strong>Studyladder is absolutely fantastic.</strong>â</p> 2070 <p class="testimonial-author">Adrianne Harding<br/><strong>Teacher</strong></p> 2071 </div> 2072 </div> 2073 <div class=" col-lg-4 text-left mb-4 testimonial-holder"> 2074 <div class="bubble-holder"><img style="" src="https://static.studyladder.co.uk/cdn/site/50/aeb91a8ce94a.png"></div> 2075 <div class="testimonial-inner px-5"> 2076 <p class="pt-5">âI have used Studyladder as a teaching tool with my intervention groups for the last 5 years. All the children who have accessed it have enjoyed it and <strong>I have seen significant improvements in both literacy and numeracy</strong> through the use of this site. I have parents who have engaged with the site and they love the way it is set out and how safe it is to use.â</p> 2077 <p class="testimonial-author">Liz Tyson<br/><strong>Teacher</strong></p> 2078 </div> 2079 </div> 2080 2081 </div> 2082 2083 </div> 2084</div> 2085 2086<div class="sl-signup-supplement section container-fluid pt-1 py-2" > 2087 <div class="" > 2088 <div class="row pb-0 "> 2089 <div class=" col-12 col-xl-4 offset-xl-4 mb-md-3 text-center"> 2090 <h2 class="pt-4 mt-0 mb-0 mb-md-3 " style=""><b>Amazing features you get with Studyladder</b></h2> 2091 </div> 2092 2093 2094 </div> 2095 2096 </div> 2097</div> 2098 2099<div class="sl-signup-supplement section container container-xxl pt-4"> 2100 <div class="row pb-1 pt-0"> 2101 2102 <div class="col-md-6 col-xl-6 pt-md-4 pt-lg-0"> 2103 <img class="mb-2 w-100 d-inline-block" style="margin-top:0px; " src="https://static.studyladder.co.uk/cdn/site/3e/9b4b85d8e7da.jpg"> 2104 </div> 2105 2106 2107 <div class="col-md-6 col-xl-6 mt-0 pb-0 text-left"> 2108 <div class="pl-3 pl-lg-4 pl-xl-5 pt-4 pt-md-0 "> 2109 <h3 class=" pb-1 d-inline-block">Teaching Packs</h3> 2110 <h4 class="pb-2 pb-md-3" >
2110Thousands of resources for teachers to use.</h4> 2111 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2 " style=""></i> Whiteboard Lessons with related activities to go along with them.</p> 2112 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Online or offline printables for each subject.</p> 2113 <p class="large mb-0"><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Mathematics, English Literacy and Science all included.</p> 2114 </div> 2115 </div> 2116 2117 2118 2119 </div> 2120</div> 2121</div> 2122 2123 2124<div class=" section container pt-4"> 2125 <div class="row pb-1 pt-0"> 2126 2127 <div class="col-md-6 col-xl-6 mt-0 pb-0 text-left order-2 order-md-1 pt-4 "> 2128 <div class="pl-3 pl-md-0"> 2129 <h3 class=" pb-1 d-inline-block">Teachers Dashboard</h3> 2130 <h4 class="pb-2 pb-md-3" >Helping teachers in the classroom</h4> 2131 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Monitor your students progress LIVE!</p> 2132 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> New student leaderboard.</p> 2133 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Exclusive rewards to motivate students.</p> 2134 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Detailed individual student reports.</p> 2135 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Manage students access to games, avatars and more.</p> 2136 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Live Classroom - includes class assessments, quizzes and more.</p> 2137 2138 </div> 2139 </div> 2140 2141 <div class="col-md-6 col-xl-6 pt-md-5 pt-lg-0 order-1 order-md-2"> 2142 <img class="mb-2 w-100 d-inline-block" style="margin-top:0px; " src="https://static.studyladder.co.uk/cdn/site/0c/33f0cc5bc98a.jpg"> 2143 </div> 2144 2145 </div> 2146</div> 2147</div> 2148 2149 2150<div class="sl-signup-supplement section container container-xxl pt-4"> 2151 <div class="row pb-1 pt-0"> 2152 2153 <div class="col-md-6 col-xl-6 pt-md-4 pt-lg-0"> 2154 <img class="mb-2 w-100 d-inline-block" style="margin-top:0px; " src="https://static.studyladder.co.uk/cdn/site/5d/9146111ee96e.jpg"> 2155 </div> 2156 2157 2158 <div class="col-md-6 col-xl-6 mt-0 pb-0 text-left"> 2159 <div class="pl-3 pl-lg-4 pl-xl-5 pt-4 pt-md-0 "> 2160 <h3 class=" pb-1 d-inline-block">Monitor Your Students</h3> 2161 <h4 class="pb-2 pb-md-3" >Check student progress instantly!</h4> 2162 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2 " style=""></i> See realtime feedback on activities as they are completed.</p> 2163 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Review which questions students are struggling with.</p> 2164 <p class="large "><i class="far fa-check-square pr-1 pr-lg-2" style=""></i> Assist and prompt students who need help.</p> 2165 </div> 2166 </div> 2167 2168 2169 2170 </div> 2171</div> 2172<style> 2173 .testimonial-inner { 2174 background-color: #e4eef9; 2175 border-radius: 80px; 2176 margin-left: 10px; 2177 margin-right: 10px; 2178 padding: 20px; 2179 box-shadow: inset 0 0 25px #d0deef; 2180 padding-top: 40px; 2181 padding-bottom: 30px; 2182 border-bottom-left-radius: 0; 2183 } 2184 .bubble-holder img { 2185 width: 120px; 2186 opacity: 1; 2187 position: absolute; 2188 left: 0; 2189 margin-left: 0; 2190 top: 0; 2191 margin-top: -20px; 2192 } 2193</style> 2194
2195<script> 2196 2197 //needed to make UI::formSelectRegion & UI::formSelectCountry work, otherwise js throws a not defined error for h() 2198 //there is a scrpt element included that automates repopulation of regions when country is changed. 2199 function h(t) { 2200 if (h.d == undefined) 2201 h.d = $('<div/>'); 2202 return h.d.text( t || '' ).html(); 2203 } 2204 2205</script>
2205 2206 2207 2208 <style> 2209 /* ------ Footer styling â targets the BS4 markup below ------ */ 2210 /* Force NO margin above the footer at any viewport. Beats the 5em 2211 margin-top in public.css and any other inherited rule. */ 2212 footer.footer, 2213 footer.footer.bg-dark, 2214 .footer.bg-dark { 2215 margin-top: 0 !important; 2216 margin-bottom: 0 !important; 2217 } 2218 @media (min-width: 0) { 2219 footer.footer, 2220 footer.footer.bg-dark, 2221 .footer.bg-dark { margin-top: 0 !important; } 2222 } 2223 @media (min-width: 992px) { 2224 footer.footer, 2225 footer.footer.bg-dark, 2226 .footer.bg-dark { margin-top: 0 !important; } 2227 } 2228 .footer.bg-dark { 2229 background: #0F172A !important; 2230 padding: 56px 0 24px; 2231 color: rgba(255, 255, 255, 0.72); 2232 font-size: 14px; 2233 } 2234 .footer.bg-dark .container { color: rgba(255, 255, 255, 0.72); } 2235 .footer.bg-dark a { transition: color .15s ease, background .15s ease; } 2236 .footer.bg-dark a.text-light { color: rgba(255, 255, 255, 0.65) !important; } 2237 .footer.bg-dark a.text-light:hover { color: #ffffff !important; text-decoration: none; } 2238 2239 /* Link lists â force size + weight + colour against public.css */ 2240 .footer.bg-dark ul.list-unstyled li a, 2241 .footer.bg-dark ul.list-unstyled li a.text-light { 2242 font-size: 14px !important; 2243 font-weight: 400 !important; 2244 color: rgba(255, 255, 255, 0.65) !important; 2245 line-height: 1.5 !important; 2246 letter-spacing: 0 !important; 2247 text-transform: none !important; 2248 } 2249 .footer.bg-dark ul.list-unstyled li a:hover, 2250 .footer.bg-dark ul.list-unstyled li a.text-light:hover { 2251 color: #ffffff !important; 2252 text-decoration: none !important; 2253 } 2254 .footer.bg-dark .logo { display: inline-block; } 2255 .footer.bg-dark .logo img { max-width: 160px; max-height: 36px; width: auto; height: auto; } 2256 .footer.bg-dark p { color: rgba(255, 255, 255, 0.65); font-size: 14px; line-height: 1.55; } 2257 2258 /* Column headers â !important needed because public.css sets h4 font-size !important globally */ 2259 .footer.bg-dark h4, 2260 .footer.bg-dark .sl-footer-heading { 2261 font-size: 12px !important; 2262 font-weight: 700 !important; 2263 text-transform: uppercase !important; 2264 letter-spacing: 0.08em !important; 2265 color: #ffffff !important; 2266 margin-bottom: 14px !important; 2267 padding-bottom: 0 !important; 2268 line-height: 1.4 !important; 2269 } 2270 .footer.bg-dark ul.list-unstyled { padding: 0; margin: 0; } 2271 .footer.bg-dark ul.list-unstyled li { margin-bottom: 10px; line-height: 1.5; } 2272 2273 /* Social icons â soft circular pill on hover */ 2274 .sl-footer-social { display: inline-flex; align-items: center; margin-top: 4px; } 2275 .sl-footer-social a { 2276 display: inline-flex; 2277 align-items: center; 2278 justify-content: center; 2279 width: 36px; 2280 height: 36px; 2281 border-radius: 50%; 2282 background: rgba(255, 255, 255, 0.08); 2283 margin-left: 0 !important; 2284 } 2285 .sl-footer-social a + a { margin-left: 8px !important; } 2286 .sl-footer-social a:hover { background: rgba(255, 255, 255, 0.18); } 2287 .sl-footer-social svg { width: 18px !important; height: 18px !important; display: block; } 2288 .sl-footer-social a.text-light { color: #ffffff !important; } 2289 2290 /* Bottom row */ 2291 .footer.bg-dark .row.no-gutters { 2292 border-top: 1px solid rgba(255, 255, 255, 0.08); 2293 padding-top: 18px; 2294 margin-top: 28px !important; 2295 font-size: 12px; 2296 color: rgba(255, 255, 255, 0.5); 2297 align-items: center; 2298 line-height: 1.6; 2299 } 2300 .footer.bg-dark .copyright { color: rgba(255, 255, 255, 0.5); font-size: 12px; } 2301 2302 /* Legal links list (bottom-right) */ 2303 .sl-footer-legal { 2304 list-style: none; 2305 padding: 0; 2306 margin: 0; 2307 display: flex; 2308 gap: 22px; 2309 justify-content: flex-end; 2310 } 2311 .sl-footer-legal li { margin: 0; padding: 0; } 2312 .footer.bg-dark .sl-footer-legal a, 2313 .footer.bg-dark .sl-footer-legal a.text-light { 2314 color: rgba(255, 255, 255, 0.5) !important; 2315 font-size: 12px !important; 2316 font-weight: 400 !important; 2317 line-height: 1.6 !important; 2318 } 2319 .footer.bg-dark .sl-footer-legal a:hover, 2320 .footer.bg-dark .sl-footer-legal a.text-light:hover { 2321 color: #ffffff !important; 2322 text-decoration: none !important; 2323 } 2324 @media (max-width: 767.98px) { 2325 .sl-footer-legal { justify-content: center; gap: 18px; margin-bottom: 8px; } 2326 } 2327 2328 /* Country switcher (student-only) inherits theme */ 2329 .footer.bg-dark #lc_select { 2330 background-color: rgba(255, 255, 255, 0.08); 2331 border-color: rgba(255, 255, 255, 0.15); 2332 color: #ffffff; 2333 } 2334 2335 /* Tighten typography on small screens */ 2336 @media (max-width: 991.98px) { 2337 .footer.bg-dark { padding: 36px 0 20px; text-align: center; } 2338 .footer.bg-dark h4 { margin-top: 12px; } 2339 .sl-footer-social { justify-content: center; display: flex; } 2340 } 2341 </style> 2342 2343 </main> 2344 <div class="d-none d-print-block text-center"> 2345 <a href="https://studyladder.com.au" title="Studyladder - Home" class="text-center mt-4"><img style="width: 150px !important;" src="https://static.studyladder.co.uk/cdn/site/13/6f597fea9532.png"></a> 2346 </div> 2347 2348 <footer class="footer bg-dark text-light d-print-none"> 2349 <div class="container"> 2350 2351 2352 <div class="row text-center text-lg-left pb-3"> 2353 2354 <!-- Brand column --> 2355 <div class="col-lg-4 col-md-12 py-4 py-lg-0"> 2356 <a class="logo d-inline-block mb-3" href="/"><img src="https://static.studyladder.co.uk/cdn/site/c7/cbe28b2ff048.png" alt="Studyladder"></a> 2357 <p class="mb-3">Helping teachers, parents and schools inspire confident learners, one activity at a time.</p> 2358 <div class="sl-footer-social"> 2359 <a class="text-light" aria-label="Studyladder on Facebook" href="https://www.facebook.com/Studyladder/" target="_blank" rel="noopener"> 2360 <svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18"><path d="M9.198 21.5h4v-8.01h3.604l.396-3.98h-4V7.5c0-1.103.897-2 2-2h2v-4h-2c-3.309 0-6 2.691-6 6v2.01H7.198l-.396 3.98h2.396v8.01z"/></svg> 2361 </a> 2362 <a class="text-light" aria-label="Studyladder on Instagram" href="https://www.instagram.com/studyladder/" target="_blank" rel="noopener"> 2363 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" fill="currentColor"/></svg> 2364 </a> 2365 <a class="text-light" aria-label="Studyladder on X / Twitter" href="https://twitter.com/studyladder" target="_blank" rel="noopener"> 2366 <svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> 2367 </a> 2368 <a class="text-light" aria-label="Studyladder on YouTube" href="https://www.youtube.com/user/StudyLadder" target="_blank" rel="noopener"> 2369 <svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg> 2370 </a> 2371 </div> 2372 2373 </div> 2374 2375 <!-- Who we help --> 2376 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 2377 <h4 class="sl-footer-heading">Who we help</h4> 2378 <ul class="list-unstyled"> 2379 <li><a class="text-light" href="/about/parent">For parents</a></li> 2380 <li><a class="text-light" href="/about/teacher">For teachers</a></li> 2381 <li><a class="text-light" href="/about/teacher-school-pricing?t=s">For schools</a></li> 2382 <li><a class="text-light" href="/about/tutor">For tutors</a></li> 2383 </ul> 2384 </div> 2385 2386 <!-- Subjects --> 2387 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 2388 <h4 class="sl-footer-heading">Subjects</h4> 2389 <ul class="list-unstyled"> 2390 <li><a class="text-light" href="/about/subjects-mathematics">Mathematics</a></li> 2391 <li><a class="text-light" href="/about/subjects-english">English</a></li> 2392 <li><a class="text-light" href="/about/subjects-science">Science</a></li> 2393 </ul> 2394 </div> 2395 2396 <!-- Learn more --> 2397 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 2398 <h4 class="sl-footer-heading">Learn more</h4> 2399 <ul class="list-unstyled"> 2400 <li><a class="text-light" href="/about">About us</a></li> 2401 <li><a class="text-light" href="/about/features">Features</a></li> 2402 <li><a class="text-light" href="/info/upgrade-benefits">Home Plus benefits</a></li> 2403 <li><a class="text-light" href="#" data-toggle="modal" data-target="#pricingModal">Pricing</a></li> 2404 <li><a class="text-light" href="/about/testimonials">Testimonials</a></li> 2405 <li><a class="text-light" href="/blog">Blog</a></li> 2406 </ul> 2407 </div> 2408 2409 <!-- Support --> 2410 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 2411 <h4 class="sl-footer-heading">Support</h4> 2412 <ul class="list-unstyled"> 2413 <li><a class="text-light" href="/about/faqs">FAQs</a></li> 2414 <li><a class="text-light" href="/about/contact-us">Contact us</a></li> 2415 </ul> 2416 </div> 2417 2418 </div> 2419 2420 <div class="row no-gutters small d-flex justify-content-between mt-lg-5 mb-2"> 2421 <div class="copyright text-center text-md-left order-2 order-md-1 pt-1 pt-lg-0">© 2026 Studyladder Pty Ltd</div> 2422 <ul class="sl-footer-legal text-center text-lg-left order-1 order-md-2"> 2423 <li><a class="text-light" href="/about/privacy">Privacy</a></li> 2424 <li><a class="text-light" href="/about/terms">Terms</a></li> 2425 <li><a class="text-light" href="/info/gdpr">GDPR</a></li> 2426 </ul> 2427 </div> 2428 </div> 2429 </footer> 2430 2431
2431<script> 2432 $(function(){ 2433 $.ajax({ 2434 url: "/secure/check-subscription-cancelled", 2435 method: "POST", 2436 dataType: "json", 2437 success: function(r){ 2438 if (r.found){ 2439 /*dataLayer.push({ 2440 event: r.event ?? "cancelled", 2441 reason: r.reason ?? "not given", 2442 feedback: r.feedback ?? "not given", 2443 comment: r.comment ?? "not given", 2444 user: r.user ?? "", 2445 user_type: r.type ?? "", 2446 plan_type: r.plan ?? "", 2447 domain_region: "GB" 2448 })*/ 2449 } 2450 } 2451 }) 2452 }) 2453 </script>
2453 2454 2455 <!-- PRICING MODAL â opened by any [data-toggle="modal" data-target="#pricingModal"] trigger. 2456 Loaded site-wide from footer-bs4.phtml so it works for student, teacher, parent and public users. --> 2457<div id="pricingModal" class="modal fade sl-pricing-modal" role="dialog" aria-hidden="true" tabindex="-1" aria-labelledby="pricingModalTitle"> 2458 <div class="modal-dialog modal-dialog-centered" role="document"> 2459 <div class="modal-content sl-pricing-modal-content"> 2460 2461 <button type="button" class="sl-pricing-modal-close" data-dismiss="modal" aria-label="Close"> 2462 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> 2463 </button> 2464 2465 <div class="sl-pricing-modal-header"> 2466 <div class="sl-pricing-modal-eyebrow">Pricing</div> 2467 <h2 class="sl-pricing-modal-title" id="pricingModalTitle">See pricing for…</h2> 2468 <p class="sl-pricing-modal-sub">Pick the option that describes you, we'll show the right plans.</p> 2469 </div> 2470 2471 <div class="sl-pricing-modal-options"> 2472 <a href="https://www.studyladder.co.uk/account/parent-pricing" class="sl-pricing-option"> 2473 <span class="sl-pricing-option-icon sl-pricing-icon-parent"> 2474 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21v-2a4 4 0 0 1 4-4h6a4 4 0 0 1 4 4v2"/><circle cx="10" cy="7" r="4"/><path d="M19 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg> 2475 </span> 2476 <span class="sl-pricing-option-body"> 2477 <strong>Parents & homeschoolers</strong> 2478 <small>Home Plus plans for up to 4 children</small> 2479 </span> 2480 <span class="sl-pricing-option-arrow">→</span> 2481 </a> 2482 2483 <a href="https://www.studyladder.co.uk/about/teacher-school-pricing?t=t" class="sl-pricing-option"> 2484 <span class="sl-pricing-option-icon sl-pricing-icon-teacher"> 2485 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg> 2486 </span> 2487 <span class="sl-pricing-option-body"> 2488 <strong>Teachers</strong> 2489 <small>For one classroom · up to 35 students</small> 2490 </span> 2491 <span class="sl-pricing-option-arrow">→</span> 2492 </a> 2493 2494 <a href="https://www.studyladder.co.uk/about/teacher-school-pricing?t=s" class="sl-pricing-option"> 2495 <span class="sl-pricing-option-icon sl-pricing-icon-school"> 2496 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21h18"/><path d="M5 21V7l7-4 7 4v14"/><path d="M9 9h1M9 13h1M9 17h1M14 9h1M14 13h1M14 17h1"/></svg> 2497 </span> 2498 <span class="sl-pricing-option-body"> 2499 <strong>Schools</strong> 2500 <small>Whole-school plans · admin tools included</small> 2501 </span> 2502 <span class="sl-pricing-option-arrow">→</span> 2503 </a> 2504 </div> 2505 2506 </div> 2507 </div> 2508</div> 2509 2510<style> 2511/* Force-correct modal overlay behaviour (sl-marketing.scss styles .modal differently) */ 2512body.sl-marketing #pricingModal, 2513body #pricingModal.sl-pricing-modal { 2514 position: fixed !important; 2515 top: 0 !important; 2516 left: 0 !important; 2517 right: 0 !important; 2518 bottom: 0 !important; 2519 width: 100vw !important; 2520 height: 100vh !important; 2521 max-width: 100vw !important; 2522 max-height: 100vh !important; 2523 margin: 0 !important; 2524 padding: 0 !important; 2525 background: rgba(15, 23, 42, 0) !important; 2526 border: 0 !important; 2527 border-radius: 0 !important; 2528 box-shadow: none !important; 2529 transform: none !important; 2530 overflow-x: hidden !important; 2531 overflow-y: auto !important; 2532 outline: 0 !important; 2533 z-index: 2050 !important; 2534 /* Animation: fade overlay + dialog */ 2535 display: block !important; 2536 opacity: 0; 2537 visibility: hidden; 2538 pointer-events: none; 2539 transition: opacity .22s ease, visibility 0s linear .22s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 2540 -webkit-backdrop-filter: blur(0px); 2541 backdrop-filter: blur(0px); 2542} 2543body.sl-marketing #pricingModal.show, 2544body #pricingModal.sl-pricing-modal.show { 2545 display: block !important; 2546 opacity: 1; 2547 visibility: visible; 2548 pointer-events: auto; 2549 background: rgba(15, 23, 42, 0.78) !important; 2550 -webkit-backdrop-filter: blur(8px) !important; 2551 backdrop-filter: blur(8px) !important; 2552 transition: opacity .22s ease, visibility 0s linear 0s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 2553} 2554body.sl-marketing #pricingModal .modal-dialog, 2555body #pricingModal.sl-pricing-modal .modal-dialog,
2556body.sl-marketing #pricingModal .modal-dialog.modal-dialog-centered, 2557body #pricingModal.sl-pricing-modal .modal-dialog.modal-dialog-centered { 2558 position: fixed !important; 2559 top: 50% !important; 2560 left: 50% !important; 2561 right: auto !important; 2562 bottom: auto !important; 2563 -webkit-transform: translate(-50%, -50%) scale(0.96) !important; 2564 transform: translate(-50%, -50%) scale(0.96) !important; 2565 margin: 0 !important; 2566 padding: 0 !important; 2567 max-width: 520px !important; 2568 width: calc(100vw - 32px) !important; 2569 height: auto !important; 2570 max-height: calc(100vh - 32px) !important; 2571 min-height: 0 !important; 2572 display: block !important; 2573 background: transparent !important; 2574 border: 0 !important; 2575 box-shadow: none !important; 2576 transition: -webkit-transform .25s cubic-bezier(0.4, 0, 0.2, 1), transform .25s cubic-bezier(0.4, 0, 0.2, 1) !important; 2577 z-index: 2060 !important; 2578 flex: none !important; 2579 align-self: auto !important; 2580} 2581body.sl-marketing #pricingModal.show .modal-dialog, 2582body #pricingModal.sl-pricing-modal.show .modal-dialog, 2583body.sl-marketing #pricingModal.show .modal-dialog.modal-dialog-centered, 2584body #pricingModal.sl-pricing-modal.show .modal-dialog.modal-dialog-centered { 2585 -webkit-transform: translate(-50%, -50%) scale(1) !important; 2586 transform: translate(-50%, -50%) scale(1) !important; 2587} 2588body.sl-marketing #pricingModal .modal-dialog-centered::before, 2589body #pricingModal.sl-pricing-modal .modal-dialog-centered::before { 2590 content: none !important; 2591 display: none !important; 2592 height: 0 !important; 2593} 2594body.sl-marketing #pricingModal .sl-pricing-modal-content, 2595body #pricingModal .sl-pricing-modal-content { 2596 position: relative; 2597 background: #FFFFFF !important; 2598 border-radius: 18px !important; 2599 padding: 28px 28px 28px !important; 2600 box-shadow: 0 24px 80px -16px rgba(15, 23, 42, 0.30), 0 4px 12px rgba(15, 23, 42, 0.06) !important; 2601 pointer-events: auto; 2602 width: 100% !important; 2603 max-width: none !important; 2604 border: 0 !important; 2605 transform: none !important; 2606 transition: none !important; 2607 max-height: calc(100vh - 48px); 2608 overflow-y: auto; 2609} 2610 2611/* Close button */ 2612#pricingModal .sl-pricing-modal-close { 2613 position: absolute; 2614 top: 14px; 2615 right: 14px; 2616 width: 32px; 2617 height: 32px; 2618 border-radius: 50%; 2619 border: 0; 2620 background: #F1F5F9; 2621 color: #475569; 2622 display: inline-flex; 2623 align-items: center; 2624 justify-content: center; 2625 cursor: pointer; 2626 padding: 0; 2627 transition: background .15s ease; 2628} 2629#pricingModal .sl-pricing-modal-close:hover { background: #E2E8F0; color: #0F172A; } 2630#pricingModal .sl-pricing-modal-close svg { width: 18px; height: 18px; } 2631 2632/* Header */ 2633#pricingModal .sl-pricing-modal-header { padding: 0 0 18px; } 2634#pricingModal .sl-pricing-modal-eyebrow { 2635 font-size: 13px; 2636 font-weight: 600; 2637 letter-spacing: 0.08em; 2638 text-transform: uppercase; 2639 color: #2D5BFF; 2640 margin: 0 0 8px; 2641} 2642#pricingModal .sl-pricing-modal-title { 2643 font-size: 28px; 2644 font-weight: 700; 2645 color: #0F172A; 2646 margin: 0 0 8px; 2647 letter-spacing: -0.02em; 2648 line-height: 1.2; 2649} 2650#pricingModal .sl-pricing-modal-sub { 2651 font-size: 15px; 2652 color: #64748B; 2653 margin: 4px 0 0; 2654 line-height: 1.45; 2655} 2656 2657/* Options */ 2658#pricingModal .sl-pricing-modal-options { 2659 display: flex; 2660 flex-direction: column; 2661 gap: 10px; 2662 margin: 0; 2663} 2664 2665/* Option cards â with hover slide animation matching the join modal */ 2666#pricingModal .sl-pricing-option { 2667 position: relative; 2668 display: flex; 2669 align-items: center; 2670 gap: 14px; 2671 padding: 16px 18px; 2672 border: 1px solid #E2E8F0; 2673 border-radius: 12px; 2674 text-decoration: none; 2675 color: #0F172A; 2676 background: #FFFFFF; 2677 overflow: hidden; 2678 transition: border-color .25s ease, transform .25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow .25s ease; 2679 z-index: 0; 2680} 2681#pricingModal .sl-pricing-option::before { 2682 content: ""; 2683 position: absolute; 2684 top: 0; 2685 left: 0; 2686 bottom: 0; 2687 width: 100%; 2688 background: linear-gradient(90deg, #F8FAFC 0%, #EFF6FF 100%); 2689 transform: translateX(-100%); 2690 transition: transform .35s cubic-bezier(0.4, 0, 0.2, 1); 2691 z-index: -1; 2692} 2693#pricingModal .sl-pricing-option:hover { 2694 border-color: #2D5BFF; 2695 color: #0F172A; 2696 text-decoration: none; 2697 transform: translateX(4px); 2698 box-shadow: 0 4px 12px -4px rgba(45, 91, 255, 0.18); 2699} 2700#pricingModal .sl-pricing-option:hover::before { transform: translateX(0); } 2701#pricingModal .sl-pricing-option:active { transform: translateX(4px) translateY(1px); } 2702 2703#pricingModal .sl-pricing-option-icon { 2704 flex: 0 0 44px; 2705 width: 44px; 2706 height: 44px; 2707 border-radius: 10px; 2708 display: inline-flex; 2709 align-items: center; 2710 justify-content: center; 2711 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1); 2712} 2713#pricingModal .sl-pricing-option:hover .sl-pricing-option-icon { transform: scale(1.06); } 2714#pricingModal .sl-pricing-option-icon svg { width: 22px; height: 22px; } 2715#pricingModal .sl-pricing-icon-parent { background: #FED7AA; color: #EA580C; } /* orange */ 2716#pricingModal .sl-pricing-icon-teacher { background: #DBE6FF; color: #2D5BFF; } /* blue */ 2717#pricingModal .sl-pricing-icon-school { background: #D1FAE5; color: #059669; } /* green */ 2718 2719#pricingModal .sl-pricing-option-body { 2720 flex: 1 1 auto; 2721 display: flex; 2722 flex-direction: column; 2723 gap: 3px; 2724} 2725#pricingModal .sl-pricing-option-body strong { 2726 font-size: 16px; 2727 font-weight: 600; 2728 color: #0F172A; 2729 letter-spacing: -0.01em; 2730} 2731#pricingModal .sl-pricing-option-body small { 2732 font-size: 14px; 2733 color: #64748B; 2734 font-weight: 400; 2735 line-height: 1.4; 2736} 2737#pricingModal .sl-pricing-option-arrow { 2738 flex: 0 0 auto; 2739 font-size: 20px; 2740 color: #94A3B8; 2741 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1), color .25s ease; 2742} 2743#pricingModal .sl-pricing-option:hover .sl-pricing-option-arrow { 2744 transform: translateX(6px); 2745 color: #2D5BFF; 2746} 2747</style> 2748
2749<script> 2750$('#pricingModal').on('show.bs.modal', function (e) { 2751 window.dataLayer = window.dataLayer || []; 2752 window.dataLayer.push({ 2753 'event': 'Pricing Modal', 2754 'Action': 'Open', 2755 'Step': '1', 2756 'Step Name': 'Choose Audience' 2757 }); 2758}); 2759</script>
2759 2760<div id="joinNow" class="modal fade sl-join-modal" role="dialog" aria-hidden="true" tabindex="-1" aria-labelledby="joinNowTitle"> 2761 <div class="modal-dialog modal-dialog-centered" role="document"> 2762 <div class="modal-content sl-join-modal-content"> 2763 2764 <button type="button" class="sl-join-modal-close" data-dismiss="modal" aria-label="Close"> 2765 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> 2766 </button> 2767 2768 <div class="sl-join-modal-header"> 2769 <div class="sl-join-modal-eyebrow">Sign up</div> 2770 <h2 class="sl-join-modal-title" id="joinNowTitle">Join Studyladder</h2> 2771 <p class="sl-join-modal-sub">I would like to register for a:</p> 2772 </div> 2773 2774 <div class="sl-join-modal-options"> 2775 <a href="https://www.studyladder.co.uk/account/parent-pricing" class="sl-join-option"> 2776 <span class="sl-join-option-icon sl-join-icon-parent"> 2777 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21v-2a4 4 0 0 1 4-4h6a4 4 0 0 1 4 4v2"/><circle cx="10" cy="7" r="4"/><path d="M19 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg> 2778 </span> 2779 <span class="sl-join-option-body"> 2780 <strong>Parent account</strong> 2781 <small>For families and homeschoolers, up to 4 children at home</small> 2782 </span> 2783 <span class="sl-join-option-arrow">→</span> 2784 </a> 2785 2786 <a href="/account/teacher?t=teacher" class="sl-join-option"> 2787 <span class="sl-join-option-icon sl-join-icon-teacher"> 2788 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg> 2789 </span> 2790 <span class="sl-join-option-body"> 2791 <strong>School teacher account</strong> 2792 <small>For one classroom or your whole school</small> 2793 </span> 2794 <span class="sl-join-option-arrow">→</span> 2795 </a> 2796 </div> 2797 2798 <div class="sl-join-modal-section-label">I would like to:</div> 2799 2800 <div class="sl-join-modal-options"> 2801 <a href="/login/account?backUrl=%2Faccount%2Fupgrade" class="sl-join-option"> 2802 <span class="sl-join-option-icon sl-join-icon-upgrade"> 2803 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg> 2804 </span> 2805 <span class="sl-join-option-body"> 2806 <strong>Upgrade an existing account</strong> 2807 <small>See what's included in Home Plus</small> 2808 </span> 2809 <span class="sl-join-option-arrow">→</span> 2810 </a> 2811 2812 <a href="/account/school-admin" class="sl-join-option"> 2813 <span class="sl-join-option-icon sl-join-icon-school"> 2814 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><line x1="2" y1="10" x2="22" y2="10"/><line x1="6" y1="15" x2="10" y2="15"/></svg> 2815 </span> 2816 <span class="sl-join-option-body"> 2817 <strong>Pay a school administration fee</strong> 2818 <small>Pay by invoice or credit card</small> 2819 </span> 2820 <span class="sl-join-option-arrow">→</span> 2821 </a> 2822 </div> 2823 2824 <div class="sl-join-modal-footer-note"> 2825 Already have an account? <a href="/login/account">Log in →</a> 2826 </div> 2827 2828 </div> 2829 </div> 2830</div> 2831 2832<style> 2833/* Force-correct modal overlay behaviour. sl-marketing.scss has its own `.modal` 2834 rules (intended as a card inside `.modal-backdrop`) that clash with Bootstrap's 2835 modal/overlay pattern. We override with very high specificity + !important. */ 2836body.sl-marketing #joinNow, 2837body #joinNow.sl-join-modal { 2838 position: fixed !important; 2839 top: 0 !important; 2840 left: 0 !important; 2841 right: 0 !important; 2842 bottom: 0 !important; 2843 width: 100vw !important; 2844 height: 100vh !important; 2845 max-width: 100vw !important; 2846 max-height: 100vh !important; 2847 margin: 0 !important; 2848 padding: 0 !important; 2849 background: rgba(15, 23, 42, 0) !important; 2850 border: 0 !important; 2851 border-radius: 0 !important; 2852 box-shadow: none !important; 2853 transform: none !important; 2854 overflow-x: hidden !important; 2855 overflow-y: auto !important; 2856 outline: 0 !important; 2857 z-index: 2050 !important; 2858 /* Animation: fade overlay + dialog */ 2859 display: block !important; 2860 opacity: 0; 2861 visibility: hidden; 2862 pointer-events: none; 2863 transition: opacity .22s ease, visibility 0s linear .22s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 2864 -webkit-backdrop-filter: blur(0px); 2865 backdrop-filter: blur(0px); 2866} 2867body.sl-marketing #joinNow.show, 2868body #joinNow.sl-join-modal.show { 2869 display: block !important; 2870 opacity: 1; 2871 visibility: visible; 2872 pointer-events: auto; 2873 background: rgba(15, 23, 42, 0.78) !important; 2874 -webkit-backdrop-filter: blur(8px) !important; 2875 backdrop-filter: blur(8px) !important; 2876 transition: opacity .22s ease, visibility 0s linear 0s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 2877} 2878body.sl-marketing #joinNow .modal-dialog, 2879body #joinNow.sl-join-modal .modal-dialog,
2880body.sl-marketing #joinNow .modal-dialog.modal-dialog-centered, 2881body #joinNow.sl-join-modal .modal-dialog.modal-dialog-centered { 2882 position: fixed !important; 2883 top: 50% !important; 2884 left: 50% !important; 2885 right: auto !important; 2886 bottom: auto !important; 2887 -webkit-transform: translate(-50%, -50%) scale(0.96) !important; 2888 transform: translate(-50%, -50%) scale(0.96) !important; 2889 margin: 0 !important; 2890 padding: 0 !important; 2891 max-width: 520px !important; 2892 width: calc(100vw - 32px) !important; 2893 height: auto !important; 2894 max-height: calc(100vh - 32px) !important; 2895 min-height: 0 !important; 2896 display: block !important; 2897 background: transparent !important; 2898 border: 0 !important; 2899 box-shadow: none !important; 2900 transition: -webkit-transform .25s cubic-bezier(0.4, 0, 0.2, 1), transform .25s cubic-bezier(0.4, 0, 0.2, 1) !important; 2901 z-index: 2060 !important; 2902 flex: none !important; 2903 align-self: auto !important; 2904} 2905body.sl-marketing #joinNow.show .modal-dialog, 2906body #joinNow.sl-join-modal.show .modal-dialog, 2907body.sl-marketing #joinNow.show .modal-dialog.modal-dialog-centered, 2908body #joinNow.sl-join-modal.show .modal-dialog.modal-dialog-centered { 2909 -webkit-transform: translate(-50%, -50%) scale(1) !important; 2910 transform: translate(-50%, -50%) scale(1) !important; 2911} 2912/* Bootstrap inserts a ::before pseudo for centered modals â neutralise it */ 2913body.sl-marketing #joinNow .modal-dialog-centered::before, 2914body #joinNow.sl-join-modal .modal-dialog-centered::before { 2915 content: none !important; 2916 display: none !important; 2917 height: 0 !important; 2918} 2919body.sl-marketing #joinNow .sl-join-modal-content, 2920body #joinNow .sl-join-modal-content { 2921 position: relative; 2922 background: #FFFFFF !important; 2923 border-radius: 18px !important; 2924 padding: 28px 28px 22px !important; 2925 box-shadow: 0 24px 80px -16px rgba(15, 23, 42, 0.30), 0 4px 12px rgba(15, 23, 42, 0.06) !important; 2926 pointer-events: auto; 2927 width: 100% !important; 2928 max-width: none !important; 2929 border: 0 !important; 2930 transform: none !important; 2931 transition: none !important; 2932 max-height: calc(100vh - 48px); 2933 overflow-y: auto; 2934} 2935#joinNow .sl-join-modal-close { 2936 position: absolute; 2937 top: 14px; 2938 right: 14px; 2939 width: 32px; 2940 height: 32px; 2941 border-radius: 50%; 2942 border: 0; 2943 background: #F1F5F9; 2944 color: #475569; 2945 display: inline-flex; 2946 align-items: center; 2947 justify-content: center; 2948 cursor: pointer; 2949 padding: 0; 2950 transition: background .15s ease; 2951} 2952#joinNow .sl-join-modal-close:hover { background: #E2E8F0; color: #0F172A; } 2953#joinNow .sl-join-modal-close svg { width: 18px; height: 18px; } 2954#joinNow .sl-join-modal-header { padding: 0 0 14px; } 2955#joinNow .sl-join-modal-eyebrow { 2956 font-size: 13px; 2957 font-weight: 600; 2958 letter-spacing: 0.08em; 2959 text-transform: uppercase; 2960 color: #2D5BFF; 2961 margin: 0 0 8px; 2962} 2963#joinNow .sl-join-modal-title { 2964 font-size: 28px; 2965 font-weight: 700; 2966 color: #0F172A; 2967 margin: 0 0 8px; 2968 letter-spacing: -0.02em; 2969 line-height: 1.2; 2970} 2971#joinNow .sl-join-modal-sub { 2972 font-size: 15px; 2973 color: #64748B; 2974 margin: 4px 0 0; 2975} 2976#joinNow .sl-join-modal-options { 2977 display: flex; 2978 flex-direction: column; 2979 gap: 10px; 2980 margin: 0 0 12px; 2981} 2982#joinNow .sl-join-modal-section-label { 2983 font-size: 15px; 2984 color: #64748B; 2985 margin: 18px 0 10px; 2986} 2987 2988/* Option cards â with hover slide animation */ 2989#joinNow .sl-join-option { 2990 position: relative; 2991 display: flex; 2992 align-items: center; 2993 gap: 14px; 2994 padding: 16px 18px; 2995 border: 1px solid #E2E8F0; 2996 border-radius: 12px; 2997 text-decoration: none; 2998 color: #0F172A; 2999 background: #FFFFFF; 3000 overflow: hidden; 3001 transition: border-color .25s ease, transform .25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow .25s ease; 3002 z-index: 0; 3003} 3004/* Sliding tinted backdrop revealed on hover (leftâright wipe) */ 3005#joinNow .sl-join-option::before { 3006 content: ""; 3007 position: absolute; 3008 top: 0; 3009 left: 0; 3010 bottom: 0; 3011 width: 100%; 3012 background: linear-gradient(90deg, #F8FAFC 0%, #EFF6FF 100%); 3013 transform: translateX(-100%); 3014 transition: transform .35s cubic-bezier(0.4, 0, 0.2, 1); 3015 z-index: -1; 3016} 3017#joinNow .sl-join-option:hover { 3018 border-color: #2D5BFF; 3019 color: #0F172A; 3020 text-decoration: none; 3021 transform: translateX(4px); 3022 box-shadow: 0 4px 12px -4px rgba(45, 91, 255, 0.18); 3023} 3024#joinNow .sl-join-option:hover::before { transform: translateX(0); } 3025#joinNow .sl-join-option:active { transform: translateX(4px) translateY(1px); } 3026 3027#joinNow .sl-join-option-icon { 3028 flex: 0 0 44px; 3029 width: 44px; 3030 height: 44px; 3031 border-radius: 10px; 3032 display: inline-flex; 3033 align-items: center; 3034 justify-content: center; 3035 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1); 3036} 3037#joinNow .sl-join-option:hover .sl-join-option-icon { transform: scale(1.06); } 3038#joinNow .sl-join-option-icon svg { width: 22px; height: 22px; } 3039#joinNow .sl-join-icon-parent { background: #FED7AA; color: #EA580C; } 3040#joinNow .sl-join-icon-teacher { background: #DBE6FF; color: #2D5BFF; } 3041#joinNow .sl-join-icon-upgrade { background: #D1FAE5; color: #059669; } 3042#joinNow .sl-join-icon-school { background: #E9D5FF; color: #7C3AED; } 3043#joinNow .sl-join-option-body { 3044 flex: 1 1 auto; 3045 display: flex; 3046 flex-direction: column; 3047 gap: 3px; 3048} 3049#joinNow .sl-join-option-body strong { 3050 font-size: 16px; 3051 font-weight: 600; 3052 color: #0F172A; 3053 letter-spacing: -0.01em; 3054} 3055#joinNow .sl-join-option-body small { 3056 font-size: 14px; 3057 color: #64748B; 3058 font-weight: 400; 3059 line-height: 1.4; 3060} 3061#joinNow .sl-join-option-arrow { 3062 flex: 0 0 auto; 3063 font-size: 20px; 3064 color: #94A3B8; 3065 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1), color .25s ease; 3066} 3067#joinNow .sl-join-option:hover .sl-join-option-arrow { 3068 transform: translateX(6px); 3069 color: #2D5BFF; 3070} 3071#joinNow .sl-join-modal-footer-note { 3072 margin: 16px 0 0; 3073 padding-top: 16px; 3074 border-top: 1px solid #E2E8F0; 3075 text-align: center; 3076 font-size: 15px; 3077 color: #64748B; 3078} 3079#joinNow .sl-join-modal-footer-note a { 3080 color: #2D5BFF; 3081 font-weight: 600; 3082 text-decoration: none; 3083} 3084#joinNow .sl-join-modal-footer-note a:hover { text-decoration: underline; } 3085</style> 3086
3087<script> 3088$('#joinNow').on('show.bs.modal', function (e) { 3089 window.dataLayer = window.dataLayer || []; 3090 window.dataLayer.push({ 3091 'event': 'User Account', 3092 'Action': 'Creation', 3093 'Step': '1', 3094 'Step Name': 'Choose Account' 3095 }); 3096}); 3097 3098</script>
3098 3099<div id="publicMenuModal" class="modal site-menu" tabindex="-1" role="dialog"> 3100 <div class="modal-dialog modal-xl" role="document"> 3101 <div class="modal-content"> 3102 <div class="modal-header"> 3103 3104 <h4 class="modal-title">Menu</h4> 3105 <button aria-hidden="true" data-dismiss="modal" class="close" type="button"><i class="far fa-times"></i></button> 3106 3107 </div> 3108 <div class="modal-body"> 3109 <div class="row text-dark"> 3110 3111 <div class="col-md"> 3112 <h3 style="color:#e3813b;border-color:#e3813b"> 3113 <i class="fas fa-book float-right"></i> 3114 Resources 3115 </h3> 3116 3117 <ul class="list-group list-group-flush"> 3118 <li class="list-group-item"><a href="/games">Browse All / Search</a></li> 3119 <li class="list-group-item"><a href="/games/mathematics/au-year-three/mathematics-addition-430">Mathematics</a></li> 3120 <li class="list-group-item"><a href="/games/literacy/au-year-three/english-spelling-and-vocabulary-185">Literacy</a></li> 3121 <li class="list-group-item"><a href="/games/science/au-year-three/science-biology-764">Science</a></li> 3122 <li class="list-group-item"><a href="/games/visual-arts-music/au-mixed-years/art-paint-and-draw-962">Visual Arts and Music</a></li> 3123 <li class="list-group-item"><a href="/games/health-safety-citizenship/au-mixed-years/health-safety-and-citizenship-citizenship-1547">Health, Safety & Citizenship</a></li> 3124 <li class="list-group-item"><a href="/games/language-culture/au-mixed-years/language-and-culture-languages-1022">Language & Culture</a></li> 3125 <li class="list-group-item"><a href="/games/information-communication-technology/au-mixed-years/information-communication-and-technology-social-and-ethical-practices-with-ict-1056">Information Communication Technology</a></li> 3126 <li class="list-group-item"><a href="/games/studysheets/au-year-three/theme-based-learning-rocks-erosion-and-changing-landscapes-1675">Theme Based Learning</a></li> 3127 </ul> 3128 </div> 3129 <div class="col-md"> 3130 <h3 style="color:#87b53e;border-color:#87b53e"> 3131 <i class="fas fa-star float-right"></i> 3132 My Account 3133 </h3> 3134 3135 <ul class="list-group list-group-flush"> 3136 <li class="list-group-item"><a href="#" data-toggle="modal" data-target="#joinNow" onclick="$('#publicMenuModal').modal('hide')">Join now</a></li> 3137 <li class="list-group-item"><a href="/login/account">Log in</a></li> 3138 <li class="list-group-item"><a href="/login/forgot">Forgot password</a></li> 3139 <li class="list-group-item"><a href="/about/pricing">Pricing</a></li> 3140 </ul> 3141 </div> 3142 <div class="col-md"> 3143 <h3 style="color:#9767b6;border-color:#9767b6"> 3144 <i class="fas fa-star float-right"></i> 3145 Other 3146 </h3> 3147 3148 <ul class="list-group list-group-flush"> 3149 <li class="list-group-item"><a href="/about/contact-us">Contact Us</a></li> 3150 <li class="list-group-item"><a href="/help/faq">Help / FAQ</a></li> 3151 <li class="list-group-item"><a href="/about/about-us">About us</a></li> 3152 <li class="list-group-item"><a href="/about/privacy">Privacy</a></li> 3153 <li class="list-group-item"><a href="/about/disclaimer">Disclaimer</a></li> 3154 <li class="list-group-item"><a href="/about/terms">Terms</a></li> 3155 </ul> 3156 3157 </div> 3158 3159 </div><!-- .row --> 3160 </div><!-- .modal-body --> 3161 </div><!-- .modal-content --> 3162 </div><!-- .modal-dialog --> 3163</div><!-- .modal --> 3164 3165</body> 3166 3167<style> 3168 3169 #SLWorldTeaserModal .modal-dialog, #HomeTutorVideoModal .modal-dialog {max-width: 1200px;} 3170 #SLWorldTeaserModal .modal-body, #HomeTutorVideoModal .modal-body {padding-left: 3rem;padding-right: 3rem;} 3171 #SLWorldTeaserModal .modal-header, #HomeTutorVideoModal .modal-header {height:1px; border:none;} 3172 3173 @media only screen and (max-width: 767px) { 3174 #SLWorldTeaserModal .modal-body, #HomeTutorVideoModal .modal-body {padding-left: 1rem;padding-right: 1rem;} 3175 #SLWorldTeaserModal .modal-header, #HomeTutorVideoModal .modal-header {height:1px; border:none;} 3176 #SLWorldTeaserModal .modal-header, #HomeTutorVideoModal .modal-header {height: 20px;padding-top:30px;} 3177 .site-menu .modal-header .close { 3178 margin-top:-45px!important; 3179 } 3180 } 3181 3182</style> 3183 3184 3185
3185<script type="text/javascript"> 3186 3187 3188 $( document ).ready(function(){ 3189 3190 $('#SLWorldTeaserModal').on('hidden.bs.modal', function () { 3191 document.getElementById('slWorldVideo').pause(); 3192 }) 3193 3194 $('#HomeTutorVideoModal').on('hidden.bs.modal', function () { 3195 document.getElementById('htVideo').pause(); 3196 }) 3197 3198 $('#SLWorldTeaserModal').on('shown.bs.modal', function () { 3199 // document.getElementById('slWorldVideo').src(); 3200 videoString = $('#slWorldVideo source').data("videourl"); 3201 $('#slWorldVideo source').attr('src', videoString); 3202 $("#slWorldVideo ")[0].load(); 3203 $("#slWorldVideo ")[0].play(); 3204 }) 3205 3206 $('#HomeTutorVideoModal').on('shown.bs.modal', function () { 3207 // document.getElementById('htVideo').pause(); 3208 videoString = $('#htVideo source').data("videourl"); 3209 $('#htVideo source').attr('src', videoString); 3210 $("#htVideo ")[0].load(); 3211 $("#htVideo ")[0].play(); 3212 }) 3213 3214 }); 3215 3216 // document.getElementById('videoId').play(); 3217 //jQuery("#video").trigger('pause'); 3218 3219 3220 </script>
3220 3221 3222 <div class="modal fade newPopUpDesign site-menu" id="SLWorldTeaserModal" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true"> 3223 <div class="modal-dialog modalBox"> 3224 <div class="modal-content"> 3225 <div class="modal-header " style="background-color:#000!important;"> 3226 <h4 class="modal-title text-center w-100 d-none" style="background-color:#000;text-shadow: none;color:#fff">Studyladder <span style="color:#3fa9f5;">World</span> Teaser<span class="sprite iconCorner3"></span></h4> 3227 <button aria-hidden="true" data-dismiss="modal" class="close" type="button"><i class="fa fa-times"></i></button> 3228 </div> 3229 <div class="modal-body pt-4" style="background-color:#000;"> 3230 3231 <video id="slWorldVideo" class="w-100 " style="border:1px solid #ccc; " controls="" poster="/images/world/sl-world-vid-thumb-1.png"> <source src="" data-videourl="https://static.studyladder.co.uk/cdn/site/3a/2161260c8cd1.mp4" type="video/mp4"></video> 3232 </div> 3233 </div> 3234 </div> 3235 </div> 3236 3237 <div class="modal fade newPopUpDesign site-menu" id="HomeTutorVideoModal" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true"> 3238 <div class="modal-dialog modalBox"> 3239 <div class="modal-content"> 3240 <div class="modal-header " style="background-color:#000!important;"> 3241 <h4 class="modal-title text-center w-100 d-none" style="background-color:#000;text-shadow: none;color:#fff">Studyladder Home Tutor Trailer<span class="sprite iconCorner3"></span></h4> 3242 <button aria-hidden="true" data-dismiss="modal" class="close" type="button"><i class="fa fa-times"></i></button> 3243 </div> 3244 <div class="modal-body pt-4" style="background-color:#000;"> 3245 <video id="htVideo" class="w-100 " style="border:1px solid #ccc; " controls="" poster="/images/home-tutor/ht-vid-thumb-1.png"> <source src="" data-videourl="https://static.studyladder.co.uk/cdn/site/92/e94af3cc87a8.mp4" type="video/mp4"></video> 3246 3247 </div> 3248 </div> 3249 </div> 3250 </div> <!DOCTYPE html> 3251<html lang="en"> 3252<head> 3253 <meta charset="UTF-8"> 3254 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 3255 <title>Cookie Consent</title> 3256 <style> 3257 #cookie-banner { 3258 position: fixed; 3259 bottom: 20px; 3260 right: 20px; 3261 width: 320px; 3262 background: #212529; 3263 color: #f8f9fa; 3264 padding: 20px; 3265 border-radius: 8px; 3266 box-shadow: 0 0px 12px -1px white; 3267 z-index: 9999; 3268 font-family: 'Quicksand', 'Helvetica Neue', sans-serif; 3269 display: none; 3270 gap: 15px; 3271 align-items: flex-start; 3272 } 3273 3274 #cookie-banner-icon, 3275 #cookie-preferences-icon { 3276 flex-shrink: 0; 3277 filter: drop-shadow(0 0 6px rgba(255,255,255,0.5)); 3278 } 3279 3280 #cookie-banner-icon img, 3281 #cookie-preferences-icon img { 3282 width: 40px; 3283 height: 40px; 3284 } 3285 3286 #cookie-banner-content { 3287 flex: 1; 3288 } 3289 3290 #cookie-preferences { 3291 position: fixed; 3292 bottom: 20px; 3293 right: 20px; 3294 width: 320px; 3295 background: #212529; 3296 color: #f8f9fa; 3297 padding: 20px; 3298 border-radius: 8px; 3299 box-shadow: 0 0px 12px -1px white; 3300 z-index: 9999; 3301 font-family: 'Quicksand', 'Helvetica Neue', sans-serif; 3302 display: none; 3303 gap: 15px; 3304 } 3305 3306 #cookie-preferences-content { 3307 flex: 1; 3308 } 3309 3310 #cookie-banner-content p, 3311 #cookie-preferences-content p { 3312 margin-bottom: 1em; 3313 line-height: 1.4em; 3314 } 3315 3316 #cookie-banner-content a { 3317 color: #ffc107; 3318 text-decoration: underline; 3319 } 3320 3321 .cookie-buttons { 3322 display: flex; 3323 flex-wrap: wrap; 3324 gap: 8px; 3325 } 3326 3327 .cookie-buttons button, 3328 .save-btn { 3329 padding: 8px 12px; 3330 border: none; 3331 border-radius: 6px; 3332 cursor: pointer; 3333 font-weight: 600; 3334 font-family: 'Quicksand', sans-serif; 3335 letter-spacing: 0.5px; 3336 } 3337 3338 .accept-btn { background: #198754; color: #fff; } 3339 .reject-btn { background: #dc3545; color: #fff; } 3340 .customize-btn { background: #ffc107; color: #000; } 3341 .save-btn { background: #0d6efd; color: #fff; width: 100%; margin-top: 10px; } 3342 3343 .toggle-wrapper { 3344 display: flex; 3345 justify-content: space-between; 3346 align-items: center; 3347 margin-bottom: 10px; 3348 } 3349 3350 .toggle-switch { 3351 position: relative; 3352 display: inline-block; 3353 width: 36px; 3354 height: 20px; 3355 } 3356 3357 .toggle-switch input { 3358 opacity: 0; 3359 width: 0; 3360 height: 0; 3361 } 3362 3363 .slider { 3364 position: absolute; 3365 cursor: pointer; 3366 top: 0; 3367 left: 0; 3368 right: 0; 3369 bottom: 0; 3370 background-color: #ccc; 3371 transition: 0.2s; 3372 border-radius: 34px; 3373 } 3374 3375 .slider:before { 3376 position: absolute; 3377 content: ""; 3378 height: 14px; 3379 width: 14px; 3380 left: 3px; 3381 bottom: 3px; 3382 background-color: white; 3383 transition: 0.2s; 3384 border-radius: 50%; 3385 } 3386 3387 .toggle-switch input:checked + .slider { 3388 background-color: #0d6efd; 3389 } 3390 3391 .toggle-switch input:checked + .slider:before { 3392 transform: translateX(16px); 3393 } 3394 </style> 3395
3395<script> 3396 window.dataLayer = window.dataLayer || []; 3397 function gtag() { dataLayer.push(arguments); } 3398 3399 const siteCountryId = "GB"; 3400 const unrestricted = ["AU", "NZ"].includes(siteCountryId); 3401 let isStudent = false; 3402 3403 if (unrestricted) { 3404 localStorage.setItem('cookie_consent', JSON.stringify({analytics: true, marketing: true})); 3405 } else if (isStudent) { 3406 localStorage.setItem('cookie_consent', JSON.stringify({analytics: false, marketing: false})); 3407 } else { 3408 gtag('consent', 'default', { 3409 'ad_storage': 'denied', 3410 'analytics_storage': 'denied', 3411 'ad_user_data': 'denied', 3412 'ad_personalization': 'denied', 3413 'functionality_storage': 'granted', 3414 'security_storage': 'granted' 3415 }); 3416 } 3417 3418 document.addEventListener('DOMContentLoaded', () => { 3419 const prefs = JSON.parse(localStorage.getItem('cookie_consent') || '{}'); 3420 3421 if (unrestricted) { 3422 // No banner, full access 3423 gtag('consent', 'update', { 3424 'ad_storage': 'granted', 3425 'ad_user_data': 'granted', 3426 'ad_personalization': 'granted', 3427 'analytics_storage': 'granted', 3428 'functionality_storage': 'granted', 3429 'security_storage': 'granted' 3430 }); 3431 return; 3432 } 3433 3434 if (!('analytics' in prefs) && !('marketing' in prefs)) { 3435 document.getElementById('cookie-banner').style.display = 'block'; 3436 document.getElementById('cookie-preferences').style.display = 'none'; 3437 } else { 3438 applyConsent(prefs); 3439 } 3440 }); 3441 3442 function applyConsent(prefs) { 3443 gtag('consent', 'update', { 3444 'ad_storage': prefs.marketing ? 'granted' : 'denied', 3445 'ad_user_data': prefs.marketing ? 'granted' : 'denied', 3446 'ad_personalization': prefs.marketing ? 'granted' : 'denied', 3447 'analytics_storage': prefs.analytics ? 'granted' : 'denied', 3448 'functionality_storage': 'granted', 3449 'security_storage': 'granted' 3450 }); 3451 } 3452 </script>
3452 3453</head> 3454<body> 3455<!-- body content remains unchanged --> 3456 3457<div id="cookie-banner"> 3458 <div class="d-flex align-items-start" style="gap:15px"> 3459 <div id="cookie-banner-icon"> 3460 <img src="https://static.studyladder.co.uk/cdn/site/71/25a349e3aa67.png" alt="Cookie Icon"> 3461 </div> 3462 <div id="cookie-banner-content"> 3463 <p>We use cookies to help tailor your educational experience. <a href="/about/privacy">Learn more</a></p> 3464 </div> 3465 </div> 3466 3467 <div class="cookie-buttons mt-3"> 3468 <button class="accept-btn" onclick="acceptAllCookies()">Accept</button> 3469 <button class="reject-btn" onclick="rejectAllCookies()">Reject</button> 3470 <button class="customize-btn" onclick="openPreferences()">Customize</button> 3471 </div> 3472</div> 3473 3474<div id="cookie-preferences"> 3475 <div id="cookie-preferences-icon"> 3476 <img src="https://static.studyladder.co.uk/cdn/site/71/25a349e3aa67.png" alt="Cookie Icon"> 3477 </div> 3478 <div id="cookie-preferences-content"> 3479 <p>Cookie Preferences:</p> 3480 <div class="toggle-wrapper"> 3481 <span>Essential (always on)</span> 3482 <div class="toggle-switch"><label><input type="checkbox" disabled checked><span class="slider"></span></label></div> 3483 </div> 3484 <div class="toggle-wrapper"> 3485 <span>Analytics</span> 3486 <div class="toggle-switch"><label><input type="checkbox" id="toggle-analytics" checked><span class="slider"></span></label></div> 3487 </div> 3488 <div class="toggle-wrapper"> 3489 <span>Marketing</span> 3490 <div class="toggle-switch"><label><input type="checkbox" id="toggle-marketing" checked><span class="slider"></span></label></div> 3491 </div> 3492 <button class="save-btn" onclick="savePreferences()">Save Preferences</button> 3493 </div> 3494</div> 3495
3496<script> 3497 function saveConsent(prefs) { 3498 localStorage.setItem('cookie_consent', JSON.stringify(prefs)); 3499 applyConsent(prefs); 3500 } 3501 3502 function getConsent() { 3503 return JSON.parse(localStorage.getItem('cookie_consent') || '{}'); 3504 } 3505 3506 function applyConsent(prefs) { 3507 if (prefs.analytics) { 3508 loadGoogleAnalytics(); 3509 } 3510 3511 gtag('consent', 'update', { 3512 'ad_storage': prefs.marketing ? 'granted' : 'denied', 3513 'ad_user_data': prefs.marketing ? 'granted' : 'denied', 3514 'ad_personalization': prefs.marketing ? 'granted' : 'denied', 3515 'analytics_storage': prefs.analytics ? 'granted' : 'denied', 3516 'functionality_storage': 'granted', 3517 'security_storage': 'granted' 3518 }); 3519 } 3520 3521 function loadGoogleAnalytics() { 3522 if (!window.gtag){ 3523 window.dataLayer = window.dataLayer || []; 3524 function gtag() { dataLayer.push(arguments); } 3525 } 3526 3527 } 3528 3529 function acceptAllCookies() { 3530 saveConsent({ analytics: true, marketing: true }); 3531 document.getElementById('cookie-banner').style.display = 'none'; 3532 } 3533 3534 function rejectAllCookies() { 3535 saveConsent({ analytics: false, marketing: false }); 3536 document.getElementById('cookie-banner').style.display = 'none'; 3537 } 3538 3539 function openPreferences() { 3540 document.getElementById('cookie-banner').style.display = 'none'; 3541 document.getElementById('cookie-preferences').style.display = 'flex'; 3542 } 3543 3544 function savePreferences() { 3545 const prefs = { 3546 analytics: document.getElementById('toggle-analytics').checked, 3547 marketing: document.getElementById('toggle-marketing').checked 3548 }; 3549 saveConsent(prefs); 3550 document.getElementById('cookie-preferences').style.display = 'none'; 3551 } 3552 3553 document.addEventListener('DOMContentLoaded', () => { 3554 const prefs = getConsent(); 3555 if (!('analytics' in prefs) && !('marketing' in prefs)) { 3556 document.getElementById('cookie-banner').style.display = 'block'; 3557 document.getElementById('cookie-preferences').style.display = 'none'; 3558 } else { 3559 document.getElementById('cookie-banner').style.display = 'none'; 3560 document.getElementById('cookie-preferences').style.display = 'none'; 3561 applyConsent(prefs); 3562 } 3563 }); 3564</script>
3564 3565</body> 3566</html> 3567 3568 3569 <!-- SL marketing reveal-on-scroll â only runs when <body> has .sl-marketing class --> 3570
3570<script> 3571 (function () { 3572 if (!document.body.classList.contains('sl-marketing')) return; 3573 if (!('IntersectionObserver' in window)) return; 3574 3575 // Selectors that fade-up when scrolled into view 3576 var fadeUp = [ 3577 '.section-eyebrow', '.section-title', '.section-sub', 3578 '.video-frame', '.year-progression', '.stats-note', '.tour-cta-row', 3579 '.curr-header', '.safety-header', '.safety-cta', 3580 '.faq-intro', '.final-cta-inner > *' 3581 ].join(','); 3582 3583 // Stagger groups â same animation but delayed in sequence for grids 3584 var staggerGroups = [ 3585 '.audience-grid > .audience-card', 3586 '.subjects-grid > .subject-card', 3587 '.why-grid > .why-item', 3588 '.stats-grid > .stat-card', 3589 '.test-grid > .test-card', 3590 '.pricing-grid > .price-card', 3591 '.safety-grid > .safety-item', 3592 '.faq-list > .faq-item', 3593 '.video-chapters > .chapter', 3594 '.platform-grid > .feature-tile', 3595 '.story-stat-stack > .story-stat', 3596 '.test-grid > .test-card', 3597 '.results-list > li' 3598 ]; 3599 3600 document.querySelectorAll(fadeUp).forEach(function (el) { 3601 el.classList.add('reveal'); 3602 }); 3603 3604 staggerGroups.forEach(function (sel) { 3605 document.querySelectorAll(sel).forEach(function (el, idx) { 3606 el.classList.add('reveal'); 3607 el.style.animationDelay = Math.min(idx * 0.05, 0.3) + 's'; 3608 }); 3609 }); 3610 3611 var obs = new IntersectionObserver(function (entries) { 3612 entries.forEach(function (entry) { 3613 if (entry.isIntersecting) { 3614 entry.target.classList.add('is-visible'); 3615 obs.unobserve(entry.target); 3616 } 3617 }); 3618 }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' }); 3619 3620 document.querySelectorAll('.reveal').forEach(function (el) { 3621 obs.observe(el); 3622 }); 3623 3624 // ---- Video player: swap poster for YouTube iframe on click ---- 3625 document.querySelectorAll('.video-player[data-video-id]').forEach(function (player) { 3626 var btn = player.querySelector('.video-play-btn'); 3627 if (!btn) return; 3628 btn.addEventListener('click', function (e) { 3629 e.preventDefault(); 3630 var id = player.getAttribute('data-video-id'); 3631 var label = player.getAttribute('data-video-label') || ''; 3632 var frame = document.createElement('iframe'); 3633 frame.src = 'https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1&rel=0'; 3634 frame.title = label; 3635 frame.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'; 3636 frame.setAttribute('allowfullscreen', ''); 3637 frame.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;border:0;border-radius:inherit;'; 3638 player.appendChild(frame); 3639 // Hide the poster and overlay so iframe shows through 3640 player.querySelectorAll('.video-poster-img, .video-poster-overlay, .video-play-btn, .video-meta').forEach(function (el) { 3641 el.style.display = 'none'; 3642 }); 3643 }); 3644 }); 3645 3646 // ---- Sticky CTA â fades in after the trigger element scrolls past ---- 3647 // Bar reads data-sticky-trigger="<elementId>" off itself. If omitted, 3648 // defaults to #pricing. The bar gets .visible once the trigger has 3649 // fully scrolled above the viewport. 3650 var stickyBar = document.getElementById('stickyCta'); 3651 if (stickyBar) { 3652 var triggerId = stickyBar.getAttribute('data-sticky-trigger') || 'pricing'; 3653 var trigger = document.getElementById(triggerId); 3654 if (trigger) { 3655 var stickyObs = new IntersectionObserver(function (entries) { 3656 entries.forEach(function (entry) { 3657 var aboveViewport = !entry.isIntersecting && entry.boundingClientRect.bottom < 0; 3658 stickyBar.classList.toggle('visible', aboveViewport); 3659 stickyBar.setAttribute('aria-hidden', aboveViewport ? 'false' : 'true'); 3660 }); 3661 }, { threshold: 0, rootMargin: '0px' }); 3662 stickyObs.observe(trigger); 3663 } 3664 } 3665 3666 // ---- Home Plus benefits tabs (parent / parent-pricing / etc.) ---- 3667 document.querySelectorAll('.benefits-tabs').forEach(function (tablist) { 3668 var tabs = tablist.querySelectorAll('.benefits-tab');
3669 tabs.forEach(function (tab) { 3670 tab.addEventListener('click', function () { 3671 var key = tab.getAttribute('data-tab'); 3672 tabs.forEach(function (t) { 3673 var isActive = t === tab; 3674 t.classList.toggle('active', isActive); 3675 t.setAttribute('aria-selected', isActive ? 'true' : 'false'); 3676 }); 3677 document.querySelectorAll('.benefits-panel').forEach(function (p) { 3678 var isMatch = p.getAttribute('id') === 'benefit-panel-' + key; 3679 p.classList.toggle('active', isMatch); 3680 if (isMatch) { 3681 p.removeAttribute('hidden'); 3682 } else { 3683 p.setAttribute('hidden', ''); 3684 } 3685 }); 3686 }); 3687 }); 3688 }); 3689 })(); 3690 </script>
3690 3691 3692 <!-- HEALTH CHECK 0049835 --> 3693</body> 3694</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.