392 lines
21 KiB
HTML
392 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8"/>
|
|
<title>FakeGPT</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Manrope:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="style.css"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
</head>
|
|
<body>
|
|
<div class="app-shell">
|
|
<section id="auth" class="card auth-card auth-card-compact">
|
|
<div class="auth-hero auth-hero-compact">
|
|
<div class="brand">
|
|
<div class="logo" data-theme-logo>FG</div>
|
|
<div>
|
|
<p class="eyebrow">Private chat</p>
|
|
<h1 data-theme-name>FakeGPT</h1>
|
|
</div>
|
|
</div>
|
|
<div class="hero-grid">
|
|
<article class="hero-panel">
|
|
<p>Sign in to start a chat immediately, then add personas when you want richer roleplay.</p>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="auth-panel">
|
|
<div class="auth-toggle">
|
|
<button class="toggle active" data-target="login">Login</button>
|
|
<button class="toggle" data-target="register">Register</button>
|
|
</div>
|
|
|
|
<div id="loginScreen" class="auth-screen active">
|
|
<form id="loginForm" class="auth-form">
|
|
<label class="field">
|
|
<span>Username</span>
|
|
<input id="loginUsername" placeholder="Enter your username" autocomplete="username"/>
|
|
</label>
|
|
<label class="field">
|
|
<span>Password</span>
|
|
<input id="loginPassword" type="password" placeholder="Enter your password" autocomplete="current-password"/>
|
|
</label>
|
|
<button id="loginSubmit" type="submit" class="primary-action">Sign in</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div id="registerScreen" class="auth-screen">
|
|
<form id="registerForm" class="auth-form">
|
|
<label class="field">
|
|
<span>Create username</span>
|
|
<input id="registerUsername" placeholder="Choose a username" autocomplete="new-username"/>
|
|
</label>
|
|
<label class="field">
|
|
<span>Create password</span>
|
|
<input id="registerPassword" type="password" placeholder="Create a password" autocomplete="new-password"/>
|
|
</label>
|
|
<div class="consent-container">
|
|
<input type="checkbox" id="consentCheckbox" required/>
|
|
<label for="consentCheckbox">
|
|
I agree to the
|
|
<a href="/tos.html" target="_blank">Terms of Service</a> and
|
|
<a href="/privacy.html" target="_blank">Privacy Policy</a>.
|
|
</label>
|
|
</div>
|
|
<button id="registerSubmit" type="submit" class="primary-action">Create account</button>
|
|
</form>
|
|
</div>
|
|
|
|
<p id="authMsg" class="status"></p>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="chat" class="card chat-card chat-focus-card" style="display:none;">
|
|
<div class="chat-layout chat-layout-focus">
|
|
<aside class="chat-sidebar">
|
|
<div class="sidebar-top">
|
|
<div class="sidebar-header">
|
|
<div>
|
|
<p class="eyebrow">Chats</p>
|
|
<h2>Conversations</h2>
|
|
</div>
|
|
<div class="sidebar-header-actions action-pair">
|
|
<button id="newChat" class="secondary-action" type="button">New chat</button>
|
|
<button id="startRoleplay" class="secondary-action" type="button">Start roleplay</button>
|
|
</div>
|
|
</div>
|
|
<label class="field compact-field">
|
|
<span>Search</span>
|
|
<input id="chatSearch" type="search" placeholder="Filter chat titles"/>
|
|
</label>
|
|
</div>
|
|
<div id="chatList" class="chat-list"></div>
|
|
<div id="chatListLoading" class="chat-loading hidden" role="status" aria-live="polite">
|
|
<span class="chat-loading-dot" aria-hidden="true"></span>
|
|
<span id="chatListLoadingText">Loading chats...</span>
|
|
</div>
|
|
<div class="sidebar-footer sidebar-footer-stack">
|
|
<details id="toolsDetails" class="tools-details">
|
|
<summary>Tools</summary>
|
|
<div class="tools-links">
|
|
<a href="/market" class="secondary-action">Browse personas</a>
|
|
<a href="/settings" class="secondary-action">Settings</a>
|
|
</div>
|
|
</details>
|
|
<details id="accountDetails" class="tools-details">
|
|
<summary>Account</summary>
|
|
<div class="session-chip">
|
|
<span class="session-chip-label">Signed in as</span>
|
|
<strong id="sessionUser">-</strong>
|
|
</div>
|
|
<button id="logout" type="button">Logout</button>
|
|
</details>
|
|
</div>
|
|
</aside>
|
|
|
|
<section class="chat-main chat-main-focus">
|
|
<header class="chat-header chat-header-focus">
|
|
<div class="chat-title-block">
|
|
<div class="chat-title">
|
|
<p class="eyebrow">Conversation</p>
|
|
<h2 id="activeChatTitle">New chat</h2>
|
|
<div class="chat-context">
|
|
<button id="contextChipButton" class="context-chip-button" type="button" aria-expanded="false" aria-controls="contextPopover">
|
|
<span>Context</span>
|
|
<strong id="contextSummaryLabel">Assistant</strong>
|
|
</button>
|
|
<div id="contextPopover" class="persona-popover hidden" role="dialog">
|
|
<div id="chatParticipants" class="chat-participants">
|
|
<span id="chatModePill" class="context-pill chat-mode-pill">Assistant mode</span>
|
|
<span id="chatCharacterPill" class="context-pill hidden">Character: none</span>
|
|
<span id="chatUserPersonaPill" class="context-pill hidden">User persona: none</span>
|
|
<span id="chatScenePill" class="context-pill hidden">Scene: none</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="chat-header-actions">
|
|
<div class="model-menu">
|
|
<button id="modelMenuButton" class="model-badge-button" type="button" aria-expanded="false" aria-controls="modelPopover">
|
|
<span class="model-badge-label"></span>
|
|
<strong id="modelBadgeName">Loading...</strong>
|
|
</button>
|
|
<div id="modelPopover" class="model-popover hidden" role="dialog">
|
|
<div class="model-select">
|
|
<div class="model-select-header">
|
|
<label for="model">Model</label>
|
|
<span id="modelCount" class="model-count">Loading</span>
|
|
</div>
|
|
<div class="model-select-control">
|
|
<select id="model">
|
|
<option disabled selected>Loading models...</option>
|
|
</select>
|
|
<span class="model-select-chevron" aria-hidden="true"></span>
|
|
</div>
|
|
</div>
|
|
<div id="modelHelp" class="model-help" aria-live="polite">
|
|
<div class="model-help-header">
|
|
<strong id="modelHelpTitle">Choose a model</strong>
|
|
<span id="modelHelpBadge" class="model-help-badge">Waiting</span>
|
|
</div>
|
|
<p id="modelHelpSummary" class="model-help-summary">Pick a model to see what it is best suited for.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="persona-menu">
|
|
<button id="personaMenuButton" class="secondary-action" type="button" aria-expanded="false" aria-controls="personaPopover">
|
|
You
|
|
</button>
|
|
<div id="personaPopover" class="persona-popover hidden" role="dialog">
|
|
<div class="persona-section">
|
|
<div class="persona-section-header">
|
|
<div>
|
|
<p class="eyebrow">User</p>
|
|
<h2>Your persona</h2>
|
|
<p class="persona-guidance">Adds context for how the assistant should read you.</p>
|
|
</div>
|
|
<div class="persona-section-actions">
|
|
<button id="clearUserPersona" class="secondary-action" type="button">Clear</button>
|
|
<a href="/settings" class="secondary-action">Manage</a>
|
|
</div>
|
|
</div>
|
|
<p id="activeUserPersonaStatus" class="status persona-status">No default user persona set.</p>
|
|
<div id="userPersonaList" class="persona-list"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="chat-actions-menu">
|
|
<button id="chatActionsMenuButton" class="secondary-action" type="button" aria-expanded="false" aria-controls="chatActionsPopover">
|
|
More
|
|
</button>
|
|
<div id="chatActionsPopover" class="persona-popover hidden" role="dialog">
|
|
<div class="persona-section">
|
|
<div class="persona-section-header">
|
|
<div>
|
|
<p class="eyebrow">Conversation</p>
|
|
<h2>Actions</h2>
|
|
</div>
|
|
</div>
|
|
<div class="persona-item-actions">
|
|
<button id="renameChat" class="icon-button" type="button">Rename</button>
|
|
<button id="clearChat" class="icon-button" type="button">Clear</button>
|
|
<button id="exportChat" class="icon-button" type="button">Export</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div id="chatActivityOverlay" class="chat-activity-overlay hidden" role="status" aria-live="polite" aria-atomic="true">
|
|
<div class="chat-activity-card">
|
|
<div class="chat-activity-mark" aria-hidden="true">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
<p id="chatActivityEyebrow" class="eyebrow">Please wait</p>
|
|
<h3 id="chatActivityTitle">Preparing chat</h3>
|
|
<p id="chatActivityDetail" class="subtitle">The assistant is still working.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="messages" class="messages-panel messages-panel-focus"></div>
|
|
|
|
<div class="input-shell input-shell-focus">
|
|
<div class="input-meta">
|
|
<p class="composer-hint">Enter to send · Shift+Enter for new line</p>
|
|
</div>
|
|
<div id="quickPrompts" class="quick-prompts" aria-label="Suggested starters"></div>
|
|
<div class="input-container">
|
|
<textarea id="msgInput" placeholder="Type your message..."></textarea>
|
|
<button id="send" type="button" aria-label="Send message"></button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div id="personaModal" class="modal-overlay hidden">
|
|
<div class="modal-card persona-modal-card">
|
|
<div class="modal-header">
|
|
<div class="persona-modal-heading">
|
|
<p class="eyebrow">Persona editor</p>
|
|
<h3 id="personaFormTitle">Create persona</h3>
|
|
</div>
|
|
<button id="personaClose" type="button" class="icon-button">Close</button>
|
|
</div>
|
|
<form id="personaForm" class="persona-form">
|
|
<div class="persona-form-intro">
|
|
<p class="persona-helper">AI Characters shape who you talk to. User personas add context for who you are in the scene.</p>
|
|
</div>
|
|
<p id="personaFormNotice" class="status hidden"></p>
|
|
<div class="persona-form-grid">
|
|
<label class="field field-wide">
|
|
<span>Persona for</span>
|
|
<select id="personaType">
|
|
<option value="assistant">AI Character</option>
|
|
<option value="user">Your persona</option>
|
|
</select>
|
|
</label>
|
|
<label class="field">
|
|
<span>Persona name</span>
|
|
<input id="personaName" placeholder="Persona name" required/>
|
|
</label>
|
|
<label class="field">
|
|
<span>Persona pronouns</span>
|
|
<input id="personaPronouns" placeholder="e.g. she/her, they/them"/>
|
|
</label>
|
|
<label class="field field-wide">
|
|
<span>Appearance</span>
|
|
<textarea id="personaAppearance" rows="3" placeholder="Describe their look"></textarea>
|
|
</label>
|
|
<label class="field field-wide">
|
|
<span>Background</span>
|
|
<textarea id="personaBackground" rows="3" placeholder="Backstory, history, role, or origins"></textarea>
|
|
</label>
|
|
<label class="field field-wide">
|
|
<span>Details</span>
|
|
<textarea id="personaDetails" rows="4" placeholder="Personality traits, voice, goals, quirks, boundaries, style"></textarea>
|
|
</label>
|
|
<label id="personaExamplesField" class="field field-wide hidden">
|
|
<span>Example dialogues</span>
|
|
<div class="dialogue-format-card" aria-hidden="true">
|
|
<p class="dialogue-format-label">Format</p>
|
|
<pre class="dialogue-format-example">{{character}}: Hello, my name is marc
|
|
{{user}}: Hi, Marc!
|
|
{{character}}: Nice to meet you</pre>
|
|
</div>
|
|
<textarea id="personaExampleDialogues" rows="5" placeholder="Write example exchanges that define the AI's tone, phrasing, pacing, and personality."></textarea>
|
|
</label>
|
|
</div>
|
|
<div class="persona-actions">
|
|
<button id="personaSave" type="submit" class="primary-action">Save persona</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="roleplayStarterModal" class="modal-overlay hidden">
|
|
<div class="modal-card roleplay-starter-card">
|
|
<div class="modal-header">
|
|
<div class="persona-modal-heading">
|
|
<p class="eyebrow">Start roleplay</p>
|
|
<h3 id="roleplayStarterTitle">Choose your roleplay</h3>
|
|
</div>
|
|
<button id="roleplayStarterClose" type="button" class="icon-button">Close</button>
|
|
</div>
|
|
<div class="roleplay-starter-intro">
|
|
<p id="roleplayStarterIntroCopy" class="persona-helper">Pick a character and choose who you are before moving on to the opening scene.</p>
|
|
</div>
|
|
<p id="roleplayStarterNotice" class="status hidden"></p>
|
|
<div class="roleplay-starter-actions">
|
|
<button id="roleplayNewPersona" class="secondary-action" type="button">Create AI Character</button>
|
|
</div>
|
|
<div id="roleplayStarterStepOne" class="persona-form-grid">
|
|
<label class="field field-wide">
|
|
<span>1. Character</span>
|
|
<select id="roleplayCharacterSelect"></select>
|
|
</label>
|
|
<label class="field field-wide">
|
|
<span>2. You in the scene</span>
|
|
<select id="roleplayUserPersonaSelect"></select>
|
|
</label>
|
|
</div>
|
|
<div id="roleplayStarterStepTwo" class="roleplay-starter-page hidden">
|
|
<label class="field field-wide">
|
|
<span>Optional opening direction</span>
|
|
<textarea id="roleplayScenarioInput" rows="4" placeholder="Describe the kind of opening scene you want, such as a setting, conflict, relationship dynamic, or mood. Leave it empty and the AI will invent its own scenario."></textarea>
|
|
</label>
|
|
<p class="subtitle">Leave this empty if you want the AI Character to invent the scenario on its own. No character limit.</p>
|
|
<div id="roleplayStarterSuggestions" class="quick-prompts" aria-label="Scenario suggestions"></div>
|
|
</div>
|
|
<div class="popup-actions">
|
|
<button id="roleplayStarterCancel" type="button" class="secondary-action">Cancel</button>
|
|
<button id="roleplayStarterBack" type="button" class="secondary-action hidden">Back</button>
|
|
<button id="roleplayStarterConfirm" type="button">Continue</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="popupModal" class="modal-overlay hidden">
|
|
<div class="modal-card popup-card" role="dialog" aria-modal="true" aria-labelledby="popupTitle" aria-describedby="popupDescription">
|
|
<div class="modal-header">
|
|
<div class="persona-modal-heading">
|
|
<p id="popupEyebrow" class="eyebrow">Action</p>
|
|
<h3 id="popupTitle">Confirm action</h3>
|
|
</div>
|
|
<button id="popupClose" type="button" class="icon-button">Close</button>
|
|
</div>
|
|
<div class="popup-content">
|
|
<p id="popupDescription" class="subtitle">Please confirm this action.</p>
|
|
<label id="popupField" class="field hidden">
|
|
<span id="popupInputLabel">Value</span>
|
|
<input id="popupInput" type="text" autocomplete="off"/>
|
|
</label>
|
|
</div>
|
|
<div class="popup-actions">
|
|
<button id="popupCancel" type="button" class="secondary-action">Cancel</button>
|
|
<button id="popupConfirm" type="button">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="onboardingModal" class="modal-overlay hidden">
|
|
<div class="modal-card onboarding-card">
|
|
<div class="modal-header">
|
|
<div class="persona-modal-heading">
|
|
<p class="eyebrow">Get started</p>
|
|
<h3 id="onboardingTitle">What do you want to do?</h3>
|
|
</div>
|
|
<button id="onboardingSkip" type="button" class="icon-button">Skip</button>
|
|
</div>
|
|
<p id="onboardingSubtitle" class="subtitle">Pick one path to set up your first successful chat.</p>
|
|
<div id="onboardingChoices" class="onboarding-choices"></div>
|
|
<div class="popup-actions">
|
|
<button id="onboardingBack" type="button" class="secondary-action hidden">Back</button>
|
|
<button id="onboardingContinue" type="button">Continue</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js" defer></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.min.js" defer></script>
|
|
<script src="script.js" defer></script>
|
|
</body>
|
|
</html>
|