Bug gixes, features added, GUI updates and more

This commit is contained in:
2026-02-12 14:29:35 +01:00
parent 52447b5e17
commit 7265d22438
21 changed files with 2187 additions and 123 deletions

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>com.rune.oAI.help</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>oAI Help</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>hbwr</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>HPDBookAccessPath</key>
<string>index.html</string>
<key>HPDBookIconPath</key>
<string>images/icon.png</string>
<key>HPDBookTitle</key>
<string>oAI Help</string>
<key>HPDBookType</key>
<string>3</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,550 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="AppleTitle" content="oAI Help">
<meta name="AppleIcon" content="images/icon.png">
<meta name="description" content="oAI - AI Chat Assistant for macOS">
<meta name="keywords" content="oAI, AI, chat, assistant, OpenAI, Anthropic, Claude, GPT, commands, help">
<title>oAI Help</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<header>
<img src="images/icon.png" alt="oAI Icon" class="app-icon">
<h1>oAI Help</h1>
<p class="subtitle">AI Chat Assistant for macOS</p>
</header>
<nav class="toc">
<h2>Contents</h2>
<ul>
<li><a href="#getting-started">Getting Started</a></li>
<li><a href="#providers">AI Providers &amp; API Keys</a></li>
<li><a href="#models">Selecting Models</a></li>
<li><a href="#sending-messages">Sending Messages</a></li>
<li><a href="#file-attachments">File Attachments</a></li>
<li><a href="#commands">Slash Commands</a></li>
<li><a href="#memory">Memory &amp; Context</a></li>
<li><a href="#online-mode">Online Mode (Web Search)</a></li>
<li><a href="#mcp">MCP (File Access)</a></li>
<li><a href="#conversations">Managing Conversations</a></li>
<li><a href="#keyboard-shortcuts">Keyboard Shortcuts</a></li>
<li><a href="#settings">Settings</a></li>
<li><a href="#system-prompts">System Prompts</a></li>
</ul>
</nav>
<main>
<!-- Getting Started -->
<section id="getting-started">
<h2>Getting Started</h2>
<p>oAI is a powerful AI chat assistant that connects to multiple AI providers including OpenAI, Anthropic, OpenRouter, and local models via Ollama.</p>
<div class="steps">
<h3>Quick Start</h3>
<ol>
<li><strong>Add an API key</strong>: Press <kbd>⌘,</kbd> to open Settings, then add your API key for your preferred provider</li>
<li><strong>Select a model</strong>: Press <kbd>⌘M</kbd> or type <code>/model</code> to choose an AI model</li>
<li><strong>Start chatting</strong>: Type your message and press <kbd>Return</kbd> to send</li>
</ol>
</div>
<div class="tip">
<strong>💡 Tip:</strong> Type <code>/</code> in the message input to see all available commands with autocomplete suggestions.
</div>
</section>
<!-- Providers -->
<section id="providers">
<h2>AI Providers &amp; API Keys</h2>
<p>oAI supports multiple AI providers. You'll need an API key from at least one provider to use the app.</p>
<h3>Supported Providers</h3>
<ul class="provider-list">
<li><strong>OpenRouter</strong> - Access to 300+ models through a single API (<a href="https://openrouter.ai">openrouter.ai</a>)</li>
<li><strong>Anthropic</strong> - Claude models (Opus, Sonnet, Haiku) (<a href="https://console.anthropic.com">console.anthropic.com</a>)</li>
<li><strong>OpenAI</strong> - GPT-4, GPT-4 Turbo, GPT-3.5 models (<a href="https://platform.openai.com">platform.openai.com</a>)</li>
<li><strong>Ollama</strong> - Run models locally on your Mac (<a href="https://ollama.ai">ollama.ai</a>)</li>
</ul>
<h3>Adding an API Key</h3>
<ol>
<li>Press <kbd>⌘,</kbd> or type <code>/config</code> to open Settings</li>
<li>Select the <strong>Providers</strong> tab</li>
<li>Enter your API key for the desired provider</li>
<li>Click <strong>Save</strong></li>
</ol>
<h3>Switching Providers</h3>
<p>Use the provider dropdown in the header or type:</p>
<code class="command">/provider anthropic</code>
<code class="command">/provider openai</code>
<code class="command">/provider openrouter</code>
</section>
<!-- Models -->
<section id="models">
<h2>Selecting Models</h2>
<p>Different models have different capabilities, speeds, and costs. Choose the right model for your task.</p>
<h3>Opening the Model Selector</h3>
<ul>
<li>Press <kbd>⌘M</kbd></li>
<li>Type <code>/model</code></li>
<li>Click the model name in the header</li>
</ul>
<h3>Model Information</h3>
<p>View details about any model:</p>
<code class="command">/info</code>
<p class="note">Shows information about the currently selected model including context length, pricing, and capabilities.</p>
<h3>Default Model</h3>
<p>Your selected model is automatically saved and will be restored when you restart the app.</p>
</section>
<!-- Sending Messages -->
<section id="sending-messages">
<h2>Sending Messages</h2>
<h3>Basic Usage</h3>
<ul>
<li>Type your message in the input field</li>
<li>Press <kbd>Return</kbd> to send (single-line messages)</li>
<li>Press <kbd>⇧Return</kbd> to add a new line without sending</li>
</ul>
<h3>During Generation</h3>
<p>While the AI is responding:</p>
<ul>
<li>Press <kbd>Esc</kbd> to cancel generation</li>
<li>Click the <strong>Stop</strong> button (red circle)</li>
<li>Cancelled responses show a <strong>⚠️ interrupted</strong> indicator</li>
</ul>
<h3>Retrying Messages</h3>
<p>If you're not satisfied with a response:</p>
<code class="command">/retry</code>
<p class="note">Resends your last message to generate a new response.</p>
</section>
<!-- File Attachments -->
<section id="file-attachments">
<h2>File Attachments</h2>
<p>Attach files to your messages for the AI to analyze. Supports images, PDFs, and text files.</p>
<h3>Attaching Files</h3>
<ul>
<li>Click the <strong>📎 paperclip icon</strong> to browse and select files</li>
<li>Type <code>@/path/to/file.txt</code> in your message</li>
<li>Type <code>@~/Documents/image.png</code> for files in your home directory</li>
</ul>
<h3>Supported File Types</h3>
<ul>
<li><strong>Images</strong>: PNG, JPEG, GIF, WebP, BMP, SVG (max 10 MB)</li>
<li><strong>Documents</strong>: PDF (max 10 MB)</li>
<li><strong>Text</strong>: TXT, code files, logs, etc. (max 50 KB)</li>
</ul>
<div class="tip">
<strong>💡 Tip:</strong> Large text files are automatically truncated to prevent token limits.
</div>
</section>
<!-- Commands -->
<section id="commands">
<h2>Slash Commands</h2>
<p>Commands start with <code>/</code> and provide quick access to features. Type <code>/</code> to see suggestions.</p>
<h3>Chat Commands</h3>
<dl class="commands">
<dt>/history</dt>
<dd>View command history with timestamps (European format: dd.MM.yyyy). Search by text or date to find previous messages</dd>
<dt>/clear</dt>
<dd>Clear all messages from the current session</dd>
<dt>/retry</dt>
<dd>Retry your last message to get a new response</dd>
<dt>/memory on|off</dt>
<dd>Toggle conversation memory. When off, only your latest message is sent (no conversation history)</dd>
<dt>/online on|off</dt>
<dd>Enable/disable web search. When on, the AI can search the web for current information</dd>
</dl>
<h3>Model &amp; Provider Commands</h3>
<dl class="commands">
<dt>/model</dt>
<dd>Open the model selector</dd>
<dt>/provider [name]</dt>
<dd>Switch AI provider or show current provider</dd>
<dt>/info</dt>
<dd>Display information about the current model</dd>
<dt>/credits</dt>
<dd>Check your account balance (OpenRouter only)</dd>
</dl>
<h3>Conversation Commands</h3>
<dl class="commands">
<dt>/save &lt;name&gt;</dt>
<dd>Save the current conversation</dd>
<dt>/load</dt>
<dd>Browse and load a saved conversation</dd>
<dt>/list</dt>
<dd>Show all saved conversations</dd>
<dt>/delete &lt;name&gt;</dt>
<dd>Delete a saved conversation</dd>
<dt>/export md|json</dt>
<dd>Export conversation as Markdown or JSON</dd>
</dl>
<h3>MCP Commands</h3>
<dl class="commands">
<dt>/mcp on|off</dt>
<dd>Enable/disable file access for the AI</dd>
<dt>/mcp add &lt;path&gt;</dt>
<dd>Grant AI access to a folder</dd>
<dt>/mcp remove &lt;path&gt;</dt>
<dd>Revoke AI access to a folder</dd>
<dt>/mcp list</dt>
<dd>Show all accessible folders</dd>
<dt>/mcp status</dt>
<dd>Display MCP status and permissions</dd>
<dt>/mcp write on|off</dt>
<dd>Enable/disable write permissions</dd>
</dl>
<h3>Settings Commands</h3>
<dl class="commands">
<dt>/config, /settings</dt>
<dd>Open the settings panel</dd>
<dt>/stats</dt>
<dd>Show session statistics (messages, tokens, cost)</dd>
</dl>
</section>
<!-- Memory -->
<section id="memory">
<h2>Memory &amp; Context</h2>
<p>Control how much conversation history the AI remembers.</p>
<h3>Memory Enabled (Default)</h3>
<p>When memory is <strong>on</strong>, the AI remembers all previous messages in your session. This allows for natural, flowing conversations.</p>
<h3>Memory Disabled</h3>
<p>When memory is <strong>off</strong>, only your latest message is sent. Each message is independent. Useful for:</p>
<ul>
<li>Quick, unrelated questions</li>
<li>Reducing token usage and cost</li>
<li>Avoiding context pollution</li>
</ul>
<h3>Toggle Memory</h3>
<code class="command">/memory on</code>
<code class="command">/memory off</code>
<div class="note">
<strong>Note:</strong> Memory state is shown in the header with a badge when enabled.
</div>
</section>
<!-- Online Mode -->
<section id="online-mode">
<h2>Online Mode (Web Search)</h2>
<p>Enable the AI to search the web for current information before responding.</p>
<h3>When to Use Online Mode</h3>
<ul>
<li>Questions about current events</li>
<li>Recent news or updates</li>
<li>Real-time data (weather, stocks, etc.)</li>
<li>Information beyond the AI's training cutoff</li>
</ul>
<h3>Enabling Online Mode</h3>
<code class="command">/online on</code>
<h3>How It Works</h3>
<p>When online mode is enabled:</p>
<ol>
<li>Your question is used to search the web</li>
<li>Relevant results are retrieved</li>
<li>Search results are added to your message context</li>
<li>The AI uses the web results to inform its response</li>
</ol>
<div class="note">
<strong>Note:</strong> Online mode is shown in the input bar with a 🌐 badge when active.
</div>
</section>
<!-- MCP -->
<section id="mcp">
<h2>MCP (File Access)</h2>
<p>MCP (Model Context Protocol) allows the AI to access, read, and optionally modify files on your computer.</p>
<div class="warning">
<strong>⚠️ Security:</strong> Only grant access to folders you trust the AI to work with. Review permissions carefully.
</div>
<h3>Setting Up MCP</h3>
<ol>
<li>Enable MCP: <code>/mcp on</code></li>
<li>Add a folder: <code>/mcp add ~/Projects/myapp</code></li>
<li>Ask the AI questions about your files</li>
</ol>
<h3>What the AI Can Do</h3>
<p><strong>Read permissions (always enabled when MCP is on):</strong></p>
<ul>
<li>Read file contents</li>
<li>List directory contents</li>
<li>Search for files</li>
<li>Get file information (size, modified date, etc.)</li>
</ul>
<p><strong>Write permissions (optional, disabled by default):</strong></p>
<ul>
<li>Write and edit files</li>
<li>Create new files</li>
<li>Delete files</li>
<li>Create directories</li>
<li>Move and copy files</li>
</ul>
<h3>Managing Permissions</h3>
<p>Toggle all write permissions:</p>
<code class="command">/mcp write on</code>
<code class="command">/mcp write off</code>
<p>For fine-grained control, open Settings → MCP to enable/disable individual permissions.</p>
<h3>Gitignore Respect</h3>
<p>When enabled in Settings, MCP will ignore files and folders listed in <code>.gitignore</code> files.</p>
<h3>Example Usage</h3>
<div class="example">
<p><strong>You:</strong> "What files are in my project folder?"</p>
<p><strong>AI:</strong> <em>(uses MCP to list files)</em> "I found 15 files including src/main.py, README.md..."</p>
</div>
</section>
<!-- Conversations -->
<section id="conversations">
<h2>Managing Conversations</h2>
<p>Save, load, and export your chat conversations.</p>
<h3>Saving Conversations</h3>
<code class="command">/save my-project-chat</code>
<p class="note">Saves all current messages under the specified name.</p>
<h3>Loading Conversations</h3>
<code class="command">/load</code>
<p class="note">Opens a list of saved conversations. Select one to load.</p>
<h3>Viewing Saved Conversations</h3>
<ul>
<li>Press <kbd>⌘L</kbd></li>
<li>Type <code>/list</code></li>
</ul>
<h3>Deleting Conversations</h3>
<code class="command">/delete old-chat</code>
<p class="warning"><strong>Warning:</strong> This action cannot be undone.</p>
<h3>Exporting Conversations</h3>
<p>Export to Markdown or JSON format:</p>
<code class="command">/export md</code>
<code class="command">/export json</code>
<p class="note">Files are saved to your Downloads folder.</p>
</section>
<!-- Keyboard Shortcuts -->
<section id="keyboard-shortcuts">
<h2>Keyboard Shortcuts</h2>
<p>Work faster with these keyboard shortcuts.</p>
<h3>General</h3>
<dl class="shortcuts">
<dt><kbd>⌘,</kbd></dt>
<dd>Open Settings</dd>
<dt><kbd>⌘/</kbd></dt>
<dd>Show in-app Help</dd>
<dt><kbd>⌘?</kbd></dt>
<dd>Open this Help (macOS Help)</dd>
<dt><kbd>⌘L</kbd></dt>
<dd>Browse Conversations</dd>
<dt><kbd>⌘H</kbd></dt>
<dd>Command History</dd>
<dt><kbd>⌘M</kbd></dt>
<dd>Model Selector</dd>
<dt><kbd>⌘K</kbd></dt>
<dd>Clear Chat</dd>
<dt><kbd>⇧⌘S</kbd></dt>
<dd>Show Statistics</dd>
</dl>
<h3>Message Input</h3>
<dl class="shortcuts">
<dt><kbd>Return</kbd></dt>
<dd>Send message (single-line messages)</dd>
<dt><kbd>⇧Return</kbd></dt>
<dd>New line (multi-line messages)</dd>
<dt><kbd>Esc</kbd></dt>
<dd>Cancel generation or close command dropdown</dd>
<dt><kbd></kbd> <kbd></kbd></dt>
<dd>Navigate command suggestions (when typing /)</dd>
<dt><kbd>Return</kbd></dt>
<dd>Select highlighted command (when dropdown is open)</dd>
</dl>
</section>
<!-- Settings -->
<section id="settings">
<h2>Settings</h2>
<p>Customize oAI to your preferences. Press <kbd>⌘,</kbd> to open Settings.</p>
<h3>Providers Tab</h3>
<ul>
<li>Add and manage API keys for different providers</li>
<li>Switch between providers</li>
<li>Set default models</li>
</ul>
<h3>MCP Tab</h3>
<ul>
<li>Manage folder access permissions</li>
<li>Enable/disable write operations</li>
<li>Configure gitignore respect</li>
</ul>
<h3>Appearance Tab</h3>
<ul>
<li>Adjust text sizes for input and dialog</li>
<li>Customize UI preferences</li>
</ul>
<h3>Advanced Tab</h3>
<ul>
<li>Enable/disable streaming responses</li>
<li>Set maximum tokens (response length limit)</li>
<li>Adjust temperature (creativity vs focus)</li>
<li>Configure system prompts (see below)</li>
</ul>
</section>
<!-- System Prompts -->
<section id="system-prompts">
<h2>System Prompts</h2>
<p>System prompts are instructions that define how the AI should behave and respond. They set the "personality" and guidelines for the AI before it sees any user messages.</p>
<div class="tip">
<strong>📚 Learn More:</strong> For a detailed explanation of system prompts and how they work, see <a href="https://en.wikipedia.org/wiki/Prompt_engineering" target="_blank">Prompt Engineering on Wikipedia</a> or the <a href="https://platform.openai.com/docs/guides/prompt-engineering" target="_blank">OpenAI Prompt Engineering Guide</a>.
</div>
<h3>What Are System Prompts?</h3>
<p>System prompts are special instructions sent to the AI with every conversation. Unlike your regular messages, system prompts:</p>
<ul>
<li>Are invisible to you in the chat interface</li>
<li>Set behavioral guidelines for the AI</li>
<li>Establish the AI's role, tone, and constraints</li>
<li>Are sent automatically with every message</li>
<li>Help ensure consistent, reliable responses</li>
</ul>
<h3>Default System Prompt</h3>
<p>oAI includes a carefully crafted default system prompt that emphasizes:</p>
<ul>
<li><strong>Accuracy First</strong> - Never invent information or make assumptions</li>
<li><strong>Ask for Clarification</strong> - Request details when requests are ambiguous</li>
<li><strong>Honest About Limitations</strong> - Clearly state when it cannot help</li>
<li><strong>Stay Grounded</strong> - Base responses on facts, not speculation</li>
<li><strong>Be Direct</strong> - Provide concise, relevant answers</li>
</ul>
<p class="note"><strong>Note:</strong> The default prompt is always active and cannot be disabled. It ensures the AI provides accurate, helpful responses and doesn't fabricate information.</p>
<h3>Custom System Prompt</h3>
<p>You can add your own custom instructions that will be appended to the default prompt. Use custom prompts to:</p>
<ul>
<li>Define a specific role (e.g., "You are a Python expert")</li>
<li>Set output format preferences (e.g., "Always provide code examples")</li>
<li>Add domain-specific knowledge or context</li>
<li>Establish tone or communication style</li>
<li>Create task-specific guidelines</li>
</ul>
<h3>How Prompts Are Combined</h3>
<p>When you send a message, oAI constructs the complete system prompt like this:</p>
<div class="example">
<p><strong>Complete System Prompt =</strong></p>
<ol>
<li>Default Prompt (always included)</li>
<li>+ Your Custom Prompt (if set)</li>
<li>+ MCP Instructions (if MCP is enabled)</li>
</ol>
<p><em>This combined prompt is sent with every message to ensure consistent behavior.</em></p>
</div>
<h3>Editing System Prompts</h3>
<p>To view or edit system prompts:</p>
<ol>
<li>Press <kbd>⌘,</kbd> to open Settings</li>
<li>Go to the <strong>Advanced</strong> tab</li>
<li>Scroll to the <strong>System Prompts</strong> section</li>
<li>View the default prompt (read-only)</li>
<li>Add your custom instructions in the editable field below</li>
</ol>
<h3>Best Practices</h3>
<ul>
<li><strong>Be Specific</strong> - Clear instructions produce better results</li>
<li><strong>Keep It Simple</strong> - Don't overcomplicate your custom prompt</li>
<li><strong>Test Changes</strong> - Try your prompt with a few messages to see if it works</li>
<li><strong>Start Empty</strong> - The default prompt works well; only add custom instructions if needed</li>
<li><strong>Avoid Contradictions</strong> - Don't contradict the default prompt's guidelines</li>
</ul>
<div class="warning">
<strong>⚠️ Important:</strong> Custom prompts affect all conversations. Changes apply immediately to new messages. If you experience unexpected behavior, try removing your custom prompt.
</div>
</section>
</main>
<footer>
<p>© 2026 oAI. For support or feedback, visit <a href="https://gitlab.pm/rune/oai-swift">gitlab.pm</a>.</p>
</footer>
</div>
</body>
</html>

View File

@@ -0,0 +1,389 @@
/* oAI Help Stylesheet - Apple Human Interface Guidelines */
:root {
--primary-color: #007AFF;
--secondary-color: #5856D6;
--success-color: #34C759;
--warning-color: #FF9500;
--error-color: #FF3B30;
--text-primary: #000000;
--text-secondary: #6E6E73;
--background: #FFFFFF;
--surface: #F5F5F7;
--border: #D1D1D6;
--code-bg: #F5F5F7;
--tip-bg: #E3F2FD;
--warning-bg: #FFF3E0;
}
@media (prefers-color-scheme: dark) {
:root {
--primary-color: #0A84FF;
--secondary-color: #5E5CE6;
--success-color: #32D74B;
--warning-color: #FF9F0A;
--error-color: #FF453A;
--text-primary: #FFFFFF;
--text-secondary: #A1A1A6;
--background: #1C1C1E;
--surface: #2C2C2E;
--border: #38383A;
--code-bg: #2C2C2E;
--tip-bg: #1A2631;
--warning-bg: #2B2116;
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 15px;
line-height: 1.6;
color: var(--text-primary);
background: var(--background);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
}
/* Header */
header {
text-align: center;
margin-bottom: 48px;
padding-bottom: 24px;
border-bottom: 1px solid var(--border);
}
.app-icon {
width: 96px;
height: 96px;
margin: 0 auto 24px;
display: block;
border-radius: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
header h1 {
font-size: 48px;
font-weight: 700;
letter-spacing: -0.5px;
margin-bottom: 8px;
}
.subtitle {
font-size: 19px;
color: var(--text-secondary);
font-weight: 400;
}
/* Table of Contents */
nav.toc {
background: var(--surface);
border-radius: 12px;
padding: 24px;
margin-bottom: 40px;
border: 1px solid var(--border);
}
nav.toc h2 {
font-size: 17px;
font-weight: 600;
margin-bottom: 16px;
}
nav.toc ul {
list-style: none;
}
nav.toc li {
margin-bottom: 8px;
}
nav.toc a {
color: var(--primary-color);
text-decoration: none;
font-size: 15px;
transition: opacity 0.2s;
}
nav.toc a:hover {
opacity: 0.7;
text-decoration: underline;
}
/* Main Content */
main {
margin-bottom: 48px;
}
section {
margin-bottom: 56px;
scroll-margin-top: 20px;
}
h2 {
font-size: 32px;
font-weight: 700;
margin-bottom: 16px;
letter-spacing: -0.3px;
}
h3 {
font-size: 22px;
font-weight: 600;
margin-top: 32px;
margin-bottom: 12px;
}
p {
margin-bottom: 16px;
color: var(--text-primary);
}
/* Lists */
ul, ol {
margin-bottom: 16px;
margin-left: 24px;
}
li {
margin-bottom: 8px;
}
ul.provider-list {
list-style: none;
margin-left: 0;
}
ul.provider-list li {
padding-left: 24px;
position: relative;
}
ul.provider-list li::before {
content: "•";
color: var(--primary-color);
font-weight: bold;
position: absolute;
left: 0;
}
/* Steps */
.steps {
background: var(--surface);
border-radius: 12px;
padding: 20px;
margin: 24px 0;
}
.steps h3 {
margin-top: 0;
margin-bottom: 16px;
font-size: 17px;
}
.steps ol {
margin-bottom: 0;
}
.steps li {
margin-bottom: 12px;
}
.steps li:last-child {
margin-bottom: 0;
}
/* Code and Commands */
code {
font-family: "SF Mono", Monaco, Menlo, Consolas, "Courier New", monospace;
font-size: 14px;
background: var(--code-bg);
padding: 2px 6px;
border-radius: 4px;
border: 1px solid var(--border);
}
code.command {
display: block;
padding: 12px;
margin: 8px 0;
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 8px;
font-size: 14px;
}
/* Keyboard Shortcuts */
kbd {
display: inline-block;
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
font-size: 13px;
font-weight: 600;
padding: 3px 8px;
background: linear-gradient(to bottom, var(--surface) 0%, var(--background) 100%);
border: 1px solid var(--border);
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
white-space: nowrap;
}
/* Definition Lists (for commands) */
dl.commands,
dl.shortcuts {
margin: 24px 0;
}
dl.commands dt,
dl.shortcuts dt {
font-family: "SF Mono", Monaco, Menlo, monospace;
font-size: 14px;
font-weight: 600;
background: var(--code-bg);
padding: 10px 12px;
border-radius: 8px 8px 0 0;
border: 1px solid var(--border);
border-bottom: none;
margin-top: 16px;
}
dl.commands dt:first-child,
dl.shortcuts dt:first-child {
margin-top: 0;
}
dl.commands dd,
dl.shortcuts dd {
background: var(--surface);
padding: 12px;
border-radius: 0 0 8px 8px;
border: 1px solid var(--border);
margin-bottom: 0;
color: var(--text-primary);
}
/* Callout Boxes */
.tip,
.note,
.warning {
padding: 16px;
border-radius: 10px;
margin: 20px 0;
border-left: 4px solid;
}
.tip {
background: var(--tip-bg);
border-left-color: var(--primary-color);
}
.note {
background: var(--surface);
border-left-color: var(--secondary-color);
}
.warning {
background: var(--warning-bg);
border-left-color: var(--warning-color);
}
.tip strong,
.note strong,
.warning strong {
display: block;
margin-bottom: 4px;
}
/* Examples */
.example {
background: var(--surface);
border-radius: 10px;
padding: 16px;
margin: 20px 0;
border: 1px solid var(--border);
}
.example p {
margin-bottom: 8px;
}
.example p:last-child {
margin-bottom: 0;
}
.example em {
color: var(--text-secondary);
font-style: italic;
}
/* Links */
a {
color: var(--primary-color);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* Footer */
footer {
text-align: center;
padding-top: 32px;
border-top: 1px solid var(--border);
color: var(--text-secondary);
font-size: 13px;
}
footer a {
color: var(--primary-color);
}
/* Responsive */
@media (max-width: 768px) {
.container {
padding: 24px 16px;
}
header h1 {
font-size: 36px;
}
h2 {
font-size: 28px;
}
h3 {
font-size: 20px;
}
}
/* Print Styles */
@media print {
body {
background: white;
color: black;
}
.container {
max-width: 100%;
}
section {
page-break-inside: avoid;
}
nav.toc {
page-break-after: always;
}
}