{
  "version": 1,
  "id": "scn_front_desk_blueprint",
  "slug": "front-desk",
  "name": "Messaging front desk",
  "icon": "bubble.left.and.bubble.right",
  "tint": "#53775D",
  "settings": {
    "description": "Bring the customer’s message, the relevant context, and your team’s decision into one place.",
    "welcomeSuggestions": [
      {
        "label": "Review this request",
        "prompt": "Read Eva’s request, the sample booking and the studio policy. Explain what we can offer and what needs a manager’s decision. Don’t send anything or change any booking."
      },
      {
        "label": "Draft a reply",
        "prompt": "Help me draft a reply to Eva using the decision saved with this case. If no decision is recorded, ask me first. Save the draft in the scene without sending it."
      },
      {
        "label": "Use our policies",
        "prompt": "Help me adapt this front desk to our business. Start with our policies and the kinds of customer requests we receive."
      }
    ]
  },
  "assets": [
    {
      "id": "desk",
      "type": "daslab/webview",
      "name": "Member care",
      "fields": {
        "html": "<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<style>\n*{box-sizing:border-box}body{margin:0;background:#fbfaf7;color:#293c38;font:13px/1.5 Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}button,input,textarea{font:inherit}button{cursor:pointer}button:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid #315fc5;outline-offset:3px}header{display:flex;justify-content:space-between;align-items:center;padding:19px 22px;border-bottom:1px solid #e5e9e2;gap:12px}.brand{display:flex;gap:10px;align-items:center}.mark{width:31px;height:31px;border:1px solid #b9c8bd;border-radius:50%;display:grid;place-items:center;color:#527264;font:18px Georgia,serif}.overline{font-size:9px;letter-spacing:.11em;text-transform:uppercase;color:#73877e}h1{font-size:18px;letter-spacing:-.6px;font-weight:600;line-height:1.2;margin:3px 0 0}.presence{font-size:10px;color:#6d8376;display:flex;gap:6px;align-items:center;white-space:nowrap}.presence i{width:5px;height:5px;background:#7d9b80;border-radius:50%}.layout{display:grid;grid-template-columns:minmax(0,1fr) 205px;min-height:392px}.conversation{min-width:0;padding:18px 22px 22px}.contact{display:flex;align-items:center;gap:10px;padding-bottom:15px;border-bottom:1px solid #e9ece6}.avatar{width:34px;height:34px;border-radius:50%;background:#e8ddd3;display:grid;place-items:center;color:#846858;font-size:11px;flex-shrink:0}.contact strong{font-size:13px;font-weight:600}.contact small{display:block;font-size:10px;color:#87948b;margin-top:2px}.status{font-size:9px;padding:4px 7px;border-radius:20px;background:#f1e9d8;color:#97773f;margin-left:auto;white-space:nowrap}.status.done{background:#e5eee5;color:#52785c}.time{text-align:center;font-size:9px;color:#95a097;margin:17px 0 13px}.bubble{font-size:12px;line-height:1.65;max-width:94%;padding:13px 15px;border-radius:3px 15px 15px 15px;background:#eef0e9;color:#455449}.bubble.reply{margin:16px 0 0 auto;background:#deebe2;border-radius:15px 3px 15px 15px}.bubble small{display:block;text-align:right;font-size:9px;color:#839887;margin-top:6px}.case-note{font-size:10px;color:#809184;display:flex;gap:6px;align-items:center;margin-top:16px}.thread{border:1px solid #d9dff0;border-radius:9px;background:#f5f6fc;margin-top:18px;overflow:hidden}.thread-head{display:flex;align-items:center;gap:6px;color:#68779a;font-size:9px;padding:9px 12px;border-bottom:1px solid #e5e8f3}.thread-head .dot{width:5px;height:5px;border-radius:50%;background:#8a99ba}.thread-content{padding:12px;font-size:11px;line-height:1.6;color:#5c6680}.mention{color:#315fc5;font-weight:600}.manager{display:flex;gap:9px;padding-top:12px;margin-top:12px;border-top:1px solid #e2e6f2}.manager .avatar{width:25px;height:25px;font-size:8px;background:#e4e6f3;color:#696383}.manager p{margin:0}.manager strong{font-weight:600;font-size:10px;color:#596181}.manager small{font-size:9px;color:#9199ae;margin-left:7px}.context{border-left:1px solid #e5e9e2;background:#f2f4ee;padding:20px 17px}.context h2{font-size:9px;letter-spacing:.08em;text-transform:uppercase;font-weight:500;color:#849081;margin:0 0 10px}.context .member{font-size:12px;font-weight:550;color:#445747}.context .muted{font-size:10px;line-height:1.7;color:#879381;margin-top:4px}.context section+section{border-top:1px solid #e0e6da;padding-top:18px;margin-top:18px}.session{padding:11px 12px;background:#fffefa;border:1px solid #dfe5d8;border-radius:7px;margin-top:8px}.session .date{font-size:10px;color:#84907f}.session strong{display:block;font-size:17px;font-weight:500;letter-spacing:-.5px;margin:2px 0;color:#486047}.session .class{font-size:10px;color:#73846c}.session.available{border-color:#bed0b8;background:#f9fcf5}.capacity{font-size:9px;color:#7d9671;margin-top:7px;display:flex;align-items:center;gap:5px}.capacity i{width:4px;height:4px;background:#8cad7a;border-radius:50%}.policy{font-size:10px;line-height:1.65;color:#7f825f}.policy b{font-weight:550;color:#626944}.waiting{display:flex;align-items:center;gap:8px;font-size:10px;color:#8f998b;margin-top:18px}.waiting i{width:5px;height:5px;border-radius:50%;background:#aebdab}.draft{border:1px solid #cedbd1;border-radius:9px;margin-top:16px;background:#fffefb;overflow:hidden}.draft-top{font-size:9px;padding:8px 12px;background:#edf3ec;color:#6e8772;display:flex;justify-content:space-between}.draft textarea{display:block;width:100%;padding:12px;resize:vertical;min-height:100px;border:0;background:transparent;color:#42574a;font-size:11px;line-height:1.65}.draft-bottom{border-top:1px solid #e7ece4;display:flex;align-items:center;justify-content:space-between;padding:9px 12px;gap:8px}.draft-bottom span{font-size:9px;color:#8e998c}.send{border:0;border-radius:5px;background:#42694f;color:#fff;padding:7px 15px;font-size:10px;white-space:nowrap}.send:disabled{opacity:.6;cursor:default}.receipt{margin-top:14px;border-top:1px solid #e0e8de;padding-top:12px;font-size:10px;color:#74896e}.receipt strong{font-weight:550;color:#4c704e}.return{display:flex;align-items:center;gap:9px;margin-top:17px;padding:11px 12px;border:1px solid #e1e7dd;border-radius:7px;background:#fffefb;color:#6b7f65;font-size:10px}.return .avatar{width:25px;height:25px;background:#dde7d7;color:#6c855e;font-size:8px}.return b{display:block;font-weight:550;color:#526c4c}.return small{font-size:9px;color:#98a18f;margin-left:auto}.starter{margin-top:18px;padding-top:16px;border-top:1px solid #e3e8df}.starter label{font-size:10px;color:#71816b;display:block;margin-bottom:7px}.decision-options{display:flex;gap:5px;margin-bottom:10px;flex-wrap:wrap}.decision-options button{font-size:10px;border:1px solid #d9e1d3;background:#fffefb;color:#6f8067;padding:7px 9px;border-radius:5px}.decision-options button[aria-pressed=true]{background:#e5eedf;border-color:#98b18a;color:#4d7040}.starter input{width:100%;background:transparent;border:0;border-bottom:1px dashed #cbd6c3;color:#596e50;padding:8px 0;font-size:11px}.saved{font-size:9px;color:#85977b;margin:6px 0 0}.context details{font-size:10px;color:#7d8c74;margin-top:12px}.context summary{cursor:pointer}.context details p{font-size:10px;line-height:1.7;color:#738167}.idle{padding:23px 0;color:#94a08f;font-size:11px}.idle span{display:block;font-size:24px;color:#72886c;margin-bottom:8px}\n@media(max-width:580px){header{padding:16px}.conversation{padding:16px}.layout{grid-template-columns:minmax(0,1fr)}.context{border-left:0;border-top:1px solid #e5e9e2;display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:16px}.context section+section{margin:0;padding:0;border:0}.context section:last-child{grid-column:1/-1}.presence{font-size:9px}.bubble{max-width:96%}}\n@media(prefers-reduced-motion:no-preference){.bubble,.thread,.draft,.receipt,.return{animation:appear .28s ease-out}@keyframes appear{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}}\n</style></head><body>\n<header><div class=\"brand\"><span class=\"mark\" aria-hidden=\"true\">a</span><div><div class=\"overline\" id=\"studio\"></div><h1>Member care</h1></div></div><span class=\"presence\"><i></i><span id=\"presence\">Front desk</span></span></header>\n<div class=\"layout\"><main class=\"conversation\" id=\"conversation\"></main><aside class=\"context\" id=\"context\"></aside></div>\n<script>\n(function(){\n  // Shared by the working scene and its replay. The host supplies fields.data.\n  // Only a replay snapshot can show an external sent/booking receipt. The\n  // starter edits local case decisions and drafts; it never calls a channel.\n  var d=window.__DASLAB_WIDGET_DATA__||{}, replay=window.__DASLAB_REPLAY__===true;\n  var stage=replay?(d.stage||'arrive'):'starter';\n  var routine=replay&&stage.indexOf('routine')===0;\n  var steps=['arrive','context','ask','decision','draft','sending','sent','return'];\n  var n=stage==='starter'?1:steps.indexOf(stage);\n  var esc=function(v){return String(v==null?'':v).replace(/[&<>\"']/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[c]})};\n  var member=d.member||{}, current=d.currentSession||{}, next=d.alternative||{};\n  var key='asset:case:'+String(d.caseId||'sample');\n  var get=function(k,f){if(replay)return f;try{return localStorage.getItem(key+':'+k)||f}catch(e){return f}};\n  var set=function(k,v){if(!replay)localStorage.setItem(key+':'+k,v)};\n  var decision=get('decision','review');\n  document.getElementById('studio').textContent=d.studio||'Your studio';\n  document.getElementById('presence').textContent=replay?'Messages · today':'Sample conversation';\n  if(routine){\n    var answered=stage==='routine-replied', visit=d.firstVisit||{}, session=visit.session||{};\n    document.getElementById('conversation').innerHTML='<div class=\"contact\"><div class=\"avatar\">NA</div><div><strong>Noah Adams</strong><small>CASE-017 · First visit</small></div><span class=\"status '+(answered?'done':'')+'\">'+(answered?'Answered':'New message')+'</span></div><div class=\"time\">Today · 16:06</div><div class=\"bubble\">'+esc(visit.question)+'<small>16:06</small></div>'+(answered?'<div class=\"bubble reply\">'+esc(visit.reply)+'<small>Delivered ✓✓</small></div><div class=\"receipt\"><strong>Answered automatically.</strong><br>Class schedule and first-visit guidance, in the same conversation.</div>':'<div class=\"waiting\"><i></i>Checking the class schedule and first-visit guide</div>');\n    document.getElementById('context').innerHTML='<section><h2>Visitor</h2><div class=\"member\">First time at Atelier</div><div class=\"muted\">Interested in reformer<br>No booking yet</div></section><section><h2>Saturday</h2><div class=\"session available\"><span class=\"date\">'+esc(session.label)+'</span><strong>'+esc(session.time)+'</strong><span class=\"class\">'+esc(session.className)+'</span><div class=\"capacity\"><i></i>'+esc(session.spaces)+' spaces available</div></div></section><section><h2>First-visit guide</h2><div class=\"policy\">'+esc(visit.guide)+'</div></section>';\n    if(answered)revealLatest('.receipt');\n    return;\n  }\n  var status=n>=6?'Resolved':n>=3?'Approved':n>=2?'Needs Jules':n>=1?'Checking':'New message';\n  if(!replay)status=decision==='review'?'Needs review':'Decision saved';\n  var body='<div class=\"contact\"><div class=\"avatar\">'+esc(member.initials||'EP')+'</div><div><strong>'+esc(member.name||'Eva Park')+'</strong><small>'+esc(d.caseId)+' · '+esc(d.subject)+'</small></div><span id=\"case-status\" class=\"status '+(n>=6?'done':'')+'\">'+status+'</span></div>';\n  body+='<div class=\"time\">'+esc(d.dateLabel)+' · '+esc(d.receivedAt)+'</div><div class=\"bubble\">'+esc(d.message)+'<small>'+esc(d.receivedAt)+'</small></div>';\n  if(n===0)body+='<div class=\"waiting\"><i></i>Looking up the booking and studio policy</div>';\n  if(n>=1)body+='<div class=\"case-note\">↳ '+esc(current.label)+' · '+esc(current.time)+' · '+esc(current.className)+'</div>';\n  if(n>=2&&replay){body+='<div class=\"thread\"><div class=\"thread-head\"><i class=\"dot\"></i>Internal · scene members</div><div class=\"thread-content\"><span class=\"mention\">@Jules</span> '+esc(d.question);if(n>=3)body+='<div class=\"manager\"><div class=\"avatar\">JR</div><p><strong>Jules Rivera</strong><small>Studio manager</small><br>'+esc(d.managerDecision)+'</p></div>';else body+='<div class=\"waiting\"><i></i>Waiting for Jules</div>';body+='</div></div>'}\n  if(n===3)body+='<div class=\"receipt\"><strong>Decision received.</strong> Turning Jules’ direction into the customer reply.</div>';\n  if(n>=4&&n<6){body+='<div class=\"draft\"><div class=\"draft-top\"><span>Reply to '+esc(member.name)+'</span><span>'+ (n===5?'Sending…':'From Jules’ decision')+'</span></div><textarea aria-label=\"Customer reply\" readonly>'+esc(d.reply)+'</textarea><div class=\"draft-bottom\"><span>'+esc(next.label)+' · '+esc(next.time)+'</span><span>'+(n===5?'Booking moved · sending reply':'Credit kept · one-time exception')+'</span></div></div>'}\n  if(n>=6){body+='<div class=\"bubble reply\">'+esc(d.reply)+'<small>Delivered ✓✓</small></div><div class=\"receipt\"><strong>Booking moved · credit kept.</strong><br>One-time exception approved by Jules. Kept with this conversation.</div>';if(n>=7)body+='<div class=\"return\"><div class=\"avatar\">LC</div><div><b>Next conversation · Lina</b>Can I join the waiting list for Sunday?</div><small>New</small></div>'}\n  if(!replay){body+='<div class=\"starter\"><label>Record your decision</label><div class=\"decision-options\"><button data-decision=\"review\">Needs review</button><button data-decision=\"approve\">Allow this change</button><button data-decision=\"decline\">Keep the booking</button></div><input id=\"decision-note\" aria-label=\"Decision note\" placeholder=\"Add a note for your team…\" maxlength=\"400\" value=\"'+esc(get('note',''))+'\"><p class=\"saved\" id=\"saved\">Kept with this conversation</p></div><div class=\"draft\"><div class=\"draft-top\"><span>Your reply draft</span><span>Not sent</span></div><textarea id=\"reply\" aria-label=\"Customer reply\" placeholder=\"Write the reply you want to send…\">'+esc(get('reply',''))+'</textarea><div class=\"draft-bottom\"><span id=\"reply-status\">Saved with this case as you type</span></div></div>'}\n  document.getElementById('conversation').innerHTML=body;\n  var context='<section><h2>Member</h2><div class=\"member\">'+esc(member.plan)+'</div><div class=\"muted\">'+esc(member.credits)+' credits remaining<br>'+esc(member.since)+'</div>';\n  if(n>=1)context+='<details><summary>Booking record</summary><p>'+esc(current.reference)+'<br>'+esc(current.label)+' · '+esc(current.time)+'<br>'+esc(current.className)+'</p></details>';\n  context+='</section>';\n  if(n>=1){context+='<section><h2>'+(n>=6?'New booking':'Available tomorrow')+'</h2><div class=\"session available\"><span class=\"date\">'+esc(next.label)+'</span><strong>'+esc(next.time)+'</strong><span class=\"class\">'+esc(next.className)+'</span><div class=\"capacity\"><i></i>'+(n>=6?'Confirmed':esc(next.spaces)+' spaces available')+'</div></div></section><section><h2>Studio policy</h2><div class=\"policy\"><b>'+esc(d.policyTitle)+'</b><br>'+esc(d.policy)+'</div></section>'}else context+='<section><h2>Tonight’s booking</h2><div class=\"session\"><span class=\"date\">'+esc(current.label)+'</span><strong>'+esc(current.time)+'</strong><span class=\"class\">'+esc(current.className)+'</span></div></section>';\n  document.getElementById('context').innerHTML=context;\n  if(replay)revealLatest(n>=7?'.return':n>=6?'.receipt':n>=4?'.draft':n>=3?'.receipt':n>=2?'.thread':null);\n  if(!replay){\n    var buttons=document.querySelectorAll('[data-decision]');var select=function(value){decision=value;buttons.forEach(function(b){b.setAttribute('aria-pressed',String(b.dataset.decision===value))})};select(decision);\n    buttons.forEach(function(b){b.addEventListener('click',function(){select(b.dataset.decision);set('decision',decision);document.getElementById('case-status').textContent=decision==='review'?'Needs review':'Decision saved';document.getElementById('saved').textContent='Decision saved with this conversation'})});\n    document.getElementById('decision-note').addEventListener('input',function(e){set('note',e.target.value)});\n    document.getElementById('reply').addEventListener('input',function(e){set('reply',e.target.value);document.getElementById('reply-status').textContent='Draft saved · not sent'});\n  }\n  function revealLatest(selector){\n    var target=selector&&document.querySelector(selector);\n    if(!target)return;\n    var follow=function(){window.scrollTo(0,Math.max(0,target.getBoundingClientRect().bottom+window.scrollY+12-window.innerHeight))};\n    requestAnimationFrame(follow);\n    window.addEventListener('resize',follow);\n  }\n})();\n</script></body></html>\n",
        "data": {
          "studio": "Atelier Studio",
          "caseId": "CASE-018",
          "subject": "Move a session",
          "dateLabel": "Thu, 17 Sep",
          "receivedAt": "16:10",
          "member": {
            "name": "Eva Park",
            "initials": "EP",
            "plan": "8-session pack",
            "credits": 2,
            "since": "Member since April"
          },
          "message": "Hi! Could I move my 18:30 session to tomorrow? I’m stuck at work and won’t make it tonight.",
          "currentSession": {
            "label": "Thu, 17 Sep",
            "time": "18:30",
            "className": "Reformer foundations",
            "reference": "Booking AT-2184"
          },
          "alternative": {
            "label": "Fri, 18 Sep",
            "time": "18:30",
            "className": "Reformer foundations",
            "spaces": 2
          },
          "policyTitle": "Changes within 12 hours",
          "policy": "A manager must approve a late move if the member is to keep their credit. Record the reason with the booking.",
          "firstVisit": {
            "name": "Noah Adams",
            "initials": "NA",
            "question": "Hi! Do you have a beginner class on Saturday? I’ve never tried reformer before.",
            "reply": "Absolutely! Reformer foundations is a great first class. We have space on Saturday at 10:00. Just arrive 10 minutes early and we’ll help you get settled.",
            "session": {
              "label": "Sat, 19 Sep",
              "time": "10:00",
              "className": "Reformer foundations",
              "spaces": 3
            },
            "guide": "Beginners welcome. Arrive 10 minutes early for an introduction to the equipment."
          }
        }
      },
      "layout": {
        "sortOrder": 0,
        "size": "xlarge"
      }
    },
    {
      "id": "policy",
      "type": "daslab/note",
      "name": "Studio policy",
      "fields": {
        "content": "# Session changes\n\nMembers may move a session at least 12 hours before it starts, subject to availability.\n\nInside 12 hours, a manager must approve an exception to preserve the credit. Keep their decision and the reason with the request. Confirm availability before changing a booking.\n\nA draft reply is not a sent message, and a suggested time is not a confirmed booking. Use connected accounts and the appropriate approval when taking either action.\n\n# First visits\n\nReformer foundations welcomes beginners. Arrive 10 minutes early for an introduction to the equipment. The sample schedule has three spaces on Saturday 19 September at 10:00."
      },
      "layout": {
        "sortOrder": 1,
        "size": "medium"
      }
    },
    {
      "id": "guide",
      "type": "daslab/note",
      "name": "Make this front desk yours",
      "fields": {
        "content": "# Make this front desk yours\n\nRead the sample request, check the booking and policy, then record a decision and draft a reply. Your notes stay with the conversation when you come back.\n\nAdd your own policies and try:\n\n> Help me handle this request using our policy. Show what you can answer and what needs a member of the team.\n\nInvite your colleagues to the scene. Use @mentions in a job to bring the right person into the conversation and keep their decision with the work.\n\nConnect your messaging and booking tools when you are ready to handle real requests. Ask Daslab to set up that flow around your accounts. This starter saves decisions and drafts; it does not send messages or change bookings.\n"
      },
      "layout": {
        "sortOrder": 2,
        "size": "medium"
      }
    }
  ],
  "meta": {
    "author": "Daslab",
    "license": "MIT"
  }
}
