Files
crank/apps/ui/html/settings.html
T
2026-03-30 00:15:02 +03:00

598 lines
33 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<base href="../">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Crank — Settings</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/layout.css">
<link rel="stylesheet" href="css/pages.css">
<link rel="stylesheet" href="css/settings.css">
<script>try{if(!localStorage.getItem('crank_user'))window.location.replace('login.html');}catch(e){}</script>
<script src="js/config.js"></script>
<script src="js/i18n.js"></script>
<script src="js/workspace.js"></script>
</head>
<body>
<nav class="navbar">
<a href="index.html" class="nav-logo">
<div class="nav-logo-mark"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" fill="white"><path fill-rule="evenodd" d="M 10.000,1.800 L 12.287,3.962 L 15.408,3.557 L 15.987,6.650 L 18.750,8.157 L 17.400,11.000 L 18.750,13.843 L 15.987,15.350 L 15.408,18.443 L 12.287,18.038 L 10.000,20.200 L 7.713,18.038 L 4.592,18.443 L 4.013,15.350 L 1.250,13.843 L 2.600,11.000 L 1.250,8.157 L 4.013,6.650 L 4.592,3.557 L 7.713,3.962 Z M 12.800,11.000 A 2.8 2.8 0 1 0 7.200,11.000 A 2.8 2.8 0 1 0 12.800,11.000 Z"/><path fill-rule="evenodd" d="M 11.791,15.604 Q 16.083,17.179 21.375,21.154 A 2.00 2.00 0 1 1 23.625,17.846 Q 19.782,15.610 14.940,10.973 Z M 24.300,19.500 A 1.8 1.8 0 1 0 20.700,19.500 A 1.8 1.8 0 1 0 24.300,19.500 Z"/><path d="M 10.0,9.7 L 11.3,11.0 L 10.0,12.3 L 8.7,11.0 Z" fill="rgba(0,0,0,0.3)"/></svg></div>
<span class="nav-logo-text">Crank</span>
</a>
<!-- Workspace switcher -->
<div class="ws-switcher" id="ws-switcher">
<button class="ws-switcher-trigger" onclick="toggleWsSwitcher(event)">
<div class="ws-dot" id="ws-dot">A</div>
<span class="ws-current-name" id="ws-current-name">acme-workspace</span>
<svg width="11" height="11" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6l4 4 4-4"/></svg>
</button>
<div class="ws-dropdown" id="ws-dropdown" style="display:none">
<div class="ws-dropdown-label">Your workspaces</div>
<div id="ws-dropdown-list"></div>
<div class="ws-dropdown-footer">
<button class="ws-dropdown-create" onclick="window.location.href='workspace-setup.html?mode=create'">
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M8 3v10M3 8h10"/></svg>
Create workspace
</button>
</div>
</div>
</div>
<div class="nav-links">
<a href="index.html" class="nav-link" data-i18n="nav.operations">Operations</a>
<a href="html/agents.html" class="nav-link" data-i18n="nav.agents">Agents</a>
<a href="html/api-keys.html" class="nav-link" data-i18n="nav.apikeys">API Keys</a>
<a href="html/logs.html" class="nav-link" data-i18n="nav.logs">Logs</a>
<a href="html/usage.html" class="nav-link" data-i18n="nav.usage">Usage</a>
</div>
<div class="nav-right">
<button class="nav-hamburger" aria-label="Menu"><span></span><span></span><span></span></button>
<div class="nav-kbd">
<svg width="12" height="12"><use href="icons/general/grid.svg#icon"/></svg>
<span>⌘K</span>
</div>
<button class="nav-icon-btn" title="Notifications">
<svg width="15" height="15"><use href="icons/general/bell.svg#icon"/></svg>
</button>
<div class="nav-divider"></div>
<div class="user-menu">
<div class="nav-avatar" title="Account">AT</div>
<div class="user-dropdown">
<div class="user-dropdown-header">
<div class="user-dropdown-name">Operator</div>
<div class="user-dropdown-role">Admin · acme-workspace</div>
</div>
<button class="user-dropdown-item" data-action="settings-link">
<svg width="13" height="13"><use href="icons/general/settings.svg#icon"/></svg>
<span data-i18n="nav.settings">Settings</span>
</button>
<div class="dropdown-divider"></div>
<button class="user-dropdown-item danger" data-action="logout">
<svg width="13" height="13"><use href="icons/general/logout.svg#icon"/></svg>
<span data-i18n="nav.logout">Log out</span>
</button>
</div>
</div>
</div>
</nav>
<div class="mobile-nav">
<a href="index.html" class="mobile-nav-link" data-i18n="nav.operations">Operations</a>
<a href="html/agents.html" class="mobile-nav-link" data-i18n="nav.agents">Agents</a>
<a href="html/api-keys.html" class="mobile-nav-link" data-i18n="nav.apikeys">API Keys</a>
<a href="html/logs.html" class="mobile-nav-link" data-i18n="nav.logs">Logs</a>
<a href="html/usage.html" class="mobile-nav-link" data-i18n="nav.usage">Usage</a>
</div>
<div class="page">
<div class="page-header" style="margin-bottom: 24px;">
<div class="page-header-text">
<h1 class="page-title">Account settings</h1>
<p class="page-subtitle">Manage your personal profile, security, and notification preferences.</p>
</div>
</div>
<div class="settings-layout">
<!-- ── Sidebar nav ── -->
<nav class="settings-nav" id="settings-nav">
<button class="settings-nav-item active" data-section="profile">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<circle cx="8" cy="5" r="3"/>
<path d="M1.5 14.5c0-3.314 2.91-6 6.5-6s6.5 2.686 6.5 6"/>
</svg>
<span data-i18n="settings.nav.profile">Profile</span>
</button>
<button class="settings-nav-item" data-section="security">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 1L2 3.5v4.5C2 11.3 4.7 14.4 8 15c3.3-.6 6-3.7 6-7V3.5L8 1z"/>
</svg>
<span data-i18n="settings.nav.security">Security</span>
</button>
<button class="settings-nav-item" data-section="notifications">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 1.5a5 5 0 015 5v2.5l1 2H2l1-2V6.5a5 5 0 015-5z"/>
<path d="M6.5 13a1.5 1.5 0 003 0"/>
</svg>
<span data-i18n="settings.nav.notif">Notifications</span>
</button>
</nav>
<!-- ── Content ── -->
<div id="settings-content">
<div id="section-workspace" style="display:none;">
<div class="section-card" style="margin-bottom: 20px;">
<div class="section-card-header">
<div>
<div class="section-card-title" data-i18n="settings.ws.title">Workspace settings</div>
<div class="section-card-subtitle" data-i18n="settings.ws.subtitle">General information about your workspace</div>
</div>
</div>
<div class="section-card-body" style="padding-bottom:8px;">
<div class="field-group">
<label class="field-label" data-i18n="settings.ws.name">Workspace name</label>
<input class="field-input" type="text" value="acme-workspace" autocomplete="off">
<div class="field-hint">Used in API endpoints and across the console. Only lowercase letters, numbers and hyphens.</div>
</div>
<div class="field-group">
<label class="field-label" data-i18n="settings.ws.display">Display name</label>
<input class="field-input" type="text" value="Acme Corp" autocomplete="off">
</div>
<div class="field-group">
<label class="field-label">Description <span style="font-size:11px;color:var(--text-muted);">(optional)</span></label>
<textarea class="field-textarea" rows="2" placeholder="What does this workspace do?">Primary production workspace for CRM and e-commerce API operations.</textarea>
</div>
<div class="field-row">
<div class="field-group">
<label class="field-label" data-i18n="settings.ws.tz">Timezone</label>
<select class="field-select">
<option selected>UTC</option>
<option>America/New_York</option>
<option>America/Los_Angeles</option>
<option>Europe/London</option>
<option>Europe/Paris</option>
<option>Asia/Tokyo</option>
</select>
</div>
<div class="field-group">
<label class="field-label" data-i18n="settings.ws.protocol">Default protocol</label>
<select class="field-select">
<option selected>REST / HTTP</option>
<option>GraphQL</option>
<option>gRPC</option>
</select>
</div>
</div>
<!-- Language -->
<div class="field-group" style="margin-top:4px;">
<label class="field-label">
<span data-i18n="settings.lang.title">Language</span>
</label>
<div class="lang-switcher">
<button class="lang-btn active" data-lang="en" onclick="setLang('en')">
<span class="lang-flag">🇬🇧</span>
<span data-i18n="settings.lang.en">English</span>
</button>
<button class="lang-btn" data-lang="ru" onclick="setLang('ru')">
<span class="lang-flag">🇷🇺</span>
<span data-i18n="settings.lang.ru">Русский</span>
</button>
</div>
<div class="field-hint" data-i18n="settings.lang.subtitle">Interface display language</div>
</div>
<div style="display:flex;justify-content:flex-end;padding-top:4px;">
<button class="btn-primary" type="button"><span data-i18n="btn.save">Save changes</span></button>
</div>
</div>
</div>
</div>
<!-- ■ PROFILE ■ -->
<div id="section-profile" class="section-anchor">
<div class="section-card" style="margin-bottom: 20px;">
<div class="section-card-header">
<div class="section-card-title" data-i18n="settings.profile.title">Profile</div>
</div>
<div class="section-card-body">
<div class="avatar-upload">
<div class="avatar-large" id="profile-avatar">AT</div>
<div class="avatar-upload-actions">
<div class="avatar-name" id="profile-display-name">Operator</div>
<div class="avatar-sub" id="profile-email">operator@acme-workspace</div>
<button class="btn-secondary" type="button" style="padding:5px 12px;font-size:12.5px;">Change photo</button>
</div>
</div>
<div class="field-hint" style="margin-bottom:16px;">Avatar will appear in the console and team views.</div>
<div class="field-row">
<div class="field-group">
<label class="field-label">First name</label>
<input class="field-input" id="field-firstname" type="text" value="Operator" autocomplete="given-name">
</div>
<div class="field-group">
<label class="field-label">Last name</label>
<input class="field-input" id="field-lastname" type="text" value="" autocomplete="family-name" placeholder="Optional">
</div>
</div>
<div class="field-group">
<label class="field-label">Email address</label>
<input class="field-input" id="field-email" type="email" value="operator@acme.com" autocomplete="email">
<div class="field-hint">Changing email requires re-verification. You'll receive a confirmation link.</div>
</div>
<div style="display:flex;justify-content:flex-end;">
<button class="btn-primary" type="button">Save profile</button>
</div>
</div>
</div>
</div>
<!-- ■ MEMBERS — moved to workspace-setup.html ■ -->
<div id="section-members" style="display:none;">
<!-- Members card -->
<div class="section-card" style="margin-bottom: 16px;">
<div class="section-card-header">
<div>
<div class="section-card-title">Team members</div>
<div class="section-card-subtitle" id="members-count-label">4 members</div>
</div>
<button class="btn-primary" type="button" style="padding:7px 14px;font-size:13px;" onclick="toggleInviteForm()">
<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor" style="margin-right:4px;"><path d="M7.75 2a.75.75 0 01.75.75V7h4.25a.75.75 0 010 1.5H8.5v4.25a.75.75 0 01-1.5 0V8.5H2.75a.75.75 0 010-1.5H7V2.75A.75.75 0 017.75 2z"/></svg>
Invite member
</button>
</div>
<!-- Invite form -->
<div id="invite-form" style="display:none; padding: 0 20px 16px; border-bottom: 1px solid var(--border-subtle);">
<div style="display:flex; gap:10px; align-items:flex-end; flex-wrap:wrap;">
<div class="field-group" style="flex:1; min-width:200px; margin-bottom:0;">
<label class="field-label">Email address</label>
<input class="field-input" id="invite-email" type="email" placeholder="colleague@company.com" autocomplete="off">
</div>
<div class="field-group" style="width:150px; margin-bottom:0;">
<label class="field-label">Role</label>
<select class="field-input" id="invite-role">
<option value="admin">Admin</option>
<option value="developer" selected>Developer</option>
<option value="viewer">Viewer</option>
</select>
</div>
<button class="btn-primary" type="button" style="padding:7px 14px;font-size:13px;white-space:nowrap;" onclick="sendInvite()">Send invite</button>
<button class="btn-secondary" type="button" style="padding:7px 12px;font-size:13px;" onclick="toggleInviteForm()">Cancel</button>
</div>
<div id="invite-success" style="display:none; margin-top:10px; font-size:13px; color: #3fb950;">
✓ Invite sent successfully.
</div>
</div>
<!-- Members list -->
<div class="section-card-body" style="padding: 4px 20px 8px;" id="members-list">
<!-- Owner row (you) -->
<div class="member-row">
<div class="member-avatar" style="background:linear-gradient(135deg,#0d9488,#6366f1);">AT</div>
<div class="member-info">
<div class="member-name">Operator <span style="font-size:11px;font-weight:400;color:var(--text-muted);">(you)</span></div>
<div class="member-email">operator@acme.com</div>
</div>
<div class="member-last-active">Today</div>
<span class="member-role-badge role-owner">Owner</span>
</div>
<!-- Admin -->
<div class="member-row">
<div class="member-avatar" style="background:linear-gradient(135deg,#7c3aed,#4f46e5);">BS</div>
<div class="member-info">
<div class="member-name">Blake Smith</div>
<div class="member-email">blake@acme.com</div>
</div>
<div class="member-last-active">2 days ago</div>
<select class="member-role-select" onchange="updateRole(this, 'blake@acme.com')">
<option value="admin" selected>Admin</option>
<option value="developer">Developer</option>
<option value="viewer">Viewer</option>
</select>
<button class="member-remove-btn" onclick="removeMember(this, 'Blake Smith')" title="Remove member">
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M2 4h12M5 4V3a1 1 0 011-1h4a1 1 0 011 1v1M10 8v4M6 8v4"/><path d="M3 4l1 9a1 1 0 001 1h6a1 1 0 001-1l1-9"/></svg>
</button>
</div>
<!-- Developer -->
<div class="member-row">
<div class="member-avatar" style="background:linear-gradient(135deg,#d29922,#f59e0b);">CL</div>
<div class="member-info">
<div class="member-name">Carol Lane</div>
<div class="member-email">carol@acme.com</div>
</div>
<div class="member-last-active">1 week ago</div>
<select class="member-role-select" onchange="updateRole(this, 'carol@acme.com')">
<option value="admin">Admin</option>
<option value="developer" selected>Developer</option>
<option value="viewer">Viewer</option>
</select>
<button class="member-remove-btn" onclick="removeMember(this, 'Carol Lane')" title="Remove member">
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M2 4h12M5 4V3a1 1 0 011-1h4a1 1 0 011 1v1M10 8v4M6 8v4"/><path d="M3 4l1 9a1 1 0 001 1h6a1 1 0 001-1l1-9"/></svg>
</button>
</div>
<!-- Viewer -->
<div class="member-row">
<div class="member-avatar" style="background:linear-gradient(135deg,#0891b2,#06b6d4);">DM</div>
<div class="member-info">
<div class="member-name">Dan Morgan</div>
<div class="member-email">dan@acme.com</div>
</div>
<div class="member-last-active">Never</div>
<select class="member-role-select" onchange="updateRole(this, 'dan@acme.com')">
<option value="admin">Admin</option>
<option value="developer">Developer</option>
<option value="viewer" selected>Viewer</option>
</select>
<button class="member-remove-btn" onclick="removeMember(this, 'Dan Morgan')" title="Remove member">
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M2 4h12M5 4V3a1 1 0 011-1h4a1 1 0 011 1v1M10 8v4M6 8v4"/><path d="M3 4l1 9a1 1 0 001 1h6a1 1 0 001-1l1-9"/></svg>
</button>
</div>
</div>
<!-- Pending invites -->
<div id="pending-invites" style="border-top: 1px solid var(--border-subtle); padding: 12px 20px 16px;">
<div style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.06em;color:var(--text-muted);margin-bottom:10px;">Pending invites <span id="pending-count" style="background:rgba(139,148,158,0.15);border-radius:10px;padding:1px 7px;font-size:10px;">1</span></div>
<div class="member-row" id="invite-john">
<div class="member-avatar" style="background:var(--bg-canvas);border:1.5px dashed var(--border);color:var(--text-muted);font-size:16px;">?</div>
<div class="member-info">
<div class="member-name">john@startup.com</div>
<div class="member-email">Invited 3 days ago · not yet accepted</div>
</div>
<div class="member-last-active"></div>
<span class="member-role-badge" style="background:rgba(139,148,158,0.12);color:var(--text-muted);border:1px solid var(--border);">Developer</span>
<button class="member-remove-btn" onclick="revokeInvite(this)" title="Revoke invite">
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><line x1="2" y1="2" x2="14" y2="14"/><line x1="14" y1="2" x2="2" y2="14"/></svg>
</button>
</div>
</div>
</div>
<!-- Roles & permissions reference -->
<div class="section-card" style="margin-bottom: 20px;">
<div class="section-card-header">
<div class="section-card-title">Roles &amp; permissions</div>
</div>
<div class="section-card-body" style="padding: 4px 0 8px; gap: 0;">
<div class="role-def-row">
<span class="member-role-badge role-owner" style="min-width:80px;text-align:center;">Owner</span>
<div class="role-def-text">Full workspace control, billing access, can transfer or delete the workspace. Only one owner per workspace.</div>
</div>
<div class="role-def-row">
<span class="member-role-badge role-admin" style="min-width:80px;text-align:center;">Admin</span>
<div class="role-def-text">Manage members and roles, create and edit all operations and agents, manage API keys.</div>
</div>
<div class="role-def-row">
<span class="member-role-badge role-developer" style="min-width:80px;text-align:center;">Developer</span>
<div class="role-def-text">Create and edit operations and agents. Cannot manage members or workspace settings.</div>
</div>
<div class="role-def-row">
<span class="member-role-badge role-viewer" style="min-width:80px;text-align:center;">Viewer</span>
<div class="role-def-text">Read-only access to operations, agents, and logs. Cannot create or modify anything.</div>
</div>
</div>
</div>
</div>
<script>
function toggleInviteForm() {
var f = document.getElementById('invite-form');
var s = document.getElementById('invite-success');
if (f.style.display === 'none') {
f.style.display = '';
s.style.display = 'none';
document.getElementById('invite-email').focus();
} else {
f.style.display = 'none';
}
}
function sendInvite() {
var email = document.getElementById('invite-email').value.trim();
if (!email || !email.includes('@')) return;
document.getElementById('invite-success').style.display = '';
document.getElementById('invite-email').value = '';
}
function updateRole(select, email) {
// In production: API call to update role
console.log('Role updated:', email, '->', select.value);
}
function removeMember(btn, name) {
if (!confirm('Remove ' + name + ' from this workspace?')) return;
btn.closest('.member-row').remove();
updateMembersCount();
}
function revokeInvite(btn) {
btn.closest('.member-row').remove();
var pending = document.getElementById('pending-invites');
if (pending && !pending.querySelector('.member-row')) {
pending.style.display = 'none';
}
}
function updateMembersCount() {
var rows = document.querySelectorAll('#members-list .member-row');
var label = document.getElementById('members-count-label');
if (label) label.textContent = rows.length + ' member' + (rows.length !== 1 ? 's' : '');
}
</script>
<!-- ■ SECURITY ■ -->
<div id="section-security" class="section-anchor">
<div class="section-card" style="margin-bottom: 20px;">
<div class="section-card-header">
<div class="section-card-title">Security</div>
</div>
<div class="section-card-body" style="padding-bottom:8px;">
<div class="field-group">
<label class="field-label">Current password</label>
<input class="field-input" type="password" placeholder="••••••••" autocomplete="current-password">
</div>
<div class="field-row">
<div class="field-group">
<label class="field-label">New password</label>
<input class="field-input" type="password" placeholder="min. 12 characters" autocomplete="new-password">
</div>
<div class="field-group">
<label class="field-label">Confirm new password</label>
<input class="field-input" type="password" placeholder="••••••••" autocomplete="new-password">
</div>
</div>
<div style="display:flex;justify-content:flex-end;padding-bottom:8px;">
<button class="btn-primary" type="button">Change password</button>
</div>
</div>
<div style="padding: 4px 20px 16px;">
<div class="settings-section-divider" style="margin-top:0;"></div>
<div style="font-size:13.5px;font-weight:600;color:var(--text-primary);margin-bottom:12px;">Two-factor authentication</div>
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">TOTP authenticator app</div>
<div class="toggle-setting-desc">Use Google Authenticator, 1Password, or any TOTP-compatible app.</div>
</div>
<span class="badge badge-active" style="margin-right:8px;">Enabled</span>
<button class="btn-secondary" type="button" style="padding:5px 12px;font-size:12.5px;">Configure</button>
</div>
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">Hardware security key</div>
<div class="toggle-setting-desc">FIDO2 / WebAuthn passkey or YubiKey.</div>
</div>
<button class="btn-secondary" type="button" style="padding:5px 12px;font-size:12.5px;">Add key</button>
</div>
</div>
</div>
<div class="section-card" style="margin-bottom: 20px;">
<div class="section-card-header">
<div class="section-card-title">Active sessions</div>
</div>
<div style="padding: 8px 20px 16px;">
<div class="member-row">
<div class="member-info">
<div class="member-name">Chrome · macOS — <span style="color:var(--green);font-size:12px;">current</span></div>
<div class="member-email">Last active: now · 93.184.216.34 (US)</div>
</div>
</div>
<div class="member-row">
<div class="member-info">
<div class="member-name">Safari · iPhone</div>
<div class="member-email">Last active: 2 days ago · 93.184.216.34 (US)</div>
</div>
<button class="btn-icon danger" title="Revoke session">
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><line x1="1" y1="1" x2="11" y2="11"/><line x1="11" y1="1" x2="1" y2="11"/></svg>
</button>
</div>
<div class="member-row">
<div class="member-info">
<div class="member-name">Firefox · Linux</div>
<div class="member-email">Last active: 8 days ago · 172.16.0.4 (Internal)</div>
</div>
<button class="btn-icon danger" title="Revoke session">
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><line x1="1" y1="1" x2="11" y2="11"/><line x1="11" y1="1" x2="1" y2="11"/></svg>
</button>
</div>
</div>
</div>
</div>
<!-- ■ NOTIFICATIONS ■ -->
<div id="section-notifications" class="section-anchor">
<div class="section-card" style="margin-bottom: 20px;">
<div class="section-card-header">
<div class="section-card-title">Notification preferences</div>
</div>
<div style="padding: 8px 20px 16px;">
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">Operation error spike</div>
<div class="toggle-setting-desc">Alert when error rate exceeds 5% over a 5-minute window.</div>
</div>
<div class="toggle-sm on" onclick="this.classList.toggle('on')"></div>
</div>
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">Upstream latency degradation</div>
<div class="toggle-setting-desc">Alert when p99 latency exceeds the baseline by 3×.</div>
</div>
<div class="toggle-sm on" onclick="this.classList.toggle('on')"></div>
</div>
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">Quota approaching limit</div>
<div class="toggle-setting-desc">Email when any operation reaches 80% of its monthly quota.</div>
</div>
<div class="toggle-sm on" onclick="this.classList.toggle('on')"></div>
</div>
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">New team member joined</div>
<div class="toggle-setting-desc">Notify workspace admins when someone accepts an invite.</div>
</div>
<div class="toggle-sm" onclick="this.classList.toggle('on')"></div>
</div>
<div class="toggle-setting-row">
<div class="toggle-setting-text">
<div class="toggle-setting-label">Weekly usage digest</div>
<div class="toggle-setting-desc">Email summary of invocations, errors and latency each Monday.</div>
</div>
<div class="toggle-sm on" onclick="this.classList.toggle('on')"></div>
</div>
</div>
</div>
</div>
<!-- ■ DANGER ZONE — moved to workspace-setup.html ■ -->
<div id="section-danger" style="display:none;">
<div class="section-card" style="border-color: rgba(248,81,73,0.25);">
<div class="section-card-header" style="border-bottom-color: rgba(248,81,73,0.15);">
<div class="section-card-title" style="color: var(--red);">Danger zone</div>
</div>
<div>
<div class="danger-zone-action">
<div class="danger-zone-text">
<div class="danger-zone-title">Rename workspace</div>
<div class="danger-zone-desc">Changes the workspace slug used in all API endpoints. Existing API keys will continue to work. All existing tool call references will break.</div>
</div>
<button class="btn-danger" type="button">Rename</button>
</div>
<div class="danger-zone-action">
<div class="danger-zone-text">
<div class="danger-zone-title">Export all data</div>
<div class="danger-zone-desc">Download a ZIP archive of all operation configs, schemas, mappings and invocation history as JSON. May take a few minutes.</div>
</div>
<button class="btn-danger" type="button">Export</button>
</div>
<div class="danger-zone-action">
<div class="danger-zone-text">
<div class="danger-zone-title">Delete workspace</div>
<div class="danger-zone-desc">Permanently deletes all operations, keys, logs and settings. This action cannot be undone. You will be logged out immediately.</div>
</div>
<button class="btn-danger" type="button" onclick="if(confirm('Delete workspace? This cannot be undone.')) { localStorage.clear(); window.location.href = 'login.html'; }">Delete workspace</button>
</div>
</div>
</div>
</div>
</div><!-- /settings-content -->
</div><!-- /settings-layout -->
</div><!-- /page -->
<script src="js/nav.js"></script>
<script src="js/settings.js"></script>
</body>
</html>