{"id":584,"date":"2026-07-21T15:48:39","date_gmt":"2026-07-21T15:48:39","guid":{"rendered":"https:\/\/freewebtools.co.in\/?page_id=584"},"modified":"2026-07-25T16:35:39","modified_gmt":"2026-07-25T16:35:39","slug":"typing-practice-2","status":"publish","type":"page","link":"https:\/\/freewebtools.co.in\/index.php\/typing-practice-2\/","title":{"rendered":"Typing Practice"},"content":{"rendered":"\n<div>\n<style>\n  @import url('https:\/\/fonts.googleapis.com\/css2?family=Quicksand:wght@500;600;700&family=Fredoka:wght@500;600&display=swap');\n\n  .tp-game-wrapper {\n    --tp-bg: #eef2f7;\n    --tp-panel-bg: #ffffff;\n    --tp-primary: #0088ff;\n    --tp-primary-hover: #0070d1;\n    --tp-accent: #22c55e;\n    --tp-accent-hover: #16a34a;\n    --tp-yellow: #f59e0b;\n    --tp-text: #1e293b;\n    --tp-text-muted: #64748b;\n    --tp-border: #cbd5e1;\n    --tp-header-blue: #29b6f6;\n    \n    font-family: 'Quicksand', sans-serif;\n    color: var(--tp-text);\n    background: #f8fafc;\n    padding: 0;\n    border-radius: 16px;\n    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);\n    box-sizing: border-box;\n    position: relative;\n    overflow: hidden;\n    width: 100%;\n    max-width: 950px;\n    margin: 0 auto;\n    border: 1px solid var(--tp-border);\n    text-align: left;\n  }\n\n  .tp-game-wrapper *, .tp-game-wrapper *::before, .tp-game-wrapper *::after {\n    box-sizing: border-box;\n  }\n\n  \/* Top Banner Bar *\/\n  .tp-game-top-bar {\n    background: linear-gradient(135deg, #1e88e5 0%, #29b6f6 100%);\n    color: white;\n    padding: 16px 24px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    border-top-left-radius: 15px;\n    border-top-right-radius: 15px;\n    flex-wrap: wrap;\n    gap: 10px;\n  }\n  .tp-game-logo-area {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n  }\n  .tp-game-brand {\n    font-family: 'Fredoka', sans-serif;\n    font-size: 1.8rem;\n    font-weight: 600;\n    letter-spacing: -0.5px;\n    margin: 0;\n    color: #fff;\n    text-shadow: 0 2px 4px rgba(0,0,0,0.1);\n  }\n  .tp-game-nav-links {\n    display: flex;\n    gap: 12px;\n    font-weight: 600;\n    font-size: 0.95rem;\n    flex-wrap: wrap;\n  }\n  .tp-game-nav-link {\n    background: rgba(255, 255, 255, 0.2);\n    padding: 6px 14px;\n    border-radius: 20px;\n    cursor: pointer;\n    transition: background 0.2s;\n  }\n  .tp-game-nav-link:hover, .tp-game-nav-link.tp-active {\n    background: rgba(255, 255, 255, 0.35);\n  }\n\n  \/* User Profile & Dashboard Header *\/\n  .tp-game-dash-header {\n    background: #ffffff;\n    padding: 20px 24px;\n    display: flex;\n    flex-wrap: wrap;\n    gap: 20px;\n    justify-content: space-between;\n    align-items: center;\n    border-bottom: 1px solid var(--tp-border);\n  }\n  .tp-game-user-profile {\n    display: flex;\n    align-items: center;\n    gap: 16px;\n  }\n  .tp-game-avatar {\n    width: 56px;\n    height: 56px;\n    background: linear-gradient(135deg, #a7f3d0 0%, #34d399 100%);\n    border-radius: 50%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 1.6rem;\n    box-shadow: 0 4px 10px rgba(52, 211, 153, 0.3);\n    border: 3px solid #fff;\n    flex-shrink: 0;\n  }\n  .tp-game-user-info h3 {\n    margin: 0 0 4px 0;\n    font-size: 1.1rem;\n    font-weight: 700;\n    color: var(--tp-text);\n  }\n  .tp-game-user-info p {\n    margin: 0;\n    font-size: 0.85rem;\n    color: var(--tp-text-muted);\n  }\n\n  .tp-game-global-stats {\n    display: flex;\n    gap: 20px;\n    flex-wrap: wrap;\n  }\n  .tp-game-gstat-item {\n    text-align: center;\n  }\n  .tp-game-gstat-label {\n    font-size: 0.75rem;\n    color: var(--tp-text-muted);\n    font-weight: 600;\n    text-transform: uppercase;\n  }\n  .tp-game-gstat-val {\n    font-size: 1.2rem;\n    font-weight: 700;\n    color: var(--tp-text);\n  }\n\n  \/* Main Layout Split - Fully Responsive Breakpoints *\/\n  .tp-game-main-layout {\n    display: grid;\n    grid-template-columns: 280px 1fr;\n    gap: 20px;\n    padding: 24px;\n  }\n  \n  @media (max-width: 900px) {\n    .tp-game-main-layout {\n      grid-template-columns: 1fr;\n      padding: 16px;\n    }\n  }\n\n  \/* Left Sidebar Curriculum *\/\n  .tp-game-sidebar {\n    display: flex;\n    flex-direction: column;\n    gap: 12px;\n  }\n  \n  @media (max-width: 900px) {\n    .tp-game-sidebar {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n      gap: 10px;\n    }\n  }\n\n  .tp-game-level-card {\n    background: #ffffff;\n    border: 1px solid var(--tp-border);\n    border-radius: 12px;\n    padding: 14px 18px;\n    cursor: pointer;\n    transition: all 0.2s;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n  }\n  .tp-game-level-card:hover {\n    border-color: var(--tp-primary);\n    box-shadow: 0 4px 12px rgba(0, 136, 255, 0.1);\n  }\n  .tp-game-level-card.tp-active {\n    background: #e0f2fe;\n    border-color: var(--tp-primary);\n    color: #0369a1;\n  }\n  .tp-game-level-title {\n    font-weight: 700;\n    font-size: 0.95rem;\n    margin: 0;\n  }\n  .tp-game-level-sub {\n    font-size: 0.75rem;\n    color: var(--tp-text-muted);\n    margin: 2px 0 0 0;\n  }\n\n  \/* Right Lesson Panel *\/\n  .tp-game-content-panel {\n    background: #ffffff;\n    border: 1px solid var(--tp-border);\n    border-radius: 16px;\n    padding: 24px;\n    box-shadow: 0 4px 15px rgba(0,0,0,0.03);\n    overflow: hidden;\n  }\n  \n  @media (max-width: 600px) {\n    .tp-game-content-panel {\n      padding: 16px;\n    }\n  }\n\n  .tp-game-panel-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 20px;\n    border-bottom: 1px solid var(--tp-border);\n    padding-bottom: 14px;\n    flex-wrap: wrap;\n    gap: 10px;\n  }\n  .tp-game-panel-title {\n    font-family: 'Fredoka', sans-serif;\n    font-size: 1.4rem;\n    margin: 0;\n    color: var(--tp-text);\n  }\n  .tp-game-progress-pill {\n    background: #f1f5f9;\n    padding: 6px 14px;\n    border-radius: 20px;\n    font-size: 0.85rem;\n    font-weight: 700;\n    color: var(--tp-primary);\n  }\n\n  \/* Lesson List Item Cards *\/\n  .tp-game-lesson-list {\n    display: flex;\n    flex-direction: column;\n    gap: 12px;\n  }\n  .tp-game-lesson-row {\n    background: #f8fafc;\n    border: 1px solid var(--tp-border);\n    border-radius: 12px;\n    padding: 16px 20px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    transition: all 0.2s;\n    flex-wrap: wrap;\n    gap: 12px;\n  }\n  .tp-game-lesson-row:hover {\n    background: #ffffff;\n    border-color: var(--tp-primary);\n    box-shadow: 0 4px 12px rgba(0,0,0,0.05);\n  }\n  .tp-game-lesson-left {\n    display: flex;\n    align-items: center;\n    gap: 16px;\n    flex: 1;\n    min-width: 200px;\n  }\n  .tp-game-lesson-num {\n    width: 32px;\n    height: 32px;\n    background: #e2e8f0;\n    border-radius: 50%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-weight: 700;\n    font-size: 0.9rem;\n    color: var(--tp-text);\n    flex-shrink: 0;\n  }\n  .tp-game-lesson-name {\n    font-weight: 700;\n    font-size: 1.05rem;\n    margin: 0 0 2px 0;\n  }\n  .tp-game-lesson-desc {\n    font-size: 0.8rem;\n    color: var(--tp-text-muted);\n    margin: 0;\n  }\n\n  \/* Buttons *\/\n  .tp-game-btn {\n    font-family: 'Fredoka', sans-serif;\n    background: var(--tp-yellow);\n    color: #fff;\n    border: none;\n    padding: 8px 22px;\n    border-radius: 8px;\n    font-weight: 600;\n    cursor: pointer;\n    transition: all 0.2s;\n    font-size: 0.95rem;\n    box-shadow: 0 4px 10px rgba(245, 158, 11, 0.3);\n    white-space: nowrap;\n  }\n  .tp-game-btn:hover {\n    transform: translateY(-2px);\n    box-shadow: 0 6px 14px rgba(245, 158, 11, 0.4);\n    background: #d97706;\n  }\n  .tp-game-btn-green {\n    background: var(--tp-accent);\n    box-shadow: 0 4px 10px rgba(34, 197, 94, 0.3);\n  }\n  .tp-game-btn-green:hover {\n    background: var(--tp-accent-hover);\n    box-shadow: 0 6px 14px rgba(34, 197, 94, 0.4);\n  }\n  .tp-game-btn-secondary {\n    background: #e2e8f0;\n    color: var(--tp-text);\n    box-shadow: none;\n  }\n  .tp-game-btn-secondary:hover {\n    background: #cbd5e1;\n  }\n\n  \/* Active Typing Arena View *\/\n  .tp-game-active-arena {\n    display: none;\n  }\n  .tp-game-active-arena.tp-show {\n    display: block;\n  }\n  \n  .tp-game-text-display {\n    background: #f8fafc;\n    border: 2px solid var(--tp-border);\n    border-radius: 12px;\n    padding: 20px;\n    font-size: 1.3rem;\n    line-height: 1.9;\n    font-family: monospace;\n    min-height: 140px;\n    max-height: 200px;\n    overflow-y: auto;\n    margin-bottom: 20px;\n    user-select: none;\n    word-break: break-word;\n  }\n  \n  @media (max-width: 600px) {\n    .tp-game-text-display {\n      font-size: 1.1rem;\n      padding: 14px;\n    }\n  }\n\n  .tp-game-char {\n    color: #94a3b8;\n    position: relative;\n    transition: color 0.1s;\n  }\n  .tp-game-char.tp-correct {\n    color: var(--tp-accent);\n    font-weight: bold;\n  }\n  .tp-game-char.tp-incorrect {\n    color: #ef4444;\n    background: rgba(239, 68, 68, 0.15);\n    border-radius: 2px;\n  }\n  .tp-game-char.tp-current {\n    border-bottom: 3px solid var(--tp-primary);\n    background: rgba(0, 136, 255, 0.1);\n  }\n\n  .tp-game-hidden-input {\n    position: absolute;\n    opacity: 0;\n    pointer-events: none;\n    width: 1px;\n    height: 1px;\n  }\n\n  \/* Live HUD Grid inside Active Arena *\/\n  .tp-game-metrics-grid {\n    display: grid;\n    grid-template-columns: repeat(4, 1fr);\n    gap: 12px;\n    margin-bottom: 20px;\n  }\n  \n  @media (max-width: 600px) {\n    .tp-game-metrics-grid {\n      grid-template-columns: repeat(2, 1fr);\n      gap: 8px;\n    }\n  }\n\n  .tp-game-metric-card {\n    background: #f8fafc;\n    border: 1px solid var(--tp-border);\n    border-radius: 10px;\n    padding: 10px;\n    text-align: center;\n  }\n  .tp-game-metric-title {\n    font-size: 0.75rem;\n    color: var(--tp-text-muted);\n    text-transform: uppercase;\n    font-weight: 600;\n  }\n  .tp-game-metric-val {\n    font-size: 1.2rem;\n    font-weight: 700;\n    color: var(--tp-primary);\n  }\n\n  \/* Result Modal *\/\n  .tp-game-modal {\n    position: absolute;\n    inset: 0;\n    background: rgba(15, 23, 42, 0.75);\n    backdrop-filter: blur(4px);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    z-index: 100;\n    opacity: 0;\n    pointer-events: none;\n    transition: opacity 0.3s ease;\n    border-radius: 16px;\n    padding: 16px;\n  }\n  .tp-game-modal.tp-show {\n    opacity: 1;\n    pointer-events: auto;\n  }\n  .tp-game-modal-content {\n    background: #ffffff;\n    border-radius: 16px;\n    padding: 28px;\n    width: 100%;\n    max-width: 420px;\n    text-align: center;\n    box-shadow: 0 20px 40px rgba(0,0,0,0.2);\n    transform: scale(0.9);\n    transition: transform 0.3s ease;\n  }\n  .tp-game-modal.tp-show .tp-game-modal-content {\n    transform: scale(1);\n  }\n  .tp-game-modal-title {\n    font-family: 'Fredoka', sans-serif;\n    font-size: 1.8rem;\n    margin-bottom: 16px;\n    color: var(--tp-accent);\n  }\n  .tp-game-result-grid {\n    display: grid;\n    grid-template-columns: repeat(2, 1fr);\n    gap: 12px;\n    margin-bottom: 24px;\n  }\n  .tp-game-result-item {\n    background: #f8fafc;\n    border: 1px solid var(--tp-border);\n    padding: 12px;\n    border-radius: 10px;\n  }\n  .tp-game-result-label {\n    font-size: 0.8rem;\n    color: var(--tp-text-muted);\n    font-weight: 600;\n  }\n  .tp-game-result-val {\n    font-size: 1.4rem;\n    font-weight: 700;\n    color: var(--tp-text);\n  }\n\n  \/* Focus Overlay *\/\n  .tp-game-focus-overlay {\n    position: absolute;\n    inset: 0;\n    background: rgba(255, 255, 255, 0.88);\n    backdrop-filter: blur(2px);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    z-index: 10;\n    border-radius: 12px;\n    cursor: pointer;\n    font-weight: 700;\n    color: var(--tp-primary);\n    font-size: 1rem;\n    transition: opacity 0.2s;\n    text-align: center;\n    padding: 0 15px;\n  }\n  .tp-game-focus-overlay.tp-hidden {\n    opacity: 0;\n    pointer-events: none;\n  }\n\n  .tp-game-confetti-container {\n    position: absolute;\n    inset: 0;\n    pointer-events: none;\n    overflow: hidden;\n    z-index: 101;\n  }\n  .tp-game-confetti {\n    position: absolute;\n    width: 8px;\n    height: 8px;\n    background: #34d399;\n    animation: tp-fall 1.5s linear forwards;\n  }\n  @keyframes tp-fall {\n    0% { transform: translateY(-20px) rotate(0deg); opacity: 1; }\n    100% { transform: translateY(400px) rotate(720deg); opacity: 0; }\n  }\n<\/style>\n\n<div class=\"tp-game-wrapper\" id=\"tp-game-main-container\">\n  \n  <!-- Top Brand Navigation Bar -->\n  <div class=\"tp-game-top-bar\">\n    <div class=\"tp-game-logo-area\">\n      <h1 class=\"tp-game-brand\">typing.academy<\/h1>\n    <\/div>\n    <div class=\"tp-game-nav-links\">\n      <span class=\"tp-game-nav-link tp-active\" id=\"tp-game-nav-lessons\">Lessons<\/span>\n      <span class=\"tp-game-nav-link\" id=\"tp-game-nav-sound\" style=\"cursor: pointer;\">Sound: ON<\/span>\n    <\/div>\n  <\/div>\n\n  <!-- Dashboard Overview Header -->\n  <div class=\"tp-game-dash-header\">\n    <div class=\"tp-game-user-profile\">\n      <div class=\"tp-game-avatar\">\ud83c\udf31<\/div>\n      <div class=\"tp-game-user-info\">\n        <h3>Typing Seedling (Level 1)<\/h3>\n        <p>Master your keyboard layout step by step<\/p>\n      <\/div>\n    <\/div>\n    <div class=\"tp-game-global-stats\">\n      <div class=\"tp-game-gstat-item\">\n        <div class=\"tp-game-gstat-label\">Avg. Speed<\/div>\n        <div class=\"tp-game-gstat-val\" id=\"tp-game-stat-wpm\">&#8212; WPM<\/div>\n      <\/div>\n      <div class=\"tp-game-gstat-item\">\n        <div class=\"tp-game-gstat-label\">Avg. Acc.<\/div>\n        <div class=\"tp-game-gstat-val\" id=\"tp-game-stat-acc\">&#8211;%<\/div>\n      <\/div>\n      <div class=\"tp-game-gstat-item\">\n        <div class=\"tp-game-gstat-label\">Completed<\/div>\n        <div class=\"tp-game-gstat-val\" id=\"tp-game-stat-completed\">0 \/ 5<\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- Main Content Split -->\n  <div class=\"tp-game-main-layout\">\n    \n    <!-- Sidebar Course Levels -->\n    <div class=\"tp-game-sidebar\">\n      <div class=\"tp-game-level-card tp-active\" data-level=\"beginner\">\n        <div>\n          <p class=\"tp-game-level-title\">Beginner<\/p>\n          <p class=\"tp-game-level-sub\">Home row keys &#038; basics<\/p>\n        <\/div>\n        <span>\u27a1\ufe0f<\/span>\n      <\/div>\n      <div class=\"tp-game-level-card\" data-level=\"intermediate\">\n        <div>\n          <p class=\"tp-game-level-title\">Intermediate<\/p>\n          <p class=\"tp-game-level-sub\">Full keyboard sentences<\/p>\n        <\/div>\n        <span>\ud83d\udd12<\/span>\n      <\/div>\n      <div class=\"tp-game-level-card\" data-level=\"advanced\">\n        <div>\n          <p class=\"tp-game-level-title\">Advanced<\/p>\n          <p class=\"tp-game-level-sub\">Complex paragraphs &#038; symbols<\/p>\n        <\/div>\n        <span>\ud83d\udd12<\/span>\n      <\/div>\n    <\/div>\n\n    <!-- Right Panel Container -->\n    <div class=\"tp-game-content-panel\">\n      \n      <!-- Lessons View Mode -->\n      <div id=\"tp-game-lessons-view\">\n        <div class=\"tp-game-panel-header\">\n          <h2 class=\"tp-game-panel-title\" id=\"tp-game-section-title\">Getting Started<\/h2>\n          <span class=\"tp-game-progress-pill\" id=\"tp-game-completion-pill\">0% Complete<\/span>\n        <\/div>\n\n        <div class=\"tp-game-lesson-list\" id=\"tp-game-lesson-container\">\n          <!-- Populated via JS -->\n        <\/div>\n      <\/div>\n\n      <!-- Active Typing Practice View -->\n      <div class=\"tp-game-active-arena\" id=\"tp-game-active-arena\">\n        <div class=\"tp-game-panel-header\">\n          <h2 class=\"tp-game-panel-title\" id=\"tp-game-active-title\">Lesson Practice<\/h2>\n          <button class=\"tp-game-btn tp-game-btn-secondary\" id=\"tp-game-back-to-lessons\" style=\"padding: 6px 14px; font-size: 0.85rem;\">\u2b05 Back to Lessons<\/button>\n        <\/div>\n\n        <div style=\"position: relative;\">\n          <div class=\"tp-game-text-display\" id=\"tp-game-text-display\">\n            <!-- Dynamic character display -->\n          <\/div>\n          <div class=\"tp-game-focus-overlay\" id=\"tp-game-focus-overlay\">Tap or click here to start typing!<\/div>\n          <input type=\"text\" class=\"tp-game-hidden-input\" id=\"tp-game-hidden-input\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\">\n        <\/div>\n\n        <div class=\"tp-game-metrics-grid\">\n          <div class=\"tp-game-metric-card\">\n            <div class=\"tp-game-metric-title\">Speed<\/div>\n            <div class=\"tp-game-metric-val\" id=\"tp-game-live-wpm\">0 WPM<\/div>\n          <\/div>\n          <div class=\"tp-game-metric-card\">\n            <div class=\"tp-game-metric-title\">Accuracy<\/div>\n            <div class=\"tp-game-metric-val\" id=\"tp-game-live-accuracy\">100%<\/div>\n          <\/div>\n          <div class=\"tp-game-metric-card\">\n            <div class=\"tp-game-metric-title\">Mistakes<\/div>\n            <div class=\"tp-game-metric-val\" id=\"tp-game-live-mistakes\" style=\"color: #ef4444;\">0<\/div>\n          <\/div>\n          <div class=\"tp-game-metric-card\">\n            <div class=\"tp-game-metric-title\">Time<\/div>\n            <div class=\"tp-game-metric-val\" id=\"tp-game-live-timer\">0s<\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n    <\/div>\n\n  <\/div>\n\n  <!-- Result Modal -->\n  <div class=\"tp-game-modal\" id=\"tp-game-result-modal\">\n    <div class=\"tp-game-modal-content\">\n      <div class=\"tp-game-modal-title\">\ud83c\udf89 Lesson Completed!<\/div>\n      <div class=\"tp-game-result-grid\">\n        <div class=\"tp-game-result-item\">\n          <div class=\"tp-game-result-label\">Speed<\/div>\n          <div class=\"tp-game-result-val\" id=\"tp-game-res-wpm\">0 WPM<\/div>\n        <\/div>\n        <div class=\"tp-game-result-item\">\n          <div class=\"tp-game-result-label\">Accuracy<\/div>\n          <div class=\"tp-game-result-val\" id=\"tp-game-res-acc\" style=\"color: var(--tp-accent);\">0%<\/div>\n        <\/div>\n      <\/div>\n      <button class=\"tp-game-btn tp-game-btn-green\" id=\"tp-game-modal-next\" style=\"width: 100%; padding: 12px; font-size: 1.05rem;\">Continue to Next Lesson<\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"tp-game-confetti-container\" id=\"tp-game-confetti-container\"><\/div>\n\n<\/div>\n\n<script>\n(function() {\n  'use strict';\n\n  const curriculum = {\n    beginner: {\n      title: \"Getting Started (Beginner)\",\n      lessons: [\n        { id: 1, name: \"J, F, and Space\", desc: \"Master your index fingers on the home row\", text: \"jjj fff jf jf jf jjj fff space jf jf\" },\n        { id: 2, name: \"U, R, and K Keys\", desc: \"Introduce upper and side home extensions\", text: \"jk uj rk ur kr ju rk uj kr ur\" },\n        { id: 3, name: \"D, E, and I Keys\", desc: \"Expand your finger reach across rows\", text: \"de id ed di ki rd ej di ke id\" },\n        { id: 4, name: \"C, G, and N Keys\", desc: \"Practice building steady rhythm\", text: \"cg nc gn cn gc ng cn gc nc\" },\n        { id: 5, name: \"Beginner Review 1\", desc: \"Comprehensive review of all learned keys\", text: \"jf uk de cn jf uk de cn jf uk de cn\" }\n      ]\n    },\n    intermediate: {\n      title: \"Sentence Builder (Intermediate)\",\n      lessons: [\n        { id: 6, name: \"Common Word Patterns\", desc: \"Build finger muscle memory with frequent words\", text: \"the quick brown fox jumps over the lazy dog\" },\n        { id: 7, name: \"Everyday Sentences\", desc: \"Practice typing flowing natural sentences\", text: \"practice makes perfect when you type every single day with care\" },\n        { id: 8, name: \"Speed & Flow\", desc: \"Maintain steady cadence without looking down\", text: \"smooth typing beats fast chaotic keystrokes every single time\" }\n      ]\n    },\n    advanced: {\n      title: \"Coding & Mastery (Advanced)\",\n      lessons: [\n        { id: 9, name: \"Programming Symbols\", desc: \"Special characters and functional statements\", text: \"function calculate(a, b) { return a + b; }\" },\n        { id: 10, name: \"Advanced Paragraphs\", desc: \"Complex technical vocabulary challenge\", text: \"asynchronous event driven architectures scale gracefully under heavy loads\" }\n      ]\n    }\n  };\n\n  let currentCategory = 'beginner';\n  let activeLessonIndex = 0;\n  let currentText = '';\n  let charList = [];\n  let currentIndex = 0;\n  let correctCount = 0;\n  let wrongCount = 0;\n  let startTime = null;\n  let timerInterval = null;\n  let soundOn = true;\n  let audioCtx = null;\n\n  function getStats() {\n    try {\n      const data = localStorage.getItem('tp_academy_data');\n      if (data) return JSON.parse(data);\n    } catch(e) {}\n    return { completedLessons: [], bestWpm: 0, bestAcc: 0 };\n  }\n\n  function saveStats(stats) {\n    try {\n      localStorage.setItem('tp_academy_data', JSON.stringify(stats));\n    } catch(e) {}\n  }\n\n  const container = document.getElementById('tp-game-main-container');\n  const lessonsView = container.querySelector('#tp-game-lessons-view');\n  const activeArena = container.querySelector('#tp-game-active-arena');\n  const lessonContainer = container.querySelector('#tp-game-lesson-container');\n  const sectionTitle = container.querySelector('#tp-game-section-title');\n  const completionPill = container.querySelector('#tp-game-completion-pill');\n  \n  const textDisplay = container.querySelector('#tp-game-text-display');\n  const hiddenInput = container.querySelector('#tp-game-hidden-input');\n  const focusOverlay = container.querySelector('#tp-game-focus-overlay');\n  \n  const liveWpm = container.querySelector('#tp-game-live-wpm');\n  const liveAccuracy = container.querySelector('#tp-game-live-accuracy');\n  const liveMistakes = container.querySelector('#tp-game-live-mistakes');\n  const liveTimer = container.querySelector('#tp-game-live-timer');\n  \n  const statWpm = container.querySelector('#tp-game-stat-wpm');\n  const statAcc = container.querySelector('#tp-game-stat-acc');\n  const statCompleted = container.querySelector('#tp-game-stat-completed');\n  \n  const resultModal = container.querySelector('#tp-game-result-modal');\n  const resWpm = container.querySelector('#tp-game-res-wpm');\n  const resAcc = container.querySelector('#tp-game-res-acc');\n  const modalNext = container.querySelector('#tp-game-modal-next');\n  const backBtn = container.querySelector('#tp-game-back-to-lessons');\n  const soundToggle = container.querySelector('#tp-game-nav-sound');\n  const confettiContainer = container.querySelector('#tp-game-confetti-container');\n\n  function initAudio() {\n    if (!audioCtx) {\n      const AudioContext = window.AudioContext || window.webkitAudioContext;\n      if (AudioContext) audioCtx = new AudioContext();\n    }\n  }\n\n  function playBeep(correct) {\n    if (!soundOn || !audioCtx) return;\n    try {\n      if (audioCtx.state === 'suspended') audioCtx.resume();\n      const osc = audioCtx.createOscillator();\n      const gain = audioCtx.createGain();\n      osc.connect(gain);\n      gain.connect(audioCtx.destination);\n      const now = audioCtx.currentTime;\n      if (correct) {\n        osc.frequency.setValueAtTime(600, now);\n        gain.gain.setValueAtTime(0.03, now);\n        gain.gain.exponentialRampToValueAtTime(0.001, now + 0.04);\n        osc.start(now);\n        osc.stop(now + 0.04);\n      } else {\n        osc.type = 'sawtooth';\n        osc.frequency.setValueAtTime(180, now);\n        gain.gain.setValueAtTime(0.05, now);\n        gain.gain.exponentialRampToValueAtTime(0.001, now + 0.08);\n        osc.start(now);\n        osc.stop(now + 0.08);\n      }\n    } catch(e) {}\n  }\n\n  function renderDashboard() {\n    const stats = getStats();\n    const lessons = curriculum[currentCategory].lessons;\n    sectionTitle.textContent = curriculum[currentCategory].title;\n\n    const completedInCat = lessons.filter(l => stats.completedLessons.includes(currentCategory + '-' + l.id)).length;\n    const percent = Math.round((completedInCat \/ lessons.length) * 100);\n    completionPill.textContent = percent + '% Complete';\n\n    statWpm.textContent = stats.bestWpm ? stats.bestWpm + ' WPM' : '-- WPM';\n    statAcc.textContent = stats.bestAcc ? stats.bestAcc + '%' : '--%';\n    statCompleted.textContent = stats.completedLessons.length + ' Total';\n\n    lessonContainer.innerHTML = lessons.map((lesson, idx) => {\n      const isDone = stats.completedLessons.includes(currentCategory + '-' + lesson.id);\n      return `\n        <div class=\"tp-game-lesson-row\">\n          <div class=\"tp-game-lesson-left\">\n            <div class=\"tp-game-lesson-num\" style=\"background: ${isDone ? '#dcfce7' : '#e2e8f0'}; color: ${isDone ? '#16a34a' : 'inherit'}\">${isDone ? '\u2713' : (idx + 1)}<\/div>\n            <div>\n              <p class=\"tp-game-lesson-name\">${lesson.name}<\/p>\n              <p class=\"tp-game-lesson-desc\">${lesson.desc}<\/p>\n            <\/div>\n          <\/div>\n          <button class=\"tp-game-btn ${isDone ? 'tp-game-btn-green' : ''}\" data-cat=\"${currentCategory}\" data-idx=\"${idx}\">\n            ${isDone ? 'Practice' : 'Start'}\n          <\/button>\n        <\/div>\n      `;\n    }).join('');\n\n    lessonContainer.querySelectorAll('button').forEach(btn => {\n      btn.addEventListener('click', (e) => {\n        const cat = e.target.getAttribute('data-cat');\n        const index = parseInt(e.target.getAttribute('data-idx'), 10);\n        startLesson(cat, index);\n      });\n    });\n  }\n\n  function startLesson(cat, idx) {\n    initAudio();\n    currentCategory = cat;\n    activeLessonIndex = idx;\n    const lesson = curriculum[cat].lessons[idx];\n    currentText = lesson.text;\n    charList = currentText.split('');\n    currentIndex = 0;\n    correctCount = 0;\n    wrongCount = 0;\n\n    textDisplay.innerHTML = charList.map((ch, i) => `<span class=\"tp-game-char ${i === 0 ? 'tp-current' : ''}\">${ch === ' ' ? '&nbsp;': escapeHtml(ch)}<\/span>`).join('');\n    textDisplay.scrollTop = 0;\n\n    lessonsView.style.display = 'none';\n    activeArena.classList.add('tp-show');\n    \n    hiddenInput.value = '';\n    hiddenInput.focus();\n    focusOverlay.classList.remove('tp-hidden');\n    focusOverlay.textContent = 'Tap or click here to start typing!';\n\n    liveWpm.textContent = '0 WPM';\n    liveAccuracy.textContent = '100%';\n    liveMistakes.textContent = '0';\n    liveTimer.textContent = '0s';\n\n    clearInterval(timerInterval);\n    startTime = null;\n  }\n\n  function escapeHtml(str) {\n    return str.replace(\/&\/g, \"&amp;\").replace(\/<\/g, \"&lt;\").replace(\/>\/g, \"&gt;\");\n  }\n\n  function beginTimer() {\n    if (startTime) return;\n    startTime = Date.now();\n    timerInterval = setInterval(() => {\n      const elapsedSec = Math.floor((Date.now() - startTime) \/ 1000);\n      liveTimer.textContent = elapsedSec + 's';\n      \n      const elapsedMin = elapsedSec \/ 60;\n      if (elapsedMin > 0) {\n        const wpm = Math.round((correctCount \/ 5) \/ elapsedMin);\n        liveWpm.textContent = Math.max(0, wpm) + ' WPM';\n      }\n    }, 1000);\n  }\n\n  hiddenInput.addEventListener('input', () => {\n    if (!startTime) beginTimer();\n    const typed = hiddenInput.value;\n    hiddenInput.value = '';\n\n    for (let i = 0; i < typed.length; i++) {\n      if (currentIndex >= charList.length) break;\n      const target = charList[currentIndex];\n      const span = textDisplay.children[currentIndex];\n\n      if (typed[i] === target) {\n        span.className = 'tp-game-char tp-correct';\n        correctCount++;\n        playBeep(true);\n      } else {\n        span.className = 'tp-game-char tp-incorrect';\n        wrongCount++;\n        playBeep(false);\n      }\n      currentIndex++;\n\n      if (currentIndex < charList.length) {\n        textDisplay.children[currentIndex].classList.add('tp-current');\n      }\n    }\n\n    const totalTyped = correctCount + wrongCount;\n    const acc = totalTyped > 0 ? Math.round((correctCount \/ totalTyped) * 100) : 100;\n    liveAccuracy.textContent = acc + '%';\n    liveMistakes.textContent = wrongCount;\n\n    if (currentIndex < charList.length) {\n      const activeSpan = textDisplay.children[currentIndex];\n      if (activeSpan) {\n        textDisplay.scrollTop = activeSpan.offsetTop - textDisplay.offsetTop - 30;\n      }\n    }\n\n    if (currentIndex >= charList.length) {\n      finishLesson();\n    }\n  });\n\n  hiddenInput.addEventListener('keydown', (e) => {\n    if (!startTime) beginTimer();\n    if (e.key === 'Backspace') {\n      e.preventDefault();\n      if (currentIndex > 0) {\n        currentIndex--;\n        textDisplay.children[currentIndex].className = 'tp-game-char tp-current';\n        if (currentIndex + 1 < charList.length) {\n          textDisplay.children[currentIndex + 1].classList.remove('tp-current');\n        }\n      }\n    }\n  });\n\n  function finishLesson() {\n    clearInterval(timerInterval);\n    const elapsedSec = Math.max(1, Math.floor((Date.now() - startTime) \/ 1000));\n    const elapsedMin = elapsedSec \/ 60;\n    const finalWpm = Math.round((correctCount \/ 5) \/ elapsedMin);\n    const totalTyped = correctCount + wrongCount;\n    const finalAcc = totalTyped > 0 ? Math.round((correctCount \/ totalTyped) * 100) : 100;\n\n    resWpm.textContent = finalWpm + ' WPM';\n    resAcc.textContent = finalAcc + '%';\n    resultModal.classList.add('tp-show');\n    triggerConfetti();\n\n    const stats = getStats();\n    const lessonKey = currentCategory + '-' + curriculum[currentCategory].lessons[activeLessonIndex].id;\n    if (!stats.completedLessons.includes(lessonKey)) {\n      stats.completedLessons.push(lessonKey);\n    }\n    if (finalWpm > stats.bestWpm) stats.bestWpm = finalWpm;\n    if (finalAcc > stats.bestAcc) stats.bestAcc = finalAcc;\n    saveStats(stats);\n  }\n\n  function triggerConfetti() {\n    confettiContainer.innerHTML = '';\n    const colors = ['#22c55e', '#0088ff', '#f59e0b', '#38bdf8', '#a855f7'];\n    for (let i = 0; i < 50; i++) {\n      const conf = document.createElement('div');\n      conf.className = 'tp-game-confetti';\n      conf.style.left = Math.random() * 100 + '%';\n      conf.style.top = '-10px';\n      conf.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];\n      conf.style.animationDuration = (Math.random() * 1 + 1) + 's';\n      confettiContainer.appendChild(conf);\n    }\n    setTimeout(() => confettiContainer.innerHTML = '', 2000);\n  }\n\n  container.querySelectorAll('.tp-game-level-card').forEach(card => {\n    card.addEventListener('click', (e) => {\n      container.querySelectorAll('.tp-game-level-card').forEach(c => c.classList.remove('tp-active'));\n      const targetCard = e.currentTarget;\n      targetCard.classList.add('tp-active');\n      currentCategory = targetCard.getAttribute('data-level');\n      renderDashboard();\n    });\n  });\n\n  backBtn.addEventListener('click', () => {\n    activeArena.classList.remove('tp-show');\n    lessonsView.style.display = 'block';\n    renderDashboard();\n  });\n\n  modalNext.addEventListener('click', () => {\n    resultModal.classList.remove('tp-show');\n    const lessons = curriculum[currentCategory].lessons;\n    if (activeLessonIndex + 1 < lessons.length) {\n      startLesson(currentCategory, activeLessonIndex + 1);\n    } else {\n      activeArena.classList.remove('tp-show');\n      lessonsView.style.display = 'block';\n      renderDashboard();\n    }\n  });\n\n  focusOverlay.addEventListener('click', () => {\n    hiddenInput.focus();\n    focusOverlay.classList.add('tp-hidden');\n  });\n\n  soundToggle.addEventListener('click', () => {\n    soundOn = !soundOn;\n    soundToggle.textContent = soundOn ? 'Sound: ON' : 'Sound: OFF';\n  });\n\n  renderDashboard();\n\n})();\n<\/script>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>typing.academy Lessons Sound: ON \ud83c\udf31 Typing Seedling (Level 1) Master your keyboard layout step by step Avg. Speed &#8212; WPM Avg. Acc. &#8211;% Completed 0 \/ 5 Beginner Home row keys &#038; basics \u27a1\ufe0f Intermediate Full keyboard sentences \ud83d\udd12 Advanced Complex paragraphs &#038; symbols \ud83d\udd12 Getting Started 0% Complete Lesson Practice \u2b05 Back to Lessons [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-584","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/comments?post=584"}],"version-history":[{"count":2,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/584\/revisions"}],"predecessor-version":[{"id":586,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/584\/revisions\/586"}],"wp:attachment":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/media?parent=584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}