{"id":11,"date":"2026-09-27T08:28:57","date_gmt":"2026-09-27T08:28:57","guid":{"rendered":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/?page_id=11"},"modified":"2026-09-27T08:57:51","modified_gmt":"2026-09-27T08:57:51","slug":"elementor-11","status":"publish","type":"page","link":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/","title":{"rendered":"Sasha demo"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"11\" class=\"elementor elementor-11\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6221c37 e-con e-atomic-element e-flexbox-base e-default-div e-b317079 \" data-id=\"6221c37\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"6221c37\">\n    \t\t<div class=\"elementor-element elementor-element-0928bc3 elementor-widget elementor-widget-html\" data-id=\"0928bc3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"utf-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\r\n<title>ESL Live Classroom<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n<link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600;12..96,800&family=Atkinson+Hyperlegible:wght@400;700&family=JetBrains+Mono:wght@500&display=swap\">\r\n<style>\r\n:root{\r\n  --bg:#f3f5f8; --surface:#ffffff; --surface-2:#e9edf3; --ink:#16233b; --muted:#5b6780; --line:#d5dbe5;\r\n  --accent:#0d7f82; --accent-ink:#ffffff; --accent-soft:#d8efef;\r\n  --stage:#0f1a2c; --tile:#1d2b44; --tile-ink:#e6ecf5;\r\n  --ok:#1f9d63; --help:#d68a0c; --lost:#d23b3b; --got:#2f6fd6; --one:#7c4dd8;\r\n  --font-d:\"Bricolage Grotesque\",ui-sans-serif,system-ui,sans-serif;\r\n  --font-b:\"Atkinson Hyperlegible\",ui-sans-serif,system-ui,sans-serif;\r\n  --font-m:\"JetBrains Mono\",ui-monospace,Menlo,monospace;\r\n}\r\n@media (prefers-color-scheme:dark){:root:not([data-theme=\"light\"]){\r\n  color-scheme:dark;--bg:#0c1320;--surface:#141e30;--surface-2:#1b273c;--ink:#e6ecf5;--muted:#9aa7bd;--line:#2a3850;\r\n  --accent:#35b7b9;--accent-ink:#06282a;--accent-soft:#113638;--stage:#070d18;--tile:#1a2740;--tile-ink:#e6ecf5;}}\r\n:root[data-theme=\"dark\"]{\r\n  color-scheme:dark;--bg:#0c1320;--surface:#141e30;--surface-2:#1b273c;--ink:#e6ecf5;--muted:#9aa7bd;--line:#2a3850;\r\n  --accent:#35b7b9;--accent-ink:#06282a;--accent-soft:#113638;--stage:#070d18;--tile:#1a2740;--tile-ink:#e6ecf5;}\r\n\r\n*{box-sizing:border-box}\r\n[hidden]{display:none!important}\r\nbody{background:var(--bg);color:var(--ink);font-family:var(--font-b);font-size:15px;line-height:1.5;padding-inline:16px;padding-block:0 40px}\r\n.wrap{max-width:1180px;margin:0 auto}\r\nh1,h2,h3{font-family:var(--font-d);text-align:center;text-wrap:balance;margin:0}\r\nh1{font-size:clamp(1.7rem,4vw,2.4rem);font-weight:800;letter-spacing:-.01em}\r\nh2{font-size:1.45rem;font-weight:800}\r\nh3{font-size:1rem;font-weight:600}\r\n.sub{text-align:center;color:var(--muted);margin:6px 0 0}\r\nbutton{font:inherit;cursor:pointer}\r\nbutton:focus-visible,[tabindex]:focus-visible{outline:3px solid var(--accent);outline-offset:2px}\r\n\r\n\/* top bar *\/\r\n.top{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding-block:18px}\r\n.brand{font-family:var(--font-d);font-weight:800;font-size:1.15rem;display:flex;align-items:center;gap:8px}\r\n.brand i{display:inline-grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--accent);color:var(--accent-ink);font-style:normal;font-size:.8rem}\r\n.tabs{display:flex;flex-wrap:wrap;align-items:center;gap:4px;background:var(--surface-2);padding:4px;border-radius:10px}\r\n.tabs button{border:0;background:none;color:var(--muted);padding:7px 14px;border-radius:7px;font-weight:700}\r\n.tabs button[aria-selected=\"true\"]{background:var(--surface);color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.12)}\r\n.hero{padding-block:22px 26px;border-bottom:1px solid var(--line);margin-bottom:26px}\r\n\r\n\/* schedule *\/\r\n.legend{display:flex;flex-wrap:wrap;justify-content:center;gap:8px 16px;color:var(--muted);font-size:.85rem;margin:14px 0 22px}\r\n.legend b{font-family:var(--font-m);color:var(--ink);font-weight:500}\r\n.day{margin-bottom:22px}\r\n.day h3{text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-size:.8rem;padding-bottom:8px;border-bottom:1px solid var(--line);margin-bottom:10px}\r\n.lesson{display:grid;grid-template-columns:78px 1fr 58px 150px;gap:14px;align-items:center;background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:8px}\r\n.lesson .t{font-family:var(--font-m);color:var(--accent);font-size:.95rem}\r\n.lesson .n{font-weight:700}\r\n.lesson .n small{display:block;font-weight:400;color:var(--muted)}\r\n.lvl{font-family:var(--font-m);font-size:.8rem;text-align:center;border:1px solid var(--line);border-radius:6px;padding:2px 0}\r\n.seats{height:4px;background:var(--surface-2);border-radius:4px;overflow:hidden;margin-top:6px}\r\n.seats span{display:block;height:100%;background:var(--accent)}\r\n.book{width:100%;border:0;border-radius:8px;padding:8px 10px;font-weight:700;background:var(--accent);color:var(--accent-ink)}\r\n.lesson.mine .book{background:var(--ok);color:#fff}\r\n.lesson.full:not(.mine){opacity:.55}\r\n.lesson.full:not(.mine) .book{background:var(--surface-2);color:var(--muted);cursor:not-allowed}\r\n.mine-list{display:grid;gap:8px;margin-top:14px}\r\n.calwrap{margin-top:34px;padding-top:26px;border-top:1px solid var(--line)}\r\n.weekpill-row{display:flex;justify-content:center;margin-top:14px}\r\n.weekpill{display:inline-flex;align-items:center;gap:10px;border:0;border-radius:999px;background:var(--ok);color:#fff;padding:8px 18px 8px 8px;font-weight:700;box-shadow:0 3px 10px rgba(31,157,99,.3);transition:transform .15s ease,box-shadow .2s ease}\r\n.weekpill:hover{transform:translateY(-1px);box-shadow:0 5px 14px rgba(31,157,99,.45)}\r\n.weekpill .ic{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.2);font-size:.9rem}\r\n.weekpill .amt{font-family:var(--font-m);font-size:1.15rem;font-variant-numeric:tabular-nums}\r\n.weekpill .sm{font-weight:400;font-size:.8rem;opacity:.92}\r\n.weekpill .chev2{font-size:.75rem;opacity:.85;transition:transform .2s ease}\r\n.weekpill[aria-expanded=\"true\"] .chev2{transform:rotate(180deg)}\r\n.weekbreak{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:10px}\r\n.weekbreak span{display:inline-flex;align-items:center;gap:6px;background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:3px 12px 3px 3px;font-size:.82rem}\r\n.weekbreak span b{font-family:var(--font-m);font-weight:500;color:var(--ok)}\r\n.weekbreak .tav{width:24px;height:24px;font-size:.65rem}\r\n.weekbreak .note2{border:0;background:none;color:var(--muted);font-size:.78rem;width:100%;justify-content:center}\r\n.calmeter{max-width:420px;height:8px;margin:12px auto 0;background:var(--surface-2);border-radius:8px;overflow:hidden}\r\n.calmeter span{display:block;height:100%;background:var(--ok);transition:width .3s ease}\r\n.callegend{display:flex;flex-wrap:wrap;justify-content:center;gap:6px 18px;font-size:.8rem;color:var(--muted);margin:14px 0}\r\n.sw{display:inline-block;width:12px;height:12px;border-radius:3px;vertical-align:-1px;margin-right:6px}\r\n.sw.conf{background:var(--ok)} .sw.open{border:1.5px dashed var(--accent)} .sw.full{background:var(--surface-2);border:1px solid var(--line)}\r\n.calscroll{overflow-x:auto;background:var(--surface);border:1px solid var(--line);border-radius:12px}\r\n.cal{display:grid;grid-template-columns:52px repeat(7,minmax(96px,1fr));min-width:740px}\r\n.cal .hd{position:sticky;top:0;text-align:center;padding:10px 4px;font-weight:700;font-size:.85rem;border-bottom:1px solid var(--line);background:var(--surface)}\r\n.cal .hd small{display:block;font-weight:400;color:var(--muted);font-size:.72rem}\r\n.cal .hd.corner{border-right:1px solid var(--line)}\r\n.cal .gut{position:relative;border-right:1px solid var(--line)}\r\n.cal .gut span{position:absolute;right:6px;transform:translateY(-50%);font-family:var(--font-m);font-size:.68rem;color:var(--muted)}\r\n.cal .col{position:relative;border-right:1px solid var(--line);background-image:linear-gradient(var(--line) 1px,transparent 1px);background-size:100% var(--hr)}\r\n.cal .col:last-child{border-right:0}\r\n.ev{position:absolute;left:4px;right:4px;border-radius:8px;padding:5px 7px;font-size:.72rem;line-height:1.3;overflow:hidden;text-align:left;border:0;transition:transform .15s ease,box-shadow .2s ease}\r\n.ev b,.ev .ft,.ev .tm{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n.ev b{font-size:.78rem;margin:1px 0}\r\n.ev .tm{font-family:var(--font-m);font-size:.66rem;opacity:.9}\r\n.ev.conf{background:var(--ok);color:#fff;box-shadow:0 2px 6px rgba(31,157,99,.35)}\r\n.ev.open{background:var(--surface);color:var(--ink);border:1.5px dashed var(--accent)}\r\n.ev.full{background:var(--surface-2);color:var(--muted);border:1px solid var(--line)}\r\n.ev.conf:hover,.ev.open:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(31,157,99,.4)}\r\n.ev.open:hover{background:var(--ok);color:#fff;border-color:var(--ok)}\r\n.ev.sel{outline:3px solid var(--ink);outline-offset:1px}\r\n.ev .tag{display:inline-block;margin-left:2px;font-weight:700;font-size:.64rem;background:rgba(255,255,255,.22);padding:1px 6px;border-radius:8px}\r\n.mine-item{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--ok);border-radius:10px;padding:12px 14px}\r\n.earnbox{text-align:center;padding:6px 16px;border-left:1px solid var(--line);border-right:1px solid var(--line)}\r\n.earnbox .ek{text-transform:uppercase;letter-spacing:.07em;font-size:.68rem;color:var(--muted)}\r\n.earnbox .ev2{font-family:var(--font-m);font-size:1.4rem;color:var(--ok);font-variant-numeric:tabular-nums}\r\n.earnbox .ec{font-size:.78rem;color:var(--muted)}\r\n@media (max-width:640px){.earnbox{border:0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);width:100%;padding:8px 0}}\r\n.mine-item .w{color:var(--muted);font-size:.85rem}\r\n.ghost{border:1px solid var(--line);background:var(--surface);color:var(--ink);border-radius:8px;padding:6px 12px;font-weight:700}\r\n.ghost.danger{color:var(--lost);border-color:var(--lost)}\r\n.empty{text-align:center;color:var(--muted);padding:24px;border:1px dashed var(--line);border-radius:10px}\r\n.cols{display:grid;grid-template-columns:1fr 340px;gap:26px;align-items:start}\r\n\r\n\/* classroom *\/\r\n.bar{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px;background:var(--stage);color:#e6ecf5;padding:10px 14px;border-radius:12px 12px 0 0}\r\n.bar .ttl{font-family:var(--font-d);font-weight:600}\r\n.bar .mono{font-family:var(--font-m);font-size:.85rem;color:#9fb0c9}\r\n.counter{display:flex;gap:10px;font-family:var(--font-m);font-size:.85rem}\r\n.role{margin-left:auto;display:flex;background:#23324d;border-radius:8px;padding:3px}\r\n.role button{border:0;background:none;color:#9fb0c9;padding:5px 12px;border-radius:6px;font-weight:700}\r\n.role button[aria-pressed=\"true\"]{background:var(--accent);color:var(--accent-ink)}\r\n.room{display:grid;grid-template-columns:1fr 330px;gap:12px;background:var(--surface-2);padding:12px;border-radius:0 0 12px 12px}\r\n.stage{background:var(--stage);border-radius:10px;aspect-ratio:16\/9;max-width:100%;display:grid;place-items:center;color:#e6ecf5;position:relative;overflow:hidden}\r\n.stage .who{text-align:center}\r\n.stage .av{width:88px;height:88px;border-radius:50%;display:grid;place-items:center;margin:0 auto 10px;background:var(--accent);color:var(--accent-ink);font-family:var(--font-d);font-size:1.9rem;font-weight:800}\r\n.stage .lbl{position:absolute;left:12px;bottom:10px;font-size:.8rem;background:rgba(0,0,0,.45);padding:3px 8px;border-radius:6px}\r\n.stage .board{position:absolute;right:12px;top:12px;font-family:var(--font-m);font-size:.8rem;background:rgba(255,255,255,.08);padding:8px 10px;border-radius:8px;max-width:48%;text-align:left}\r\n.tools{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:10px}\r\n.tools button{border:0;background:var(--surface);color:var(--ink);border-radius:8px;padding:8px 14px;font-weight:700;border:1px solid var(--line)}\r\n.tools button.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}\r\n.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}\r\n.tile{position:relative;background:var(--tile);color:var(--tile-ink);border-radius:9px;border:3px solid transparent;aspect-ratio:4\/3;max-width:100%;display:grid;place-items:center;overflow:hidden}\r\n.tile .ini{font-family:var(--font-d);font-weight:800;font-size:1.15rem;opacity:.85}\r\n.tile .nm{position:absolute;left:5px;top:3px;font-size:.7rem;text-shadow:0 1px 2px #000}\r\n.tile .st{position:absolute;right:5px;top:3px;font-size:.7rem}\r\n.tile.cam-off .ini{opacity:.35}\r\n.tile.you{outline:2px dashed var(--accent);outline-offset:1px}\r\n.tile.empty-seat{background:transparent;border:2px dashed var(--line);color:var(--muted);font-size:.72rem}\r\n.tile.sig-ok{border-color:var(--ok)} .tile.sig-help{border-color:var(--help)} .tile.sig-lost{border-color:var(--lost)}\r\n.tile.sig-got{border-color:var(--got)} .tile.sig-one{border-color:var(--one)}\r\n.tile.spot{box-shadow:0 0 0 3px #fff inset}\r\n.ctl{position:absolute;inset:auto 0 0 0;display:none;justify-content:space-around;background:rgba(0,0,0,.6);padding:2px 0}\r\n.tutor .tile:hover .ctl,.tutor .tile:focus-within .ctl{display:flex}\r\n.ctl button{border:0;background:none;color:#fff;font-size:.8rem;padding:2px 4px}\r\n.chip{position:absolute;left:5px;bottom:4px;font-size:.66rem;font-weight:700;padding:1px 6px;border-radius:10px;color:#fff}\r\n.tutor .tile:hover .chip{display:none}\r\n\r\n.side{display:grid;gap:12px;align-content:start}\r\n.panel{background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:12px}\r\n.panel h3{margin-bottom:10px}\r\n.sigbar{display:grid;gap:6px}\r\n.sigbar button{display:flex;align-items:center;gap:10px;text-align:left;border:1px solid var(--line);background:var(--surface);color:var(--ink);border-radius:8px;padding:8px 10px;font-weight:700}\r\n.sigbar button .dot{width:12px;height:12px;border-radius:50%;flex:none}\r\n.sigbar button small{display:block;font-weight:400;color:var(--muted);font-size:.78rem}\r\n.sigbar button[aria-pressed=\"true\"]{border-width:2px;background:var(--accent-soft)}\r\n.req{display:grid;gap:6px}\r\n.req-row{display:grid;grid-template-columns:12px 1fr auto;gap:10px;align-items:center;padding:8px;border-radius:8px;background:var(--surface-2)}\r\n.req-row .dot{width:12px;height:12px;border-radius:50%}\r\n.req-row .w{font-family:var(--font-m);font-size:.75rem;color:var(--muted)}\r\n.req-row button{border:0;border-radius:6px;padding:5px 10px;font-weight:700;background:var(--accent);color:var(--accent-ink);font-size:.8rem}\r\n.okline{font-size:.82rem;color:var(--muted);text-align:center;margin-top:8px}\r\n.global{display:flex;flex-wrap:wrap;gap:6px;justify-content:center}\r\n.chat{height:130px;overflow-y:auto;font-size:.85rem;display:grid;gap:4px;align-content:start;margin-bottom:8px}\r\n.chat b{color:var(--accent)}\r\n.chatform{display:flex;gap:6px}\r\n.chatform input{flex:1;min-width:0;border:1px solid var(--line);background:var(--bg);color:var(--ink);border-radius:8px;padding:7px 10px;font:inherit}\r\n.note{font-size:.8rem;color:var(--muted);text-align:center;margin-top:14px}\r\n.toast{position:fixed;left:50%;bottom:calc(20px + env(safe-area-inset-bottom,0px));transform:translateX(-50%);background:var(--ink);color:var(--bg);padding:9px 16px;border-radius:8px;font-weight:700;font-size:.9rem;opacity:0;transition:opacity .2s;pointer-events:none}\r\n.toast.show{opacity:1}\r\n\r\n.profile{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:18px;margin-bottom:26px;text-align:center}\r\n.profile img.tav{width:112px;height:112px;border-radius:50%;object-fit:cover;display:block;margin:0 auto 10px;border:3px solid var(--accent)}\r\n.profile .role-lbl{text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;color:var(--muted);margin-top:2px}\r\n.profile p{margin:10px 0 12px;color:var(--muted);font-size:.9rem}\r\n.tags{display:flex;flex-wrap:wrap;justify-content:center;gap:6px}\r\n.tags span{font-size:.75rem;background:var(--accent-soft);color:var(--ink);padding:3px 9px;border-radius:12px}\r\n.stats{display:flex;justify-content:center;gap:18px;margin-top:12px;font-size:.8rem;color:var(--muted)}\r\n.stats b{display:block;font-family:var(--font-m);color:var(--ink);font-size:1rem;font-weight:500}\r\n.stage .av img{width:100%;height:100%;border-radius:50%;object-fit:cover}\r\n.stage .av.photo{width:120px;height:120px;background:none;border:3px solid var(--accent)}\r\n.mini{width:22px;height:22px;border-radius:50%;object-fit:cover;vertical-align:-6px;margin-right:4px}\r\n.kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:22px}\r\n.kpi{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:16px;text-align:center}\r\n.kpi .k{text-transform:uppercase;letter-spacing:.08em;font-size:.72rem;color:var(--muted)}\r\n.kpi .v{font-family:var(--font-m);font-size:1.7rem;margin-top:4px;font-variant-numeric:tabular-nums}\r\n.kpi .v.money{color:var(--ok)}\r\n.kpi .d{font-size:.8rem;color:var(--muted);margin-top:2px}\r\n.tablebox{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:6px 14px;overflow-x:auto}\r\n.tablebox table{width:100%;min-width:560px;border-collapse:collapse;font-size:.9rem;font-variant-numeric:tabular-nums}\r\n.tablebox th,.tablebox td{padding:10px 6px;border-bottom:1px solid var(--line);text-align:left}\r\n.tablebox th{color:var(--muted);font-size:.72rem;text-transform:uppercase;letter-spacing:.06em}\r\n.tablebox .r{text-align:right}\r\n.tablebox tr.live td{background:var(--accent-soft)}\r\n.tablebox tfoot td{font-weight:700;border-bottom:0}\r\n.lockline{text-align:center;font-size:.82rem;color:var(--muted);margin-top:14px}\r\n@media (max-width:560px){.kpis{grid-template-columns:1fr}}\r\n.earn .big{text-align:center;font-family:var(--font-m);font-size:1.7rem;color:var(--ok);font-variant-numeric:tabular-nums}\r\n.earn .calc{text-align:center;font-size:.8rem;color:var(--muted);margin-bottom:10px}\r\n.earn table{width:100%;border-collapse:collapse;font-size:.8rem;font-variant-numeric:tabular-nums}\r\n.earn td,.earn th{padding:5px 4px;border-bottom:1px solid var(--line);text-align:left}\r\n.earn th{color:var(--muted);font-weight:700;font-size:.72rem;text-transform:uppercase;letter-spacing:.05em}\r\n.earn td:last-child,.earn th:last-child,.earn td:nth-child(2),.earn th:nth-child(2){text-align:right}\r\n.earn tfoot td{font-weight:700;border-bottom:0}\r\n.earn .lock{text-align:center;font-size:.72rem;color:var(--muted);margin-top:8px}\r\n.earn-scroll{max-height:220px;overflow-y:auto}\r\n.pickrow{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:10px;margin-bottom:4px}\r\n.pickrow label{text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;color:var(--muted);font-weight:700}\r\n.pill{position:relative;display:inline-flex;align-items:center;gap:6px;background:var(--surface);border:1.5px solid var(--accent);border-radius:999px;padding:2px 12px 2px 3px}\r\n.pill:focus-within{outline:3px solid var(--accent-soft)}\r\n.pill .tav{width:26px;height:26px;font-size:.7rem}\r\n.pill select{appearance:none;-webkit-appearance:none;border:0;background:transparent;color:var(--ink);font:inherit;font-weight:700;padding:3px 16px 3px 0;cursor:pointer;outline:none}\r\n.pill select option{color:#16233b;background:#fff}\r\n.pill .chev{position:absolute;right:10px;pointer-events:none;color:var(--accent);font-size:.8rem}\r\n.tutors{display:grid;grid-template-columns:repeat(auto-fill,minmax(112px,1fr));gap:8px;margin:14px 0 4px}\r\n.tutors button{display:grid;justify-items:center;gap:6px;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:12px 6px;color:var(--ink)}\r\n.tutors button[aria-checked=\"true\"]{border:2px solid var(--accent);background:var(--accent-soft);padding:11px 5px}\r\n.tutors .nm2{font-weight:700;font-size:.9rem}\r\n.tutors .ct{font-size:.72rem;color:var(--muted)}\r\n.tav{width:52px;height:52px;border-radius:50%;object-fit:cover;display:grid;place-items:center;font-family:var(--font-d);font-weight:800;color:#fff;font-size:1.1rem;flex:none}\r\n.tav.all{background:var(--surface-2);color:var(--ink);font-size:.8rem}\r\n.tav.sm{width:20px;height:20px;font-size:.6rem;display:inline-grid;vertical-align:-5px;margin-right:4px}\r\n.profile .tav.lg{width:112px;height:112px;margin:0 auto 10px;font-size:2.4rem;border:3px solid var(--accent)}\r\n.stage .av .tav{width:100%;height:100%;font-size:2.4rem}\r\n.tabs button,.pill,.pill select,.pill .chev{transition:background-color .2s ease,color .2s ease,border-color .2s ease,transform .15s ease,box-shadow .2s ease}\r\n.tabs button:hover,.tabs button[aria-selected=\"true\"]:hover{background:var(--ok);color:#fff;transform:translateY(-1px);box-shadow:0 3px 10px rgba(31,157,99,.35)}\r\n.pill:hover{background:var(--ok);border-color:var(--ok);transform:translateY(-1px);box-shadow:0 3px 10px rgba(31,157,99,.35)}\r\n.pill:hover select,.pill:hover .chev{color:#fff}\r\n.tabs button:active,.pill:active{transform:translateY(0)}\r\n.tourbtn{border:1.5px solid var(--ok);background:var(--surface);color:var(--ok);border-radius:999px;padding:6px 14px;font-weight:700;display:inline-flex;align-items:center;gap:8px;transition:background-color .2s,color .2s,transform .15s}\r\n.tourbtn:hover{background:var(--ok);color:#fff;transform:translateY(-1px)}\r\n.tourbtn .pulse{width:8px;height:8px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 0 rgba(31,157,99,.6);animation:pulse 1.6s infinite}\r\n.tourbtn:hover .pulse{background:#fff}\r\n@keyframes pulse{70%{box-shadow:0 0 0 8px rgba(31,157,99,0)}100%{box-shadow:0 0 0 0 rgba(31,157,99,0)}}\r\n.tour-ring{position:fixed;z-index:900;border-radius:12px;border:3px solid var(--ok);box-shadow:0 0 0 9999px rgba(8,15,28,.55);pointer-events:none;transition:all .35s ease}\r\n.tour-arrow{position:fixed;z-index:902;width:44px;height:44px;pointer-events:none;transition:left .35s ease,top .35s ease}\r\n.tour-arrow svg{width:100%;height:100%;filter:drop-shadow(0 2px 4px rgba(0,0,0,.35))}\r\n.tour-arrow.down svg{animation:bob-d .9s ease-in-out infinite}\r\n.tour-arrow.up svg{transform:rotate(180deg);animation:bob-u .9s ease-in-out infinite}\r\n@keyframes bob-d{50%{transform:translateY(8px)}}\r\n@keyframes bob-u{0%,100%{transform:rotate(180deg)}50%{transform:rotate(180deg) translateY(8px)}}\r\n.tour-card{position:fixed;z-index:903;width:min(340px,calc(100vw - 32px));background:var(--surface);color:var(--ink);border-radius:14px;border:2px solid var(--ok);box-shadow:0 12px 32px rgba(0,0,0,.3);padding:14px 16px 12px;transition:left .35s ease,top .35s ease}\r\n.tour-card .stp{font-family:var(--font-m);font-size:.72rem;color:var(--ok);text-transform:uppercase;letter-spacing:.08em}\r\n.tour-card h3{text-align:left;font-size:1.05rem;margin:4px 0 6px}\r\n.tour-card p{margin:0 0 10px;font-size:.9rem;color:var(--muted)}\r\n.tour-bar{height:4px;background:var(--surface-2);border-radius:4px;overflow:hidden;margin-bottom:10px}\r\n.tour-bar span{display:block;height:100%;width:0;background:var(--ok)}\r\n.tour-bar span.run{animation:fill var(--dur) linear forwards}\r\n@keyframes fill{to{width:100%}}\r\n.tour-nav{display:flex;gap:6px;justify-content:space-between;align-items:center}\r\n.tour-nav button{border:1px solid var(--line);background:var(--surface);color:var(--ink);border-radius:8px;padding:6px 10px;font-weight:700;font-size:.82rem}\r\n.tour-nav .nx{background:var(--ok);border-color:var(--ok);color:#fff}\r\n.tour-nav .x{border:0;color:var(--muted);background:none}\r\n@media (prefers-reduced-motion:reduce){.tour-arrow svg{animation:none!important}.tour-bar span.run{animation:none;width:100%}}\r\n@media (max-width:900px){.cols,.room{grid-template-columns:1fr}}\r\n@media (max-width:560px){\r\n  .lesson{grid-template-columns:70px 1fr 50px}\r\n  .lesson .act{grid-column:1\/-1}\r\n  .grid{grid-template-columns:repeat(3,1fr)}\r\n  .role{margin-left:0}\r\n}\r\n@media (prefers-reduced-motion:reduce){*{transition:none!important}}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<div class=\"wrap\">\r\n  <header class=\"top\">\r\n    <div class=\"brand\"><i>EN<\/i>ESL Live Classroom<\/div>\r\n    <nav class=\"tabs\" role=\"tablist\">\r\n      <button role=\"tab\" id=\"tab-schedule\" aria-selected=\"true\" data-view=\"schedule\">Book lessons<\/button>\r\n      <button role=\"tab\" id=\"tab-classroom\" aria-selected=\"false\" data-view=\"classroom\">Classroom<\/button>\r\n      <div class=\"pill\"><span id=\"pill-av\"><\/span>\r\n        <select id=\"tutor-select\" aria-label=\"Choose your tutor\"><\/select>\r\n        <span class=\"chev\" aria-hidden=\"true\">\u25be<\/span>\r\n      <\/div>\r\n      <button role=\"tab\" id=\"tab-earnings\" aria-selected=\"false\" data-view=\"earnings\">My Earnings<\/button>\r\n      <button id=\"tour-start\" class=\"tourbtn\" type=\"button\"><span class=\"pulse\"><\/span>Tutor guide \u25b6<\/button>\r\n    <\/nav>\r\n  <\/header>\r\n\r\n  <!-- ============ SCHEDULE VIEW ============ -->\r\n  <section id=\"view-schedule\">\r\n    <div class=\"hero\">\r\n      <h1>This Week's Live Lessons<\/h1>\r\n      <p class=\"sub\">Week of Mon 28 Sep \u2013 Sun 4 Oct 2026 \u00b7 12 seats per class \u00b7 times in Bangkok (ICT)<\/p>\r\n    <\/div>\r\n    <div class=\"cols\">\r\n      <div>\r\n        <div class=\"legend\">\r\n          <span><b>A1<\/b> Beginner<\/span><span><b>A2<\/b> Elementary<\/span><span><b>B1<\/b> Intermediate<\/span><span><b>B2<\/b> Upper-intermediate<\/span>\r\n        <\/div>\r\n        <div id=\"schedule\"><\/div>\r\n      <\/div>\r\n      <aside>\r\n        <div class=\"profile\" id=\"tutor-profile\"><\/div>\r\n      <\/aside>\r\n    <\/div>\r\n\r\n    <div class=\"calwrap\">\r\n      <h2>My Lessons<\/h2>\r\n      <p class=\"sub\" id=\"mine-count\"><\/p>\r\n      <div class=\"calmeter\"><span id=\"cal-fill\"><\/span><\/div>\r\n      <div class=\"weekpill-row\">\r\n        <button class=\"weekpill\" id=\"weekpill\" aria-expanded=\"false\" aria-controls=\"weekbreak\"><\/button>\r\n      <\/div>\r\n      <div class=\"weekbreak\" id=\"weekbreak\" hidden><\/div>\r\n      <div class=\"callegend\"><span><i class=\"sw conf\"><\/i>Confirmed booking<\/span><span><i class=\"sw open\"><\/i>Open seats<\/span><span>Tap any class to see its earnings<\/span><span><i class=\"sw full\"><\/i>Class full<\/span><\/div>\r\n      <div class=\"calscroll\"><div class=\"cal\" id=\"cal\"><\/div><\/div>\r\n      <div class=\"mine-list\" id=\"mine\"><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ============ CLASSROOM VIEW ============ -->\r\n  <section id=\"view-classroom\" hidden>\r\n    <div class=\"hero\">\r\n      <h1>Live Classroom<\/h1>\r\n      <p class=\"sub\">Switch between Student and Tutor to see both sides of the lesson<\/p>\r\n    <\/div>\r\n\r\n    <div id=\"room-wrap\">\r\n      <div class=\"bar\">\r\n        <span class=\"ttl\" id=\"room-title\">Everyday Conversation \u00b7 A2<\/span>\r\n        <span class=\"mono\" id=\"timer\">00:00<\/span>\r\n        <span class=\"mono\" id=\"room-count\">9\/12 students<\/span>\r\n        <span class=\"counter\" id=\"counter\" title=\"Open requests\"><\/span>\r\n        <div class=\"role\" role=\"group\" aria-label=\"View as\">\r\n          <button id=\"as-student\" aria-pressed=\"true\">Student<\/button>\r\n          <button id=\"as-tutor\" aria-pressed=\"false\">Tutor<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"room\">\r\n        <div>\r\n          <div class=\"stage\" id=\"stage\">\r\n            <div class=\"who\"><div class=\"av photo\" id=\"stage-av\"><\/div><div id=\"stage-name\">Tutor \u00b7 Sasha<\/div><\/div>\r\n            <div class=\"board\" id=\"board\">Today: ordering food<br>\"Could I have\u2026?\"<br>\"I'd like\u2026, please.\"<\/div>\r\n            <span class=\"lbl\" id=\"stage-lbl\">Main stage<\/span>\r\n          <\/div>\r\n          <div class=\"tools\" id=\"tools-student\">\r\n            <button id=\"my-mic\">\ud83c\udfa4 Mic off<\/button>\r\n            <button id=\"my-cam\">\ud83c\udfa5 Camera off<\/button>\r\n            <button id=\"leave\" class=\"ghost danger\" style=\"border-width:1px\">Leave class<\/button>\r\n          <\/div>\r\n          <div class=\"tools\" id=\"tools-tutor\" hidden>\r\n            <button id=\"t-share\">\ud83d\udda5 Share screen<\/button>\r\n            <button id=\"t-board\" class=\"on\">Whiteboard<\/button>\r\n            <button id=\"t-muteall\">Mute all<\/button>\r\n            <button id=\"t-camsoff\">Cameras off<\/button>\r\n            <button id=\"t-lock\">Lock room<\/button>\r\n            <button id=\"t-end\" class=\"ghost danger\" style=\"border-width:1px\">End class<\/button>\r\n          <\/div>\r\n          <div style=\"margin-top:12px\">\r\n            <h3 style=\"margin-bottom:8px\">Students<\/h3>\r\n            <div class=\"grid\" id=\"grid\"><\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"side\">\r\n          <div class=\"panel\" id=\"panel-signals\">\r\n            <h3>How are you doing?<\/h3>\r\n            <div class=\"sigbar\" id=\"sigbar\"><\/div>\r\n          <\/div>\r\n          <div class=\"panel\" id=\"panel-requests\" hidden>\r\n            <h3>Requests<\/h3>\r\n            <div class=\"req\" id=\"req\"><\/div>\r\n            <p class=\"okline\" id=\"okline\"><\/p>\r\n          <\/div>\r\n          <div class=\"panel\">\r\n            <h3>Chat<\/h3>\r\n            <div class=\"chat\" id=\"chat\"><\/div>\r\n            <form class=\"chatform\" id=\"chatform\">\r\n              <input id=\"chatinput\" placeholder=\"Type a message\u2026\" autocomplete=\"off\">\r\n              <button class=\"book\" style=\"width:auto\">Send<\/button>\r\n            <\/form>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n    <p class=\"note\">Prototype: video tiles are placeholders. In the live build, Daily supplies the video and the signals travel over its data channel.<\/p>\r\n  <\/section>\r\n<\/div>\r\n<section id=\"view-earnings\" hidden class=\"wrap\">\r\n  <div class=\"hero\">\r\n    <h1>My Earnings<\/h1>\r\n    <p class=\"sub\">Sasha \u00b7 \u0e3f1,000 per student per hour \u00b7 visible to the tutor only<\/p>\r\n  <\/div>\r\n  <div class=\"kpis\">\r\n    <div class=\"kpi\"><div class=\"k\">This session<\/div><div class=\"v money\" id=\"e-session\">\u0e3f0<\/div><div class=\"d\" id=\"e-session-d\"><\/div><\/div>\r\n    <div class=\"kpi\"><div class=\"k\">This week<\/div><div class=\"v money\" id=\"e-week\">\u0e3f0<\/div><div class=\"d\" id=\"e-week-d\"><\/div><\/div>\r\n    <div class=\"kpi\"><div class=\"k\">Students taught this week<\/div><div class=\"v\" id=\"e-stu\">0<\/div><div class=\"d\" id=\"e-avg\"><\/div><\/div>\r\n  <\/div>\r\n  <h2 style=\"margin-bottom:12px\">Earnings by Lesson<\/h2>\r\n  <div class=\"tablebox\"><table>\r\n    <thead><tr><th>Day<\/th><th>Time<\/th><th>Lesson<\/th><th>Level<\/th><th class=\"r\">Students<\/th><th class=\"r\">Hours<\/th><th class=\"r\">Earned<\/th><\/tr><\/thead>\r\n    <tbody id=\"e-rows\"><\/tbody>\r\n    <tfoot><tr><td colspan=\"4\">Week total<\/td><td class=\"r\" id=\"e-ft-stu\"><\/td><td class=\"r\" id=\"e-ft-hrs\"><\/td><td class=\"r\" id=\"e-ft-tot\"><\/td><\/tr><\/tfoot>\r\n  <\/table><\/div>\r\n  <p class=\"lockline\">\ud83d\udd12 Demo only. In the live platform this page is shown only when Sasha is logged in.<\/p>\r\n<\/section>\r\n<div id=\"tour\" hidden>\r\n  <div class=\"tour-ring\" id=\"tour-ring\"><\/div>\r\n  <div class=\"tour-arrow\" id=\"tour-arrow\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 22 3 11h6V2h6v9h6z\" fill=\"#1f9d63\" stroke=\"#fff\" stroke-width=\"1.5\" stroke-linejoin=\"round\"\/><\/svg><\/div>\r\n  <div class=\"tour-card\" id=\"tour-card\" role=\"dialog\" aria-live=\"polite\" aria-label=\"Tutor guide\">\r\n    <div class=\"stp\" id=\"tour-stp\"><\/div>\r\n    <h3 id=\"tour-h\"><\/h3>\r\n    <p id=\"tour-p\"><\/p>\r\n    <div class=\"tour-bar\"><span id=\"tour-fill\"><\/span><\/div>\r\n    <div class=\"tour-nav\">\r\n      <button class=\"x\" id=\"tour-x\">Close guide<\/button>\r\n      <div style=\"display:flex;gap:6px\"><button id=\"tour-back\">Back<\/button><button id=\"tour-play\">Pause<\/button><button class=\"nx\" id=\"tour-next\">Next<\/button><\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n<div class=\"toast\" id=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<script>\r\n\/* ---------- data ---------- *\/\r\nconst TUTORS=[\r\n {n:\"Sasha\",photo:true,hue:\"#0d7f82\",bio:\"Friendly, patient lessons for every level, from first words to IELTS speaking.\",tags:[\"Conversation\",\"Travel English\",\"Review & Q&A\"]},\r\n {n:\"Kanya\",hue:\"#b0527a\",bio:\"Loves grammar made simple. Clear explanations and lots of practice for new learners.\",tags:[\"Grammar\",\"Vocabulary\",\"Beginners\"]},\r\n {n:\"Anan\",hue:\"#3d64b8\",bio:\"Former hotel manager who teaches the English you need at work and in interviews.\",tags:[\"Business English\",\"Job interviews\"]},\r\n {n:\"Pim\",hue:\"#c07a12\",bio:\"Fun, high-energy classes with games and songs. Great with kids and shy speakers.\",tags:[\"Kids\",\"Pronunciation\"]},\r\n {n:\"Wichai\",hue:\"#5b7a2e\",bio:\"Exam specialist focused on IELTS speaking, reading and writing skills.\",tags:[\"IELTS\",\"Reading & Writing\"]}\r\n];\r\nlet selTutor=\"all\", curTutor=\"Sasha\";\r\nconst SASHA=\"data:image\/jpeg;base64,\/9j\/4AAQSkZJRgABAQAAAQABAAD\/2wBDAAYEBAUEBAYFBQUGBgYHCQ4JCQgICRINDQoOFRIWFhUSFBQXGiEcFxgfGRQUHScdHyIjJSUlFhwpLCgkKyEkJST\/2wBDAQYGBgkICREJCREkGBQYJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCT\/wAARCADIAMgDASIAAhEBAxEB\/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL\/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6\/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL\/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6\/9oADAMBAAIRAxEAPwD18dqdTelO7VxHqCHmg9afTGxnigYq9ak70wdcU8daYmOXjinL1NNp46UCHcEUoHWmggZ7Uofvgn3AoAUU8ckU3qRilBxTAeOlGKB3FLQAw9KjYelSNTG4oAp3Hf3rk\/Ew\/wBGeutuRmuU8Sj\/AEd6llHA3n3B9RWlon3PxrOvB+6\/EVo6J938aAO98FceIbL\/AIF\/6Ca9Oc815j4M\/wCQ\/ZfVv5GvTX681pHYxnuc94m\/48Jv9018vWuP7Xu\/9\/8Aqa+oPE3\/AB4zf7hr5ftv+Qxd\/wC\/\/jWctzSOxe1b\/kY\/Cv8A16XX\/oYoo1X\/AJGPwr\/16XX\/AKGKKCj36nGkHaloEBPFIO1KegpBimMVevWpRTFH504DJ4oExc4rM8Q+JtK8K6e1\/rOoQWNuOhc8yH0UdSa4f4pfGrTfAvmaXp6pqGt4\/wBXn93b+7n19hXzL4l8Vax4u1JtR1u9e7uOig8LEPRV6AUrAev+LP2l7+eV7fwtYwwQDgXd2uXb3C9vxrhB8UvFF3cNPe+I9QLNzhHKj8AK4bzOaePehjPevBnx++yQLa6ybq8Ib5ZAQGA9CT1r1bRPip4U1i5S1t9WBdsBfMQrz6V8c2t4LY5EY+mK39N1QXL\/AL+OEehAwR+NTcLXPtgkDjBpwr548PfGnXfCYt4tUVdV0IKqecWHnw\/j3\/GvdNA8Q6Z4o01NS0i7W5tn\/wC+oz6MOxq0xWNI81G1Sds9KY3IpiKtxx9K5XxIM2711U4O33rl\/EgzbSfSpY0efX\/yQk+hq\/oDCSMEdCao3wzAfrV7QRiMD3oGd74O\/wCQ\/Y\/7x\/ka9Nk6mvMvB\/8AyHrH\/eP8jXpkneqhsYz3Oe8Tf8eE3+6a+YLf\/kMXf+9\/jX0\/4nP+gzemw\/yr5ht\/+Qvd\/wC\/\/jUy3NI7F7Vf+Rh8L\/8AXpdf+hiijVf+Rg8Mf9ed1\/6GKKko99BpRTAakHSqEHak9jSikIwKBi78dDXB\/F3x2fBvhqY28uy+uFKwkDPl574ruS\/HFfKPx18SHW\/HN3ZRTtLaaeRCPQsBz\/hQB53LPJcSPLM7PJIxZmY5LE9SajpaSrAM+lOBI96ZSigCZDkVNDLsYZJxVZOPrUg7Vm0B2NhfW93YG2kOFcbWDdMVL4b8TeIPhfq0eo6NcGW2dtssDDKSr6MP5GuVtpWjcbcg165oXwy1jVvCUt1NceS865jTHI96Cj2\/wN8RtH8e6St7YyeXKp2z2zH5oW9Pp6GupbpkHNfG3w+1bUPAnj1LacyQGR\/s9wmcBgeh96+t9LvvtMS89RTTIsWJulcz4hGbaT6V01z93Arm\/EI\/0eT6UMEed32fKOPWr2ifdPpmqd3zEauaJyD9akZ3fhHjXbD\/AH\/6GvTZO9eY+Ev+Q7Yf7\/8AQ16bIetaQ2MZ7nPeJv8Ajxm\/3T\/KvmG2\/wCQxd\/73+NfTnib\/jxm\/wB0\/wAq+Y7f\/kM3f+9US3NY7F\/Vf+Q\/4Y\/69Lr\/ANDWijVP+Q94Z\/69Lr\/0JaKQz3sU8HIqPpTwelUIhvdQt9OWE3MuwTSCFOM5Y9v0qckHB7Y4rifiFqMqa\/4W0tFBWeSa5bn+6AoH\/jxroPEPiLTvCWjLe6hJgBQscI+9K2OgoGGr6nHpdjPeSH\/VAnn2Ga+J9TvjqWoXd47Ze4neU\/iSa9h8ZfEjXr6V5J2WDT5gVW3RdygHs3qTXN6hd3XiDw5\/ZctnZwReasqStAFljx2XHYjrmkmBS0D4Qa7r\/h86vFLBA0ql7W1kB33AHoegz2z1rF8D+E38ZeLbLw+87WPnswllMZYwhQScrxzxivf9E8VaTf6ZbSWQYiGNYTCo5iKjGD6dKxV0KCx+Jdt4r05CsN7DItwo48q4IxuI9GGfxz61SkB5x8V\/hXL8N7mxmt706lpWoBhDcNHsdXXG5GAJGcEEHuD7GuAr3z493NzqXh3RtJtdOvrqaK4e8mmit2ZYUK7QCQMZPJ\/CvBAQapCFA5Aq7GsccW5hlugFVYlJbgVp6Tam7volb7gOTWchnQ+EtEUyJfXIyQQyqf519EeDdYjuLVYHYYC8V5jpXh6d44ZECmMgdO1dzo2mSWDAg89OKQHA\/H7Q4NP1bSNctgI5JHMEpXjJHzKf517P4GvWvdCtrpyQ6hA\/HfpXj37Q5mj0zR92dgnc599ter\/D2Mx6TdQc4\/csvf7yq39TVAdnNxXOeIP+PeT6V0k4yOa5zxAM28n0oYkeeXf+qerWifdOPWq93\/q3qfQvufjQM7rwkf8AieWH\/XT+leny8k15f4V41yx\/66CvTpOpq4mU9znvE3\/HlN\/un+VfMcH\/ACGrr\/e\/qa+mvEx\/0Kb\/AHT\/ACr5mh\/5DV3\/AL3+NZy3NI7F7VP+Q74a\/wCvS7\/9CWil1T\/kOeGv+vS7\/wDQlopjPeR2pw6VGDzxTx0oEeWfFq9Fj458IyMxUfZ5sHt98Vz3i\/TdT17xddx3906bVDWW7lDCR8uPqc5969E+LfhyTxF4KuJLSES6hpjC9tsD5sL\/AKxR9Vzx7CuR8KX8PjrRbEeeseoWQKox\/wCWiH+H+oqRmN4q0zTtH0DSdHspDLfagq3d3O+NwA6KPTnP5V5vffbbXV49ORhiZgBJ7f416f4k8HSW9\/JffbPMmWPaIbgbosexGCvPOR0NebXtreqJr67iZTbSKqTAgqCfu\/8A66Cj0LQtC0PRbZrwn7LsTfLch9pIHJJNX7DOurZ6xDNcQWkuXj848sgPVvYjmvF\/EXi\/UPEEUWmpH5MSn51Vs+a3v7e1fQWggHSNOWBQU+zRBAOn3RVEm7Z6lLpwhmRtynBXHKsPUeorxT9pGz0O38d2sukQww3F1YJcX0UIwqzEnkgdCRgn8Kz\/ABj4h1r4deK7\/RvDusvBpw2zJa\/LIluXUMUUMDjBJ6Vwl7f3msX89\/qFxJc3dw26SZzyxp7CI4Y84A6mt\/TrO3gXddSCMt6tjis3T4Q8o3dB1r0rR9P0zxPYLpl7Eok24STHIP1qCy94IsdL1adbNL27jB6tHMRiu40IxabLcRpfNcQwZLFjngd65Pw98J9U0Cc3EGptAig4dTg49CO9bujaYry3unQyqJ76B4YXIyPN6rx6EjH40AeZ\/GjWb3VL23E0+bYq0kcA6R9vzr6F+H9uyWAVmYsbeyLZ9RAK+Sdct7yO8mjvmLTb8YP8OT0A7emK+yfBNr9n09znJIQfTCgf0qkSzbn6Gud1\/wD495PpXRS9Diue14fuJPpQxI86unG1xS+FbuK8gaSFsqJGQn3B5pmpJ\/o8uACcHg0eD4YILFVto1jjZi4AGOT1qRnoXhf\/AJDdgf8ApqK9Ol6mvMfDPGs2H\/XYV6bIfmNaxMp7nO+Jv+PKb\/dP8q+Z4v8AkNXf+9\/jX0t4lP8AoUwP90181Q\/8hu7\/AN7+tZy3NI7F7VP+Q34b4\/5dLv8A9CWijVP+Q14c\/wCvO7\/9CWikM93FOBqItik8zIqhFqKTy3Vhjg9K+dr2Nvh58SNR08KYrXz\/AD7f0ML\/ADLj6ZI\/Cvdru6lWWKCNjGXBYsOuB6fnXknx00mUDStf86WZYSbOQuBlQfmXkds5H40mNHU69bf29pC6tZTK8bptfj7p\/wAK8S8bzfZbB7dgpkK7QByc16F8MfGC2K\/YrrEltL8rKemDV3xt4K+yTf2haYfTZ8FHHJjPo3+NBR4X4a0W9+3LPLZTCNV4ZlwCTXd+L9YvvDXhW1\/s27uLKaeXZ8jYIXGTj0rtfDGixyHaqEn+IMK4T45mK21Ow0yL\/lihmYf3c8D+VO5J5azSSyNJIzPIxyzMckn1JqxbR5b6VEo9O9XbSPB6UmwNCzi8vFdRoEhhnjYZzkdKw7KHd0rq9CsA0iknABqSj1i48WQ23g6eefG6GPqfpXnGjahqDomrxtFJAkgLBXw8XcGtXXbu0m05dNdT5M\/Bz3qfQPCmn22j316bya4ksITIltC4XzeOA3rzxTA5D4u6XB\/wlVhrNsYxDrEUN1sB+7L5gVxj0zz+NfT2jRCGGWNR91tv5Zr5C1bVrvWtRsX1LHn\/AGmOIAcCJRIPlHt1r7Eso\/LN0B93zjj3FNEMdN05rA1sfuH+ldBN92sLWhmB\/pTYI83vR8r\/AENQeCo5Y9MiWYESBmzk571avx8slHh0fuuueetSM7rw5\/yF7H\/rqtemS\/eNeZ+HP+QtY\/8AXYV6XN1f8a1iZz3Oc8S\/8ec3+6f5V81wj\/id3f8Avf1r6T8Sf8eU3+6f5V83Q5\/tu7+v9TWcy0XdU\/5DXh72s73\/ANCWijVf+QxoGP8Anyvf\/QlopDPbSc04fSmA08dKoRT1Q2yojSXAgmTLRnG76gjuDXBeLLTU\/EmgX9nKwHmwl1hAxhl+ZT+ldzqEXlXBnkGYXUKX\/wCeRHr7H1rH8Q3MOl6Nc6k4Di3TK7W6k8AZ9KBngfh2SaJllTqOo719A+C9Qg1jRjazASwuuGQnpXh2k28VjfRzNp4lhdsupJ7nsa9X8GR29sUu7dZ44Hcj72cDtkGpQ2bX9lDRHkjgO8Z+Qgckdgfevnr4wrKfiHrkcrbmiMSD2GxTj9a+oUtVutRQE5XhvrXy58TLkal8QPEtwuCG1B1BH+zhf6UMRxcMe9voM1o2kfzVQiHly59OtakCYAIpFGtY4VgTXT6fdxRyoS2FHJHrXJRLNtyikgelSxSyiQcmgDb1DTZbzUheQNO3mnhS5wvtjtXUxadb266BaSRXVtd3OoK0w8zMUsKKWfr24Ws3wtcTx3cZEIlGRweldn8VtWg\/sHT9WRUiurRJ7aMf7UqqMD3pgeKW+dW8U6clvyJb\/wAzGe3mFuPavtGCIxQgN1PJr5q+EfgK4fxDZXd5ERHbAYU93YdPwHP419MscmqiQyKYfL+FYerDMDfStyXlDWLqgzCfpQwR5xf8b\/xpNAJ2duval1FciUdOTTdBAAIA71IzuPDp\/wCJrY\/9dlr0yb+P615j4e\/5Ctl\/12X+denTHhvrWsSJbnN+JP8Ajzm\/3T\/KvnCH\/kN3f1\/qa+jvEn\/HnN\/umvnKL\/kN3f1\/rWbKRc1b\/kL6D\/15Xv8A6EtFGscapoX\/AF5Xf\/oS0UhntSmnioh1qRTVCJM4NeI\/GvxXcabrVvpiaVc2NvtZTJJCFiu84IZGHDDtjqDXtoNcJ8bHSfwTHYSqsv2i7QqjjI+UHJ9vwpMaPMfCPimzMkVnqCxIzcKzdvY5r3DwnYeRYRrJCDFMoKuOVb3Br5pk8OXsMBaOKS7t4xkQ4+Zf9x+o+hyK7T4f\/EHXvDxhgsbuXU9ORiJNNuxieEd8J1wM9Vz9BQUeleLviPpXgPV7izmcy3MFkLhYh1d2JCL7HIz9K+Z555bmSSec7pp3aSQ+rMcn9TXrvxf8Fx+Jreb4kaFds8TogvLKfGYVUBQ0bD7w9VPIryRFVmwRg+9KRKKRh+cnHBq\/ZRk7Vxk9j6j\/ABqf7MAPuitDTtLjuyFG4ZOVIPQ0ijpvC2jCdVZ1r0bwvpOhreT2uq6RbXqzRjZviBKkHt+BrnfCsU9pAI7jbIR0lHGR7irur3ktrOk0LBXgUvk0yTY8PW3he2vNQvHt4ILS0uZ8+fwBjCovP0Jrm9MsJfHl8NUujDb6NbXMv2WEsM3E7Nxgf3QMDNY2j69Z32m3Fpq0kpY3kskkSgkMTyMj6V3fgzwxJr4+0zwNZ2aYWMFcEr6D0oA7jw1YWWnx+cJbcKgMKvuADN\/Ef5D8K6ESKVDeam3pncMVzVxYW8ET6TFGoWWFp4eOkseDx9QT+VVx9j1jTmgmgSSKZMEH3HX61QrHVzDgjvWNqQzEfpUfw+1CXVvCFqL6UNeWzy2rvnJOxioz+GKs6tE0IaNxg4\/OgDzXUB88uPU1B4fOVY8\/exVrUuJJfrVXQeN\/Ofm61IzttAP\/ABM7L\/rsv869On6kV5foR\/4mVmf+my\/zr02Y5ZqtEy3Of8R\/8ek3+6a+dIh\/xO7v6\/1r6J8RH\/Q5fTaa+dof+Q3d\/X+tS9xos60canoZ\/wCnG9\/9CWik17jUdEP\/AE43v\/oS0UhntANZ2u+J9O8NxJJfSSl3+5DCu52\/CjWdYi0TTJ9QlG4RD5U\/vMegrwLxHNqfie\/lvr69mMr8KiNtSNewAptgerSfGXSIZFjl0nUIWY7UMhUAn0z2Nc54z+I3hvVZ4Bq1pd+VBkxxI+089SSOK82\/tDVtGt5o7iP7ZEVAj3\/MQ2eOf8atWGu69alRPpdhfRdGikUEkemaVx2PQPDXjLwVdSi3t7qe0LjANzhlB92HI\/KvRb74eaB4vjt2vrOFrlMNbahAcOp7HcvUV5lo2geFvHGmSW9zo7aJexOGXdGUGcdmHY13\/gzS9Y+HTIoml1vwzMwIKjdcWJJ6kD76epHI64poTPAb7U7uL7bpCXV35JuZVnjd8rIQx5\/SqC2uMHGR7V1vi7wutj4z1yCLDxLeyshB\/hY7h\/OoLXRF4J6elSUZFsInAikA25z0wT+NanhWykXUBBPEzRN0dOcGtE6FH\/COK3vCtqNPu1ZgGWmBpFYrFW+Ysq8cDoSOhposf+EmyVzFEvyn1Yelat7p8c32gwtKq3O0yR7iVYrnacevJ5qXRLE2jYXgHqKCRuheAbS2vBqMe3zGXbNE5+WUDofYivQ7Bf3CxKixovQL0qrY26vCuR0rTt8KMY4NUgZzGtaodL8R6H5wKxvfLDu9nBX+ornVv5tKu7qydiDbzOn5E4ro\/iVphudBW9iyJLC4iusjqArAk1j+OtN\/4nl1eQ\/6u6VZwR7qKAKvw41ljbapZRSfvhfXUi+wKqc\/TJruYdSOveErPUmA85QUkx6g4P6ivHPh\/Kou9Shc+XNLfPBDMrFSrPDgcj3xXdfDjVCmi6Xo1xw12txDz\/fUj9c0kDMbVR+8mHvVTRuCR71d1MEXEwPUEg1R0k4ZvrSA7LQz\/wATC0\/67L\/OvTZ2+Z\/qa8s0Vv8ATrU\/9Nl\/nXpN3Nhm571SEzE8RyAWU3+6a+e4P+Q5d\/5717n4puwtjLz1BFeEWzf8T26Hr\/jSY0XPEGPt2i\/9g+9\/9CWiq\/iWdV1DSVyMrp91n8WWikUdp8T74x2VpZA\/6xjI30HAry\/zx5nXmuw+J120uuPCD\/qI0T8xmvPhPH5gUTruJwAOaGB0Q0rUNZsZFsJI96Dc4ZNxx6j1qlpmmKLjytQ1O5K9CkA8vB9yOan03xDPoF\/YXeflV8OpxkqeoruPFPhiO6EGvaUA1pcLmRAPuk96AGW\/hPw5JoaTG31p4oTta5tbxw4J9ef6VZ0+6HhHV4J4NY12WwWPc1tdlHilB7AgAg03wamoeH9RhWKVjBMuXRuQ2exr0ebStM161kimhBt5VIGBzGfUVRJwvxItDLqNjrsUSGyuYFjkO3Dxt1Xce4wcA\/hXO\/ZFxlehFdt4mA0y+WznU3VtFaJDJD182Hvj\/aGNw9x71yj2J0y5Fv5wuLd1EltcKciaI9CKAKi27EitCxtCjAgdPWrEcIOOK0bSEbgcVIFy2jLxgFauQwhHBxzUtpHHgAippowFytUBo2U2AAa0UcYzXP2sprUhl6ZJoA0niivoJLeYBoplMbg9wRg1gHTTd+H7COfDTQQm1du5MZK\/yA\/OtyCTAGadNp81vYXM5AZBcGcqvVVZRnP4gn8aBbHz+1jPo83ikJuWaxvre6T8V6\/pXU3N+LDVtBvIfljfUXuFx6SIj\/zJq\/4t0+GPUtQuAP3WoadEWI7mOTaf\/HX\/AErltSLCz8JWrZ8xZPLJ7\/KNv9KkZ1HieIRa5fxjgCYkfQ8\/1rG0ziRvrW\/4vGPEF36\/Ln67RXPWHErfWgDqtJk\/0u39fMX+dd\/fzn5ua870o\/6Xbj\/pov8AOu+1NFXfuZV+pqkJnD+LL8mJ1zXk1o\/\/ABPLj6CvQvGN1DEkhWTzMA8Ipb+VeVW+rRx6lLLNDcQhsDc8ZxUsZt32j3ep63ZahA0DRW0JjaOTI3ZOaK0NM1S0uAojuIWPpnBooKMP4sXj23iPUY1P7yd4lT2AjGTXK6HZH7bABG0jkgtj+Ffeuh+MTrH49aQ8qtkkmP8AaPH9K5+3t7u2sPPW4lhnnOfkbFAF7xDYmIsyk5BzzXrPw71H+2PCMunMWWS3GFYHrXmPh7UI\/E4bR9RKw6jjEE\/RZv8AZPvXY\/C0T2N9qWnThlkUdD2xQBv6THeDUIoVbc\/zYB7+1ej6HG0dnBDJ+7YDBHcGuM00Nb+JpGYr5bRb0yOjdCK7TRZftEq7wQENNEnnOv6ncTeI7tbrCyW7\/ZwAcjC9Kl0LS49V066gml8m0huC9pMBkxMR86+6Z5x2JNc74ottSHj3VtIWTfO1x5xnIwFibBDfkf0rt7Iw2OnW2nwMBHChHXOT3JpgVLjwzq1hIYkWK8wNw8lsMR6gHr+FRWl2qymKYGGVeCjjaR+BrsbNVu7Rbe4mWWML8jdHj+hpdNPm6hNZOLbWbiK38+0FwgDjDbWG49QMigDOsjHKBjkVPdxiNc9q1JNIvbqV2Nnp8TAg4twY5Y\/qOhFZWoCWJWimUq68EGgDLGorHIVNbFnerIu7IAHPNcLfXQjuMbuhrb8MEa7ffZMn7NABJckdxnhfxoA73RkFxD\/aEvEQ5jB7j+9W1oDSNHLLL0lbKg+lYsZa9mEEXywL1A7D0robfdwAu0AdKaIkeYeOLb+zPGMOmQoRFJYXN9B2AAKhkz7HBH1FcN4jvRL480yFmDLaQpMx9S+MfjivXfiLpDT32jawmf8AR47qzce0iBgfzT9a8ZXTo5viU91cyjymFqEj9fkFKS1HB3R1\/jHB8Q3hHfaf\/HRXOWR\/fN9a6DxWd+v3xHTzMD8q5214uX+tBRuRyNHCzISGUEgjsa6G012YRp50NvcZAJMi8muaU\/uH\/wB01own92v+6KSA331i0uEKy2AT\/cxWJd6Lo93IWaMKT\/eWnU1jxTAqN4C0e6PyxwE+2M0VOTRQB5R8VbAXPjm28ziOW2ikc+irkfzrnrm4EztNED5YOyRD2x0aus+JpWLxLFI5+aW1SGP\/AGeSf51wlvdGGfziPkJ2TL6GoKEuN1peQXsJwyMMmvY\/DN39ruINRMe1pkAcgZB9815Te2gCnb80LjIPpXoHw4uPN0nyWOWRtv4U0JncQo02o+avILHAx2rsdMkAjVV4OeRXH2UgGopEhJ57ntXX6c6RKO7E8U0I818WTSjx1q7SxFHBVBxyVCjB\/KnrdssY24GF7mpfiO8g8YySSjaj20RRh0kA4J\/Pisf7SvlDAJ+XuaYHZaLqhztJXG2tJdGa7dZoL4Wc0TedBOvDRMeDg+hHBHQ1xmn3e0nCj7tdNpNzA8n77byB1NAHZ21zqTFFvZ7O92gbZoXCyr\/Kq\/iS4tXt1imiuo3YkANakhjjsRwDTV03S76IeZEp4HI4ps+my6bEz6VrotwPm8i9Jkgb2PcfUUCOXlstJ1qzS71Gxknn8trFVify3DhhtI9Tgjr6VW037Z4ItI4zYw3trO\/7+Mny7gn1De3oeKlN1JdTTtN5BmXUobl2tn3wxZGMq3cfKPepPEt3BJqVzdiUJE5eEM5wIyDgjnvjBoGdFD4i0m2W2aO8khiupPLDTLyHPRW9D2\/KuitomjkyfMLA8ksa8htDpGoRNptrDc3BlPNyc7Qw\/TNepQSfaTAplk3i3RnTPXjBP5j9aExM1NeiFzo0gbnayv8Arj+teH6TorX3xWu\/MJMVsYlRewCoDXtmpSrb+HryTPCIDj8RXD6NYTL4+vr1dv2Z7QN93BDnjGe\/ApyJhsctrEhlvriRuSzsT+dYkJxctW3qgxdSjH8bfzrEj4uWpFm1bAy4jBwW+UfjXTjwzeoihDG5AxjpXM6bzdW4PeRf51675IRzikgbOCm0i+gGZLSXHqo3D9KqMP4eQfQjFenpGRjtXn\/x8vbnSPhlf6hYStbXkNxB5c6Ably4B\/McU7CuZbA0V03w+8O2fiTwBoOp6kZTfXVqryzo20sx746UUWZPOj57+MYkHiK3DFgstmDCe24E5rkUmE6rdgffGydPf1ooqDU1rBvMtWt5DkLyre1dZ8P5Ws5LlSRjtmiimB6X4WtPNimvX\/iby1GPzrUFzcSXKrENsadS3aiiqJOc+LEsMJ0NUeMyBZgw6nBwc\/nXHRzFkX5uxHFFFSBp2ADleWOV9a1rOT7PMpAJyCKKKAO30ad7mCMzSbRyNorcjNmISJLfzsjkYzRRVIGcja2mnxXWpWEFu1murL9nhySPnX5l46ZyPyrD1648u9uIrm0t5pGuCY4iQflKAkDPQ5oooANL8RrYomntplxac5wqYz+Irs\/Cssd\/bzzSziKaJ\/s8SueWi4P8xRRSQM0fGd+dM8A6xdOQuxUGc+sij+tVhd\/8VFPbxqqLtR8gfeytFFNiRw2uRmO\/uFI6Oa55T\/pTUUVIzb0z\/j7tv+uy\/wA69o25c\/WiiqiJjwK85\/aJT\/i0mrD\/AKbW5\/8AHxRRVPYhbnT\/AApB\/wCFYeGlUgH7CmD+FFFFVHYh7n\/\/2Q==\";\r\nconst LESSONS=[\r\n {id:1,day:\"Mon 28 Sep\",t:\"19:00\",n:\"Everyday Conversation\",lv:\"A2\",tu:\"Sasha\",taken:8},\r\n {id:2,day:\"Mon 28 Sep\",t:\"20:30\",n:\"Business English Basics\",lv:\"B1\",tu:\"Anan\",taken:5},\r\n {id:3,day:\"Tue 29 Sep\",t:\"18:00\",n:\"Grammar Foundations\",lv:\"A1\",tu:\"Kanya\",taken:10},\r\n {id:4,day:\"Tue 29 Sep\",t:\"19:30\",n:\"Pronunciation & Fluency\",lv:\"B1\",tu:\"Pim\",taken:6},\r\n {id:5,day:\"Wed 30 Sep\",t:\"19:00\",n:\"Travel & Everyday Situations\",lv:\"A2\",tu:\"Sasha\",taken:9},\r\n {id:6,day:\"Wed 30 Sep\",t:\"20:30\",n:\"IELTS Speaking Prep\",lv:\"B2\",tu:\"Wichai\",taken:4},\r\n {id:7,day:\"Thu 1 Oct\",t:\"18:30\",n:\"Vocabulary Builder\",lv:\"A2\",tu:\"Kanya\",taken:7},\r\n {id:8,day:\"Thu 1 Oct\",t:\"20:00\",n:\"Job Interview English\",lv:\"B1\",tu:\"Anan\",taken:5},\r\n {id:9,day:\"Fri 2 Oct\",t:\"19:00\",n:\"Conversation Club (open topic)\",lv:\"B1\",tu:\"Sasha\",taken:11},\r\n {id:10,day:\"Sat 3 Oct\",t:\"10:00\",n:\"Kids' English (fun & games)\",lv:\"A1\",tu:\"Pim\",taken:6},\r\n {id:11,day:\"Sat 3 Oct\",t:\"16:00\",n:\"Reading & Writing Skills\",lv:\"B2\",tu:\"Wichai\",taken:12},\r\n {id:12,day:\"Sun 4 Oct\",t:\"17:00\",n:\"Weekly Review & Q&A\",lv:\"All\",tu:\"Sasha\",taken:8}\r\n];\r\nconst CAP=12;\r\nconst RATE=1000;      \/\/ baht per student per hour\r\nconst HOURS=1;        \/\/ lesson length in hours\r\nconst baht=n=>\"\u0e3f\"+n.toLocaleString(\"en-US\");\r\nlet booked=new Set([1,2,3,5,7,9,10,12]);   \/\/ demo: 8 of 12 classes confirmed (~70%)\r\nlet selLesson=null;\r\ntry{const s=JSON.parse(localStorage.getItem(\"esl-booked-v2\")||\"null\");if(Array.isArray(s))booked=new Set(s)}catch(e){}\r\nconst save=()=>{try{localStorage.setItem(\"esl-booked-v2\",JSON.stringify([...booked]))}catch(e){}};\r\n\r\nconst SIG={\r\n ok:{c:\"--ok\",e:\"\ud83d\udfe2\",s:\"OK\",msg:\"No, everything is okay\",tut:\"All okay\"},\r\n help:{c:\"--help\",e:\"\ud83d\udfe1\",s:\"Help\",msg:\"I need more help\",tut:\"Needs more help\"},\r\n lost:{c:\"--lost\",e:\"\ud83d\udd34\",s:\"Lost\",msg:\"I don't understand\",tut:\"Doesn't understand\"},\r\n got:{c:\"--got\",e:\"\u2705\",s:\"Got it\",msg:\"Yes, I fully understand\",tut:\"Fully understands\"},\r\n one:{c:\"--one\",e:\"\ud83d\ude4b\",s:\"1:1\",msg:\"Can I have a one-to-one, please?\",tut:\"Wants a one-to-one\"}\r\n};\r\nconst ORDER={lost:0,one:1,help:2,got:3};\r\nconst now=Date.now();\r\nlet students=[\r\n {id:\"you\",n:\"You\",mic:false,cam:false,sig:null,at:0},\r\n {id:\"s2\",n:\"Nattapong\",mic:false,cam:true,sig:\"lost\",at:now-95000},\r\n {id:\"s3\",n:\"Mai\",mic:false,cam:true,sig:\"ok\",at:now-40000},\r\n {id:\"s4\",n:\"Somchai\",mic:true,cam:true,sig:null,at:0},\r\n {id:\"s5\",n:\"Yuki\",mic:false,cam:true,sig:\"one\",at:now-62000},\r\n {id:\"s6\",n:\"Ploy\",mic:false,cam:false,sig:\"help\",at:now-30000},\r\n {id:\"s7\",n:\"Arun\",mic:false,cam:true,sig:\"got\",at:now-15000},\r\n {id:\"s8\",n:\"Linh\",mic:false,cam:true,sig:\"ok\",at:now-50000},\r\n {id:\"s9\",n:\"Kenji\",mic:false,cam:true,sig:null,at:0}\r\n];\r\nlet tutor=false, spot=null;\r\nconst chat=[[\"Sasha\",\"Welcome! Cameras on when you're ready.\"],[\"Mai\",\"Hello teacher \ud83d\udc4b\"]];\r\n\r\nconst $=s=>document.querySelector(s);\r\nconst toast=m=>{const t=$(\"#toast\");t.textContent=m;t.classList.add(\"show\");clearTimeout(t._h);t._h=setTimeout(()=>t.classList.remove(\"show\"),1800)};\r\nconst esc=s=>String(s).replace(\/[&<>\"]\/g,c=>({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\"}[c]));\r\n\r\n\/* ---------- tabs ---------- *\/\r\ndocument.querySelectorAll(\".tabs button\").forEach(b=>b.onclick=()=>{\r\n  document.querySelectorAll(\".tabs button\").forEach(x=>x.setAttribute(\"aria-selected\",x===b));\r\n  $(\"#view-schedule\").hidden=b.dataset.view!==\"schedule\";\r\n  $(\"#view-classroom\").hidden=b.dataset.view!==\"classroom\";\r\n  $(\"#view-earnings\").hidden=b.dataset.view!==\"earnings\";\r\n  if(b.dataset.view===\"earnings\")renderEarnings();\r\n});\r\n\r\n\/* ---------- tutors ---------- *\/\r\nconst T=n=>TUTORS.find(t=>t.n===n);\r\nfunction tav(n,cls=\"\"){const t=T(n);return t.photo?`<img decoding=\"async\" class=\"tav ${cls}\" src=\"${SASHA}\" alt=\"${esc(n)}\">`:`<span class=\"tav ${cls}\" style=\"background:${t.hue}\" aria-hidden=\"true\">${n[0]}<\/span>`}\r\nfunction renderTutors(){\r\n  const cnt=n=>LESSONS.filter(l=>l.tu===n).length;\r\n  $(\"#tutor-select\").innerHTML=`<option value=\"all\">${selTutor===\"all\"?\"Choose your tutor\":\"All tutors\"}<\/option>`+\r\n    TUTORS.map(t=>`<option value=\"${t.n}\">${t.n} \u00b7 ${cnt(t.n)} classes<\/option>`).join(\"\");\r\n  $(\"#tutor-select\").value=selTutor;\r\n  $(\"#pill-av\").innerHTML=selTutor===\"all\"?`<span class=\"tav all\">ALL<\/span>`:tav(selTutor);\r\n  const p=$(\"#tutor-profile\");\r\n  if(selTutor===\"all\"){p.hidden=true;return}\r\n  const t=T(selTutor),ls=LESSONS.filter(l=>l.tu===t.n),lv=[...new Set(ls.map(l=>l.lv))].join(\" \u00b7 \");\r\n  p.hidden=false;\r\n  p.innerHTML=`${tav(t.n,\"lg\")}<h2>${t.n}<\/h2><div class=\"role-lbl\">English tutor<\/div><p>${esc(t.bio)}<\/p>\r\n    <div class=\"tags\">${t.tags.map(x=>`<span>${esc(x)}<\/span>`).join(\"\")}<\/div>\r\n    <div class=\"stats\"><div><b>${ls.length}<\/b>classes this week<\/div><div><b>${lv}<\/b>levels<\/div><\/div>`;\r\n}\r\n$(\"#tutor-select\").onchange=e=>{selTutor=e.target.value;renderTutors();renderSchedule();$(\"#tab-schedule\").click()};\r\n\r\n\/* ---------- schedule ---------- *\/\r\nfunction taken(l){return l.taken+(booked.has(l.id)?1:0)}\r\nfunction renderSchedule(){\r\n  const list=LESSONS.filter(l=>selTutor===\"all\"||l.tu===selTutor);\r\n  const days=[...new Set(list.map(l=>l.day))];\r\n  $(\"#schedule\").innerHTML=days.map(d=>`<div class=\"day\"><h3>${d}<\/h3>${\r\n    list.filter(l=>l.day===d).map(l=>{\r\n      const tk=Math.min(taken(l),CAP),mine=booked.has(l.id),full=tk>=CAP;\r\n      const label=mine?\"Booked \u2713\":full?\"Full\":`Book \u00b7 ${CAP-tk} left`;\r\n      return `<div class=\"lesson ${mine?\"mine\":\"\"} ${full?\"full\":\"\"}\">\r\n        <div class=\"t\">${l.t}<\/div>\r\n        <div class=\"n\">${esc(l.n)}<small>${tav(l.tu,\"sm\")}${esc(l.tu)} \u00b7 ${tk}\/${CAP} seats<\/small><div class=\"seats\"><span style=\"width:${tk\/CAP*100}%\"><\/span><\/div><\/div>\r\n        <div class=\"lvl\">${l.lv}<\/div>\r\n        <div class=\"act\"><button class=\"book\" data-id=\"${l.id}\" ${full&&!mine?\"disabled\":\"\"}>${label}<\/button><\/div>\r\n      <\/div>`}).join(\"\")}<\/div>`).join(\"\");\r\n  renderCalendar();\r\n}\r\n\/* ---------- My Lessons: weekly calendar ---------- *\/\r\nconst DAYS=[[\"Mon 28 Sep\",\"Mon\",\"28 Sep\"],[\"Tue 29 Sep\",\"Tue\",\"29 Sep\"],[\"Wed 30 Sep\",\"Wed\",\"30 Sep\"],[\"Thu 1 Oct\",\"Thu\",\"1 Oct\"],[\"Fri 2 Oct\",\"Fri\",\"2 Oct\"],[\"Sat 3 Oct\",\"Sat\",\"3 Oct\"],[\"Sun 4 Oct\",\"Sun\",\"4 Oct\"]];\r\nconst H0=9,H1=22,HR=64;\r\nconst hm=t=>{const[a,b]=t.split(\":\").map(Number);return a+b\/60};\r\nconst endT=t=>{const m=Math.round(hm(t)*60+HOURS*60);return `${String(Math.floor(m\/60)).padStart(2,\"0\")}:${String(m%60).padStart(2,\"0\")}`};\r\nfunction renderCalendar(){\r\n  const mine=LESSONS.filter(l=>booked.has(l.id)),pct=Math.round(mine.length\/LESSONS.length*100);\r\n  $(\"#mine-count\").textContent=`${mine.length} of ${LESSONS.length} classes confirmed this week \u00b7 ${pct}% booked \u00b7 ${mine.length*HOURS} hours of English`;\r\n  $(\"#cal-fill\").style.width=pct+\"%\";\r\n  renderWeekPill(mine);\r\n  const cal=$(\"#cal\");cal.style.setProperty(\"--hr\",HR+\"px\");\r\n  let html=`<div class=\"hd corner\"><\/div>`+DAYS.map(d=>`<div class=\"hd\">${d[1]}<small>${d[2]}<\/small><\/div>`).join(\"\");\r\n  html+=`<div class=\"gut\" style=\"height:${(H1-H0)*HR}px\">${Array.from({length:H1-H0},(_,i)=>i?`<span style=\"top:${i*HR}px\">${String(H0+i).padStart(2,\"0\")}:00<\/span>`:\"\").join(\"\")}<\/div>`;\r\n  html+=DAYS.map(d=>`<div class=\"col\" style=\"height:${(H1-H0)*HR}px\">${LESSONS.filter(l=>l.day===d[0]).map(l=>{\r\n    const tk=Math.min(taken(l),CAP),isMine=booked.has(l.id),full=tk>=CAP&&!isMine;\r\n    const cls=isMine?\"conf\":full?\"full\":\"open\";\r\n    const top=(hm(l.t)-H0)*HR+2,ht=HOURS*HR-4;\r\n    const tag=isMine?\"Confirmed \u2713\":full?\"Full\":`${CAP-tk} seats left`;\r\n    return `<button class=\"ev ${cls} ${selLesson===l.id?\"sel\":\"\"}\" style=\"top:${top}px;height:${ht}px\" data-ev=\"${l.id}\" title=\"${esc(l.n)} with ${esc(l.tu)}\">\r\n      <span class=\"tm\">${l.t}\u2013${endT(l.t)} \u00b7 ${l.lv}<\/span><b>${esc(l.n)}<\/b><span class=\"ft\">${esc(l.tu)} <span class=\"tag\">${tag}<\/span><\/span><\/button>`}).join(\"\")}<\/div>`).join(\"\");\r\n  cal.innerHTML=html;\r\n  \/\/ detail of the selected confirmed class (defaults to the next one)\r\n  if(selLesson&&!LESSONS.some(l=>l.id===selLesson))selLesson=null;\r\n  const show=LESSONS.find(l=>l.id===selLesson)||mine[0];\r\n  if(!show){$(\"#mine\").innerHTML=`<div class=\"empty\">No confirmed lessons yet. Tap a class in the calendar.<\/div>`;return}\r\n  const isMine=booked.has(show.id),k=Math.min(taken(show),CAP),full=k>=CAP&&!isMine,earn=k*RATE*HOURS;\r\n  const status=isMine?`<span style=\"color:var(--ok);font-weight:700\">Confirmed \u2713<\/span>`:full?`<span style=\"color:var(--muted);font-weight:700\">Full<\/span>`:`<span style=\"color:var(--accent);font-weight:700\">${CAP-k} seats left<\/span>`;\r\n  const btns=isMine?`<button class=\"ghost\" data-join=\"${show.id}\">Join<\/button><button class=\"ghost danger\" data-cancel=\"${show.id}\">Cancel<\/button>`\r\n    :full?\"\":`<button class=\"book\" style=\"width:auto\" data-bookev=\"${show.id}\">Book this class<\/button>`;\r\n  $(\"#mine\").innerHTML=`<div class=\"mine-item\">\r\n      <div><strong>${selLesson?\"Selected\":\"Next up\"}: ${esc(show.n)}<\/strong><div class=\"w\">${show.day} \u00b7 ${show.t}\u2013${endT(show.t)} \u00b7 ${show.lv} \u00b7 with ${esc(show.tu)} \u00b7 ${status}<\/div><\/div>\r\n      <div class=\"earnbox\" aria-label=\"Tutor earnings for this class\">\r\n        <div class=\"ek\">Tutor earnings \u00b7 this class<\/div>\r\n        <div class=\"ev2\">${baht(earn)}<\/div>\r\n        <div class=\"ec\">${k} student${k===1?\"\":\"s\"} \u00d7 ${baht(RATE)} \u00d7 ${HOURS} hr<\/div>\r\n      <\/div>\r\n      <div style=\"display:flex;gap:6px\">${btns}<\/div>\r\n    <\/div>`;\r\n}\r\nfunction renderWeekPill(mine){\r\n  const scope=selTutor===\"all\"?mine:mine.filter(l=>l.tu===selTutor);\r\n  let stu=0;const by={};\r\n  scope.forEach(l=>{const k=Math.min(taken(l),CAP);stu+=k;by[l.tu]=(by[l.tu]||{c:0,s:0});by[l.tu].c++;by[l.tu].s+=k});\r\n  const tot=stu*RATE*HOURS,who=selTutor===\"all\"?\"All tutors\":selTutor;\r\n  $(\"#weekpill\").innerHTML=`<span class=\"ic\">\u0e3f<\/span><span>Week earnings \u00b7 ${esc(who)}<br><span class=\"sm\">${scope.length} confirmed class${scope.length===1?\"\":\"es\"} \u00b7 ${stu} students<\/span><\/span><span class=\"amt\">${baht(tot)}<\/span><span class=\"chev2\">\u25be<\/span>`;\r\n  $(\"#weekbreak\").innerHTML=Object.entries(by).sort((a,b)=>b[1].s-a[1].s).map(([n,v])=>`<span>${tav(n)}${esc(n)} \u00b7 ${v.c} class${v.c===1?\"\":\"es\"} \u00b7 ${v.s} students \u00b7 <b>${baht(v.s*RATE*HOURS)}<\/b><\/span>`).join(\"\")\r\n    +`<span class=\"note2\">Confirmed classes only \u00b7 ${baht(RATE)} per student per hour \u00b7 tutor view<\/span>`;\r\n}\r\n$(\"#weekpill\").onclick=()=>{const b=$(\"#weekbreak\"),x=b.hidden;b.hidden=!x;$(\"#weekpill\").setAttribute(\"aria-expanded\",x)};\r\n\r\n$(\"#cal\").onclick=e=>{\r\n  const b=e.target.closest(\"[data-ev]\");if(!b)return;\r\n  selLesson=+b.dataset.ev;renderCalendar();\r\n  $(\"#mine\").scrollIntoView({block:\"nearest\",behavior:\"smooth\"});\r\n};\r\n\r\n$(\"#schedule\").onclick=e=>{\r\n  const b=e.target.closest(\"[data-id]\");if(!b||b.disabled)return;\r\n  const id=+b.dataset.id,l=LESSONS.find(x=>x.id===id);\r\n  if(booked.has(id)){booked.delete(id);toast(\"Booking cancelled\")}else{booked.add(id);toast(`Booked: ${l.n}`)}\r\n  save();renderSchedule();\r\n};\r\n$(\"#mine\").onclick=e=>{\r\n  const bk=e.target.closest(\"[data-bookev]\");\r\n  if(bk){const l=LESSONS.find(x=>x.id===+bk.dataset.bookev);booked.add(l.id);save();renderSchedule();toast(`Confirmed: ${l.n}, ${l.day} ${l.t}`);return}\r\n  const c=e.target.closest(\"[data-cancel]\"),j=e.target.closest(\"[data-join]\");\r\n  if(c){booked.delete(+c.dataset.cancel);save();renderSchedule();toast(\"Booking cancelled\")}\r\n  if(j){const l=LESSONS.find(x=>x.id===+j.dataset.join);$(\"#room-title\").textContent=`${l.n} \u00b7 ${l.lv}`;$(\"#stage-name\").textContent=`Tutor \u00b7 ${l.tu}`;curTutor=l.tu;$(\"#stage-av\").innerHTML=tav(l.tu);chat.splice(0,1,[l.tu,\"Welcome! Cameras on when you're ready.\"]);renderChat();$(\"#tab-classroom\").click();toast(\"Joined muted with camera off\")}\r\n};\r\n\r\n\/* ---------- classroom ---------- *\/\r\nfunction renderGrid(){\r\n  const g=$(\"#grid\");\r\n  let html=students.map(s=>{\r\n    const cls=[\"tile\",s.sig?\"sig-\"+s.sig:\"\",s.cam?\"\":\"cam-off\",s.id===\"you\"?\"you\":\"\",spot===s.id?\"spot\":\"\"].join(\" \");\r\n    const chip=s.sig?`<span class=\"chip\" style=\"background:var(${SIG[s.sig].c})\">${SIG[s.sig].e} ${SIG[s.sig].s}<\/span>`:\"\";\r\n    return `<div class=\"${cls}\" data-sid=\"${s.id}\" tabindex=\"0\">\r\n      <span class=\"nm\">${esc(s.n)}<\/span><span class=\"st\">${s.mic?\"\ud83c\udfa4\":\"\ud83d\udd07\"}${s.cam?\"\":\" \ud83d\udcf7\u2715\"}<\/span>\r\n      <span class=\"ini\">${esc(s.n.slice(0,2).toUpperCase())}<\/span>${chip}\r\n      <div class=\"ctl\"><button data-act=\"mic\" title=\"Mute\">\ud83d\udd07<\/button><button data-act=\"cam\" title=\"Camera off\">\ud83d\udcf7<\/button><button data-act=\"spot\" title=\"Spotlight\">\u2b50<\/button><button data-act=\"remove\" title=\"Remove\">\u2715<\/button><\/div>\r\n    <\/div>`}).join(\"\");\r\n  for(let i=students.length;i<CAP;i++)html+=`<div class=\"tile empty-seat\">Seat ${i+1}<\/div>`;\r\n  g.innerHTML=html;\r\n  $(\"#room-count\").textContent=`${students.length}\/${CAP} students`;\r\n  const you=students.find(s=>s.id===\"you\");\r\n  if(you){$(\"#my-mic\").textContent=you.mic?\"\ud83c\udfa4 Mic on\":\"\ud83c\udfa4 Mic off\";$(\"#my-mic\").classList.toggle(\"on\",you.mic);\r\n    $(\"#my-cam\").textContent=you.cam?\"\ud83c\udfa5 Camera on\":\"\ud83c\udfa5 Camera off\";$(\"#my-cam\").classList.toggle(\"on\",you.cam);}\r\n  renderRequests();renderSigbar();renderEarnings();\r\n}\r\nfunction renderEarnings(){\r\n  const n=students.length,sess=n*RATE*HOURS,cur=$(\"#room-title\").textContent;\r\n  $(\"#e-session\").textContent=baht(sess);\r\n  $(\"#e-session-d\").textContent=`${n} students \u00d7 ${baht(RATE)} \u00d7 ${HOURS} hr`;\r\n  let tot=0,stu=0,hrs=0;\r\n  $(\"#e-rows\").innerHTML=LESSONS.filter(l=>l.tu===\"Sasha\").map(l=>{const k=Math.min(taken(l),CAP),e=k*RATE*HOURS;tot+=e;stu+=k;hrs+=HOURS;\r\n    const live=cur.startsWith(l.n);\r\n    return `<tr class=\"${live?\"live\":\"\"}\"><td>${l.day}<\/td><td>${l.t}<\/td><td>${esc(l.n)}${live?\" \u00b7 <b>live now<\/b>\":\"\"}<\/td><td>${l.lv}<\/td><td class=\"r\">${k}<\/td><td class=\"r\">${HOURS}<\/td><td class=\"r\">${baht(e)}<\/td><\/tr>`}).join(\"\");\r\n  $(\"#e-week\").textContent=baht(tot);const mineN=LESSONS.filter(l=>l.tu===\"Sasha\").length;$(\"#e-week-d\").textContent=`${mineN} lessons \u00b7 ${hrs} hours`;\r\n  $(\"#e-stu\").textContent=stu;$(\"#e-avg\").textContent=`Average ${(stu\/mineN).toFixed(1)} per class`;\r\n  $(\"#e-ft-stu\").textContent=stu;$(\"#e-ft-hrs\").textContent=hrs;$(\"#e-ft-tot\").textContent=baht(tot);\r\n}\r\nfunction renderSigbar(){\r\n  const you=students.find(s=>s.id===\"you\");\r\n  $(\"#sigbar\").innerHTML=Object.entries(SIG).map(([k,v])=>`<button data-sig=\"${k}\" aria-pressed=\"${you&&you.sig===k}\">\r\n    <span class=\"dot\" style=\"background:var(${v.c})\"><\/span><span>${v.e} ${v.s}<small>${esc(v.msg)}<\/small><\/span><\/button>`).join(\"\")\r\n    +`<button data-sig=\"clear\" style=\"justify-content:center\">Clear my signal<\/button>`;\r\n}\r\nfunction renderRequests(){\r\n  const open=students.filter(s=>s.sig&&s.sig!==\"ok\").sort((a,b)=>ORDER[a.sig]-ORDER[b.sig]||a.at-b.at);\r\n  $(\"#req\").innerHTML=open.length?open.map(s=>{\r\n    const w=Math.max(0,Math.round((Date.now()-s.at)\/1000));\r\n    return `<div class=\"req-row\"><span class=\"dot\" style=\"background:var(${SIG[s.sig].c})\"><\/span>\r\n      <div><strong>${esc(s.n)}<\/strong> \u00b7 ${SIG[s.sig].tut}<div class=\"w\">waiting ${w<60?w+\"s\":Math.floor(w\/60)+\"m \"+(w%60)+\"s\"}<\/div><\/div>\r\n      <button data-ack=\"${s.id}\">${s.sig===\"one\"?\"Accept\":s.sig===\"got\"?\"Clear\":\"Go to\"}<\/button><\/div>`}).join(\"\")\r\n    :`<div class=\"empty\" style=\"padding:14px\">All clear \ud83d\udfe2<\/div>`;\r\n  const ok=students.filter(s=>s.sig===\"ok\").map(s=>s.n);\r\n  $(\"#okline\").textContent=ok.length?`\ud83d\udfe2 OK: ${ok.join(\", \")}`:\"\";\r\n  const c={lost:0,one:0,help:0};students.forEach(s=>{if(c[s.sig]!==undefined)c[s.sig]++});\r\n  $(\"#counter\").innerHTML=tutor?`<span>\ud83d\udd34 ${c.lost}<\/span><span>\ud83d\ude4b ${c.one}<\/span><span>\ud83d\udfe1 ${c.help}<\/span>`:\"\";\r\n}\r\nfunction renderChat(){$(\"#chat\").innerHTML=chat.map(([w,m])=>`<div>${T(w)?tav(w,\"sm\"):\"\"}<b>${esc(w)}:<\/b> ${esc(m)}<\/div>`).join(\"\");$(\"#chat\").scrollTop=1e6}\r\n\r\nfunction setRole(t){\r\n  tutor=t;$(\"#room-wrap\").classList.toggle(\"tutor\",t);\r\n  $(\"#as-student\").setAttribute(\"aria-pressed\",!t);$(\"#as-tutor\").setAttribute(\"aria-pressed\",t);\r\n  $(\"#tools-student\").hidden=t;$(\"#tools-tutor\").hidden=!t;\r\n  $(\"#panel-signals\").hidden=t;$(\"#panel-requests\").hidden=!t;\r\n  renderGrid();\r\n}\r\n$(\"#as-student\").onclick=()=>setRole(false);\r\n$(\"#as-tutor\").onclick=()=>setRole(true);\r\n\r\n$(\"#sigbar\").onclick=e=>{\r\n  const b=e.target.closest(\"[data-sig]\");if(!b)return;\r\n  const you=students.find(s=>s.id===\"you\");if(!you)return;\r\n  const k=b.dataset.sig;\r\n  if(k===\"clear\"){you.sig=null;toast(\"Signal cleared\")}else{you.sig=k;you.at=Date.now();toast(`Sent to tutor: \"${SIG[k].msg}\"`)}\r\n  renderGrid();\r\n};\r\n$(\"#req\").onclick=e=>{\r\n  const b=e.target.closest(\"[data-ack]\");if(!b)return;\r\n  const s=students.find(x=>x.id===b.dataset.ack);\r\n  if(s.sig===\"one\"){toast(`1:1 accepted with ${s.n}`);chat.push([curTutor,`${s.n}, I'll take you into a 1:1 after this activity.`]);renderChat()}\r\n  else if(s.sig===\"got\"){toast(`${s.n} cleared`)}\r\n  else{spot=s.id;toast(`${s.n} spotlighted`)}\r\n  s.sig=null;renderGrid();\r\n};\r\n$(\"#grid\").onclick=e=>{\r\n  const b=e.target.closest(\"[data-act]\");if(!b||!tutor)return;\r\n  const id=b.closest(\"[data-sid]\").dataset.sid,s=students.find(x=>x.id===id);\r\n  const a=b.dataset.act;\r\n  if(a===\"mic\"){s.mic=false;toast(`${s.n} muted`)}\r\n  if(a===\"cam\"){s.cam=false;toast(`${s.n}'s camera off`)}\r\n  if(a===\"spot\"){spot=spot===id?null:id;toast(spot?`${s.n} spotlighted`:\"Spotlight off\")}\r\n  if(a===\"remove\"){students=students.filter(x=>x.id!==id);if(spot===id)spot=null;toast(`${s.n} removed from class`)}\r\n  renderGrid();\r\n};\r\n$(\"#my-mic\").onclick=()=>{const y=students.find(s=>s.id===\"you\");if(!y)return;y.mic=!y.mic;renderGrid()};\r\n$(\"#my-cam\").onclick=()=>{const y=students.find(s=>s.id===\"you\");if(!y)return;y.cam=!y.cam;renderGrid()};\r\n$(\"#leave\").onclick=()=>{toast(\"You left the class\");$(\"#tab-schedule\").click()};\r\n$(\"#t-muteall\").onclick=()=>{students.forEach(s=>s.mic=false);toast(\"Everyone muted\");renderGrid()};\r\n$(\"#t-camsoff\").onclick=()=>{students.forEach(s=>s.cam=false);toast(\"All student cameras off\");renderGrid()};\r\n$(\"#t-lock\").onclick=e=>{e.target.classList.toggle(\"on\");toast(e.target.classList.contains(\"on\")?\"Room locked\":\"Room unlocked\")};\r\n$(\"#t-board\").onclick=e=>{e.target.classList.toggle(\"on\");$(\"#board\").hidden=!e.target.classList.contains(\"on\")};\r\n$(\"#t-share\").onclick=e=>{e.target.classList.toggle(\"on\");$(\"#stage-lbl\").textContent=e.target.classList.contains(\"on\")?\"Screen share\":\"Main stage\"};\r\n$(\"#t-end\").onclick=()=>toast(\"Class ended for everyone\");\r\n$(\"#chatform\").onsubmit=e=>{e.preventDefault();const v=$(\"#chatinput\").value.trim();if(!v)return;chat.push([tutor?curTutor:\"You\",v]);$(\"#chatinput\").value=\"\";renderChat()};\r\n\r\n\/* timer + live wait counters *\/\r\nconst start=Date.now()-12*60000;\r\nsetInterval(()=>{const s=Math.floor((Date.now()-start)\/1000);$(\"#timer\").textContent=`${String(Math.floor(s\/60)).padStart(2,\"0\")}:${String(s%60).padStart(2,\"0\")}`;if(tutor)renderRequests()},1000);\r\n\r\n$(\"#stage-av\").innerHTML=tav(\"Sasha\");renderTutors();renderSchedule();renderChat();setRole(false);\r\n\r\n\/* ---------- Tutor guide: auto-advancing arrows ---------- *\/\r\nconst go=v=>$(\"#tab-\"+v).click();\r\nconst TOUR=[\r\n {el:\"#tab-schedule\",h:\"Book lessons\",t:\"Your home page. It lists every class this week with live seat counts.\",pre:()=>{go(\"schedule\");selTutor=\"all\";renderTutors();renderSchedule()}},\r\n {el:\"#tutor-select\",box:\".pill\",h:\"Choose your tutor\",t:\"Pick your own name here to see only your classes and your profile card.\",pre:()=>go(\"schedule\")},\r\n {el:\"#schedule .lesson\",h:\"Each class\",t:\"Time, level, tutor and seats taken. The bar fills as students book.\",pre:()=>go(\"schedule\")},\r\n {el:\"#cal\",h:\"Weekly calendar\",t:\"Green blocks are confirmed bookings. Dashed blocks still have seats. Grey means full.\",pre:()=>go(\"schedule\")},\r\n {el:\"#weekpill\",h:\"Week earnings\",t:\"Your total for the week from confirmed classes. Tap it to see the split by tutor.\",pre:()=>{go(\"schedule\");$(\"#weekbreak\").hidden=false;$(\"#weekpill\").setAttribute(\"aria-expanded\",\"true\")}},\r\n {el:\"#mine .mine-item\",h:\"Earnings per class\",t:\"Tap any class in the calendar and its earnings appear here: students \u00d7 \u0e3f1,000 \u00d7 hours.\",pre:()=>{go(\"schedule\");selLesson=1;renderCalendar()}},\r\n {el:\"#tab-classroom\",h:\"Classroom\",t:\"Open this at lesson time to teach live. Up to 12 students join you here.\",pre:()=>{go(\"classroom\");setRole(true)}},\r\n {el:\".role\",h:\"Tutor view\",t:\"Tutor mode gives you the controls. Student mode shows what your students see.\",pre:()=>{go(\"classroom\");setRole(true)}},\r\n {el:\"#grid .tile:nth-child(2)\",h:\"Student tiles\",t:\"Hover a student to mute them, turn their camera off, spotlight them or remove them.\",pre:()=>{go(\"classroom\");setRole(true)}},\r\n {el:\"#panel-requests\",h:\"Student requests\",t:\"\ud83d\udd34 Lost and \ud83d\ude4b 1:1 requests jump to the top, with how long each student has waited.\",pre:()=>{go(\"classroom\");setRole(true)}},\r\n {el:\"#tools-tutor\",h:\"Room controls\",t:\"Share your screen, open the whiteboard, mute everyone, lock the room or end the class.\",pre:()=>{go(\"classroom\");setRole(true)}},\r\n {el:\"#tab-earnings\",h:\"My Earnings\",t:\"Your private earnings page. Only you can see it when you're logged in.\",pre:()=>go(\"earnings\")},\r\n {el:\".kpis\",h:\"Your totals\",t:\"This session, this week, and how many students you taught.\",pre:()=>go(\"earnings\")},\r\n {el:\".tablebox\",h:\"Earnings by lesson\",t:\"Every class with students, hours and baht earned, plus the week total.\",pre:()=>go(\"earnings\")}\r\n];\r\nconst DUR=6000;let ti=0,playing=true,tTimer=null;\r\nfunction placeTour(){\r\n  const s=TOUR[ti],t=document.querySelector(s.box||s.el);if(!t)return;\r\n  const r=t.getBoundingClientRect(),pad=6,vw=innerWidth,vh=innerHeight;\r\n  Object.assign($(\"#tour-ring\").style,{left:r.left-pad+\"px\",top:r.top-pad+\"px\",width:r.width+pad*2+\"px\",height:r.height+pad*2+\"px\"});\r\n  const card=$(\"#tour-card\"),cw=card.offsetWidth,ch=card.offsetHeight,arrow=$(\"#tour-arrow\");\r\n  const below=vh-r.bottom>ch+70||r.top<ch+70;\r\n  const cx=Math.min(Math.max(r.left+r.width\/2-cw\/2,16),vw-cw-16);\r\n  const ay=below?r.bottom+pad+4:r.top-pad-48;\r\n  const cy=below?ay+48:ay-ch-4;\r\n  card.style.left=cx+\"px\";card.style.top=Math.max(8,Math.min(cy,vh-ch-8))+\"px\";\r\n  arrow.className=\"tour-arrow \"+(below?\"up\":\"down\");\r\n  arrow.style.left=(r.left+r.width\/2-22)+\"px\";arrow.style.top=ay+\"px\";\r\n}\r\nfunction showStep(i){\r\n  ti=(i+TOUR.length)%TOUR.length;const s=TOUR[ti];\r\n  s.pre&&s.pre();\r\n  $(\"#tour-stp\").textContent=`Step ${ti+1} of ${TOUR.length}`;$(\"#tour-h\").textContent=s.h;$(\"#tour-p\").textContent=s.t;\r\n  $(\"#tour-next\").textContent=ti===TOUR.length-1?\"Finish\":\"Next\";\r\n  const t=document.querySelector(s.box||s.el);\r\n  if(t)t.scrollIntoView({block:\"center\",behavior:\"smooth\"});\r\n  setTimeout(placeTour,420);\r\n  const f=$(\"#tour-fill\");f.classList.remove(\"run\");void f.offsetWidth;f.style.setProperty(\"--dur\",DUR+\"ms\");\r\n  clearTimeout(tTimer);\r\n  if(playing){f.classList.add(\"run\");tTimer=setTimeout(()=>ti===TOUR.length-1?endTour():showStep(ti+1),DUR)}\r\n}\r\nfunction startTour(){$(\"#tour\").hidden=false;playing=true;$(\"#tour-play\").textContent=\"Pause\";showStep(0)}\r\nfunction endTour(){clearTimeout(tTimer);$(\"#tour\").hidden=true;go(\"schedule\");setRole(false);try{localStorage.setItem(\"esl-tour-seen\",\"1\")}catch(e){}}\r\n$(\"#tour-start\").onclick=startTour;\r\n$(\"#tour-x\").onclick=endTour;\r\n$(\"#tour-next\").onclick=()=>ti===TOUR.length-1?endTour():showStep(ti+1);\r\n$(\"#tour-back\").onclick=()=>showStep(ti-1);\r\n$(\"#tour-play\").onclick=()=>{playing=!playing;$(\"#tour-play\").textContent=playing?\"Pause\":\"Play\";showStep(ti)};\r\naddEventListener(\"resize\",()=>{if(!$(\"#tour\").hidden)placeTour()});\r\naddEventListener(\"scroll\",()=>{if(!$(\"#tour\").hidden)placeTour()},{passive:true});\r\naddEventListener(\"keydown\",e=>{if($(\"#tour\").hidden)return;if(e.key===\"Escape\")endTour();if(e.key===\"ArrowRight\")$(\"#tour-next\").click();if(e.key===\"ArrowLeft\")showStep(ti-1)});\r\nlet seen=false;try{seen=localStorage.getItem(\"esl-tour-seen\")===\"1\"}catch(e){}\r\nif(!seen)setTimeout(startTour,1800);\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>ESL Live Classroom ENESL Live Classroom Book lessons Classroom \u25be My Earnings Tutor guide \u25b6 This Week&#8217;s Live Lessons Week of Mon 28 Sep \u2013 Sun 4 Oct 2026 \u00b7 12 seats per class \u00b7 times in Bangkok (ICT) A1 BeginnerA2 ElementaryB1 IntermediateB2 Upper-intermediate My Lessons Confirmed bookingOpen seatsTap any class to see its earningsClass [&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-11","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Sasha demo - Sasha Born To Be Wild<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Sasha demo - Sasha Born To Be Wild\" \/>\n<meta property=\"og:description\" content=\"ESL Live Classroom ENESL Live Classroom Book lessons Classroom \u25be My Earnings Tutor guide \u25b6 This Week&#8217;s Live Lessons Week of Mon 28 Sep \u2013 Sun 4 Oct 2026 \u00b7 12 seats per class \u00b7 times in Bangkok (ICT) A1 BeginnerA2 ElementaryB1 IntermediateB2 Upper-intermediate My Lessons Confirmed bookingOpen seatsTap any class to see its earningsClass [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/\" \/>\n<meta property=\"og:site_name\" content=\"Sasha Born To Be Wild\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-27T08:57:51+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/\",\"url\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/\",\"name\":\"Sasha demo - Sasha Born To Be Wild\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/#website\"},\"datePublished\":\"2026-09-27T08:28:57+00:00\",\"dateModified\":\"2026-09-27T08:57:51+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Sasha demo\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/#website\",\"url\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/\",\"name\":\"Sasha Born To Be Wild\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/sasha-pre-demo.migrify-visa-solutions.asia\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Sasha demo - Sasha Born To Be Wild","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/","og_locale":"en_US","og_type":"article","og_title":"Sasha demo - Sasha Born To Be Wild","og_description":"ESL Live Classroom ENESL Live Classroom Book lessons Classroom \u25be My Earnings Tutor guide \u25b6 This Week&#8217;s Live Lessons Week of Mon 28 Sep \u2013 Sun 4 Oct 2026 \u00b7 12 seats per class \u00b7 times in Bangkok (ICT) A1 BeginnerA2 ElementaryB1 IntermediateB2 Upper-intermediate My Lessons Confirmed bookingOpen seatsTap any class to see its earningsClass [&hellip;]","og_url":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/","og_site_name":"Sasha Born To Be Wild","article_modified_time":"2026-09-27T08:57:51+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/","url":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/","name":"Sasha demo - Sasha Born To Be Wild","isPartOf":{"@id":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/#website"},"datePublished":"2026-09-27T08:28:57+00:00","dateModified":"2026-09-27T08:57:51+00:00","breadcrumb":{"@id":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/"},{"@type":"ListItem","position":2,"name":"Sasha demo"}]},{"@type":"WebSite","@id":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/#website","url":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/","name":"Sasha Born To Be Wild","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=\/wp\/v2\/pages\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11"}],"version-history":[{"count":8,"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=\/wp\/v2\/pages\/11\/revisions"}],"predecessor-version":[{"id":23,"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=\/wp\/v2\/pages\/11\/revisions\/23"}],"wp:attachment":[{"href":"https:\/\/sasha-pre-demo.migrify-visa-solutions.asia\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}