Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>MediFlow Assistant Prototype</title> | |
| <style> | |
| :root { | |
| color-scheme: light; | |
| --ink: #17202a; | |
| --muted: #566374; | |
| --line: #d8e0e8; | |
| --soft: #eef5f7; | |
| --teal: #0f766e; | |
| --blue: #1d4ed8; | |
| --red: #b42318; | |
| --white: #ffffff; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| } | |
| body { | |
| margin: 0; | |
| font-family: Arial, Helvetica, sans-serif; | |
| color: var(--ink); | |
| background: #f7fafc; | |
| } | |
| header { | |
| border-bottom: 1px solid var(--line); | |
| background: var(--white); | |
| } | |
| .wrap { | |
| width: min(1180px, calc(100% - 36px)); | |
| margin: 0 auto; | |
| } | |
| .nav { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| min-height: 68px; | |
| gap: 20px; | |
| } | |
| .brand { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| font-weight: 700; | |
| } | |
| .mark { | |
| display: grid; | |
| place-items: center; | |
| width: 38px; | |
| height: 38px; | |
| border-radius: 8px; | |
| color: var(--white); | |
| background: var(--teal); | |
| font-weight: 800; | |
| } | |
| .status { | |
| color: var(--muted); | |
| font-size: 14px; | |
| } | |
| main { | |
| padding: 34px 0; | |
| } | |
| .intro { | |
| display: grid; | |
| grid-template-columns: minmax(0, 1fr) auto; | |
| gap: 24px; | |
| align-items: end; | |
| margin-bottom: 24px; | |
| } | |
| h1 { | |
| max-width: 780px; | |
| margin: 0 0 12px; | |
| font-size: clamp(34px, 5.2vw, 62px); | |
| line-height: 1; | |
| letter-spacing: 0; | |
| } | |
| .lead { | |
| max-width: 720px; | |
| margin: 0; | |
| color: var(--muted); | |
| font-size: 18px; | |
| line-height: 1.55; | |
| } | |
| .button { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| min-height: 42px; | |
| padding: 0 14px; | |
| border: 1px solid var(--line); | |
| border-radius: 7px; | |
| color: var(--ink); | |
| background: var(--white); | |
| font-weight: 700; | |
| text-decoration: none; | |
| cursor: pointer; | |
| } | |
| .button.danger { | |
| color: var(--red); | |
| } | |
| .app-grid { | |
| display: grid; | |
| grid-template-columns: minmax(0, 1fr) 320px; | |
| gap: 20px; | |
| align-items: start; | |
| } | |
| .chat-shell, | |
| .side-panel { | |
| border: 1px solid var(--line); | |
| border-radius: 8px; | |
| background: var(--white); | |
| box-shadow: 0 18px 48px rgba(23, 32, 42, 0.08); | |
| overflow: hidden; | |
| } | |
| .chat-top, | |
| .side-top { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 16px; | |
| border-bottom: 1px solid var(--line); | |
| background: var(--soft); | |
| } | |
| .chat-top span, | |
| .side-top span { | |
| color: var(--muted); | |
| font-size: 13px; | |
| } | |
| .chat-log { | |
| display: grid; | |
| align-content: start; | |
| gap: 14px; | |
| height: min(64vh, 620px); | |
| min-height: 460px; | |
| padding: 18px; | |
| overflow-y: auto; | |
| background: linear-gradient(#ffffff, #fbfdff); | |
| } | |
| .message { | |
| max-width: min(82%, 680px); | |
| padding: 12px 14px; | |
| border-radius: 8px; | |
| line-height: 1.45; | |
| font-size: 15px; | |
| } | |
| .message.bot { | |
| justify-self: start; | |
| background: #e8f3f1; | |
| } | |
| .message.user { | |
| justify-self: end; | |
| color: var(--white); | |
| background: var(--blue); | |
| } | |
| .card-message { | |
| width: min(100%, 560px); | |
| background: #f8fafc; | |
| border: 1px solid var(--line); | |
| } | |
| .quick-actions { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| padding: 14px 18px 0; | |
| border-top: 1px solid var(--line); | |
| } | |
| .choice { | |
| min-height: 38px; | |
| padding: 8px 12px; | |
| border: 1px solid var(--line); | |
| border-radius: 7px; | |
| background: var(--white); | |
| color: var(--ink); | |
| font-weight: 700; | |
| cursor: pointer; | |
| } | |
| .choice:hover, | |
| .button:hover { | |
| border-color: var(--teal); | |
| } | |
| .chat-form { | |
| display: grid; | |
| grid-template-columns: minmax(0, 1fr) auto; | |
| gap: 10px; | |
| padding: 14px 18px 18px; | |
| } | |
| input { | |
| width: 100%; | |
| min-height: 44px; | |
| padding: 0 12px; | |
| border: 1px solid var(--line); | |
| border-radius: 7px; | |
| font: inherit; | |
| } | |
| input:focus { | |
| outline: 2px solid rgba(15, 118, 110, 0.22); | |
| border-color: var(--teal); | |
| } | |
| .side-stack { | |
| display: grid; | |
| gap: 20px; | |
| } | |
| .side-body { | |
| padding: 16px; | |
| } | |
| dl { | |
| display: grid; | |
| grid-template-columns: 100px 1fr; | |
| gap: 10px 12px; | |
| margin: 0; | |
| } | |
| dt { | |
| color: var(--muted); | |
| } | |
| dd { | |
| margin: 0; | |
| font-weight: 700; | |
| } | |
| .mini-card { | |
| display: grid; | |
| gap: 6px; | |
| padding: 12px; | |
| border: 1px solid var(--line); | |
| border-radius: 8px; | |
| background: #fbfdff; | |
| } | |
| .mini-card + .mini-card { | |
| margin-top: 10px; | |
| } | |
| .mini-card span { | |
| color: var(--muted); | |
| font-size: 14px; | |
| } | |
| .doctor-card { | |
| display: grid; | |
| grid-template-columns: 58px minmax(0, 1fr); | |
| gap: 14px; | |
| align-items: center; | |
| } | |
| .doctor-card div:last-child, | |
| .confirmation-card { | |
| display: grid; | |
| gap: 5px; | |
| } | |
| .doctor-card span, | |
| .confirmation-card span, | |
| .confirmation-card em, | |
| .doctor-card small { | |
| color: var(--muted); | |
| } | |
| .avatar { | |
| display: grid; | |
| place-items: center; | |
| width: 58px; | |
| height: 58px; | |
| border-radius: 8px; | |
| color: var(--white); | |
| background: var(--teal); | |
| font-size: 24px; | |
| font-weight: 800; | |
| } | |
| .confirmation-card { | |
| padding: 14px; | |
| border-left: 4px solid var(--teal); | |
| background: #ffffff; | |
| } | |
| .confirmation-card strong { | |
| font-size: 20px; | |
| } | |
| .note { | |
| margin-top: 20px; | |
| padding: 14px; | |
| border: 1px dashed var(--teal); | |
| border-radius: 8px; | |
| color: var(--muted); | |
| background: #f0fdfa; | |
| line-height: 1.5; | |
| } | |
| @media (max-width: 900px) { | |
| .intro, | |
| .app-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .chat-log { | |
| min-height: 420px; | |
| height: 58vh; | |
| } | |
| .message { | |
| max-width: 92%; | |
| } | |
| } | |
| @media (max-width: 560px) { | |
| .wrap { | |
| width: min(100% - 24px, 1180px); | |
| } | |
| .nav, | |
| .chat-form { | |
| grid-template-columns: 1fr; | |
| } | |
| .nav { | |
| align-items: flex-start; | |
| padding: 12px 0; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div class="wrap nav"> | |
| <div class="brand"> | |
| <span class="mark">M</span> | |
| <span>MediFlow Assistant</span> | |
| </div> | |
| <div class="status">Working local prototype</div> | |
| </div> | |
| </header> | |
| <main class="wrap"> | |
| <section class="intro"> | |
| <div> | |
| <h1>Hospital appointment support as an interactive chatbot.</h1> | |
| <p class="lead"> | |
| This prototype implements the portfolio project flow locally: | |
| booking, cancellation, FAQs, feedback, appointment memory, doctor | |
| cards, confirmation cards, and accessible text fallbacks. | |
| </p> | |
| </div> | |
| <a class="button" href="./PORTFOLIO_CASE_STUDY.md">Case study</a> | |
| </section> | |
| <section class="app-grid" aria-label="MediFlow Assistant interactive prototype"> | |
| <div class="chat-shell"> | |
| <div class="chat-top"> | |
| <strong>Prototype chat</strong> | |
| <span>No real patient data</span> | |
| </div> | |
| <div class="chat-log" data-chat-log aria-live="polite"></div> | |
| <div class="quick-actions" data-quick-actions></div> | |
| <form class="chat-form" data-chat-form> | |
| <input data-chat-input aria-label="Message MediFlow Assistant" autocomplete="off" placeholder="Type a request, symptom, FAQ, or appointment ID"> | |
| <button class="button" type="submit">Send</button> | |
| </form> | |
| </div> | |
| <aside class="side-stack"> | |
| <section class="side-panel"> | |
| <div class="side-top"> | |
| <strong>Memory</strong> | |
| <span>localStorage</span> | |
| </div> | |
| <div class="side-body"> | |
| <dl data-memory></dl> | |
| </div> | |
| </section> | |
| <section class="side-panel"> | |
| <div class="side-top"> | |
| <strong>Appointments</strong> | |
| <span>prototype only</span> | |
| </div> | |
| <div class="side-body" data-appointments></div> | |
| </section> | |
| <button class="button danger" type="button" data-reset>Reset prototype data</button> | |
| </aside> | |
| </section> | |
| <p class="note"> | |
| Botpress Cloud is still the intended production platform. This local | |
| prototype exists so the portfolio has a working interaction model before | |
| the Botpress Studio build and export are completed. | |
| </p> | |
| </main> | |
| <script src="./app.js"></script> | |
| </body> | |
| </html> | |