Created
June 9, 2026 08:10
-
-
Save shahidcodes/58da208000e34c6fb9ff677ad0cc7533 to your computer and use it in GitHub Desktop.
PP-Idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PainFree — App Concept</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600;9..40,700&family=Instrument+Serif:ital@0;1&display=swap" rel="stylesheet"> | |
| <style> | |
| :root{ | |
| --bg:#FAF7F2;--white:#FFFFFF;--dim:#F2EEE7; | |
| --primary:#3D7B6F;--primary-d:#2D6258;--primary-l:#E4F0EC; | |
| --accent:#D47B5B;--accent-l:#FDF0EC; | |
| --text:#1A1816;--t2:#6B6560;--t3:#A9A39D; | |
| --line:#EBE6DF;--green:#4A9E6F;--red:#C85A4A;--amber:#D4A34A; | |
| } | |
| *{margin:0;padding:0;box-sizing:border-box} | |
| body{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#111010;font-family:'DM Sans',sans-serif;color:var(--text);padding:20px} | |
| /* ── Demo Frame ── */ | |
| .demo-head{text-align:center;margin-bottom:24px} | |
| .demo-head h1{font-family:'Instrument Serif',serif;font-size:28px;color:#E8E4DE;font-weight:400} | |
| .demo-head p{font-size:12px;color:#6B6560;margin-top:4px;letter-spacing:1.5px;text-transform:uppercase;font-weight:500} | |
| /* ── Phone ── */ | |
| .phone{width:390px;height:844px;background:var(--bg);border-radius:50px;position:relative;overflow:hidden;box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.06),0 0 0 3px #1E1C1A,0 40px 80px rgba(0,0,0,.5);flex-shrink:0} | |
| .phone::after{content:'';position:absolute;bottom:9px;left:50%;transform:translateX(-50%);width:134px;height:4.5px;background:rgba(0,0,0,.14);border-radius:3px;z-index:999;pointer-events:none} | |
| .island{position:absolute;top:10px;left:50%;transform:translateX(-50%);width:124px;height:35px;background:#000;border-radius:18px;z-index:999} | |
| /* ── Status Bar ── */ | |
| .sbar{height:54px;display:flex;align-items:center;justify-content:space-between;padding:0 30px;font-size:15px;font-weight:600;position:relative;z-index:10} | |
| .sb-r{display:flex;align-items:center;gap:6px} | |
| .sb-r svg{height:12px} | |
| .bat{width:24px;height:11px;border:1.5px solid var(--text);border-radius:3px;display:flex;align-items:center;padding:1.5px;position:relative} | |
| .bat::after{content:'';position:absolute;right:-3.5px;top:2.5px;width:2px;height:4.5px;background:var(--text);border-radius:0 1px 1px 0} | |
| .bat-f{width:72%;height:100%;background:var(--text);border-radius:1px} | |
| /* ── Screens Container ── */ | |
| .scrs{position:absolute;top:54px;left:0;right:0;bottom:0} | |
| .scr{position:absolute;inset:0;overflow-y:auto;opacity:0;pointer-events:none;transform:translateY(5px);transition:opacity .3s,transform .3s;-webkit-overflow-scrolling:touch;scrollbar-width:none} | |
| .scr::-webkit-scrollbar{display:none} | |
| .scr.on{opacity:1;pointer-events:auto;transform:translateY(0)} | |
| .si{padding:14px 22px 100px} | |
| /* ── Tab Bar ── */ | |
| .tbar{position:absolute;bottom:0;left:0;right:0;display:flex;justify-content:space-around;padding:6px 4px 28px;background:rgba(250,247,242,.88);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-top:1px solid var(--line);z-index:50;transition:opacity .3s,transform .3s} | |
| .tbar.hide{opacity:0;transform:translateY(10px);pointer-events:none} | |
| .tbtn{display:flex;flex-direction:column;align-items:center;gap:3px;border:none;background:none;cursor:pointer;padding:5px 14px;color:var(--t3);transition:color .2s;font-family:inherit} | |
| .tbtn svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round} | |
| .tbtn span{font-size:10px;font-weight:600;letter-spacing:.3px} | |
| .tbtn.on{color:var(--primary)} | |
| .tbtn.on svg{stroke-width:2.3} | |
| /* ── Shared Components ── */ | |
| .card{background:var(--white);border-radius:18px;padding:18px;border:1px solid var(--line)} | |
| .btn{width:100%;padding:16px;border-radius:14px;border:none;font-family:'DM Sans',sans-serif;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s;letter-spacing:.2px} | |
| .btn-p{background:var(--primary);color:#fff} | |
| .btn-p:hover:not(:disabled){background:var(--primary-d);transform:translateY(-1px);box-shadow:0 6px 20px rgba(61,123,111,.3)} | |
| .btn-p:disabled{background:var(--t3);cursor:default} | |
| .btn-g{background:var(--dim);color:var(--t2);border:1px solid var(--line)} | |
| .btn-g:hover{background:var(--line)} | |
| .sec-h{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:14px} | |
| .sec-h h2{font-family:'Instrument Serif',serif;font-size:20px;font-weight:400} | |
| .sec-h .dur{font-size:13px;color:var(--t3);font-weight:500} | |
| /* ── Stagger Animations ── */ | |
| [data-a]{opacity:0} | |
| .scr.on [data-a]{animation:fu .45s ease both} | |
| .scr.on [data-a="1"]{animation-delay:.04s} | |
| .scr.on [data-a="2"]{animation-delay:.1s} | |
| .scr.on [data-a="3"]{animation-delay:.16s} | |
| .scr.on [data-a="4"]{animation-delay:.22s} | |
| .scr.on [data-a="5"]{animation-delay:.28s} | |
| .scr.on [data-a="6"]{animation-delay:.34s} | |
| .scr.on [data-a="7"]{animation-delay:.4s} | |
| @keyframes fu{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}} | |
| /* ═══════════════════════════════════ | |
| ONBOARDING | |
| ═══════════════════════════════════ */ | |
| .ob-head{text-align:center;margin-bottom:2px} | |
| .ob-head h1{font-family:'Instrument Serif',serif;font-size:28px;font-weight:400;line-height:1.15} | |
| .ob-head .sub{color:var(--t2);font-size:15px;margin-top:6px} | |
| .body-wrap{display:flex;justify-content:center;height:310px;position:relative;margin:6px 0} | |
| .body-svg{height:100%;width:auto} | |
| .body-svg path,.body-svg line,.body-svg circle.base{fill:none;stroke:#C4BDB4;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round} | |
| .hs{fill:transparent;stroke:transparent;stroke-width:2.5;cursor:pointer;transition:fill .25s,stroke .25s,filter .25s} | |
| .hs:hover{fill:rgba(61,123,111,.1);stroke:rgba(61,123,111,.3)} | |
| .hs.sel{fill:rgba(61,123,111,.22);stroke:var(--primary);filter:drop-shadow(0 0 8px rgba(61,123,111,.3))} | |
| .chips{display:flex;flex-wrap:wrap;gap:8px;min-height:36px;justify-content:center;margin:8px 0 22px} | |
| .chip{background:var(--primary-l);color:var(--primary-d);font-size:12px;font-weight:600;padding:6px 12px 6px 14px;border-radius:20px;animation:chipIn .25s ease;display:flex;align-items:center;gap:6px} | |
| .chip button{width:16px;height:16px;background:rgba(61,123,111,.18);border:none;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--primary-d);line-height:1;font-family:inherit} | |
| @keyframes chipIn{from{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}} | |
| .ob-foot{padding:0 0 10px} | |
| /* ═══════════════════════════════════ | |
| HOME | |
| ═══════════════════════════════════ */ | |
| .hdr{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:18px} | |
| .greet{color:var(--t2);font-size:14px;font-weight:500;margin-bottom:2px} | |
| .hdr h1{font-family:'Instrument Serif',serif;font-size:28px;font-weight:400} | |
| .strk{background:linear-gradient(135deg,#FFF3E0,#FFE0B2);padding:8px 14px;border-radius:14px;font-weight:700;font-size:15px;color:#E65100;display:flex;align-items:center;gap:4px;box-shadow:0 2px 8px rgba(230,81,0,.1)} | |
| .chk{background:linear-gradient(135deg,var(--primary),var(--primary-d));border:none;border-radius:20px;padding:20px 20px 18px;margin-bottom:16px;color:#fff} | |
| .chk-t{font-size:16px;font-weight:600;margin-bottom:14px} | |
| .pain-sc{display:flex;gap:6px;flex-wrap:wrap} | |
| .pn{width:30px;height:30px;border-radius:50%;border:1.5px solid rgba(255,255,255,.3);background:rgba(255,255,255,.08);color:rgba(255,255,255,.65);font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;font-family:inherit} | |
| .pn:hover{background:rgba(255,255,255,.18)} | |
| .pn.sel{background:#fff;color:var(--primary-d);border-color:#fff;transform:scale(1.12)} | |
| .start-card{background:var(--white);border:1.5px solid var(--primary-l);border-radius:18px;padding:18px 20px;margin-bottom:20px;cursor:pointer;transition:border-color .2s,transform .15s,box-shadow .2s;display:flex;align-items:center;gap:16px} | |
| .start-card:hover{border-color:var(--primary);transform:translateY(-1px);box-shadow:0 4px 16px rgba(61,123,111,.1)} | |
| .play-btn{width:48px;height:48px;border-radius:14px;background:var(--primary);display:flex;align-items:center;justify-content:center;flex-shrink:0} | |
| .play-btn svg{width:20px;height:20px;fill:#fff;margin-left:2px} | |
| .start-info h3{font-size:15px;font-weight:600;margin-bottom:3px} | |
| .start-info p{font-size:13px;color:var(--t3);font-weight:400} | |
| .ex-item{display:flex;align-items:center;gap:14px;padding:13px 16px;background:var(--white);border-radius:16px;border:1px solid var(--line);margin-bottom:9px;cursor:pointer;transition:border-color .2s,transform .15s} | |
| .ex-item:hover{border-color:var(--primary);transform:translateX(3px)} | |
| .ex-n{width:36px;height:36px;border-radius:12px;background:var(--primary-l);color:var(--primary);font-weight:700;font-size:14px;display:flex;align-items:center;justify-content:center;flex-shrink:0} | |
| .ex-bd{flex:1} | |
| .ex-nm{font-weight:600;font-size:14px;margin-bottom:2px} | |
| .ex-mt{font-size:12px;color:var(--t3)} | |
| .ex-ar{color:var(--t3);font-size:18px} | |
| .st-row{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:18px} | |
| .st-c{background:var(--white);border-radius:16px;border:1px solid var(--line);padding:16px;text-align:center} | |
| .st-v{font-family:'Instrument Serif',serif;font-size:28px;color:var(--primary);line-height:1} | |
| .st-l{font-size:11px;color:var(--t3);font-weight:600;text-transform:uppercase;letter-spacing:.8px;margin-top:4px} | |
| /* ═══════════════════════════════════ | |
| SESSION | |
| ═══════════════════════════════════ */ | |
| .dots{display:flex;justify-content:center;gap:10px;margin-bottom:6px} | |
| .dot{width:10px;height:10px;border-radius:50%;background:var(--line);transition:all .3s} | |
| .dot.done{background:var(--primary)} | |
| .dot.cur{background:var(--accent);transform:scale(1.3)} | |
| .timer-wrap{position:relative;width:200px;height:200px;margin:8px auto 14px} | |
| .t-ring{width:200px;height:200px;transform:rotate(-90deg)} | |
| .tbg{fill:none;stroke:var(--line);stroke-width:6} | |
| .tprog{fill:none;stroke:var(--primary);stroke-width:6;stroke-linecap:round;stroke-dasharray:534;stroke-dashoffset:0;transition:stroke-dashoffset 1s linear} | |
| .t-disp{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center} | |
| .t-time{font-family:'Instrument Serif',serif;font-size:50px;letter-spacing:-1px;line-height:1} | |
| .t-sub{font-family:'DM Sans',sans-serif;font-size:12px;color:var(--t3);font-weight:500;margin-top:2px} | |
| .s-info{text-align:center;margin-bottom:24px} | |
| .s-vis{width:150px;height:110px;margin:0 auto 14px;border-radius:20px;background:linear-gradient(135deg,var(--primary-l),#F5EDE6);display:flex;align-items:center;justify-content:center} | |
| .s-vis svg{width:70px;height:50px;stroke:var(--primary);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round} | |
| .s-info h2{font-family:'Instrument Serif',serif;font-size:22px;font-weight:400;margin-bottom:8px} | |
| .s-info p{color:var(--t2);font-size:14px;line-height:1.5;max-width:280px;margin:0 auto} | |
| .s-btns{display:flex;gap:12px} | |
| .s-btns .btn{flex:1} | |
| /* ═══════════════════════════════════ | |
| PROGRESS | |
| ═══════════════════════════════════ */ | |
| .t-tabs{display:flex;gap:6px;margin:12px 0 18px;background:var(--dim);border-radius:12px;padding:4px} | |
| .t-tb{flex:1;padding:9px;border:none;border-radius:10px;font-family:inherit;font-size:13px;font-weight:600;cursor:pointer;background:transparent;color:var(--t3);transition:all .2s} | |
| .t-tb.on{background:var(--white);color:var(--text);box-shadow:0 1px 4px rgba(0,0,0,.06)} | |
| .chart-c{background:var(--white);border-radius:18px;border:1px solid var(--line);padding:20px 14px 12px;margin-bottom:20px} | |
| .chart-h{display:flex;justify-content:space-between;margin-bottom:8px} | |
| .chart-h span:first-child{font-weight:600;font-size:14px} | |
| .chart-h .cv{font-weight:700;font-size:14px;color:var(--green)} | |
| .chart-svg{width:100%;height:auto;display:block} | |
| .cg{stroke:var(--line);stroke-width:1} | |
| .cl{fill:none;stroke:var(--primary);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:500;stroke-dashoffset:500} | |
| .scr.on .cl{animation:drawLine 1.2s .3s ease forwards} | |
| @keyframes drawLine{to{stroke-dashoffset:0}} | |
| .ca{fill:url(#cg);opacity:0} | |
| .scr.on .ca{animation:fadeInA .8s .8s ease forwards} | |
| @keyframes fadeInA{to{opacity:.35}} | |
| .cd{fill:var(--primary)} | |
| .scr.on .cd{opacity:0} | |
| .scr.on .cd{animation:fu .35s ease both} | |
| .scr.on .cd:nth-child(7){animation-delay:.5s} | |
| .scr.on .cd:nth-child(8){animation-delay:.6s} | |
| .scr.on .cd:nth-child(9){animation-delay:.7s} | |
| .scr.on .cd:nth-child(10){animation-delay:.8s} | |
| .scr.on .cd:nth-child(11){animation-delay:.9s} | |
| .scr.on .cd:nth-child(12){animation-delay:1s} | |
| .scr.on .cd:nth-child(13){animation-delay:1.1s} | |
| .dl{font-size:10px;fill:var(--t3);font-family:'DM Sans',sans-serif;font-weight:500} | |
| .imp-row{display:flex;align-items:center;gap:12px;margin-bottom:14px} | |
| .imp-area{width:85px;font-size:13px;font-weight:600;flex-shrink:0} | |
| .imp-track{flex:1;height:10px;background:var(--dim);border-radius:5px;overflow:hidden} | |
| .imp-fill{height:100%;border-radius:5px;transition:width 1.2s ease} | |
| .imp-pct{font-size:13px;font-weight:700;width:42px;text-align:right;color:var(--green)} | |
| .ins-card{background:linear-gradient(135deg,#F5EDE6,#EDE4DA);border-radius:18px;padding:20px;margin-top:4px} | |
| .ins-hd{display:flex;align-items:center;gap:8px;margin-bottom:8px} | |
| .ins-icon{width:32px;height:32px;border-radius:10px;background:var(--amber);display:flex;align-items:center;justify-content:center;font-size:16px} | |
| .ins-hd span{font-weight:700;font-size:14px} | |
| .ins-txt{font-size:13px;color:var(--t2);line-height:1.55} | |
| /* ═══════════════════════════════════ | |
| PROFILE | |
| ═══════════════════════════════════ */ | |
| .pr-av{width:80px;height:80px;border-radius:50%;background:linear-gradient(135deg,var(--primary),var(--primary-d));display:flex;align-items:center;justify-content:center;font-family:'Instrument Serif',serif;font-size:28px;color:#fff;margin:0 auto 14px;box-shadow:0 4px 16px rgba(61,123,111,.2)} | |
| .pr-name{text-align:center;font-family:'Instrument Serif',serif;font-size:24px;font-weight:400;margin-bottom:2px} | |
| .pr-email{text-align:center;font-size:13px;color:var(--t3);margin-bottom:4px} | |
| .pr-since{text-align:center;font-size:12px;color:var(--t3);margin-bottom:22px} | |
| .pr-stats{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-bottom:24px} | |
| .pr-st{text-align:center;background:var(--white);border:1px solid var(--line);border-radius:14px;padding:14px 8px} | |
| .pr-st-v{font-family:'Instrument Serif',serif;font-size:24px;color:var(--primary);line-height:1} | |
| .pr-st-l{font-size:10px;color:var(--t3);font-weight:600;text-transform:uppercase;letter-spacing:.6px;margin-top:3px} | |
| .pr-sec{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:1px;color:var(--t3);margin-bottom:12px} | |
| .pr-pi{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;background:var(--white);border:1px solid var(--line);border-radius:14px;margin-bottom:8px} | |
| .pr-pl{display:flex;align-items:center;gap:12px} | |
| .pr-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0} | |
| .pr-pn{font-size:14px;font-weight:600} | |
| .pr-ps{font-size:13px;font-weight:700} | |
| .pr-si{display:flex;align-items:center;justify-content:space-between;padding:15px 16px;background:var(--white);border:1px solid var(--line);border-radius:14px;margin-bottom:8px;cursor:pointer;transition:border-color .2s} | |
| .pr-si:hover{border-color:var(--primary)} | |
| .pr-sl{display:flex;align-items:center;gap:12px} | |
| .pr-sic{width:34px;height:34px;border-radius:10px;background:var(--dim);display:flex;align-items:center;justify-content:center;font-size:16px} | |
| .pr-stx{font-size:14px;font-weight:500} | |
| .pr-sr{display:flex;align-items:center;gap:8px} | |
| .pr-sv{font-size:13px;color:var(--t3);font-weight:500} | |
| .pr-sa{color:var(--t3);font-size:16px} | |
| .btn-out{margin-top:18px;background:transparent;color:var(--red);border:1.5px solid rgba(200,90,74,.2);font-weight:600} | |
| .btn-out:hover{background:rgba(200,90,74,.06);border-color:rgba(200,90,74,.35)} | |
| /* ── Loading Overlay ── */ | |
| .ld{position:absolute;inset:0;background:rgba(250,247,242,.96);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);display:flex;align-items:center;justify-content:center;z-index:200;opacity:0;pointer-events:none;transition:opacity .4s} | |
| .ld.show{opacity:1;pointer-events:auto} | |
| .ld-body{text-align:center} | |
| .ld-star{font-size:32px;margin-bottom:20px;animation:pls 1.5s ease infinite} | |
| @keyframes pls{0%,100%{transform:scale(1)}50%{transform:scale(1.15)}} | |
| .ld-step{font-size:15px;color:var(--t2);margin-bottom:10px;opacity:0;transform:translateY(6px);transition:all .4s} | |
| .ld-step.vis{opacity:1;transform:translateY(0)} | |
| .ld-step.done{color:var(--green);font-weight:600} | |
| .ld-dots{display:flex;gap:6px;justify-content:center;margin-top:14px} | |
| .ld-dot{width:8px;height:8px;border-radius:50%;background:var(--line);transition:background .3s} | |
| .ld-dot.active{background:var(--primary);animation:pls .6s ease infinite} | |
| /* ── Responsive ── */ | |
| @media(max-height:920px){.phone{height:780px;border-radius:44px}.body-wrap{height:260px}} | |
| @media(max-width:420px){.phone{width:100%;height:100vh;border-radius:0;box-shadow:none}body{padding:0}.demo-head{display:none}} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="demo-head"> | |
| <h1>PainFree</h1> | |
| <p>Interactive App Mockup</p> | |
| </div> | |
| <div class="phone"> | |
| <div class="island"></div> | |
| <!-- Status Bar --> | |
| <div class="sbar"> | |
| <span>9:41</span> | |
| <div class="sb-r"> | |
| <svg viewBox="0 0 16 12"><path d="M1 8.5C3.5 4 7 2 8 1c1 1 4.5 3 7 7.5" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round"/><path d="M4 10.5C5.5 7 7 5.5 8 4.5c1 1 2.5 2.5 4 6" stroke="currentColor" stroke-width="1.4" fill="none" stroke-linecap="round"/><circle cx="8" cy="11" r="1" fill="currentColor"/></svg> | |
| <div class="bat"><div class="bat-f"></div></div> | |
| </div> | |
| </div> | |
| <div class="scrs"> | |
| <!-- ════ ONBOARDING ════ --> | |
| <div class="scr on" id="s-ob"> | |
| <div class="si"> | |
| <div class="ob-head" data-a="1"> | |
| <h1>Where does<br>it hurt?</h1> | |
| <p class="sub">Tap the areas where you feel pain</p> | |
| </div> | |
| <div class="body-wrap" data-a="2"> | |
| <svg class="body-svg" viewBox="0 0 200 400"> | |
| <circle class="base" cx="100" cy="32" r="22"/> | |
| <line x1="88" y1="54" x2="88" y2="68"/> | |
| <line x1="112" y1="54" x2="112" y2="68"/> | |
| <path d="M58,88 C58,72 74,66 88,68 L112,68 C126,66 142,72 142,88"/> | |
| <path d="M58,88 L58,182 C58,196 70,200 82,200 L118,200 C130,200 142,196 142,182 L142,88"/> | |
| <path d="M58,88 L32,140 L22,186"/> | |
| <path d="M142,88 L168,140 L178,186"/> | |
| <path d="M22,186 L16,200 M22,186 L22,202 M22,186 L28,200"/> | |
| <path d="M178,186 L184,200 M178,186 L178,202 M178,186 L172,200"/> | |
| <path d="M82,200 L78,286 L76,348"/> | |
| <path d="M118,200 L122,286 L124,348"/> | |
| <path d="M76,348 L62,360 L78,358"/> | |
| <path d="M124,348 L122,360 L138,360"/> | |
| <!-- Hotspots --> | |
| <circle class="hs" data-area="Neck" cx="100" cy="64" r="14"/> | |
| <circle class="hs" data-area="L Shoulder" cx="58" cy="86" r="15"/> | |
| <circle class="hs" data-area="R Shoulder" cx="142" cy="86" r="15"/> | |
| <circle class="hs" data-area="Upper Back" cx="100" cy="112" r="20"/> | |
| <circle class="hs" data-area="Lower Back" cx="100" cy="162" r="18"/> | |
| <circle class="hs" data-area="L Elbow" cx="30" cy="156" r="12"/> | |
| <circle class="hs" data-area="R Elbow" cx="170" cy="156" r="12"/> | |
| <circle class="hs" data-area="L Wrist" cx="22" cy="190" r="11"/> | |
| <circle class="hs" data-area="R Wrist" cx="178" cy="190" r="11"/> | |
| <circle class="hs" data-area="L Hip" cx="82" cy="196" r="13"/> | |
| <circle class="hs" data-area="R Hip" cx="118" cy="196" r="13"/> | |
| <circle class="hs" data-area="L Knee" cx="76" cy="305" r="14"/> | |
| <circle class="hs" data-area="R Knee" cx="124" cy="305" r="14"/> | |
| </svg> | |
| </div> | |
| <div class="chips" id="chips" data-a="3"></div> | |
| <div class="ob-foot" data-a="4"> | |
| <button class="btn btn-p" id="btnBuild" disabled>Build My Routine</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ════ HOME ════ --> | |
| <div class="scr" id="s-home"> | |
| <div class="si"> | |
| <div class="hdr" data-a="1"> | |
| <div><p class="greet">Good morning</p><h1>Alex</h1></div> | |
| <div class="strk">🔥 7 days</div> | |
| </div> | |
| <div class="chk" data-a="2"> | |
| <p class="chk-t">How's your pain today?</p> | |
| <div class="pain-sc" id="painSc"></div> | |
| </div> | |
| <div class="start-card" id="startRoutine" data-a="3"> | |
| <div class="play-btn"> | |
| <svg viewBox="0 0 24 24"><polygon points="8,5 20,12 8,19"/></svg> | |
| </div> | |
| <div class="start-info"> | |
| <h3>Start Today's Routine</h3> | |
| <p>12 min · 5 exercises</p> | |
| </div> | |
| </div> | |
| <div class="sec-h" data-a="4"><h2>Exercises</h2><span class="dur">Preview</span></div> | |
| <div data-a="5"> | |
| <div class="ex-item" data-goto="s-sess"><div class="ex-n">1</div><div class="ex-bd"><div class="ex-nm">Cat-Cow Stretch</div><div class="ex-mt">8 reps · Spine mobility</div></div><div class="ex-ar">›</div></div> | |
| <div class="ex-item" data-goto="s-sess"><div class="ex-n">2</div><div class="ex-bd"><div class="ex-nm">Child's Pose</div><div class="ex-mt">45 sec · Lower back release</div></div><div class="ex-ar">›</div></div> | |
| <div class="ex-item" data-goto="s-sess"><div class="ex-n">3</div><div class="ex-bd"><div class="ex-nm">Bird Dog</div><div class="ex-mt">6 each side · Core stability</div></div><div class="ex-ar">›</div></div> | |
| <div class="ex-item" data-goto="s-sess"><div class="ex-n">4</div><div class="ex-bd"><div class="ex-nm">Doorway Chest Stretch</div><div class="ex-mt">30 sec · Shoulder opener</div></div><div class="ex-ar">›</div></div> | |
| <div class="ex-item" data-goto="s-sess"><div class="ex-n">5</div><div class="ex-bd"><div class="ex-nm">Neck Tilts</div><div class="ex-mt">10 each side · Neck relief</div></div><div class="ex-ar">›</div></div> | |
| </div> | |
| <div class="st-row" data-a="6"> | |
| <div class="st-c"><div class="st-v">23</div><div class="st-l">Sessions</div></div> | |
| <div class="st-c"><div class="st-v">4.2</div><div class="st-l">Avg Pain</div></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ════ SESSION ════ --> | |
| <div class="scr" id="s-sess"> | |
| <div class="si"> | |
| <div class="dots" data-a="1"> | |
| <div class="dot done"></div> | |
| <div class="dot cur"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| <div class="timer-wrap" data-a="2"> | |
| <svg class="t-ring" viewBox="0 0 200 200"> | |
| <circle class="tbg" cx="100" cy="100" r="85"/> | |
| <circle class="tprog" id="tprog" cx="100" cy="100" r="85"/> | |
| </svg> | |
| <div class="t-disp"> | |
| <span class="t-time" id="tdisp">0:30</span> | |
| <span class="t-sub">hold & breathe</span> | |
| </div> | |
| </div> | |
| <div class="s-info" data-a="3"> | |
| <div class="s-vis"> | |
| <svg viewBox="0 0 100 70"> | |
| <circle cx="30" cy="14" r="8"/> | |
| <path d="M30 22L30 42Q30 48 38 48L62 48Q68 48 68 42L68 36"/> | |
| <path d="M30 28L18 38L12 50"/> | |
| <path d="M42 48L40 64M56 48L58 64"/> | |
| </svg> | |
| </div> | |
| <h2>Cat-Cow Stretch</h2> | |
| <p>Slowly alternate between arching your back upward and dipping it down. Breathe deeply with each movement.</p> | |
| </div> | |
| <div class="s-btns" data-a="4"> | |
| <button class="btn btn-g" id="btnSkip">Skip</button> | |
| <button class="btn btn-p" id="btnDone">Done →</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ════ PROGRESS ════ --> | |
| <div class="scr" id="s-prog"> | |
| <div class="si"> | |
| <h1 style="font-family:'Instrument Serif',serif;font-size:28px;font-weight:400" data-a="1">Your Progress</h1> | |
| <div class="t-tabs" data-a="2"> | |
| <button class="t-tb on">7D</button> | |
| <button class="t-tb">30D</button> | |
| <button class="t-tb">All</button> | |
| </div> | |
| <div class="chart-c" data-a="2"> | |
| <div class="chart-h"><span>Pain Level</span><span class="cv">↓ 42%</span></div> | |
| <svg class="chart-svg" viewBox="0 0 320 130"> | |
| <defs> | |
| <linearGradient id="cg" x1="0" y1="0" x2="0" y2="1"> | |
| <stop offset="0%" stop-color="#3D7B6F" stop-opacity=".3"/> | |
| <stop offset="100%" stop-color="#3D7B6F" stop-opacity="0"/> | |
| </linearGradient> | |
| </defs> | |
| <line class="cg" x1="0" y1="26" x2="320" y2="26"/> | |
| <line class="cg" x1="0" y1="52" x2="320" y2="52"/> | |
| <line class="cg" x1="0" y1="78" x2="320" y2="78"/> | |
| <line class="cg" x1="0" y1="104" x2="320" y2="104"/> | |
| <polygon class="ca" points="24,28 68,37 112,32 156,46 200,51 244,64 288,76 288,130 24,130"/> | |
| <polyline class="cl" points="24,28 68,37 112,32 156,46 200,51 244,64 288,76"/> | |
| <circle class="cd" cx="24" cy="28" r="4.5"/> | |
| <circle class="cd" cx="68" cy="37" r="4.5"/> | |
| <circle class="cd" cx="112" cy="32" r="4.5"/> | |
| <circle class="cd" cx="156" cy="46" r="4.5"/> | |
| <circle class="cd" cx="200" cy="51" r="4.5"/> | |
| <circle class="cd" cx="244" cy="64" r="4.5"/> | |
| <circle class="cd" cx="288" cy="76" r="4.5"/> | |
| <text class="dl" x="24" y="124" text-anchor="middle">Mon</text> | |
| <text class="dl" x="68" y="124" text-anchor="middle">Tue</text> | |
| <text class="dl" x="112" y="124" text-anchor="middle">Wed</text> | |
| <text class="dl" x="156" y="124" text-anchor="middle">Thu</text> | |
| <text class="dl" x="200" y="124" text-anchor="middle">Fri</text> | |
| <text class="dl" x="244" y="124" text-anchor="middle">Sat</text> | |
| <text class="dl" x="288" y="124" text-anchor="middle">Sun</text> | |
| </svg> | |
| </div> | |
| <div class="sec-h" data-a="3"><h2>Pain Reduction</h2></div> | |
| <div data-a="3"> | |
| <div class="imp-row"> | |
| <span class="imp-area">Lower Back</span> | |
| <div class="imp-track"><div class="imp-fill" style="width:65%;background:var(--primary)"></div></div> | |
| <span class="imp-pct">−65%</span> | |
| </div> | |
| <div class="imp-row"> | |
| <span class="imp-area">Neck</span> | |
| <div class="imp-track"><div class="imp-fill" style="width:40%;background:var(--primary)"></div></div> | |
| <span class="imp-pct">−40%</span> | |
| </div> | |
| <div class="imp-row"> | |
| <span class="imp-area">R Shoulder</span> | |
| <div class="imp-track"><div class="imp-fill" style="width:55%;background:var(--amber)"></div></div> | |
| <span class="imp-pct">−55%</span> | |
| </div> | |
| </div> | |
| <div class="ins-card" data-a="4"> | |
| <div class="ins-hd"><div class="ins-icon">✦</div><span>AI Insight</span></div> | |
| <p class="ins-txt">Your lower back pain dropped significantly this week. The Cat-Cow stretch and Bird Dog exercises seem most effective. On days you completed sessions, your pain was <strong>40% lower</strong> than rest days. Keep the streak going.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ════ PROFILE ════ --> | |
| <div class="scr" id="s-prof"> | |
| <div class="si"> | |
| <div class="pr-av" data-a="1">AM</div> | |
| <div class="pr-name" data-a="1">Alex Mitchell</div> | |
| <div class="pr-email" data-a="1">alex.m@email.com</div> | |
| <div class="pr-since" data-a="1">Member since Jan 2024</div> | |
| <div class="pr-stats" data-a="2"> | |
| <div class="pr-st"><div class="pr-st-v">23</div><div class="pr-st-l">Sessions</div></div> | |
| <div class="pr-st"><div class="pr-st-v">7</div><div class="pr-st-l">Streak</div></div> | |
| <div class="pr-st"><div class="pr-st-v">4.2</div><div class="pr-st-l">Avg Pain</div></div> | |
| </div> | |
| <div class="pr-sec" data-a="3">Pain Areas</div> | |
| <div data-a="3"> | |
| <div class="pr-pi"> | |
| <div class="pr-pl"><div class="pr-dot" style="background:var(--red)"></div><div class="pr-pn">Lower Back</div></div> | |
| <div class="pr-ps" style="color:var(--red)">7/10</div> | |
| </div> | |
| <div class="pr-pi"> | |
| <div class="pr-pl"><div class="pr-dot" style="background:var(--amber)"></div><div class="pr-pn">Right Shoulder</div></div> | |
| <div class="pr-ps" style="color:var(--amber)">5/10</div> | |
| </div> | |
| <div class="pr-pi"> | |
| <div class="pr-pl"><div class="pr-dot" style="background:var(--amber)"></div><div class="pr-pn">Neck</div></div> | |
| <div class="pr-ps" style="color:var(--amber)">4/10</div> | |
| </div> | |
| </div> | |
| <div class="pr-sec" style="margin-top:22px" data-a="4">Settings</div> | |
| <div data-a="4"> | |
| <div class="pr-si"><div class="pr-sl"><div class="pr-sic">🔔</div><div class="pr-stx">Notifications</div></div><div class="pr-sr"><div class="pr-sv">On</div><div class="pr-sa">›</div></div></div> | |
| <div class="pr-si"><div class="pr-sl"><div class="pr-sic">⏰</div><div class="pr-stx">Daily Reminder</div></div><div class="pr-sr"><div class="pr-sv">9:00 AM</div><div class="pr-sa">›</div></div></div> | |
| <div class="pr-si"><div class="pr-sl"><div class="pr-sic">⏱</div><div class="pr-stx">Session Length</div></div><div class="pr-sr"><div class="pr-sv">15 min</div><div class="pr-sa">›</div></div></div> | |
| <div class="pr-si"><div class="pr-sl"><div class="pr-sic">📊</div><div class="pr-stx">Export My Data</div></div><div class="pr-sr"><div class="pr-sa">›</div></div></div> | |
| <div class="pr-si"><div class="pr-sl"><div class="pr-sic">❓</div><div class="pr-stx">Help & FAQ</div></div><div class="pr-sr"><div class="pr-sa">›</div></div></div> | |
| </div> | |
| <button class="btn btn-out" data-a="5">Sign Out</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Loading Overlay --> | |
| <div class="ld" id="load"> | |
| <div class="ld-body"> | |
| <div class="ld-star">✦</div> | |
| <div class="ld-step" id="ls1">Analyzing your pain profile...</div> | |
| <div class="ld-step" id="ls2">Selecting personalized exercises...</div> | |
| <div class="ld-step" id="ls3">Your plan is ready!</div> | |
| <div class="ld-dots"> | |
| <div class="ld-dot" id="ld1"></div> | |
| <div class="ld-dot" id="ld2"></div> | |
| <div class="ld-dot" id="ld3"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Tab Bar --> | |
| <div class="tbar hide" id="tbar"> | |
| <button class="tbtn on" data-s="s-home"> | |
| <svg viewBox="0 0 24 24"><path d="M3 12L12 4l9 8"/><path d="M5 10v9a1 1 0 001 1h4v-5h4v5h4a1 1 0 001-1v-9"/></svg> | |
| <span>Home</span> | |
| </button> | |
| <button class="tbtn" data-s="s-sess"> | |
| <svg viewBox="0 0 24 24"><path d="M4 6h16"/><path d="M4 12h16"/><path d="M4 18h10"/></svg> | |
| <span>Routine</span> | |
| </button> | |
| <button class="tbtn" data-s="s-prog"> | |
| <svg viewBox="0 0 24 24"><path d="M4 20h16"/><path d="M4 16l5-5 4 3 7-8"/></svg> | |
| <span>Progress</span> | |
| </button> | |
| <button class="tbtn" data-s="s-prof"> | |
| <svg viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M4 21v-1a7 7 0 0114 0v1"/></svg> | |
| <span>Profile</span> | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| const $ = s => document.querySelector(s); | |
| const $$ = s => document.querySelectorAll(s); | |
| const areas = new Set(); | |
| let tInt = null; | |
| let tSec = 30; | |
| const CIRC = 2 * Math.PI * 85; | |
| const tprog = $('#tprog'); | |
| tprog.style.strokeDasharray = CIRC; | |
| tprog.style.strokeDashoffset = '0'; | |
| /* ── Screen Navigation ── */ | |
| function show(id) { | |
| $$('.scr').forEach(s => s.classList.remove('on')); | |
| const el = $('#' + id); | |
| if (el) el.classList.add('on'); | |
| $$('.tbtn').forEach(t => t.classList.toggle('on', t.dataset.s === id)); | |
| if (id === 's-ob') { | |
| $('#tbar').classList.add('hide'); | |
| } else { | |
| $('#tbar').classList.remove('hide'); | |
| } | |
| if (id === 's-sess') { | |
| resetTimer(); | |
| startTimer(); | |
| } | |
| } | |
| /* Tab bar clicks */ | |
| $$('.tbtn').forEach(t => { | |
| t.addEventListener('click', () => { | |
| const s = t.dataset.s; | |
| if (s) show(s); | |
| }); | |
| }); | |
| /* Exercise items navigate to session */ | |
| $$('[data-goto]').forEach(el => { | |
| el.addEventListener('click', () => show(el.dataset.goto)); | |
| }); | |
| /* Start Routine card */ | |
| $('#startRoutine').addEventListener('click', () => show('s-sess')); | |
| /* ── Body Map Interaction ── */ | |
| $$('.hs').forEach(h => { | |
| h.addEventListener('click', () => { | |
| const a = h.dataset.area; | |
| if (areas.has(a)) { | |
| areas.delete(a); | |
| h.classList.remove('sel'); | |
| } else { | |
| areas.add(a); | |
| h.classList.add('sel'); | |
| } | |
| renderChips(); | |
| $('#btnBuild').disabled = areas.size === 0; | |
| }); | |
| }); | |
| function renderChips() { | |
| const c = $('#chips'); | |
| c.innerHTML = ''; | |
| areas.forEach(a => { | |
| const d = document.createElement('div'); | |
| d.className = 'chip'; | |
| d.innerHTML = a + '<button data-area="' + a + '">×</button>'; | |
| c.appendChild(d); | |
| }); | |
| c.querySelectorAll('button').forEach(b => { | |
| b.addEventListener('click', e => { | |
| e.stopPropagation(); | |
| const a = b.dataset.area; | |
| areas.delete(a); | |
| document.querySelector('.hs[data-area="' + a + '"]').classList.remove('sel'); | |
| renderChips(); | |
| $('#btnBuild').disabled = areas.size === 0; | |
| }); | |
| }); | |
| } | |
| /* ── Build Routine → Loading → Home ── */ | |
| $('#btnBuild').addEventListener('click', () => { | |
| if (areas.size === 0) return; | |
| const ld = $('#load'); | |
| const s1 = $('#ls1'), s2 = $('#ls2'), s3 = $('#ls3'); | |
| const d1 = $('#ld1'), d2 = $('#ld2'), d3 = $('#ld3'); | |
| /* Reset */ | |
| [s1, s2, s3].forEach(s => s.className = 'ld-step'); | |
| [d1, d2, d3].forEach(d => d.className = 'ld-dot'); | |
| ld.classList.add('show'); | |
| /* Step 1 */ | |
| setTimeout(() => { | |
| s1.classList.add('vis'); | |
| d1.classList.add('active'); | |
| }, 100); | |
| /* Step 2 */ | |
| setTimeout(() => { | |
| s1.classList.add('done'); | |
| s1.classList.remove('vis'); | |
| s2.classList.add('vis'); | |
| d2.classList.add('active'); | |
| }, 900); | |
| /* Step 3 */ | |
| setTimeout(() => { | |
| s2.classList.add('done'); | |
| s2.classList.remove('vis'); | |
| s3.classList.add('vis'); | |
| d3.classList.add('active'); | |
| }, 1700); | |
| /* Transition to home */ | |
| setTimeout(() => { | |
| ld.classList.remove('show'); | |
| show('s-home'); | |
| }, 2600); | |
| }); | |
| /* ── Pain Scale (Home) ── */ | |
| for (let i = 1; i <= 10; i++) { | |
| const b = document.createElement('button'); | |
| b.className = 'pn'; | |
| b.textContent = i; | |
| b.addEventListener('click', () => { | |
| $$('.pn').forEach(p => p.classList.remove('sel')); | |
| b.classList.add('sel'); | |
| }); | |
| $('#painSc').appendChild(b); | |
| } | |
| /* ── Timer ── */ | |
| function resetTimer() { | |
| clearInterval(tInt); | |
| tSec = 30; | |
| $('#tdisp').textContent = '0:30'; | |
| tprog.style.strokeDashoffset = '0'; | |
| } | |
| function startTimer() { | |
| tInt = setInterval(() => { | |
| tSec--; | |
| if (tSec < 0) { | |
| clearInterval(tInt); | |
| $('#tdisp').textContent = '0:00'; | |
| return; | |
| } | |
| const m = Math.floor(tSec / 60); | |
| const s = tSec % 60; | |
| $('#tdisp').textContent = m + ':' + String(s).padStart(2, '0'); | |
| tprog.style.strokeDashoffset = String(CIRC * ((30 - tSec) / 30)); | |
| }, 1000); | |
| } | |
| $('#btnSkip').addEventListener('click', () => { resetTimer(); startTimer(); }); | |
| $('#btnDone').addEventListener('click', () => { resetTimer(); startTimer(); }); | |
| /* ── Time Tabs (Progress) ── */ | |
| $$('.t-tb').forEach(t => { | |
| t.addEventListener('click', () => { | |
| $$('.t-tb').forEach(x => x.classList.remove('on')); | |
| t.classList.add('on'); | |
| }); | |
| }); | |
| /* ── Preselect Lower Back for demo ── */ | |
| setTimeout(() => { | |
| const demo = document.querySelector('.hs[data-area="Lower Back"]'); | |
| if (demo) demo.click(); | |
| }, 500); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment