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
24<script> 25function sl_errorJsLog_HIE371(errorData) { 26 const endpoint = '/error-js-log/log?token=OriginCookie1f1l6v6ab509d58b3123Z84xMYAPMxSH915d0951c7edDGXghRlS'; 27 28 const body = JSON.stringify(errorData); 29 const headers = { type: 'application/json' }; 30 31 if (navigator.sendBeacon) { 32 const blob = new Blob([body], headers); 33 navigator.sendBeacon(endpoint, blob); 34 } 35} 36window.addEventListener('error', function (event) { 37 if (event.error instanceof Error) { 38 sl_errorJsLog_HIE371({ 39 type: 'Javascript', 40 message: event.error.message, 41 stack: event.error.stack, 42 filename: event.filename, 43 lineno: event.lineno, 44 colno: event.colno, 45 url: window.location.href, 46 userAgent: navigator.userAgent, 47 timestamp: Date.now() 48 }); 49 } 50}, true); 51</script>
51 52 53 <!-- Google Tag Manager --> 54
54<script>
vendor: 387 bytes, lines 54-58
54 55 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'}); 56 var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:''; 57 j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl; f.parentNode.insertBefore(j,f); 58 })(window,document,'script','dataLayer','
58GTM-MRVSQXKH
vendor: 12 bytes, lines 58-59
58'); 59
59</script>
59 60 61 62
62<script> 63 window.dataLayer = window.dataLayer || []; 64 function gtag(){dataLayer.push(arguments);} 65 gtag('config', 'AW-1071699385'); 66 </script>
66 67 68 <!-- End Google Tag Manager --> 69 70 <title>Studyladder, online english literacy & mathematics. Kids activity games, worksheets and lesson plans.</title> 71 72
72<script type="text/javascript" src="/cdn/lib/vendor/jquery/jquery-3.7.1-v1.min.js"></script>
72 73
73<script type="text/javascript" src="/cdn/lib/vendor/bootstrap/4.6.2/js/bootstrap.bundle.min.js"></script>
73 74
74<script type="module"> 75 import { DotLottie } from "https://static.studyladder.co.uk/cdn/site/d7/d82cd2118b99.js";//"https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/+esm"; 76 window.DotLottie = DotLottie; // Attach DotLottie to the window object for global access 77 </script>
77 78
78<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/1c/6548deb1bcf7.js"></script>
78 79 80
80<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/30/152a03965f6d.js"></script>
80 81
81<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/6b/6f6a16f17ffa.js"></script>
81 82
82<script type="text/javascript" src="https://static.studyladder.co.uk/cdn/site/85/8149e1190b9d.js"></script>
82 83 <link rel="preconnect" href="https://fonts.gstatic.com"> 84 <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@800&display=swap" rel="stylesheet"> 85 <link href="https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap" rel="stylesheet"> 86 <link href='https://fonts.googleapis.com/css?family=ABeeZee:400,400italic' rel='stylesheet' type='text/css'> 87 <link href="https://fonts.googleapis.com/css?family=Muli|Quicksand:400,500,700" rel="stylesheet"> 88 <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"> 89 <link rel="stylesheet" type="text/css" href="/cdn/lib/vendor/font-awesome/pro-5.5.00-web/css/fontawesome-solid-regular.min.css"/> 90 <link rel="stylesheet" href="https://static.studyladder.co.uk/cdn/dist/scss/ad0326d857b829a3/scss/bootstrap.min.css"/> 91 92 <link rel="stylesheet" type="text/css" href="https://static.studyladder.co.uk/cdn/dist/scss/b0d969d290c3b536/global.min.css"/> 93 <link rel="stylesheet" type="text/css" href="https://static.studyladder.co.uk/cdn/dist/scss/47bf43b33f3c98b5/scss/sl-marketing.min.css"/> 94 95 96
96<script> 97 window.MathJax = { 98 loader: { 99 paths: { 100 mathjax: "\/lib\/vendor\/mathjax\/3.2.2\/es5" } 101 }, 102 tex: { 103 inlineMath: [['\\(', '\\)']], 104 }, 105 svg: { 106 fontCache: 'global' 107 } 108 }; 109 </script>
109 110 111
111<script src="https://static.studyladder.co.uk/cdn/site/cf/b8e18acf40a7.js" async></script>
111 112 113 </head> 114 <body style="" class=" sl-marketing"> 115
115<script>var animation; var swalAnimation; var cacheVersion = 0.01</script>
115 116 117 <!-- Google Tag Manager (noscript) -->
vendor: 89 bytes, lines 117-119
117 118 <noscript> 119 <iframe src="https://www.googletagmanager.com/ns.html?id=
119GTM-MRVSQXKH
vendor: 92 bytes, lines 119-120
119" height="0" width="0" style="display:none;visibility:hidden"></iframe> 120 </noscript>
120<!-- End Google Tag Manager (noscript) --> 121 <header id="site-header" class="site-header-container public "> 122 <nav class="site-header"> 123 <div class="">
124<script> 125 // Set data-locale on <html> as early as possible so .au-only / .intl-only 126 // spans render correctly without a flash of wrong content. 127 (function(){ 128 try { document.documentElement.setAttribute('data-locale', "intl"); } catch(e){} 129 })(); 130</script>
130 131 132<style> 133/* âââ Country bar (top strip) ââââââââââââââââââââââââââââââââââââââ */ 134.country-bar { 135 background: #F8FAFC; 136 border-bottom: 1px solid #E2E8F0; 137 padding: 2px 0; 138 font-size: 12px; 139 color: #475569; 140 line-height: 1.2; 141} 142.country-bar-inner { 143 max-width: 1280px; 144 margin: 0 auto; 145 padding: 0 20px; 146 display: flex; 147 align-items: center; 148 justify-content: flex-end; 149 gap: 12px; 150} 151.country-selector { 152 display: inline-flex; 153 align-items: center; 154 gap: 6px; 155 position: relative; 156} 157.country-flag { 158 display: inline-flex; 159 align-items: center; 160 justify-content: center; 161 width: 18px; 162 height: 12px; 163 overflow: hidden; 164 border-radius: 2px; 165 flex: 0 0 auto; 166} 167.country-flag img { 168 width: 18px !important; 169 height: auto !important; 170 max-width: 18px !important; 171 display: block; 172} 173.country-select { 174 background: transparent; 175 border: 0; 176 padding: 2px 20px 2px 6px; 177 font: inherit; 178 font-size: 12px; 179 color: #0F172A; 180 cursor: pointer; 181 -webkit-appearance: none; 182 appearance: none; 183 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>"); 184 background-repeat: no-repeat; 185 background-position: right 4px center; 186 line-height: 1.2; 187} 188.country-select:hover { color: #2D5BFF; } 189.country-caret { display: none; } /* selector renders its own arrow */ 190 191/* âââ Main nav âââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 192nav.top { 193 background: #FFFFFF; 194 border-bottom: 1px solid #E2E8F0; 195 position: relative; 196 z-index: 100; 197} 198nav.top .nav-inner { 199 max-width: 1280px; 200 margin: 0 auto; 201 padding: 8px 20px; 202 display: flex; 203 align-items: center; 204 gap: 24px; 205} 206nav.top .logo { 207 display: inline-flex; 208 align-items: center; 209 flex: 0 0 auto; 210} 211nav.top .logo img { 212 height: 36px; 213 width: auto; 214 display: block; 215} 216nav.top .nav-links { 217 list-style: none; 218 margin: 0; 219 padding: 0; 220 display: flex; 221 align-items: center; 222 gap: 4px; 223 flex: 1 1 auto; 224} 225nav.top .nav-links > li { position: relative; } 226nav.top .nav-links > li > a, 227nav.top .nav-links > li > .nav-dropdown-trigger { 228 display: inline-flex; 229 align-items: center; 230 gap: 4px; 231 padding: 10px 14px; 232 font-size: 14px; 233 font-weight: 500; 234 color: #475569; 235 text-decoration: none; 236 border-radius: 8px; 237 transition: background .15s ease, color .15s ease;
238 cursor: pointer; 239} 240nav.top .nav-links > li > a:hover, 241nav.top .nav-links > li > .nav-dropdown-trigger:hover { 242 color: #0F172A; 243 background: #F8FAFC; 244} 245nav.top .nav-caret { 246 font-size: 14px; 247 opacity: 0.8; 248 margin-left: 2px; 249 display: inline-block; 250 line-height: 1; 251 transition: transform .15s ease; 252} 253nav.top .nav-dropdown:hover .nav-caret { transform: rotate(180deg); } 254nav.top .nav-dropdown-menu { 255 display: none; 256 position: absolute !important; 257 top: 100% !important; 258 left: 50% !important; 259 transform: translateX(-50%) !important; 260 margin-top: 5px !important; 261 min-width: 220px; 262 background: #FFFFFF; 263 border: 1px solid #E2E8F0; 264 border-radius: 12px; 265 box-shadow: 0 12px 32px -8px rgba(15,23,42,0.18), 0 2px 6px rgba(15,23,42,0.06); 266 padding: 8px; 267 z-index: 200; 268} 269/* Hover-bridge so mouse can travel from trigger to dropdown without losing hover */ 270nav.top .nav-dropdown::after { 271 content: ""; 272 position: absolute; 273 top: 100%; 274 left: 0; 275 right: 0; 276 height: 8px; 277 pointer-events: auto; 278} 279nav.top .nav-dropdown:hover .nav-dropdown-menu, 280nav.top .nav-dropdown:focus-within .nav-dropdown-menu { display: block; } 281nav.top .nav-dropdown-menu a { 282 display: flex; 283 align-items: center; 284 gap: 10px; 285 padding: 10px 12px; 286 border-radius: 8px; 287 font-size: 14px; 288 color: #0F172A; 289 text-decoration: none; 290 transition: background .15s ease; 291} 292nav.top .nav-dropdown-menu a:hover { background: #F1F5F9; } 293nav.top .nav-dropdown-icon { 294 display: inline-flex !important; 295 align-items: center !important; 296 justify-content: center !important; 297 width: 28px !important; 298 height: 28px !important; 299 min-width: 28px !important; 300 border-radius: 6px !important; 301 font-size: 14px !important; 302 font-weight: 700 !important; 303 flex: 0 0 28px !important; 304 line-height: 1 !important; 305 text-transform: none !important; 306 font-family: inherit !important; 307} 308/* Soft pastel backgrounds with deep coloured letters â matches subject-page topic-card-icon style */ 309nav.top .nav-dropdown-icon.maths { background: #DBE6FF !important; color: #2D5BFF !important; } /* blue */ 310nav.top .nav-dropdown-icon.english { background: #D1FAE5 !important; color: #059669 !important; } /* green */ 311nav.top .nav-dropdown-icon.science { background: #FED7AA !important; color: #EA580C !important; } /* orange */ 312nav.top .nav-dropdown-icon.parent { background: #FED7AA !important; color: #EA580C !important; } /* orange */ 313nav.top .nav-dropdown-icon.teacher { background: #DBE6FF !important; color: #2D5BFF !important; } /* blue */ 314nav.top .nav-dropdown-icon.school { background: #D1FAE5 !important; color: #059669 !important; } /* green */ 315 316nav.top .nav-cta { 317 display: flex; 318 align-items: center; 319 gap: 8px; 320 flex: 0 0 auto; 321} 322nav.top .nav-cta .btn { 323 font-size: 14px; 324 padding: 8px 16px; 325 border-radius: 999px; 326 font-weight: 600; 327 text-decoration: none; 328 display: inline-flex; 329 align-items: center; 330} 331nav.top .nav-cta .btn-ghost { 332 background: transparent; 333 color: #0F172A; 334 border: 1px solid transparent; 335} 336nav.top .nav-cta .btn-ghost:hover { background: #F1F5F9; } 337nav.top .nav-cta .btn-primary { 338 background: #2D5BFF; 339 color: #FFFFFF; 340 border: 1px solid #2D5BFF; 341} 342nav.top .nav-cta .btn-primary:hover { background: #1E40AF; border-color: #1E40AF; } 343 344nav.top .nav-menu-toggle { 345 display: none; 346 background: transparent; 347 border: 0; 348 width: 40px; 349 height: 40px; 350 padding: 8px; 351 cursor: pointer; 352 flex-direction: column; 353 justify-content: space-between; 354 align-items: stretch; 355} 356nav.top .nav-menu-toggle span { 357 display: block; 358 height: 2px; 359 width: 100%; 360 background: #0F172A; 361 border-radius: 2px; 362 transition: transform .2s ease, opacity .2s ease; 363} 364 365.nav-mobile-only { display: none; } 366 367/* Force white text on the mobile Join Now button, regardless of viewport width. 368 sl-marketing.scss's mobile nav kicks in at â¤1024px and its `.sl-marketing a { color: blue }` 369 base rule would otherwise leave the button reading blue-on-blue. */ 370nav.top .nav-mobile-only .nav-mobile-join, 371nav.top .nav-mobile-only .nav-mobile-join:link, 372nav.top .nav-mobile-only .nav-mobile-join:visited, 373nav.top .nav-mobile-only .nav-mobile-join:hover, 374nav.top .nav-mobile-only .nav-mobile-join:focus, 375nav.top .nav-mobile-only .nav-mobile-join:active { 376 color: #FFFFFF !important; 377 background: #2D5BFF !important; 378} 379 380/* âââ Mobile breakpoint ââââââââââââââââââââââââââââââââââââââââââââ */ 381/* Aligned to sl-marketing.scss's own 1024px nav breakpoint so both stylesheets 382 flip to mobile at the same viewport width. Also toggles on `.open` (the 383 class name sl-marketing already targets) instead of a bespoke `.is-open`. */ 384@media (max-width: 1024px) { 385 nav.top .nav-links { 386 display: none; 387 position: absolute; 388 top: 100%; 389 left: 0; 390 right: 0; 391 flex-direction: column; 392 align-items: stretch; 393 background: #FFFFFF; 394 border-bottom: 1px solid #E2E8F0; 395 padding: 12px 16px; 396 gap: 4px; 397 box-shadow: 0 12px 24px -10px rgba(15,23,42,0.15); 398 max-height: calc(100vh - 80px); 399 overflow-y: auto; 400 } 401 nav.top .nav-links.open, 402 nav.top .nav-links.is-open { display: flex; } 403 nav.top .nav-links > li > a, 404 nav.top .nav-links > li > .nav-dropdown-trigger { padding: 12px 10px; font-size: 16px; } 405 nav.top .nav-dropdown-menu { 406 display: none !important; 407 position: static !important; 408 top: auto !important; 409 left: auto !important; 410 right: auto !important; 411 transform: none !important; 412 margin: 0 !important; 413 box-shadow: none !important; 414 border: 0 !important; 415 border-radius: 0 !important; 416 padding: 4px 0 8px 24px !important; 417 background: transparent !important; 418 min-width: 0 !important; 419 width: 100% !important; 420 } 421 /* Kill desktop hover/focus reveal on mobile (touch devices shouldn't use hover) */ 422 nav.top .nav-dropdown:hover > .nav-dropdown-menu, 423 nav.top .nav-dropdown:focus-within > .nav-dropdown-menu, 424 nav.top .nav-dropdown:hover .nav-dropdown-menu, 425 nav.top .nav-dropdown:focus-within .nav-dropdown-menu { display: none !important; } 426 /* .open wins via source order over the hover/focus block above */ 427 nav.top .nav-dropdown.open > .nav-dropdown-menu, 428 nav.top .nav-dropdown.open:hover > .nav-dropdown-menu, 429 nav.top .nav-dropdown.open:focus-within > .nav-dropdown-menu { display: block !important; } 430 nav.top .nav-dropdown.open > .nav-dropdown-trigger .nav-caret { transform: rotate(180deg); } 431 nav.top .nav-dropdown::after { display: none; } 432 nav.top .nav-dropdown { position: static !important; } 433 .nav-mobile-only .nav-mobile-join, 434 .nav-mobile-only .nav-mobile-join:hover, 435 .nav-mobile-only .nav-mobile-join:focus, 436 .nav-mobile-only .nav-mobile-join:active { color: #FFFFFF !important; background: #2D5BFF !important; } 437 nav.top .nav-menu-toggle { display: flex; } 438 nav.top .nav-cta .btn-ghost, 439 nav.top .nav-cta .btn-primary { display: none; } 440 .nav-mobile-only { display: block; margin-top: 10px; padding-top: 10px; border-top: 1px solid #E2E8F0; } 441 .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; } 442 .nav-mobile-only .nav-mobile-join { background: #2D5BFF; color: #FFFFFF; } 443 .nav-mobile-only .nav-mobile-login { background: #FFFFFF; color: #0F172A; border: 1px solid #E2E8F0; }
444 body.nav-open { overflow: hidden; } 445} 446 447/* âââ Short viewports â pin Join Now / Login to the top of the menu ââââ 448 On landscape phones / small laptops (Nest Hub etc.) the CTA row at the 449 bottom of the menu can fall below the fold. Flex `order` moves it to 450 the top of the column without touching the DOM. */ 451@media (max-width: 1024px) and (max-height: 650px) { 452 nav.top .nav-links .nav-mobile-cta { 453 order: -1; 454 margin-top: 0; 455 padding-top: 0; 456 border-top: 0; 457 margin-bottom: 10px; 458 padding-bottom: 10px; 459 border-bottom: 1px solid #E2E8F0; 460 } 461} 462</style> 463 464<!-- COUNTRY BAR â thin strip at the top, replaces the old dark navbar --> 465<div class="country-bar"> 466 <div class="country-bar-inner"> 467 <form class="country-selector" id="lcForm"> 468 <span class="country-flag" aria-hidden="true"> 469 <img src="https://static.studyladder.co.uk/cdn/site/66/a8cfb86cfc1b.png" alt=""> 470 </span> 471 <select id="lc_select" name="lc_set" class="country-select" aria-label="Change country"> 472 <option value="https://www.studyladder.com.au/login/account">Australia</option> 473 <option value="https://www.studyladder.ca/login/account">Canada</option> 474 <option value="https://www.studyladder.co.nz/login/account">New Zealand</option> 475 <option value="https://www.studyladder.co.uk/login/account" selected="selected">United Kingdom</option> 476 <option value="https://www.studyladder.com/login/account">United States</option> 477 </select> 478 <span class="country-caret" aria-hidden="true">▾</span> 479 </form> 480 </div> 481</div> 482
483<script> 484 // Locale switcher â submit to the selected URL 485 document.getElementById('lc_select').addEventListener('change', function(){ 486 var u = this.value; 487 var f = document.getElementById('lcForm'); 488 f.setAttribute('action', u); 489 f.submit(); 490 }); 491</script>
491 492 493<!-- MAIN NAV â new marketing design --> 494<nav class="top"> 495 <div class="nav-inner"> 496 <a href="/" class="logo"> 497 <img src="https://static.studyladder.co.uk/cdn/site/13/6f597fea9532.png" alt="Studyladder"> 498 </a> 499 500 <ul class="nav-links" id="primaryNav"> 501 <li><a href="/about/parent">Parents</a></li> 502 <li><a href="/about/teacher">Teachers</a></li> 503 <li><a href="/about/schools">Schools</a></li> 504 505 <li class="nav-dropdown"> 506 <a href="/about/subjects" class="nav-dropdown-trigger">Subjects <span class="nav-caret">▾</span></a> 507 <div class="nav-dropdown-menu"> 508 <a href="/about/subjects-mathematics"><span class="nav-dropdown-icon maths">M</span>Mathematics</a> 509 <a href="/about/subjects-english"><span class="nav-dropdown-icon english">E</span>English</a> 510 <a href="/about/subjects-science"><span class="nav-dropdown-icon science">S</span>Science</a> 511 </div> 512 </li> 513 514 <li><a href="/info/curriculum-aligned?jurisdiction=gb">Curriculum</a></li> 515 516 <li class="nav-dropdown"> 517 <a href="#pricing" class="nav-dropdown-trigger">Pricing <span class="nav-caret">▾</span></a> 518 <div class="nav-dropdown-menu"> 519 <a href="/account/parent-pricing"><span class="nav-dropdown-icon parent">P</span>For parents</a> 520 <a href="/about/teacher-school-pricing?t=t"><span class="nav-dropdown-icon teacher">T</span>For teachers</a> 521 <a href="/about/teacher-school-pricing?t=s"><span class="nav-dropdown-icon school">S</span>For schools</a> 522 </div> 523 </li> 524 525 <li><a href="/about/contact-us">Support</a></li> 526 527 <!-- Mobile-only CTAs (collapse into the menu when open on small screens) --> 528 <li class="nav-mobile-only nav-mobile-cta"> 529 <a href="#joinNow" data-toggle="modal" class="btn btn-primary nav-mobile-join">Join Now</a> 530 <a href="/login/account" class="btn btn-secondary nav-mobile-login">Login</a> 531 </li> 532 </ul> 533 534 <div class="nav-cta"> 535 <a href="/login/account" class="btn btn-ghost">Login</a> 536 <a href="#joinNow" data-toggle="modal" class="btn btn-primary nav-join-btn">Join Now</a> 537 <button type="button" class="nav-menu-toggle" aria-label="Open menu" aria-expanded="false" aria-controls="primaryNav"> 538 <span></span> 539 <span></span> 540 <span></span> 541 </button> 542 </div> 543 </div> 544</nav> 545
546<script> 547 // Mobile menu toggle â opens / closes the primary nav on small screens 548 (function(){ 549 var toggle = document.querySelector('.nav-menu-toggle'); 550 var nav = document.getElementById('primaryNav'); 551 if (!toggle || !nav) return; 552 toggle.addEventListener('click', function(){ 553 var open = nav.classList.toggle('is-open'); 554 nav.classList.toggle('open', open); // matches sl-marketing.scss's `.nav-links.open` rule 555 toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); 556 document.body.classList.toggle('nav-open', open); 557 }); 558 559 // Mobile = the burger button is currently rendered 560 function isMobileNav(){ 561 return toggle && toggle.offsetParent !== null; 562 } 563 564 // Bind tap-to-toggle directly on each dropdown trigger so it runs before any 565 // delegated handlers and we can stopPropagation reliably. 566 nav.querySelectorAll('.nav-dropdown-trigger').forEach(function(trig){ 567 trig.addEventListener('click', function(e){ 568 if (!isMobileNav()) return; // desktop: link navigates as normal 569 e.preventDefault(); 570 e.stopPropagation(); 571 var parent = trig.parentElement; 572 if (!parent || !parent.classList.contains('nav-dropdown')) return; 573 // Close other open dropdowns (accordion behaviour) 574 nav.querySelectorAll('.nav-dropdown.open').forEach(function(d){ 575 if (d !== parent) d.classList.remove('open'); 576 }); 577 parent.classList.toggle('open'); 578 }); 579 }); 580 581 // Close burger menu when a child link inside a submenu is clicked 582 nav.addEventListener('click', function(e){ 583 var t = e.target; 584 if (!t || !t.closest) return; 585 if (t.closest('.nav-dropdown-trigger')) return; // handled above 586 var link = t.closest('a'); 587 if (!link) return; 588 nav.classList.remove('is-open'); 589 nav.classList.remove('open'); 590 toggle.setAttribute('aria-expanded', 'false'); 591 document.body.classList.remove('nav-open'); 592 nav.querySelectorAll('.nav-dropdown.open').forEach(function(d){ d.classList.remove('open'); }); 593 }); 594 })(); 595 596 // Clear stale dashboard localStorage flags (preserved from original) 597 try { 598 localStorage.removeItem('liveClassroomOpen'); 599 localStorage.removeItem('teacherDashboardOpen'); 600 } catch (e) {} 601</script>
601 602 <style> 603 main p, 604 main b, 605 main span, 606 main label, 607 main li, 608 main h1, 609 main h2, 610 main h3, 611 main h4, 612 main h5, 613 main h6, 614 main small { 615 opacity: 0; 616 transition: opacity 0.2s ease-in; 617 } 618 </style> 619 620 621
622<script> 623document.addEventListener("DOMContentLoaded", function () { 624 // Idempotency guard â the copy-localisation partial can end up rendered twice 625 // via the header include chain, which would swap the same text twice 626 // (e.g. "English" â "English Language Arts" â "English Language Arts Language Arts"). 627 if (window.__slLocalisationRan) return; 628 window.__slLocalisationRan = true; 629 630 const country = "GB"; // AU, US, GB, NZ, CA 631//if(country=="GB"){country="UK";} 632 633console.log("country="+country); 634 if (country !== "AU") { 635const terms = { 636 "Foundation / Prep": { US: "Kindergarten", GB: "Reception", CA: "Kindergarten", NZ: "Year 1" }, 637 "Foundation": { US: "Kindergarten", GB: "Reception", CA: "Kindergarten", NZ: "Year 1" }, 638 "Year": { US: "Grade", GB: "Year", CA: "Grade", NZ: "Year" }, 639 "Kindergarten â Year 6": { US: "Kindergarten â Grade 6",GB: "Reception â Year 6",CA: "Kindergarten â Grade 6",NZ: "Year 1 â Year 6" }, 640 "K-6": { US: "Kâ6",GB: "Râ6",CA: "Kâ6",NZ: "1â6" }, 641 "FâYr 6": { US: "Kâ6",GB: "Râ6",CA: "Kâ6",NZ: "Yr1âYr6" }, 642 "Primary School": { US: "Elementary School", GB: "Primary School", CA: "Elementary School", NZ: "Primary School" }, 643 "High School": { US: "High School", GB: "Secondary School", CA: "High School", NZ: "Secondary School" }, 644 //"Year 12": { US: "Grade 12", GB: "Year 13 / Sixth Form", CA: "Grade 12", NZ: "Year 13" }, 645 "Principal": { US: "Principal", GB: "Headteacher", CA: "Principal", NZ: "Principal" }, 646 "Deputy Principal": { US: "Vice Principal", GB: "Deputy Headteacher", CA: "Vice Principal", NZ: "Deputy Principal" }, 647 "Student": { US: "Student", GB: "Student", CA: "Student", NZ: "Student" }, 648 //"Class": { US: "Class", GB: "Class", CA: "Homeroom", NZ: "Class" }, 649 "Class Teacher": { US: "Homeroom Teacher", GB: "Form Tutor", CA: "Homeroom Teacher", NZ: "Class Teacher" }, 650 "Marking": { US: "Grading", GB: "Marking", CA: "Grading", NZ: "Marking" }, 651 "Mark": { US: "Grade", GB: "Mark", CA: "Grade", NZ: "Mark" }, 652 "School Report": { US: "Report Card", GB: "School Report", CA: "Report Card", NZ: "School Report" }, 653 "Revision": { US: "Review", GB: "Revision", CA: "Studying", NZ: "Revision" }, 654 // "Exam": { US: "Test / Exam", GB: "Exam", CA: "Exam", NZ: "Exam" }, 655 "Maths": { US: "Math", GB: "Maths", CA: "Math", NZ: "Maths" }, 656 "Digital Technologies": { US: "Computer Class", GB: "ICT", CA: "Tech Ed / ICT", NZ: "Digital Technologies" },
657 "English": { US: "English Language Arts", GB: "English", CA: "English", NZ: "English" }, 658 "History": { US: "Social Studies", GB: "History", CA: "Social Studies", NZ: "Social Studies" }, 659 "School Holidays": { US: "Vacation", GB: "School Holidays", CA: "School Holidays", NZ: "School Holidays" }, 660 661 "Programme": { US: "Program", GB: "Programme", CA: "Programme", NZ: "Programme" }, 662 "Centre": { US: "Center", GB: "Centre", CA: "Centre", NZ: "Centre" }, 663 "Practice": { US: "Practice", GB: "Practice", CA: "Practice", NZ: "Practice" }, 664 "practising": { US: "practicing", GB: "practising", CA: "practicing", NZ: "practising" }, 665 "Honours": { US: "Honors", GB: "Honours", CA: "Honours", NZ: "Honours" }, 666 "Colour": { US: "Color", GB: "Colour", CA: "Colour", NZ: "Colour" }, 667 "Judgement": { US: "Judgment", GB: "Judgement", CA: "Judgement", NZ: "Judgement" }, 668 "Learnt": { US: "Learned", GB: "Learnt", CA: "Learnt", NZ: "Learnt" }, 669 670 "Customise": { US: "Customize", GB: "Customise", CA: "Customise", NZ: "Customise" }, 671 "Personalise": { US: "Personalize", GB: "Personalise", CA: "Personalise", NZ: "Personalise" }, 672 "Personalised": { US: "Personalized", GB: "Personalised", CA: "Personalised", NZ: "Personalised" }, 673 "Behaviour": { US: "Behavior", GB: "Behaviour", CA: "Behaviour", NZ: "Behaviour" }, 674 "Organisation": { US: "Organization", GB: "Organisation", CA: "Organisation", NZ: "Organisation" }, 675 "Analyse": { US: "Analyze", GB: "Analyse", CA: "Analyse", NZ: "Analyse" }, 676 "Specialisation": { US: "Specialization", GB: "Specialisation", CA: "Specialisation", NZ: "Specialisation" }, 677 "Recognise": { US: "Recognize", GB: "Recognise", CA: "Recognise", NZ: "Recognise" }, 678 "Utilise": { US: "Utilize", GB: "Utilise", CA: "Utilise", NZ: "Utilise" }, 679 "Utilising": { US: "Utilizing", GB: "Utilising", CA: "Utilising", NZ: "Utilising" }, 680 "Authorisation": { US: "Authorization", GB: "Authorisation", CA: "Authorisation", NZ: "Authorisation" }, 681 "Authorise": { US: "Authorize", GB: "Authorise", CA: "Authorise", NZ: "Authorise" }, 682 "Memorise": { US: "Memorize", GB: "Memorise", CA: "Memorise", NZ: "Memorise" }, 683 "Optimise": { US: "Optimize", GB: "Optimise", CA: "Optimise", NZ: "Optimise" }, 684 "Realise": { US: "Realize", GB: "Realise", CA: "Realise", NZ: "Realise" }, 685 "Initialise": { US: "Initialize", GB: "Initialise", CA: "Initialise", NZ: "Initialise" }, 686 687 "Defence": { US: "Defense", GB: "Defence", CA: "Defence", NZ: "Defence" }, 688 "Organising": { US: "Organizing", GB: "Organising", CA: "Organizing", NZ: "Organising" }, 689 "Organisational": { US: "Organizational",GB: "Organisational",CA: "Organizational",NZ: "Organisational" }, 690 "Analysed": { US: "Analyzed", GB: "Analysed", CA: "Analyzed", NZ: "Analysed" }, 691 "Apologise": { US: "Apologize", GB: "Apologise", CA: "Apologize", NZ: "Apologise" }, 692 "Dialogue": { US: "Dialog", GB: "Dialogue", CA: "Dialogue", NZ: "Dialogue" }, 693 "Catalogue": { US: "Catalog", GB: "Catalogue", CA: "Catalogue", NZ: "Catalogue" }, 694 "Aluminium": { US: "Aluminum", GB: "Aluminium", CA: "Aluminium", NZ: "Aluminium" }, 695 "Traveller": { US: "Traveler", GB: "Traveller", CA: "Traveller", NZ: "Traveller" }, 696 "Travelling": { US: "Traveling", GB: "Travelling", CA: "Travelling", NZ: "Travelling" }, 697 "Cancelled": { US: "Canceled", GB: "Cancelled", CA: "Cancelled", NZ: "Cancelled" }, 698 "Cancelling": { US: "Canceling", GB: "Cancelling", CA: "Cancelling", NZ: "Cancelling" }, 699 "Fuelled": { US: "Fueled", GB: "Fuelled", CA: "Fuelled", NZ: "Fuelled" }, 700 "Enrol": { US: "Enroll", GB: "Enrol", CA: "Enrol", NZ: "Enrol" }, 701 "Fulfil": { US: "Fulfill", GB: "Fulfil", CA: "Fulfill", NZ: "Fulfil" }, 702 "Instalment": { US: "Installment", GB: "Instalment", CA: "Instalment", NZ: "Instalment" }, 703 "Practise": { US: "Practice", GB: "Practise", CA: "Practise", NZ: "Practise" }, 704 "Acknowledgement":{ US: "Acknowledgment",GB: "Acknowledgement",CA: "Acknowledgment",NZ: "Acknowledgement" }, 705 "Manoeuvre": { US: "Maneuver", GB: "Manoeuvre", CA: "Manoeuvre", NZ: "Manoeuvre" }, 706 "Paediatric": { US: "Pediatric", GB: "Paediatric", CA: "Paediatric", NZ: "Paediatric" } 707 708/* 709 "Recess / Break": { US: "Recess", GB: "Break Time", CA: "Recess", NZ: "Morning Tea /
709Lunch" }, 710 "Relief Teacher": { US: "Substitute Teacher", GB: "Supply Teacher", CA: "Substitute Teacher", NZ: "Relief Teacher" }, 711 "PE": { US: "PE / Gym", GB: "PE", CA: "PE", NZ: "PE" }, 712 "Timetable": { US: "Schedule", GB: "Timetable", CA: "Schedule", NZ: "Timetable" }, 713 "Learning Support": { US: "SPED", GB: "SEN", CA: "Special Education", NZ: "SEN / Learning Support"}, 714 "Gifted & Talented": { US: "Gifted and Talented", GB: "More Able / G&T", CA: "Gifted", NZ: "Extension / Gifted" }, 715 "Enrolment": { US: "Enrollment", GB: "Enrolment", CA: "Enrolment", NZ: "Enrolment" }, 716 "Labour": { US: "Labor", GB: "Labour", CA: "Labour", NZ: "Labour" }, 717 "Licence": { US: "License", GB: "Licence", CA: "Licence", NZ: "Licence" }, 718 "Ageing": { US: "Aging", GB: "Ageing", CA: "Ageing", NZ: "Ageing" }, 719 "Tonne": { US: "Ton", GB: "Tonne", CA: "Tonne", NZ: "Tonne" }, 720 "Modelled": { US: "Modeled", GB: "Modelled", CA: "Modelled", NZ: "Modelled" }, 721 "Fulfil": { US: "Fulfill", GB: "Fulfil", CA: "Fulfil", NZ: "Fulfil" }, 722 "Counsellor": { US: "Counselor", GB: "Counsellor", CA: "Counsellor", NZ: "Counsellor" }, 723 "Dialogue": { US: "Dialog", GB: "Dialogue", CA: "Dialogue", NZ: "Dialogue" } 724 */ 725 726}; 727 728 729 730 function preserveCase(from, to) { 731 if (from === from.toUpperCase()) return to.toUpperCase(); 732 if (from === from.toLowerCase()) return to.toLowerCase(); 733 if (from[0] === from[0].toUpperCase()) return to[0].toUpperCase() + to.slice(1); 734 return to; 735 } 736 737 function replaceTerms(countryCode) { 738 // Walk every text node in the document body once. Skip nodes inside site chrome 739 // (nav/header/footer/country-bar/modals/dropdowns), script/style/noscript, and anything opted out via .no-change. 740 // This captures text directly inside any element â including <div> wrappers that don't use <p>/<span>. 741 const EXCLUDE_SEL = "nav, header, footer, script, style, noscript, .no-change, .country-bar, .modal, .nav-dropdown-menu, .nav-links"; 742 743 const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, { 744 acceptNode: (node) => { 745 if (!node.parentElement) return NodeFilter.FILTER_REJECT; 746 if (!node.nodeValue || !node.nodeValue.trim()) return NodeFilter.FILTER_REJECT; 747 if (node.parentElement.closest(EXCLUDE_SEL)) return NodeFilter.FILTER_REJECT; 748 return NodeFilter.FILTER_ACCEPT; 749 } 750 }); 751 752 const textNodes = []; 753 while (walker.nextNode()) { 754 textNodes.push(walker.currentNode); 755 } 756 757 textNodes.forEach(node => { 758 let text = node.nodeValue; 759 const originalText = text; 760 761 Object.entries(terms).forEach(([key, translations]) => { 762 const target = translations[countryCode]; 763 if (!target || target === "Either") return; 764 765 // Escape regex metacharacters in the key (handles dots, parens, etc.) 766 const safeKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 767 const pattern = new RegExp(`\\b(${safeKey})(s?)\\b`, "gi"); 768 769 text = text.replace(pattern, (match, word, plural) => { 770 let replaced = preserveCase(word, target); 771 if (plural && !replaced.endsWith('s')) replaced += 's'; 772 return replaced; 773 }); 774 }); 775 776 if (text !== originalText) { 777 node.nodeValue = text; 778 const el = node.parentElement; 779 if (el) { 780 el.style.visibility = "visible"; 781 el.style.transition = "opacity 0.4s ease"; 782 el.style.opacity = 1; 783 } 784 } 785 }); 786 787 788 789 } 790 791 replaceTerms(country); 792 793 document.querySelectorAll("p, b, span, label, li, h1, h2, h3, h4, h5, h6") 794 .forEach(el => { 795 el.style.opacity = "1"; 796 797 }); 798 } 799if (country !== "AU") { 800$('<style>') 801 .prop('type', 'text/css') 802 .html('p, b, span, label, li, h1, h2, h3, h4, h5, h6 { opacity: 1!important; }') 803 .appendTo('head'); 804} 805}); 806 807</script>
807 808 </div> 809 </nav> 810 </header> 811 <main> 812<style id="antiClickjack"> 813 body{display:none !important;} 814</style>
815<script type="text/javascript"> 816if (self === top) { 817 var antiClickjack = document.getElementById("antiClickjack"); 818 antiClickjack.parentNode.removeChild(antiClickjack); 819} else { 820 top.location = self.location; 821} 822</script>
vendor: 1 bytes, line 822
822
823<script src="https://static.studyladder.co.uk/cdn/site/94/221ec0bbe7a5.js"></script>
823 824 825<!-- LOGIN PAGE STYLE OVERRIDES (cosmetic; form fields keep their PHP-rendered IDs/names) --> 826<style> 827.sl-marketing .login-page { 828 padding: 56px 0 80px; 829 background: linear-gradient(160deg, #EFF6FF 0%, #F8FAFC 50%, #FEF3F2 100%); 830 min-height: calc(100vh - 200px); 831} 832.sl-marketing .login-page .login-container { max-width: 480px; margin: 0 auto; padding: 0 20px; } 833.sl-marketing .login-page .notification { 834 background: #FFFBEB; 835 border: 1px solid #FDE68A; 836 color: #78350F; 837 border-radius: 10px; 838 padding: 12px 16px; 839 font-size: 14px; 840 margin: 0 0 18px; 841 text-align: center; 842} 843.sl-marketing .login-page .login-card { 844 background: #FFFFFF; 845 border: 1px solid #E5E7EB; 846 border-radius: 16px; 847 padding: 32px 32px 28px; 848 box-shadow: 0 12px 40px -16px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15,23,42,0.05); 849} 850.sl-marketing .login-page .login-avatar { 851 width: 76px; 852 height: 76px; 853 border-radius: 50%; 854 margin: 0 auto 16px; 855 display: flex; 856 align-items: center; 857 justify-content: center; 858 background: #EFF6FF; 859 color: #2D5BFF; 860 overflow: hidden; 861} 862.sl-marketing .login-page .login-avatar img { 863 width: 100%; height: 100%; object-fit: cover; border-radius: 50%; 864} 865.sl-marketing .login-page .login-title { 866 font-size: 24px; 867 font-weight: 700; 868 text-align: center; 869 margin: 0 0 6px; 870 color: #0F172A; 871 letter-spacing: -0.02em; 872} 873.sl-marketing .login-page .login-username-banner { 874 text-align: center; 875 font-size: 14px; 876 color: #64748B; 877 margin: 0 0 18px; 878} 879.sl-marketing .login-page .login-username-banner strong { color: #0F172A; } 880 881/* Tabs */ 882.sl-marketing .login-page .login-tabs { 883 display: flex; 884 gap: 4px; 885 background: #F1F5F9; 886 padding: 4px; 887 border-radius: 10px; 888 margin: 18px 0 22px; 889} 890.sl-marketing .login-page .login-tab { 891 flex: 1; 892 border: 0; 893 background: transparent; 894 padding: 10px 8px; 895 border-radius: 8px; 896 font-size: 13px; 897 font-weight: 600; 898 color: #475569; 899 cursor: pointer; 900 transition: background .15s ease, color .15s ease, box-shadow .15s ease; 901 letter-spacing: -0.01em; 902} 903.sl-marketing .login-page .login-tab:hover { color: #0F172A; } 904.sl-marketing .login-page .login-tab.active { 905 background: #FFFFFF; 906 color: #2D5BFF; 907 box-shadow: 0 1px 2px rgba(15,23,42,0.10); 908} 909 910/* Per-tab intro text */ 911.sl-marketing .login-page .login-intro { 912 font-size: 14px; 913 color: #475569; 914 text-align: center; 915 margin: -4px 0 16px; 916 line-height: 1.5; 917} 918 919/* Form field overrides (against the PHP helper's .form-control output) */ 920.sl-marketing .login-page form#login .form-group { margin-bottom: 16px; text-align: left; } 921.sl-marketing .login-page form#login label { 922 display: block; 923 font-weight: 500; 924 font-size: 13px; 925 color: #64748B; 926 margin-bottom: 6px; 927 text-align: left; 928 letter-spacing: 0; 929} 930 931/* Inline student hint under the form fields */ 932.sl-marketing .login-page form#login .login-hint { 933 font-size: 13px; 934 color: #64748B; 935 line-height: 1.5; 936 margin: -4px 0 14px; 937 text-align: left; 938} 939.sl-marketing .login-page form#login .form-control, 940.sl-marketing .login-page form#login input[type="text"], 941.sl-marketing .login-page form#login input[type="password"] { 942 width: 100%; 943 background: #FFFFFF; 944 border: 1px solid #E5E7EB; 945 border-radius: 10px; 946 padding: 12px 14px; 947 font: inherit; 948 font-size: 15px; 949 line-height: 1.45; 950 color: #0F172A; 951 min-height: 46px; 952 transition: border-color .15s ease, box-shadow .15s ease; 953 -webkit-appearance: none; 954 appearance: none; 955} 956.sl-marketing .login-page form#login .form-control:focus, 957.sl-marketing .login-page form#login input[type="text"]:focus, 958.sl-marketing .login-page form#login input[type="password"]:focus { 959 outline: none; 960 border-color: #2D5BFF; 961 box-shadow: 0 0 0 4px rgba(45,91,255,0.12); 962} 963.sl-marketing .login-page form#login .hidden { display: none !important; } 964.sl-marketing .login-page form#login .btn-link { 965 font-size: 13px; 966 color: #2D5BFF; 967 text-decoration: none; 968 font-weight: 500; 969} 970.sl-marketing .login-page form#login .btn-link:hover { text-decoration: underline; } 971.sl-marketing .login-page .pull-right { float: right; } 972 973/* Remember + submit row â stack vertically, button full width */ 974.sl-marketing .login-page form#login .d-flex.justify-content-between.align-items-center { 975 flex-direction: column !important; 976 align-items: stretch !important; 977 gap: 18px !important; 978 margin-top: -4px; 979 padding: 0 0 6px; 980} 981.sl-marketing .login-page form#login .login-options-row { 982 display: flex; 983 align-items: center; 984 justify-content: space-between; 985 width: 100%; 986} 987.sl-marketing .login-page form#login .signInLabel { 988 font-size: 14px; 989 color: #475569; 990 font-weight: 500; 991 margin: 0; 992 display: inline-flex; 993 align-items: center; 994 gap: 6px; 995} 996.sl-marketing .login-page form#login .login-forgot { 997 font-size: 14px; 998 color: #2D5BFF; 999 font-weight: 500; 1000 text-decoration: none; 1001} 1002.sl-marketing .login-page form#login .login-forgot:hover { text-decoration: underline; } 1003.sl-marketing .login-page form#login button[type="submit"] { 1004 width: 100%; 1005 display: block; 1006 background: #2D5BFF; 1007 color: #FFFFFF; 1008 border: 1px solid #2D5BFF; 1009 border-radius: 10px; 1010 padding: 14px 20px !important; 1011 font-weight: 600; 1012 font-size: 15px; 1013 cursor: pointer; 1014 transition: background .12s ease, color .12s ease, box-shadow .12s ease, transform .08s ease; 1015} 1016.sl-marketing .login-page form#login button[type="submit"]:hover { background: #1E40AF; border-color: #1E40AF; } 1017.sl-marketing .login-page form#login button[type="submit"]:active { 1018 background: #FFFFFF !important; 1019 color: #2D5BFF !important; 1020 transform: translateY(1px); 1021 box-shadow: 0 0 0 4px rgba(45,91,255,0.12) !important; 1022} 1023 1024/* Error / notice */ 1025.sl-marketing .login-page form#login .login-errmsg { 1026 background: #FEF2F2; 1027 border: 1px solid #FECACA; 1028 color: #7F1D1D; 1029 border-radius: 10px; 1030 padding: 12px 14px; 1031 font-size: 14px; 1032 margin: 4px 0 12px; 1033} 1034.sl-marketing .login-page form#login .login-errmsg strong { color: #991B1B; } 1035.sl-marketing .login-page form#login .d-none { display: none !important; } 1036 1037/* Divider + Google */
1038.sl-marketing .login-page .login-divider { 1039 display: flex; 1040 align-items: center; 1041 gap: 12px; 1042 text-align: center; 1043 margin: 18px 0; 1044 color: #94A3B8; 1045 font-size: 13px; 1046 font-weight: 500; 1047} 1048.sl-marketing .login-page .login-divider::before, 1049.sl-marketing .login-page .login-divider::after { 1050 content: ""; 1051 flex: 1; 1052 height: 1px; 1053 background: #E2E8F0; 1054} 1055 1056/* Google + QR-row container */ 1057.sl-marketing .login-page .login-secondary-row { 1058 display: flex; 1059 flex-direction: column; 1060 gap: 10px; 1061 align-items: stretch; 1062} 1063.sl-marketing .login-page .login-secondary-row #buttonDiv { 1064 display: flex; 1065 justify-content: center; 1066 width: 100%; 1067} 1068.sl-marketing .login-page .login-secondary-row #buttonDiv > div, 1069.sl-marketing .login-page .login-secondary-row #buttonDiv iframe { 1070 width: 100% !important; 1071 max-width: 100% !important; 1072} 1073.sl-marketing .login-page .login-secondary-row .qr-login { 1074 display: inline-flex; align-items: center; justify-content: center; gap: 8px; 1075 background: #FFFFFF; 1076 color: #0F172A; 1077 border: 1px solid #E2E8F0; 1078 border-radius: 10px; 1079 padding: 12px 16px; 1080 font-weight: 600; 1081 font-size: 15px; 1082 cursor: pointer; 1083 width: 100%; 1084} 1085.sl-marketing .login-page .login-secondary-row .qr-login:hover { background: #F8FAFC; } 1086 1087/* Signup link */ 1088.sl-marketing .login-page .signup-container { 1089 text-align: center; 1090 font-size: 14px; 1091 color: #475569; 1092 margin: 18px 0 0; 1093} 1094.sl-marketing .login-page .signup-container a { 1095 color: #2D5BFF; 1096 font-weight: 600; 1097 margin-left: 4px; 1098} 1099 1100/* Loading spinner block */ 1101.sl-marketing .login-page #login-loading { 1102 padding: 32px 0; 1103 text-align: center; 1104} 1105 1106/* Tab visibility helpers */ 1107.sl-marketing .login-page [data-show-on-tab] { display: none !important; } 1108.sl-marketing .login-page[data-active-tab="adult"] [data-show-on-tab~="adult"] { display: block !important; } 1109.sl-marketing .login-page[data-active-tab="student"] [data-show-on-tab~="student"] { display: block !important; } 1110.sl-marketing .login-page[data-active-tab="qr"] [data-show-on-tab~="qr"] { display: block !important; } 1111 1112/* Inline-display restorations for elements that shouldn't be block */ 1113.sl-marketing .login-page[data-active-tab="adult"] .login-secondary-row #buttonDiv, 1114.sl-marketing .login-page[data-active-tab="qr"] .login-secondary-row .qr-login { 1115 display: inline-flex !important; 1116} 1117 1118/* Force-hide non-active tab regions */ 1119.sl-marketing .login-page[data-active-tab="adult"] .login-secondary-row .qr-login, 1120.sl-marketing .login-page[data-active-tab="student"] .login-secondary-row .qr-login { 1121 display: none !important; 1122} 1123.sl-marketing .login-page[data-active-tab="student"] .login-secondary-row #buttonDiv, 1124.sl-marketing .login-page[data-active-tab="student"] .login-divider { display: none !important; } 1125.sl-marketing .login-page[data-active-tab="qr"] form#login, 1126.sl-marketing .login-page[data-active-tab="qr"] .login-divider, 1127.sl-marketing .login-page[data-active-tab="qr"] .login-secondary-row #buttonDiv { display: none !important; } 1128 1129/* QR tab â make the QR button the hero */ 1130.sl-marketing .login-page[data-active-tab="qr"] .login-secondary-row .qr-login { 1131 font-size: 15px; padding: 14px 22px; background: #2D5BFF; color: #FFF; border-color: #2D5BFF; 1132} 1133</style> 1134 1135<section class="login-page" data-active-tab="student"> 1136 <div class="login-container"> 1137 1138 1139 <div class="login-card"> 1140 1141 <div class="login-avatar"> 1142 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="40" height="40"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> 1143 </div> 1144 1145 <h1 class="login-title">Sign in to Studyladder</h1> 1146 1147 1148 <div class="login-tabs" role="tablist" aria-label="Sign-in type"> 1149 <button type="button" class="login-tab" role="tab" aria-selected="false" data-login-tab="adult">Parents & teachers</button> 1150 <button type="button" class="login-tab active" role="tab" aria-selected="true" data-login-tab="student">Students</button> 1151 <button type="button" class="login-tab" role="tab" aria-selected="false" data-login-tab="qr">Student QR code</button> 1152 </div> 1153 1154 <p class="login-intro" data-show-on-tab="qr">Hold your Studyladder QR card up to the camera to sign in instantly. No username or password to remember.</p> 1155 1156 <form id="login" method="POST"> 1157 <fieldset> 1158 <div class='form-group'> 1159
1159<script src="https://accounts.google.com/gsi/client" async defer></script>
1159 1160
1160<script> 1161 function handleCredentialResponse(response) { 1162 $('#login').slideUp(); 1163 $('.signup-container, #buttonDiv').css({visibility: 'hidden'}); 1164 $('#login-loading').css({display: ""}); 1165 $.ajax({ 1166 url: "/login/account-post", 1167 method: "POST", 1168 data: {token: response.credential}, 1169 dataType: 'json', 1170 success: function(r){ 1171 if (r.ok) { 1172 window.location.href = r.location; 1173 } else if (r.error) { 1174 $('#login').slideDown(); 1175 $('#login-loading').css({display: "none"}); 1176 $('.signup-container, #buttonDiv').css({visibility: 'visible'}); 1177 inFlight = false; 1178 1179 $('form#login') 1180 .find('.login-errmsg') 1181 .html('<strong class="d-block">Error</strong> ' + h(r.error)) 1182 .removeClass('d-none'); 1183 1184 $('form#login').find('button[type=submit]>i.fa-spinner') 1185 .removeClass('fa-spin') 1186 .css({visibility:'hidden'}); 1187 if (r.ignoreReplaced){ 1188 $('form#login').append(`<input type="hidden" name="ignoreReplaced" value=1>`) 1189 } else { 1190 $('[name="ignoreReplaced"]').remove() 1191 } 1192 1193 1194 } else if (r.retry) { 1195 $('#login').slideDown(); 1196 $('#login-loading').css({display: "none"}); 1197 $('.signup-container, #buttonDiv').css({visibility: 'visible'}); 1198 inFlight = false; 1199 window.setTimeout(handleCredentialResponse, 1250, response); 1200 1201 } 1202 }, 1203 error: function(){ 1204 inFlight = false; 1205 $('#login').slideDown(); 1206 $('#login-loading').css({display: "none"}); 1207 $('.signup-container').css({visibility: 'visible'}); 1208 $('form#login') 1209 .find('.login-errmsg') 1210 .html('<strong class="d-block">Error</strong> A system error occurred. Please try again or contact support.') 1211 .removeClass('d-none'); 1212 1213 $('form#login').find('button[type=submit]>i.fa-spinner') 1214 .removeClass('fa-spin') 1215 .css({visibility:'hidden'}); 1216 } 1217 }) 1218 } 1219 window.addEventListener("load", function () { 1220 if (!window.google || !google.accounts || !google.accounts.id) { 1221 return; 1222 } 1223 google.accounts.id.initialize({ 1224 client_id: "436701450551-qb7rmj3n0i4c4jihgenss78n32bssvg7.apps.googleusercontent.com", 1225 callback: handleCredentialResponse, 1226 itp_support: true, 1227 context: 'signin' 1228 }); 1229 google.accounts.id.disableAutoSelect(); 1230 google.accounts.id.renderButton( 1231 document.getElementById("buttonDiv"), 1232 { theme: "outline", size: "large", text: "signin_with", shape: "rectangular", logo_alignment: "left", width: 400, click_listener: googleSigninClicked } // customization attributes 1233 ); 1234 }); 1235 1236 function googleSigninClicked(){ 1237 1238 } 1239 </script>
1239 1240 <label for="username" data-show-on-tab="adult">Username or email</label> 1241 <label for="username" data-show-on-tab="student">Student username</label> 1242 <input class="form-control" id="username" name="username" type="text" placeholder="Student username" spellcheck="false"> 1243 </div> 1244 1245 <div class='form-group'> 1246 <label for="password">Password</label> 1247 <input class="form-control" name="password" type="password" id="password" placeholder="Password"> 1248 </div> 1249 1250 <p class="login-hint" data-show-on-tab="student">Your teacher or parent will have given you these. If you've forgotten them, ask them to help.</p> 1251 1252 1253 <div class="login-errmsg alert alert-danger d-none"></div> 1254 1255 </fieldset> 1256 <div class="d-flex justify-content-between align-items-center"> 1257 <div class="login-options-row"> 1258 <label class="label signInLabel"> 1259 <input id="remember" name="remember" type="checkbox" value="yes" checked = checked/> 1260 Stay signed in 1261 </label> 1262 <a href="/login/forgot" class="btn-link link login-forgot">Forgot password?</a> 1263 </div> 1264 <button type="submit" class="btn btn-primary" style="padding-right:28px"> 1265 <i class="fa fa-spinner" style="visibility:hidden"></i> Sign In 1266 </button> 1267 </div> 1268 </form> 1269
1270<script> 1271(function() { 1272 1273 var 1274 $f = $('form#login'), 1275 inFlight = false, 1276 redirectOnceFn = function(url) { 1277 var hasRedirected = false; 1278 return function() { 1279 if (hasRedirected) { 1280 return; 1281 } 1282 hasRedirected = true; 1283 window.location.href = url; 1284 }; 1285 }, 1286 submitLogin = function() { 1287 1288 var $i = $f.find('button[type=submit]>i.fa-spinner'); 1289 1290 if (inFlight) { 1291 return; 1292 } 1293 1294 inFlight = true; 1295 1296 $i 1297 .addClass('fa-spin') 1298 .css({visibility:'visible'}); 1299 1300 $.post('/login/account-post', $f.serialize(), function(r) { 1301 1302 if (r.ok) { 1303 1304 var redirectOnce = redirectOnceFn(r.location); 1305 window.setTimeout(redirectOnce, 200); 1306 var deviceType = window.Widgets ? Widgets.getDeviceType() : 'unknown'; 1307 if (window.dataLayer && Array.isArray(window.dataLayer)) { 1308 dataLayer.push({ 1309 event: 'login', 1310 user_id: r.id, 1311 user_type: r.type, 1312 method: r.method || "unknown", 1313 source_platform: 'direct', 1314 domain_region: "GB", 1315 login_status: 'success', 1316 login_device: deviceType, 1317 login_time: r.ts * 1000, 1318 eventCallback: redirectOnce, 1319 eventTimeout: 2000 1320 }); 1321 } else { 1322 redirectOnce(); 1323 } 1324 1325 } else if (r.error) { 1326 1327 inFlight = false; 1328 1329 $f 1330 .find('.login-errmsg') 1331 .html('<strong class="d-block">Error</strong> ' + h(r.error)) 1332 .removeClass('d-none').addClass('alert-danger').removeClass('alert-primary'); 1333 1334 $i 1335 .removeClass('fa-spin') 1336 .css({visibility:'hidden'}); 1337 if (r.ignoreReplaced){ 1338 $f.append(`<input type="hidden" name="ignoreReplaced" value=1>`) 1339 $f 1340 .find('.login-errmsg') 1341 .html('<strong class="d-block text-danger">Not your current account!</strong> ' + h(r.error)) 1342 .removeClass('d-none').removeClass('alert-danger').addClass('alert-primary'); 1343 } else { 1344 $('[name="ignoreReplaced"]').remove() 1345 } 1346 1347 } else if (r.retry) { 1348 window.setTimeout(function() { inFlight = false; submitLogin(); }, 1250); 1349 } 1350 }); 1351 }; 1352 1353 $f.on('submit', function(e) { 1354 1355 e.preventDefault(); 1356 1357 submitLogin(); 1358 }); 1359 1360}()); 1361</script>
1361 1362 1363 <div style="display:none;" id="login-loading"> 1364 <div class="text-center"> 1365 <div class="spinner-border text-primary" style="width: 3rem; height: 3rem;" role="status"></div><br> 1366 <strong>Loading, please wait...</strong> 1367 </div> 1368 </div> 1369 1370 <div class="login-divider" data-show-on-tab="adult"><span>or</span></div> 1371 1372 <div class="login-secondary-row"> 1373 <div id="buttonDiv" data-show-on-tab="adult"></div> 1374 <button type="button" class="btn btn-secondary qr-login" data-show-on-tab="qr"> 1375 <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><line x1="14" y1="14" x2="14" y2="21"/><line x1="18" y1="14" x2="18" y2="21"/><line x1="14" y1="18" x2="21" y2="18"/></svg> 1376 <span>QR Code Sign in</span> 1377 </button> 1378 </div> 1379 1380 <div class="signup-container"> 1381 Don't have an account yet? 1382 <a class="btn-link link" href="#joinNow" data-toggle="modal">Sign up</a> 1383 </div> 1384 1385
1385<script> 1386 $('form#login input:first').focus(); 1387 1388 function originToken(){var m=null;if(m=document.cookie.match(/(^|;)\s*O=([a-z0-9]{16})/i)){return m[2]}} 1389 1390 $('.qr-login').on('click', function(){ 1391 const thisButton = $(this); 1392 let bData = {n: $(this).attr("data-fName"), l: $(this).attr("data-lName")}; 1393 swal.fire({ 1394 title: "Scan my code (Step 1)", 1395 width: "95%", 1396 html: '<div class="w-100 d-flex align-items-center justify-content-center"><div id="qr-reader" style="width: 600px"></div></div>', 1397 showConfirmButton: false 1398 }).then(() => { 1399 html5QrcodeScanner.clear(); 1400 }); 1401 1402 function onScanSuccess(decodedText, decodedResult) { 1403 1404 html5QrcodeScanner.clear(); 1405 swal.fire({ 1406 icon: "success", 1407 title: "QR Code successful", 1408 html: "Code scanned successfully, logging in",
1409 showConfirmButton: false 1410 }); 1411 swal.showLoading(); 1412 window.location.href = decodedText; 1413 } 1414 1415 const html5QrcodeScanner = new Html5QrcodeScanner( 1416 "qr-reader", { fps: 10, qrbox: 250 }); 1417 html5QrcodeScanner.render(onScanSuccess); 1418 $("#html5-qrcode-anchor-scan-type-change, [alt='Info icon']").addClass("d-none"); 1419 $("html5-qrcode-button-camera-permission").trigger('click'); 1420 }); 1421 </script>
1421 1422 1423 </div> 1424 </div> 1425</section> 1426 1427<!-- TAB SWITCHER (visual only â single underlying form) -->
1428<script> 1429(function(){ 1430 var page = document.querySelector('.login-page'); 1431 if (!page) return; 1432 var tabs = page.querySelectorAll('.login-tab'); 1433 var username = document.getElementById('username'); 1434 1435 tabs.forEach(function(btn){ 1436 btn.addEventListener('click', function(){ 1437 tabs.forEach(function(b){ 1438 b.classList.remove('active'); 1439 b.setAttribute('aria-selected','false'); 1440 }); 1441 btn.classList.add('active'); 1442 btn.setAttribute('aria-selected','true'); 1443 var which = btn.getAttribute('data-login-tab') || 'adult'; 1444 page.setAttribute('data-active-tab', which); 1445 1446 // Tweak input placeholder + autocomplete for student vs adult 1447 if (username) { 1448 if (which === 'student') { 1449 username.setAttribute('placeholder', 'Student username'); 1450 username.setAttribute('autocomplete', 'username'); 1451 } else if (which === 'adult') { 1452 username.setAttribute('placeholder', 'Username or email'); 1453 username.setAttribute('autocomplete', 'username'); 1454 } 1455 } 1456 }); 1457 }); 1458})(); 1459</script>
1459 1460 1461 1462 <style> 1463 /* ------ Footer styling â targets the BS4 markup below ------ */ 1464 /* Force NO margin above the footer at any viewport. Beats the 5em 1465 margin-top in public.css and any other inherited rule. */ 1466 footer.footer, 1467 footer.footer.bg-dark, 1468 .footer.bg-dark { 1469 margin-top: 0 !important; 1470 margin-bottom: 0 !important; 1471 } 1472 @media (min-width: 0) { 1473 footer.footer, 1474 footer.footer.bg-dark, 1475 .footer.bg-dark { margin-top: 0 !important; } 1476 } 1477 @media (min-width: 992px) { 1478 footer.footer, 1479 footer.footer.bg-dark, 1480 .footer.bg-dark { margin-top: 0 !important; } 1481 } 1482 .footer.bg-dark { 1483 background: #0F172A !important; 1484 padding: 56px 0 24px; 1485 color: rgba(255, 255, 255, 0.72); 1486 font-size: 14px; 1487 } 1488 .footer.bg-dark .container { color: rgba(255, 255, 255, 0.72); } 1489 .footer.bg-dark a { transition: color .15s ease, background .15s ease; } 1490 .footer.bg-dark a.text-light { color: rgba(255, 255, 255, 0.65) !important; } 1491 .footer.bg-dark a.text-light:hover { color: #ffffff !important; text-decoration: none; } 1492 1493 /* Link lists â force size + weight + colour against public.css */ 1494 .footer.bg-dark ul.list-unstyled li a, 1495 .footer.bg-dark ul.list-unstyled li a.text-light { 1496 font-size: 14px !important; 1497 font-weight: 400 !important; 1498 color: rgba(255, 255, 255, 0.65) !important; 1499 line-height: 1.5 !important; 1500 letter-spacing: 0 !important; 1501 text-transform: none !important; 1502 } 1503 .footer.bg-dark ul.list-unstyled li a:hover, 1504 .footer.bg-dark ul.list-unstyled li a.text-light:hover { 1505 color: #ffffff !important; 1506 text-decoration: none !important; 1507 } 1508 .footer.bg-dark .logo { display: inline-block; } 1509 .footer.bg-dark .logo img { max-width: 160px; max-height: 36px; width: auto; height: auto; } 1510 .footer.bg-dark p { color: rgba(255, 255, 255, 0.65); font-size: 14px; line-height: 1.55; } 1511 1512 /* Column headers â !important needed because public.css sets h4 font-size !important globally */ 1513 .footer.bg-dark h4, 1514 .footer.bg-dark .sl-footer-heading { 1515 font-size: 12px !important; 1516 font-weight: 700 !important; 1517 text-transform: uppercase !important; 1518 letter-spacing: 0.08em !important; 1519 color: #ffffff !important; 1520 margin-bottom: 14px !important; 1521 padding-bottom: 0 !important; 1522 line-height: 1.4 !important; 1523 } 1524 .footer.bg-dark ul.list-unstyled { padding: 0; margin: 0; } 1525 .footer.bg-dark ul.list-unstyled li { margin-bottom: 10px; line-height: 1.5; } 1526 1527 /* Social icons â soft circular pill on hover */ 1528 .sl-footer-social { display: inline-flex; align-items: center; margin-top: 4px; } 1529 .sl-footer-social a { 1530 display: inline-flex; 1531 align-items: center; 1532 justify-content: center; 1533 width: 36px; 1534 height: 36px; 1535 border-radius: 50%; 1536 background: rgba(255, 255, 255, 0.08); 1537 margin-left: 0 !important; 1538 } 1539 .sl-footer-social a + a { margin-left: 8px !important; } 1540 .sl-footer-social a:hover { background: rgba(255, 255, 255, 0.18); } 1541 .sl-footer-social svg { width: 18px !important; height: 18px !important; display: block; } 1542 .sl-footer-social a.text-light { color: #ffffff !important; } 1543 1544 /* Bottom row */ 1545 .footer.bg-dark .row.no-gutters { 1546 border-top: 1px solid rgba(255, 255, 255, 0.08); 1547 padding-top: 18px; 1548 margin-top: 28px !important; 1549 font-size: 12px; 1550 color: rgba(255, 255, 255, 0.5); 1551 align-items: center; 1552 line-height: 1.6; 1553 } 1554 .footer.bg-dark .copyright { color: rgba(255, 255, 255, 0.5); font-size: 12px; } 1555 1556 /* Legal links list (bottom-right) */ 1557 .sl-footer-legal { 1558 list-style: none; 1559 padding: 0; 1560 margin: 0; 1561 display: flex; 1562 gap: 22px; 1563 justify-content: flex-end; 1564 } 1565 .sl-footer-legal li { margin: 0; padding: 0; } 1566 .footer.bg-dark .sl-footer-legal a, 1567 .footer.bg-dark .sl-footer-legal a.text-light { 1568 color: rgba(255, 255, 255, 0.5) !important; 1569 font-size: 12px !important; 1570 font-weight: 400 !important; 1571 line-height: 1.6 !important; 1572 } 1573 .footer.bg-dark .sl-footer-legal a:hover, 1574 .footer.bg-dark .sl-footer-legal a.text-light:hover { 1575 color: #ffffff !important; 1576 text-decoration: none !important; 1577 } 1578 @media (max-width: 767.98px) { 1579 .sl-footer-legal { justify-content: center; gap: 18px; margin-bottom: 8px; } 1580 } 1581 1582 /* Country switcher (student-only) inherits theme */ 1583 .footer.bg-dark #lc_select { 1584 background-color: rgba(255, 255, 255, 0.08); 1585 border-color: rgba(255, 255, 255, 0.15); 1586 color: #ffffff; 1587 } 1588 1589 /* Tighten typography on small screens */ 1590 @media (max-width: 991.98px) { 1591 .footer.bg-dark { padding: 36px 0 20px; text-align: center; } 1592 .footer.bg-dark h4 { margin-top: 12px; } 1593 .sl-footer-social { justify-content: center; display: flex; } 1594 } 1595 </style> 1596 1597 </main> 1598 <div class="d-none d-print-block text-center"> 1599 <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> 1600 </div> 1601 1602 <footer class="footer bg-dark text-light d-print-none"> 1603 <div class="container"> 1604 1605 1606 <div class="row text-center text-lg-left pb-3"> 1607 1608 <!-- Brand column --> 1609 <div class="col-lg-4 col-md-12 py-4 py-lg-0"> 1610 <a class="logo d-inline-block mb-3" href="/"><img src="https://static.studyladder.co.uk/cdn/site/c7/cbe28b2ff048.png" alt="Studyladder"></a> 1611 <p class="mb-3">Helping teachers, parents and schools inspire confident learners, one activity at a time.</p> 1612 <div class="sl-footer-social"> 1613 <a class="text-light" aria-label="Studyladder on Facebook" href="https://www.facebook.com/Studyladder/" target="_blank" rel="noopener"> 1614 <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> 1615 </a> 1616 <a class="text-light" aria-label="Studyladder on Instagram" href="https://www.instagram.com/studyladder/" target="_blank" rel="noopener"> 1617 <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> 1618 </a> 1619 <a class="text-light" aria-label="Studyladder on X / Twitter" href="https://twitter.com/studyladder" target="_blank" rel="noopener"> 1620 <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> 1621 </a> 1622 <a class="text-light" aria-label="Studyladder on YouTube" href="https://www.youtube.com/user/StudyLadder" target="_blank" rel="noopener"> 1623 <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> 1624 </a> 1625 </div> 1626 1627 </div> 1628 1629 <!-- Who we help --> 1630 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 1631 <h4 class="sl-footer-heading">Who we help</h4> 1632 <ul class="list-unstyled"> 1633 <li><a class="text-light" href="/about/parent">For parents</a></li> 1634 <li><a class="text-light" href="/about/teacher">For teachers</a></li> 1635 <li><a class="text-light" href="/about/teacher-school-pricing?t=s">For schools</a></li> 1636 <li><a class="text-light" href="/about/tutor">For tutors</a></li> 1637 </ul> 1638 </div> 1639 1640 <!-- Subjects --> 1641 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 1642 <h4 class="sl-footer-heading">Subjects</h4> 1643 <ul class="list-unstyled"> 1644 <li><a class="text-light" href="/about/subjects-mathematics">Mathematics</a></li> 1645 <li><a class="text-light" href="/about/subjects-english">English</a></li> 1646 <li><a class="text-light" href="/about/subjects-science">Science</a></li> 1647 </ul> 1648 </div> 1649 1650 <!-- Learn more --> 1651 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 1652 <h4 class="sl-footer-heading">Learn more</h4> 1653 <ul class="list-unstyled"> 1654 <li><a class="text-light" href="/about">About us</a></li> 1655 <li><a class="text-light" href="/about/features">Features</a></li> 1656 <li><a class="text-light" href="/info/upgrade-benefits">Home Plus benefits</a></li> 1657 <li><a class="text-light" href="#" data-toggle="modal" data-target="#pricingModal">Pricing</a></li> 1658 <li><a class="text-light" href="/about/testimonials">Testimonials</a></li> 1659 <li><a class="text-light" href="/blog">Blog</a></li> 1660 </ul> 1661 </div> 1662 1663 <!-- Support --> 1664 <div class="col-lg-2 col-md-6 py-4 py-lg-0"> 1665 <h4 class="sl-footer-heading">Support</h4> 1666 <ul class="list-unstyled"> 1667 <li><a class="text-light" href="/about/faqs">FAQs</a></li> 1668 <li><a class="text-light" href="/about/contact-us">Contact us</a></li> 1669 </ul> 1670 </div> 1671 1672 </div> 1673 1674 <div class="row no-gutters small d-flex justify-content-between mt-lg-5 mb-2"> 1675 <div class="copyright text-center text-md-left order-2 order-md-1 pt-1 pt-lg-0">© 2026 Studyladder Pty Ltd</div> 1676 <ul class="sl-footer-legal text-center text-lg-left order-1 order-md-2"> 1677 <li><a class="text-light" href="/about/privacy">Privacy</a></li> 1678 <li><a class="text-light" href="/about/terms">Terms</a></li> 1679 <li><a class="text-light" href="/info/gdpr">GDPR</a></li> 1680 </ul> 1681 </div> 1682 </div> 1683 </footer> 1684 1685
1685<script> 1686 $(function(){ 1687 $.ajax({ 1688 url: "/secure/check-subscription-cancelled", 1689 method: "POST", 1690 dataType: "json", 1691 success: function(r){ 1692 if (r.found){ 1693 /*dataLayer.push({ 1694 event: r.event ?? "cancelled", 1695 reason: r.reason ?? "not given", 1696 feedback: r.feedback ?? "not given", 1697 comment: r.comment ?? "not given", 1698 user: r.user ?? "", 1699 user_type: r.type ?? "", 1700 plan_type: r.plan ?? "", 1701 domain_region: "GB" 1702 })*/ 1703 } 1704 } 1705 }) 1706 }) 1707 </script>
1707 1708 1709 <!-- PRICING MODAL â opened by any [data-toggle="modal" data-target="#pricingModal"] trigger. 1710 Loaded site-wide from footer-bs4.phtml so it works for student, teacher, parent and public users. --> 1711<div id="pricingModal" class="modal fade sl-pricing-modal" role="dialog" aria-hidden="true" tabindex="-1" aria-labelledby="pricingModalTitle"> 1712 <div class="modal-dialog modal-dialog-centered" role="document"> 1713 <div class="modal-content sl-pricing-modal-content"> 1714 1715 <button type="button" class="sl-pricing-modal-close" data-dismiss="modal" aria-label="Close"> 1716 <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> 1717 </button> 1718 1719 <div class="sl-pricing-modal-header"> 1720 <div class="sl-pricing-modal-eyebrow">Pricing</div> 1721 <h2 class="sl-pricing-modal-title" id="pricingModalTitle">See pricing for…</h2> 1722 <p class="sl-pricing-modal-sub">Pick the option that describes you, we'll show the right plans.</p> 1723 </div> 1724 1725 <div class="sl-pricing-modal-options"> 1726 <a href="https://www.studyladder.co.uk/account/parent-pricing" class="sl-pricing-option"> 1727 <span class="sl-pricing-option-icon sl-pricing-icon-parent"> 1728 <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> 1729 </span> 1730 <span class="sl-pricing-option-body"> 1731 <strong>Parents & homeschoolers</strong> 1732 <small>Home Plus plans for up to 4 children</small> 1733 </span> 1734 <span class="sl-pricing-option-arrow">→</span> 1735 </a> 1736 1737 <a href="https://www.studyladder.co.uk/about/teacher-school-pricing?t=t" class="sl-pricing-option"> 1738 <span class="sl-pricing-option-icon sl-pricing-icon-teacher"> 1739 <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> 1740 </span> 1741 <span class="sl-pricing-option-body"> 1742 <strong>Teachers</strong> 1743 <small>For one classroom · up to 35 students</small> 1744 </span> 1745 <span class="sl-pricing-option-arrow">→</span> 1746 </a> 1747 1748 <a href="https://www.studyladder.co.uk/about/teacher-school-pricing?t=s" class="sl-pricing-option"> 1749 <span class="sl-pricing-option-icon sl-pricing-icon-school"> 1750 <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> 1751 </span> 1752 <span class="sl-pricing-option-body"> 1753 <strong>Schools</strong> 1754 <small>Whole-school plans · admin tools included</small> 1755 </span> 1756 <span class="sl-pricing-option-arrow">→</span> 1757 </a> 1758 </div> 1759 1760 </div> 1761 </div> 1762</div> 1763 1764<style> 1765/* Force-correct modal overlay behaviour (sl-marketing.scss styles .modal differently) */ 1766body.sl-marketing #pricingModal, 1767body #pricingModal.sl-pricing-modal { 1768 position: fixed !important; 1769 top: 0 !important; 1770 left: 0 !important; 1771 right: 0 !important; 1772 bottom: 0 !important; 1773 width: 100vw !important; 1774 height: 100vh !important; 1775 max-width: 100vw !important; 1776 max-height: 100vh !important; 1777 margin: 0 !important; 1778 padding: 0 !important; 1779 background: rgba(15, 23, 42, 0) !important; 1780 border: 0 !important; 1781 border-radius: 0 !important; 1782 box-shadow: none !important; 1783 transform: none !important; 1784 overflow-x: hidden !important; 1785 overflow-y: auto !important; 1786 outline: 0 !important; 1787 z-index: 2050 !important; 1788 /* Animation: fade overlay + dialog */ 1789 display: block !important; 1790 opacity: 0; 1791 visibility: hidden; 1792 pointer-events: none; 1793 transition: opacity .22s ease, visibility 0s linear .22s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 1794 -webkit-backdrop-filter: blur(0px); 1795 backdrop-filter: blur(0px); 1796} 1797body.sl-marketing #pricingModal.show, 1798body #pricingModal.sl-pricing-modal.show { 1799 display: block !important; 1800 opacity: 1; 1801 visibility: visible; 1802 pointer-events: auto; 1803 background: rgba(15, 23, 42, 0.78) !important; 1804 -webkit-backdrop-filter: blur(8px) !important; 1805 backdrop-filter: blur(8px) !important; 1806 transition: opacity .22s ease, visibility 0s linear 0s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 1807} 1808body.sl-marketing #pricingModal .modal-dialog, 1809body #pricingModal.sl-pricing-modal .modal-dialog,
1810body.sl-marketing #pricingModal .modal-dialog.modal-dialog-centered, 1811body #pricingModal.sl-pricing-modal .modal-dialog.modal-dialog-centered { 1812 position: fixed !important; 1813 top: 50% !important; 1814 left: 50% !important; 1815 right: auto !important; 1816 bottom: auto !important; 1817 -webkit-transform: translate(-50%, -50%) scale(0.96) !important; 1818 transform: translate(-50%, -50%) scale(0.96) !important; 1819 margin: 0 !important; 1820 padding: 0 !important; 1821 max-width: 520px !important; 1822 width: calc(100vw - 32px) !important; 1823 height: auto !important; 1824 max-height: calc(100vh - 32px) !important; 1825 min-height: 0 !important; 1826 display: block !important; 1827 background: transparent !important; 1828 border: 0 !important; 1829 box-shadow: none !important; 1830 transition: -webkit-transform .25s cubic-bezier(0.4, 0, 0.2, 1), transform .25s cubic-bezier(0.4, 0, 0.2, 1) !important; 1831 z-index: 2060 !important; 1832 flex: none !important; 1833 align-self: auto !important; 1834} 1835body.sl-marketing #pricingModal.show .modal-dialog, 1836body #pricingModal.sl-pricing-modal.show .modal-dialog, 1837body.sl-marketing #pricingModal.show .modal-dialog.modal-dialog-centered, 1838body #pricingModal.sl-pricing-modal.show .modal-dialog.modal-dialog-centered { 1839 -webkit-transform: translate(-50%, -50%) scale(1) !important; 1840 transform: translate(-50%, -50%) scale(1) !important; 1841} 1842body.sl-marketing #pricingModal .modal-dialog-centered::before, 1843body #pricingModal.sl-pricing-modal .modal-dialog-centered::before { 1844 content: none !important; 1845 display: none !important; 1846 height: 0 !important; 1847} 1848body.sl-marketing #pricingModal .sl-pricing-modal-content, 1849body #pricingModal .sl-pricing-modal-content { 1850 position: relative; 1851 background: #FFFFFF !important; 1852 border-radius: 18px !important; 1853 padding: 28px 28px 28px !important; 1854 box-shadow: 0 24px 80px -16px rgba(15, 23, 42, 0.30), 0 4px 12px rgba(15, 23, 42, 0.06) !important; 1855 pointer-events: auto; 1856 width: 100% !important; 1857 max-width: none !important; 1858 border: 0 !important; 1859 transform: none !important; 1860 transition: none !important; 1861 max-height: calc(100vh - 48px); 1862 overflow-y: auto; 1863} 1864 1865/* Close button */ 1866#pricingModal .sl-pricing-modal-close { 1867 position: absolute; 1868 top: 14px; 1869 right: 14px; 1870 width: 32px; 1871 height: 32px; 1872 border-radius: 50%; 1873 border: 0; 1874 background: #F1F5F9; 1875 color: #475569; 1876 display: inline-flex; 1877 align-items: center; 1878 justify-content: center; 1879 cursor: pointer; 1880 padding: 0; 1881 transition: background .15s ease; 1882} 1883#pricingModal .sl-pricing-modal-close:hover { background: #E2E8F0; color: #0F172A; } 1884#pricingModal .sl-pricing-modal-close svg { width: 18px; height: 18px; } 1885 1886/* Header */ 1887#pricingModal .sl-pricing-modal-header { padding: 0 0 18px; } 1888#pricingModal .sl-pricing-modal-eyebrow { 1889 font-size: 13px; 1890 font-weight: 600; 1891 letter-spacing: 0.08em; 1892 text-transform: uppercase; 1893 color: #2D5BFF; 1894 margin: 0 0 8px; 1895} 1896#pricingModal .sl-pricing-modal-title { 1897 font-size: 28px; 1898 font-weight: 700; 1899 color: #0F172A; 1900 margin: 0 0 8px; 1901 letter-spacing: -0.02em; 1902 line-height: 1.2; 1903} 1904#pricingModal .sl-pricing-modal-sub { 1905 font-size: 15px; 1906 color: #64748B; 1907 margin: 4px 0 0; 1908 line-height: 1.45; 1909} 1910 1911/* Options */ 1912#pricingModal .sl-pricing-modal-options { 1913 display: flex; 1914 flex-direction: column; 1915 gap: 10px; 1916 margin: 0; 1917} 1918 1919/* Option cards â with hover slide animation matching the join modal */ 1920#pricingModal .sl-pricing-option { 1921 position: relative; 1922 display: flex; 1923 align-items: center; 1924 gap: 14px; 1925 padding: 16px 18px; 1926 border: 1px solid #E2E8F0; 1927 border-radius: 12px; 1928 text-decoration: none; 1929 color: #0F172A; 1930 background: #FFFFFF; 1931 overflow: hidden; 1932 transition: border-color .25s ease, transform .25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow .25s ease; 1933 z-index: 0; 1934} 1935#pricingModal .sl-pricing-option::before { 1936 content: ""; 1937 position: absolute; 1938 top: 0; 1939 left: 0; 1940 bottom: 0; 1941 width: 100%; 1942 background: linear-gradient(90deg, #F8FAFC 0%, #EFF6FF 100%); 1943 transform: translateX(-100%); 1944 transition: transform .35s cubic-bezier(0.4, 0, 0.2, 1); 1945 z-index: -1; 1946} 1947#pricingModal .sl-pricing-option:hover { 1948 border-color: #2D5BFF; 1949 color: #0F172A; 1950 text-decoration: none; 1951 transform: translateX(4px); 1952 box-shadow: 0 4px 12px -4px rgba(45, 91, 255, 0.18); 1953} 1954#pricingModal .sl-pricing-option:hover::before { transform: translateX(0); } 1955#pricingModal .sl-pricing-option:active { transform: translateX(4px) translateY(1px); } 1956 1957#pricingModal .sl-pricing-option-icon { 1958 flex: 0 0 44px; 1959 width: 44px; 1960 height: 44px; 1961 border-radius: 10px; 1962 display: inline-flex; 1963 align-items: center; 1964 justify-content: center; 1965 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1); 1966} 1967#pricingModal .sl-pricing-option:hover .sl-pricing-option-icon { transform: scale(1.06); } 1968#pricingModal .sl-pricing-option-icon svg { width: 22px; height: 22px; } 1969#pricingModal .sl-pricing-icon-parent { background: #FED7AA; color: #EA580C; } /* orange */ 1970#pricingModal .sl-pricing-icon-teacher { background: #DBE6FF; color: #2D5BFF; } /* blue */ 1971#pricingModal .sl-pricing-icon-school { background: #D1FAE5; color: #059669; } /* green */ 1972 1973#pricingModal .sl-pricing-option-body { 1974 flex: 1 1 auto; 1975 display: flex; 1976 flex-direction: column; 1977 gap: 3px; 1978} 1979#pricingModal .sl-pricing-option-body strong { 1980 font-size: 16px; 1981 font-weight: 600; 1982 color: #0F172A; 1983 letter-spacing: -0.01em; 1984} 1985#pricingModal .sl-pricing-option-body small { 1986 font-size: 14px; 1987 color: #64748B; 1988 font-weight: 400; 1989 line-height: 1.4; 1990} 1991#pricingModal .sl-pricing-option-arrow { 1992 flex: 0 0 auto; 1993 font-size: 20px; 1994 color: #94A3B8; 1995 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1), color .25s ease; 1996} 1997#pricingModal .sl-pricing-option:hover .sl-pricing-option-arrow { 1998 transform: translateX(6px); 1999 color: #2D5BFF; 2000} 2001</style> 2002
2003<script> 2004$('#pricingModal').on('show.bs.modal', function (e) { 2005 window.dataLayer = window.dataLayer || []; 2006 window.dataLayer.push({ 2007 'event': 'Pricing Modal', 2008 'Action': 'Open', 2009 'Step': '1', 2010 'Step Name': 'Choose Audience' 2011 }); 2012}); 2013</script>
2013 2014<div id="joinNow" class="modal fade sl-join-modal" role="dialog" aria-hidden="true" tabindex="-1" aria-labelledby="joinNowTitle"> 2015 <div class="modal-dialog modal-dialog-centered" role="document"> 2016 <div class="modal-content sl-join-modal-content"> 2017 2018 <button type="button" class="sl-join-modal-close" data-dismiss="modal" aria-label="Close"> 2019 <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> 2020 </button> 2021 2022 <div class="sl-join-modal-header"> 2023 <div class="sl-join-modal-eyebrow">Sign up</div> 2024 <h2 class="sl-join-modal-title" id="joinNowTitle">Join Studyladder</h2> 2025 <p class="sl-join-modal-sub">I would like to register for a:</p> 2026 </div> 2027 2028 <div class="sl-join-modal-options"> 2029 <a href="https://www.studyladder.co.uk/account/parent-pricing" class="sl-join-option"> 2030 <span class="sl-join-option-icon sl-join-icon-parent"> 2031 <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> 2032 </span> 2033 <span class="sl-join-option-body"> 2034 <strong>Parent account</strong> 2035 <small>For families and homeschoolers, up to 4 children at home</small> 2036 </span> 2037 <span class="sl-join-option-arrow">→</span> 2038 </a> 2039 2040 <a href="/account/teacher?t=teacher" class="sl-join-option"> 2041 <span class="sl-join-option-icon sl-join-icon-teacher"> 2042 <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> 2043 </span> 2044 <span class="sl-join-option-body"> 2045 <strong>School teacher account</strong> 2046 <small>For one classroom or your whole school</small> 2047 </span> 2048 <span class="sl-join-option-arrow">→</span> 2049 </a> 2050 </div> 2051 2052 <div class="sl-join-modal-section-label">I would like to:</div> 2053 2054 <div class="sl-join-modal-options"> 2055 <a href="/login/account?backUrl=%2Faccount%2Fupgrade" class="sl-join-option"> 2056 <span class="sl-join-option-icon sl-join-icon-upgrade"> 2057 <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> 2058 </span> 2059 <span class="sl-join-option-body"> 2060 <strong>Upgrade an existing account</strong> 2061 <small>See what's included in Home Plus</small> 2062 </span> 2063 <span class="sl-join-option-arrow">→</span> 2064 </a> 2065 2066 <a href="/account/school-admin" class="sl-join-option"> 2067 <span class="sl-join-option-icon sl-join-icon-school"> 2068 <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> 2069 </span> 2070 <span class="sl-join-option-body"> 2071 <strong>Pay a school administration fee</strong> 2072 <small>Pay by invoice or credit card</small> 2073 </span> 2074 <span class="sl-join-option-arrow">→</span> 2075 </a> 2076 </div> 2077 2078 <div class="sl-join-modal-footer-note"> 2079 Already have an account? <a href="/login/account">Log in →</a> 2080 </div> 2081 2082 </div> 2083 </div> 2084</div> 2085 2086<style> 2087/* Force-correct modal overlay behaviour. sl-marketing.scss has its own `.modal` 2088 rules (intended as a card inside `.modal-backdrop`) that clash with Bootstrap's 2089 modal/overlay pattern. We override with very high specificity + !important. */ 2090body.sl-marketing #joinNow, 2091body #joinNow.sl-join-modal { 2092 position: fixed !important; 2093 top: 0 !important; 2094 left: 0 !important; 2095 right: 0 !important; 2096 bottom: 0 !important; 2097 width: 100vw !important; 2098 height: 100vh !important; 2099 max-width: 100vw !important; 2100 max-height: 100vh !important; 2101 margin: 0 !important; 2102 padding: 0 !important; 2103 background: rgba(15, 23, 42, 0) !important; 2104 border: 0 !important; 2105 border-radius: 0 !important; 2106 box-shadow: none !important; 2107 transform: none !important; 2108 overflow-x: hidden !important; 2109 overflow-y: auto !important; 2110 outline: 0 !important; 2111 z-index: 2050 !important; 2112 /* Animation: fade overlay + dialog */ 2113 display: block !important; 2114 opacity: 0; 2115 visibility: hidden; 2116 pointer-events: none; 2117 transition: opacity .22s ease, visibility 0s linear .22s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 2118 -webkit-backdrop-filter: blur(0px); 2119 backdrop-filter: blur(0px); 2120} 2121body.sl-marketing #joinNow.show, 2122body #joinNow.sl-join-modal.show { 2123 display: block !important; 2124 opacity: 1; 2125 visibility: visible; 2126 pointer-events: auto; 2127 background: rgba(15, 23, 42, 0.78) !important; 2128 -webkit-backdrop-filter: blur(8px) !important; 2129 backdrop-filter: blur(8px) !important; 2130 transition: opacity .22s ease, visibility 0s linear 0s, background-color .22s ease, -webkit-backdrop-filter .22s ease, backdrop-filter .22s ease !important; 2131} 2132body.sl-marketing #joinNow .modal-dialog, 2133body #joinNow.sl-join-modal .modal-dialog,
2134body.sl-marketing #joinNow .modal-dialog.modal-dialog-centered, 2135body #joinNow.sl-join-modal .modal-dialog.modal-dialog-centered { 2136 position: fixed !important; 2137 top: 50% !important; 2138 left: 50% !important; 2139 right: auto !important; 2140 bottom: auto !important; 2141 -webkit-transform: translate(-50%, -50%) scale(0.96) !important; 2142 transform: translate(-50%, -50%) scale(0.96) !important; 2143 margin: 0 !important; 2144 padding: 0 !important; 2145 max-width: 520px !important; 2146 width: calc(100vw - 32px) !important; 2147 height: auto !important; 2148 max-height: calc(100vh - 32px) !important; 2149 min-height: 0 !important; 2150 display: block !important; 2151 background: transparent !important; 2152 border: 0 !important; 2153 box-shadow: none !important; 2154 transition: -webkit-transform .25s cubic-bezier(0.4, 0, 0.2, 1), transform .25s cubic-bezier(0.4, 0, 0.2, 1) !important; 2155 z-index: 2060 !important; 2156 flex: none !important; 2157 align-self: auto !important; 2158} 2159body.sl-marketing #joinNow.show .modal-dialog, 2160body #joinNow.sl-join-modal.show .modal-dialog, 2161body.sl-marketing #joinNow.show .modal-dialog.modal-dialog-centered, 2162body #joinNow.sl-join-modal.show .modal-dialog.modal-dialog-centered { 2163 -webkit-transform: translate(-50%, -50%) scale(1) !important; 2164 transform: translate(-50%, -50%) scale(1) !important; 2165} 2166/* Bootstrap inserts a ::before pseudo for centered modals â neutralise it */ 2167body.sl-marketing #joinNow .modal-dialog-centered::before, 2168body #joinNow.sl-join-modal .modal-dialog-centered::before { 2169 content: none !important; 2170 display: none !important; 2171 height: 0 !important; 2172} 2173body.sl-marketing #joinNow .sl-join-modal-content, 2174body #joinNow .sl-join-modal-content { 2175 position: relative; 2176 background: #FFFFFF !important; 2177 border-radius: 18px !important; 2178 padding: 28px 28px 22px !important; 2179 box-shadow: 0 24px 80px -16px rgba(15, 23, 42, 0.30), 0 4px 12px rgba(15, 23, 42, 0.06) !important; 2180 pointer-events: auto; 2181 width: 100% !important; 2182 max-width: none !important; 2183 border: 0 !important; 2184 transform: none !important; 2185 transition: none !important; 2186 max-height: calc(100vh - 48px); 2187 overflow-y: auto; 2188} 2189#joinNow .sl-join-modal-close { 2190 position: absolute; 2191 top: 14px; 2192 right: 14px; 2193 width: 32px; 2194 height: 32px; 2195 border-radius: 50%; 2196 border: 0; 2197 background: #F1F5F9; 2198 color: #475569; 2199 display: inline-flex; 2200 align-items: center; 2201 justify-content: center; 2202 cursor: pointer; 2203 padding: 0; 2204 transition: background .15s ease; 2205} 2206#joinNow .sl-join-modal-close:hover { background: #E2E8F0; color: #0F172A; } 2207#joinNow .sl-join-modal-close svg { width: 18px; height: 18px; } 2208#joinNow .sl-join-modal-header { padding: 0 0 14px; } 2209#joinNow .sl-join-modal-eyebrow { 2210 font-size: 13px; 2211 font-weight: 600; 2212 letter-spacing: 0.08em; 2213 text-transform: uppercase; 2214 color: #2D5BFF; 2215 margin: 0 0 8px; 2216} 2217#joinNow .sl-join-modal-title { 2218 font-size: 28px; 2219 font-weight: 700; 2220 color: #0F172A; 2221 margin: 0 0 8px; 2222 letter-spacing: -0.02em; 2223 line-height: 1.2; 2224} 2225#joinNow .sl-join-modal-sub { 2226 font-size: 15px; 2227 color: #64748B; 2228 margin: 4px 0 0; 2229} 2230#joinNow .sl-join-modal-options { 2231 display: flex; 2232 flex-direction: column; 2233 gap: 10px; 2234 margin: 0 0 12px; 2235} 2236#joinNow .sl-join-modal-section-label { 2237 font-size: 15px; 2238 color: #64748B; 2239 margin: 18px 0 10px; 2240} 2241 2242/* Option cards â with hover slide animation */ 2243#joinNow .sl-join-option { 2244 position: relative; 2245 display: flex; 2246 align-items: center; 2247 gap: 14px; 2248 padding: 16px 18px; 2249 border: 1px solid #E2E8F0; 2250 border-radius: 12px; 2251 text-decoration: none; 2252 color: #0F172A; 2253 background: #FFFFFF; 2254 overflow: hidden; 2255 transition: border-color .25s ease, transform .25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow .25s ease; 2256 z-index: 0; 2257} 2258/* Sliding tinted backdrop revealed on hover (leftâright wipe) */ 2259#joinNow .sl-join-option::before { 2260 content: ""; 2261 position: absolute; 2262 top: 0; 2263 left: 0; 2264 bottom: 0; 2265 width: 100%; 2266 background: linear-gradient(90deg, #F8FAFC 0%, #EFF6FF 100%); 2267 transform: translateX(-100%); 2268 transition: transform .35s cubic-bezier(0.4, 0, 0.2, 1); 2269 z-index: -1; 2270} 2271#joinNow .sl-join-option:hover { 2272 border-color: #2D5BFF; 2273 color: #0F172A; 2274 text-decoration: none; 2275 transform: translateX(4px); 2276 box-shadow: 0 4px 12px -4px rgba(45, 91, 255, 0.18); 2277} 2278#joinNow .sl-join-option:hover::before { transform: translateX(0); } 2279#joinNow .sl-join-option:active { transform: translateX(4px) translateY(1px); } 2280 2281#joinNow .sl-join-option-icon { 2282 flex: 0 0 44px; 2283 width: 44px; 2284 height: 44px; 2285 border-radius: 10px; 2286 display: inline-flex; 2287 align-items: center; 2288 justify-content: center; 2289 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1); 2290} 2291#joinNow .sl-join-option:hover .sl-join-option-icon { transform: scale(1.06); } 2292#joinNow .sl-join-option-icon svg { width: 22px; height: 22px; } 2293#joinNow .sl-join-icon-parent { background: #FED7AA; color: #EA580C; } 2294#joinNow .sl-join-icon-teacher { background: #DBE6FF; color: #2D5BFF; } 2295#joinNow .sl-join-icon-upgrade { background: #D1FAE5; color: #059669; } 2296#joinNow .sl-join-icon-school { background: #E9D5FF; color: #7C3AED; } 2297#joinNow .sl-join-option-body { 2298 flex: 1 1 auto; 2299 display: flex; 2300 flex-direction: column; 2301 gap: 3px; 2302} 2303#joinNow .sl-join-option-body strong { 2304 font-size: 16px; 2305 font-weight: 600; 2306 color: #0F172A; 2307 letter-spacing: -0.01em; 2308} 2309#joinNow .sl-join-option-body small { 2310 font-size: 14px; 2311 color: #64748B; 2312 font-weight: 400; 2313 line-height: 1.4; 2314} 2315#joinNow .sl-join-option-arrow { 2316 flex: 0 0 auto; 2317 font-size: 20px; 2318 color: #94A3B8; 2319 transition: transform .25s cubic-bezier(0.4, 0, 0.2, 1), color .25s ease; 2320} 2321#joinNow .sl-join-option:hover .sl-join-option-arrow { 2322 transform: translateX(6px); 2323 color: #2D5BFF; 2324} 2325#joinNow .sl-join-modal-footer-note { 2326 margin: 16px 0 0; 2327 padding-top: 16px; 2328 border-top: 1px solid #E2E8F0; 2329 text-align: center; 2330 font-size: 15px; 2331 color: #64748B; 2332} 2333#joinNow .sl-join-modal-footer-note a { 2334 color: #2D5BFF; 2335 font-weight: 600; 2336 text-decoration: none; 2337} 2338#joinNow .sl-join-modal-footer-note a:hover { text-decoration: underline; } 2339</style> 2340
2341<script> 2342$('#joinNow').on('show.bs.modal', function (e) { 2343 window.dataLayer = window.dataLayer || []; 2344 window.dataLayer.push({ 2345 'event': 'User Account', 2346 'Action': 'Creation', 2347 'Step': '1', 2348 'Step Name': 'Choose Account' 2349 }); 2350}); 2351 2352</script>
2352 2353<div id="publicMenuModal" class="modal site-menu" tabindex="-1" role="dialog"> 2354 <div class="modal-dialog modal-xl" role="document"> 2355 <div class="modal-content"> 2356 <div class="modal-header"> 2357 2358 <h4 class="modal-title">Menu</h4> 2359 <button aria-hidden="true" data-dismiss="modal" class="close" type="button"><i class="far fa-times"></i></button> 2360 2361 </div> 2362 <div class="modal-body"> 2363 <div class="row text-dark"> 2364 2365 <div class="col-md"> 2366 <h3 style="color:#e3813b;border-color:#e3813b"> 2367 <i class="fas fa-book float-right"></i> 2368 Resources 2369 </h3> 2370 2371 <ul class="list-group list-group-flush"> 2372 <li class="list-group-item"><a href="/games">Browse All / Search</a></li> 2373 <li class="list-group-item"><a href="/games/mathematics/au-year-three/mathematics-addition-430">Mathematics</a></li> 2374 <li class="list-group-item"><a href="/games/literacy/au-year-three/english-spelling-and-vocabulary-185">Literacy</a></li> 2375 <li class="list-group-item"><a href="/games/science/au-year-three/science-biology-764">Science</a></li> 2376 <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> 2377 <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> 2378 <li class="list-group-item"><a href="/games/language-culture/au-mixed-years/language-and-culture-languages-1022">Language & Culture</a></li> 2379 <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> 2380 <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> 2381 </ul> 2382 </div> 2383 <div class="col-md"> 2384 <h3 style="color:#87b53e;border-color:#87b53e"> 2385 <i class="fas fa-star float-right"></i> 2386 My Account 2387 </h3> 2388 2389 <ul class="list-group list-group-flush"> 2390 <li class="list-group-item"><a href="#" data-toggle="modal" data-target="#joinNow" onclick="$('#publicMenuModal').modal('hide')">Join now</a></li> 2391 <li class="list-group-item"><a href="/login/account">Log in</a></li> 2392 <li class="list-group-item"><a href="/login/forgot">Forgot password</a></li> 2393 <li class="list-group-item"><a href="/about/pricing">Pricing</a></li> 2394 </ul> 2395 </div> 2396 <div class="col-md"> 2397 <h3 style="color:#9767b6;border-color:#9767b6"> 2398 <i class="fas fa-star float-right"></i> 2399 Other 2400 </h3> 2401 2402 <ul class="list-group list-group-flush"> 2403 <li class="list-group-item"><a href="/about/contact-us">Contact Us</a></li> 2404 <li class="list-group-item"><a href="/help/faq">Help / FAQ</a></li> 2405 <li class="list-group-item"><a href="/about/about-us">About us</a></li> 2406 <li class="list-group-item"><a href="/about/privacy">Privacy</a></li> 2407 <li class="list-group-item"><a href="/about/disclaimer">Disclaimer</a></li> 2408 <li class="list-group-item"><a href="/about/terms">Terms</a></li> 2409 </ul> 2410 2411 </div> 2412 2413 </div><!-- .row --> 2414 </div><!-- .modal-body --> 2415 </div><!-- .modal-content --> 2416 </div><!-- .modal-dialog --> 2417</div><!-- .modal --> 2418 2419</body> 2420 2421<style> 2422 2423 #SLWorldTeaserModal .modal-dialog, #HomeTutorVideoModal .modal-dialog {max-width: 1200px;} 2424 #SLWorldTeaserModal .modal-body, #HomeTutorVideoModal .modal-body {padding-left: 3rem;padding-right: 3rem;} 2425 #SLWorldTeaserModal .modal-header, #HomeTutorVideoModal .modal-header {height:1px; border:none;} 2426 2427 @media only screen and (max-width: 767px) { 2428 #SLWorldTeaserModal .modal-body, #HomeTutorVideoModal .modal-body {padding-left: 1rem;padding-right: 1rem;} 2429 #SLWorldTeaserModal .modal-header, #HomeTutorVideoModal .modal-header {height:1px; border:none;} 2430 #SLWorldTeaserModal .modal-header, #HomeTutorVideoModal .modal-header {height: 20px;padding-top:30px;} 2431 .site-menu .modal-header .close { 2432 margin-top:-45px!important; 2433 } 2434 } 2435 2436</style> 2437 2438 2439
2439<script type="text/javascript"> 2440 2441 2442 $( document ).ready(function(){ 2443 2444 $('#SLWorldTeaserModal').on('hidden.bs.modal', function () { 2445 document.getElementById('slWorldVideo').pause(); 2446 }) 2447 2448 $('#HomeTutorVideoModal').on('hidden.bs.modal', function () { 2449 document.getElementById('htVideo').pause(); 2450 }) 2451 2452 $('#SLWorldTeaserModal').on('shown.bs.modal', function () { 2453 // document.getElementById('slWorldVideo').src(); 2454 videoString = $('#slWorldVideo source').data("videourl"); 2455 $('#slWorldVideo source').attr('src', videoString); 2456 $("#slWorldVideo ")[0].load(); 2457 $("#slWorldVideo ")[0].play(); 2458 }) 2459 2460 $('#HomeTutorVideoModal').on('shown.bs.modal', function () { 2461 // document.getElementById('htVideo').pause(); 2462 videoString = $('#htVideo source').data("videourl"); 2463 $('#htVideo source').attr('src', videoString); 2464 $("#htVideo ")[0].load(); 2465 $("#htVideo ")[0].play(); 2466 }) 2467 2468 }); 2469 2470 // document.getElementById('videoId').play(); 2471 //jQuery("#video").trigger('pause'); 2472 2473 2474 </script>
2474 2475 2476 <div class="modal fade newPopUpDesign site-menu" id="SLWorldTeaserModal" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true"> 2477 <div class="modal-dialog modalBox"> 2478 <div class="modal-content"> 2479 <div class="modal-header " style="background-color:#000!important;"> 2480 <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> 2481 <button aria-hidden="true" data-dismiss="modal" class="close" type="button"><i class="fa fa-times"></i></button> 2482 </div> 2483 <div class="modal-body pt-4" style="background-color:#000;"> 2484 2485 <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> 2486 </div> 2487 </div> 2488 </div> 2489 </div> 2490 2491 <div class="modal fade newPopUpDesign site-menu" id="HomeTutorVideoModal" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true"> 2492 <div class="modal-dialog modalBox"> 2493 <div class="modal-content"> 2494 <div class="modal-header " style="background-color:#000!important;"> 2495 <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> 2496 <button aria-hidden="true" data-dismiss="modal" class="close" type="button"><i class="fa fa-times"></i></button> 2497 </div> 2498 <div class="modal-body pt-4" style="background-color:#000;"> 2499 <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> 2500 2501 </div> 2502 </div> 2503 </div> 2504 </div> <!DOCTYPE html> 2505<html lang="en"> 2506<head> 2507 <meta charset="UTF-8"> 2508 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 2509 <title>Cookie Consent</title> 2510 <style> 2511 #cookie-banner { 2512 position: fixed; 2513 bottom: 20px; 2514 right: 20px; 2515 width: 320px; 2516 background: #212529; 2517 color: #f8f9fa; 2518 padding: 20px; 2519 border-radius: 8px; 2520 box-shadow: 0 0px 12px -1px white; 2521 z-index: 9999; 2522 font-family: 'Quicksand', 'Helvetica Neue', sans-serif; 2523 display: none; 2524 gap: 15px; 2525 align-items: flex-start; 2526 } 2527 2528 #cookie-banner-icon, 2529 #cookie-preferences-icon { 2530 flex-shrink: 0; 2531 filter: drop-shadow(0 0 6px rgba(255,255,255,0.5)); 2532 } 2533 2534 #cookie-banner-icon img, 2535 #cookie-preferences-icon img { 2536 width: 40px; 2537 height: 40px; 2538 } 2539 2540 #cookie-banner-content { 2541 flex: 1; 2542 } 2543 2544 #cookie-preferences { 2545 position: fixed; 2546 bottom: 20px; 2547 right: 20px; 2548 width: 320px; 2549 background: #212529; 2550 color: #f8f9fa; 2551 padding: 20px; 2552 border-radius: 8px; 2553 box-shadow: 0 0px 12px -1px white; 2554 z-index: 9999; 2555 font-family: 'Quicksand', 'Helvetica Neue', sans-serif; 2556 display: none; 2557 gap: 15px; 2558 } 2559 2560 #cookie-preferences-content { 2561 flex: 1; 2562 } 2563 2564 #cookie-banner-content p, 2565 #cookie-preferences-content p { 2566 margin-bottom: 1em; 2567 line-height: 1.4em; 2568 } 2569 2570 #cookie-banner-content a { 2571 color: #ffc107; 2572 text-decoration: underline; 2573 } 2574 2575 .cookie-buttons { 2576 display: flex; 2577 flex-wrap: wrap; 2578 gap: 8px; 2579 } 2580 2581 .cookie-buttons button, 2582 .save-btn { 2583 padding: 8px 12px; 2584 border: none; 2585 border-radius: 6px; 2586 cursor: pointer; 2587 font-weight: 600; 2588 font-family: 'Quicksand', sans-serif; 2589 letter-spacing: 0.5px; 2590 } 2591 2592 .accept-btn { background: #198754; color: #fff; } 2593 .reject-btn { background: #dc3545; color: #fff; } 2594 .customize-btn { background: #ffc107; color: #000; } 2595 .save-btn { background: #0d6efd; color: #fff; width: 100%; margin-top: 10px; } 2596 2597 .toggle-wrapper { 2598 display: flex; 2599 justify-content: space-between; 2600 align-items: center; 2601 margin-bottom: 10px; 2602 } 2603 2604 .toggle-switch { 2605 position: relative; 2606 display: inline-block; 2607 width: 36px; 2608 height: 20px; 2609 } 2610 2611 .toggle-switch input { 2612 opacity: 0; 2613 width: 0; 2614 height: 0; 2615 } 2616 2617 .slider { 2618 position: absolute; 2619 cursor: pointer; 2620 top: 0; 2621 left: 0; 2622 right: 0; 2623 bottom: 0; 2624 background-color: #ccc; 2625 transition: 0.2s; 2626 border-radius: 34px; 2627 } 2628 2629 .slider:before { 2630 position: absolute; 2631 content: ""; 2632 height: 14px; 2633 width: 14px; 2634 left: 3px; 2635 bottom: 3px; 2636 background-color: white; 2637 transition: 0.2s; 2638 border-radius: 50%; 2639 } 2640 2641 .toggle-switch input:checked + .slider { 2642 background-color: #0d6efd; 2643 } 2644 2645 .toggle-switch input:checked + .slider:before { 2646 transform: translateX(16px); 2647 } 2648 </style> 2649
2649<script> 2650 window.dataLayer = window.dataLayer || []; 2651 function gtag() { dataLayer.push(arguments); } 2652 2653 const siteCountryId = "GB"; 2654 const unrestricted = ["AU", "NZ"].includes(siteCountryId); 2655 let isStudent = false; 2656 2657 if (unrestricted) { 2658 localStorage.setItem('cookie_consent', JSON.stringify({analytics: true, marketing: true})); 2659 } else if (isStudent) { 2660 localStorage.setItem('cookie_consent', JSON.stringify({analytics: false, marketing: false})); 2661 } else { 2662 gtag('consent', 'default', { 2663 'ad_storage': 'denied', 2664 'analytics_storage': 'denied', 2665 'ad_user_data': 'denied', 2666 'ad_personalization': 'denied', 2667 'functionality_storage': 'granted', 2668 'security_storage': 'granted' 2669 }); 2670 } 2671 2672 document.addEventListener('DOMContentLoaded', () => { 2673 const prefs = JSON.parse(localStorage.getItem('cookie_consent') || '{}'); 2674 2675 if (unrestricted) { 2676 // No banner, full access 2677 gtag('consent', 'update', { 2678 'ad_storage': 'granted', 2679 'ad_user_data': 'granted', 2680 'ad_personalization': 'granted', 2681 'analytics_storage': 'granted', 2682 'functionality_storage': 'granted', 2683 'security_storage': 'granted' 2684 }); 2685 return; 2686 } 2687 2688 if (!('analytics' in prefs) && !('marketing' in prefs)) { 2689 document.getElementById('cookie-banner').style.display = 'block'; 2690 document.getElementById('cookie-preferences').style.display = 'none'; 2691 } else { 2692 applyConsent(prefs); 2693 } 2694 }); 2695 2696 function applyConsent(prefs) { 2697 gtag('consent', 'update', { 2698 'ad_storage': prefs.marketing ? 'granted' : 'denied', 2699 'ad_user_data': prefs.marketing ? 'granted' : 'denied', 2700 'ad_personalization': prefs.marketing ? 'granted' : 'denied', 2701 'analytics_storage': prefs.analytics ? 'granted' : 'denied', 2702 'functionality_storage': 'granted', 2703 'security_storage': 'granted' 2704 }); 2705 } 2706 </script>
2706 2707</head> 2708<body> 2709<!-- body content remains unchanged --> 2710 2711<div id="cookie-banner"> 2712 <div class="d-flex align-items-start" style="gap:15px"> 2713 <div id="cookie-banner-icon"> 2714 <img src="https://static.studyladder.co.uk/cdn/site/71/25a349e3aa67.png" alt="Cookie Icon"> 2715 </div> 2716 <div id="cookie-banner-content"> 2717 <p>We use cookies to help tailor your educational experience. <a href="/about/privacy">Learn more</a></p> 2718 </div> 2719 </div> 2720 2721 <div class="cookie-buttons mt-3"> 2722 <button class="accept-btn" onclick="acceptAllCookies()">Accept</button> 2723 <button class="reject-btn" onclick="rejectAllCookies()">Reject</button> 2724 <button class="customize-btn" onclick="openPreferences()">Customize</button> 2725 </div> 2726</div> 2727 2728<div id="cookie-preferences"> 2729 <div id="cookie-preferences-icon"> 2730 <img src="https://static.studyladder.co.uk/cdn/site/71/25a349e3aa67.png" alt="Cookie Icon"> 2731 </div> 2732 <div id="cookie-preferences-content"> 2733 <p>Cookie Preferences:</p> 2734 <div class="toggle-wrapper"> 2735 <span>Essential (always on)</span> 2736 <div class="toggle-switch"><label><input type="checkbox" disabled checked><span class="slider"></span></label></div> 2737 </div> 2738 <div class="toggle-wrapper"> 2739 <span>Analytics</span> 2740 <div class="toggle-switch"><label><input type="checkbox" id="toggle-analytics" checked><span class="slider"></span></label></div> 2741 </div> 2742 <div class="toggle-wrapper"> 2743 <span>Marketing</span> 2744 <div class="toggle-switch"><label><input type="checkbox" id="toggle-marketing" checked><span class="slider"></span></label></div> 2745 </div> 2746 <button class="save-btn" onclick="savePreferences()">Save Preferences</button> 2747 </div> 2748</div> 2749
2750<script> 2751 function saveConsent(prefs) { 2752 localStorage.setItem('cookie_consent', JSON.stringify(prefs)); 2753 applyConsent(prefs); 2754 } 2755 2756 function getConsent() { 2757 return JSON.parse(localStorage.getItem('cookie_consent') || '{}'); 2758 } 2759 2760 function applyConsent(prefs) { 2761 if (prefs.analytics) { 2762 loadGoogleAnalytics(); 2763 } 2764 2765 gtag('consent', 'update', { 2766 'ad_storage': prefs.marketing ? 'granted' : 'denied', 2767 'ad_user_data': prefs.marketing ? 'granted' : 'denied', 2768 'ad_personalization': prefs.marketing ? 'granted' : 'denied', 2769 'analytics_storage': prefs.analytics ? 'granted' : 'denied', 2770 'functionality_storage': 'granted', 2771 'security_storage': 'granted' 2772 }); 2773 } 2774 2775 function loadGoogleAnalytics() { 2776 if (!window.gtag){ 2777 window.dataLayer = window.dataLayer || []; 2778 function gtag() { dataLayer.push(arguments); } 2779 } 2780 2781 } 2782 2783 function acceptAllCookies() { 2784 saveConsent({ analytics: true, marketing: true }); 2785 document.getElementById('cookie-banner').style.display = 'none'; 2786 } 2787 2788 function rejectAllCookies() { 2789 saveConsent({ analytics: false, marketing: false }); 2790 document.getElementById('cookie-banner').style.display = 'none'; 2791 } 2792 2793 function openPreferences() { 2794 document.getElementById('cookie-banner').style.display = 'none'; 2795 document.getElementById('cookie-preferences').style.display = 'flex'; 2796 } 2797 2798 function savePreferences() { 2799 const prefs = { 2800 analytics: document.getElementById('toggle-analytics').checked, 2801 marketing: document.getElementById('toggle-marketing').checked 2802 }; 2803 saveConsent(prefs); 2804 document.getElementById('cookie-preferences').style.display = 'none'; 2805 } 2806 2807 document.addEventListener('DOMContentLoaded', () => { 2808 const prefs = getConsent(); 2809 if (!('analytics' in prefs) && !('marketing' in prefs)) { 2810 document.getElementById('cookie-banner').style.display = 'block'; 2811 document.getElementById('cookie-preferences').style.display = 'none'; 2812 } else { 2813 document.getElementById('cookie-banner').style.display = 'none'; 2814 document.getElementById('cookie-preferences').style.display = 'none'; 2815 applyConsent(prefs); 2816 } 2817 }); 2818</script>
2818 2819</body> 2820</html> 2821 2822 2823 <!-- SL marketing reveal-on-scroll â only runs when <body> has .sl-marketing class --> 2824
2824<script> 2825 (function () { 2826 if (!document.body.classList.contains('sl-marketing')) return; 2827 if (!('IntersectionObserver' in window)) return; 2828 2829 // Selectors that fade-up when scrolled into view 2830 var fadeUp = [ 2831 '.section-eyebrow', '.section-title', '.section-sub', 2832 '.video-frame', '.year-progression', '.stats-note', '.tour-cta-row', 2833 '.curr-header', '.safety-header', '.safety-cta', 2834 '.faq-intro', '.final-cta-inner > *' 2835 ].join(','); 2836 2837 // Stagger groups â same animation but delayed in sequence for grids 2838 var staggerGroups = [ 2839 '.audience-grid > .audience-card', 2840 '.subjects-grid > .subject-card', 2841 '.why-grid > .why-item', 2842 '.stats-grid > .stat-card', 2843 '.test-grid > .test-card', 2844 '.pricing-grid > .price-card', 2845 '.safety-grid > .safety-item', 2846 '.faq-list > .faq-item', 2847 '.video-chapters > .chapter', 2848 '.platform-grid > .feature-tile', 2849 '.story-stat-stack > .story-stat', 2850 '.test-grid > .test-card', 2851 '.results-list > li' 2852 ]; 2853 2854 document.querySelectorAll(fadeUp).forEach(function (el) { 2855 el.classList.add('reveal'); 2856 }); 2857 2858 staggerGroups.forEach(function (sel) { 2859 document.querySelectorAll(sel).forEach(function (el, idx) { 2860 el.classList.add('reveal'); 2861 el.style.animationDelay = Math.min(idx * 0.05, 0.3) + 's'; 2862 }); 2863 }); 2864 2865 var obs = new IntersectionObserver(function (entries) { 2866 entries.forEach(function (entry) { 2867 if (entry.isIntersecting) { 2868 entry.target.classList.add('is-visible'); 2869 obs.unobserve(entry.target); 2870 } 2871 }); 2872 }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' }); 2873 2874 document.querySelectorAll('.reveal').forEach(function (el) { 2875 obs.observe(el); 2876 }); 2877 2878 // ---- Video player: swap poster for YouTube iframe on click ---- 2879 document.querySelectorAll('.video-player[data-video-id]').forEach(function (player) { 2880 var btn = player.querySelector('.video-play-btn'); 2881 if (!btn) return; 2882 btn.addEventListener('click', function (e) { 2883 e.preventDefault(); 2884 var id = player.getAttribute('data-video-id'); 2885 var label = player.getAttribute('data-video-label') || ''; 2886 var frame = document.createElement('iframe'); 2887 frame.src = 'https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1&rel=0'; 2888 frame.title = label; 2889 frame.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'; 2890 frame.setAttribute('allowfullscreen', ''); 2891 frame.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;border:0;border-radius:inherit;'; 2892 player.appendChild(frame); 2893 // Hide the poster and overlay so iframe shows through 2894 player.querySelectorAll('.video-poster-img, .video-poster-overlay, .video-play-btn, .video-meta').forEach(function (el) { 2895 el.style.display = 'none'; 2896 }); 2897 }); 2898 }); 2899 2900 // ---- Sticky CTA â fades in after the trigger element scrolls past ---- 2901 // Bar reads data-sticky-trigger="<elementId>" off itself. If omitted, 2902 // defaults to #pricing. The bar gets .visible once the trigger has 2903 // fully scrolled above the viewport. 2904 var stickyBar = document.getElementById('stickyCta'); 2905 if (stickyBar) { 2906 var triggerId = stickyBar.getAttribute('data-sticky-trigger') || 'pricing'; 2907 var trigger = document.getElementById(triggerId); 2908 if (trigger) { 2909 var stickyObs = new IntersectionObserver(function (entries) { 2910 entries.forEach(function (entry) { 2911 var aboveViewport = !entry.isIntersecting && entry.boundingClientRect.bottom < 0; 2912 stickyBar.classList.toggle('visible', aboveViewport); 2913 stickyBar.setAttribute('aria-hidden', aboveViewport ? 'false' : 'true'); 2914 }); 2915 }, { threshold: 0, rootMargin: '0px' }); 2916 stickyObs.observe(trigger); 2917 } 2918 } 2919 2920 // ---- Home Plus benefits tabs (parent / parent-pricing / etc.) ---- 2921 document.querySelectorAll('.benefits-tabs').forEach(function (tablist) { 2922 var tabs = tablist.querySelectorAll('.benefits-tab');
2923 tabs.forEach(function (tab) { 2924 tab.addEventListener('click', function () { 2925 var key = tab.getAttribute('data-tab'); 2926 tabs.forEach(function (t) { 2927 var isActive = t === tab; 2928 t.classList.toggle('active', isActive); 2929 t.setAttribute('aria-selected', isActive ? 'true' : 'false'); 2930 }); 2931 document.querySelectorAll('.benefits-panel').forEach(function (p) { 2932 var isMatch = p.getAttribute('id') === 'benefit-panel-' + key; 2933 p.classList.toggle('active', isMatch); 2934 if (isMatch) { 2935 p.removeAttribute('hidden'); 2936 } else { 2937 p.setAttribute('hidden', ''); 2938 } 2939 }); 2940 }); 2941 }); 2942 }); 2943 })(); 2944 </script>
2944 2945 2946 <!-- HEALTH CHECK 0049835 --> 2947</body> 2948</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.