# Apollo DS — Patterns (long-tail)

The components in `components.css` cover the high-frequency primitives. Everything below is observed in the snapshot but appears once or twice — not enough usage to justify a named class. Documented here so a screen author can grab the right composition by name without having to re-derive it from the raw snapshot.

Every pattern shows the actual class string from `screens/apollo/auditor.html` (or wherever noted) and the semantic role it plays. Tailwind is fine to use here only if you're staying inside the snapshot's Tailwind layer — when porting these into a DS-only screen, translate them to `var(--*)` tokens.

---

## Three-pane workspace layout
**Used in:** Auditor (`/auditor`).
**Frame:** `<div class="h-screen flex flex-col bg-background overflow-hidden">` → `<header>` (fixed) + `<main class="flex-1 overflow-hidden">` (flex children) + tri-column row inside.

```
<main class="flex-1 overflow-hidden">
  <div class="flex h-full">
    <aside class="w-1/4 min-w-[280px] border-r border-border ...">[preview]</aside>
    <section class="flex-1 min-w-0 ...">[center tabs + body]</section>
    <aside class="w-1/5 min-w-[300px] border-l border-border ...">[task list]</aside>
  </div>
</main>
```
**Notes:** The right rail collapses to ~`w-1/5 min-w-[300px]`; left preview is `w-1/4 min-w-[280px]`. Center pane is `flex-1` so it eats the remaining space. The header is `border-b border-border bg-card shadow-sm flex-shrink-0`.

---

## Top header bar
**Used in:** Every page.
**Markup:**
```
<header class="border-b border-border bg-card shadow-sm flex-shrink-0">
  <div class="mx-auto px-6 py-4">
    <div class="flex items-center justify-between">
      <img src="./logo.svg" alt="Apollo" class="h-8" />
      <div class="flex items-center gap-4">
        <nav class="flex gap-2">[ap-nav-tab × 3]</nav>
        [avatar button]
      </div>
    </div>
  </div>
</header>
```

---

## Game-preview toolbar (left pane top)
**Used in:** Auditor left pane.
**Layout:** Two rows. Top row has tool buttons left + dropdowns right. Bottom is the build status bar (`Modified · 4.4 MB · Live`) with action icons.
**Build-status bar markup pattern:**
```
<div class="flex items-center justify-between px-3 py-2 border-b border-border text-xs">
  <div class="flex items-center gap-2 text-muted-foreground">
    <span class="font-medium text-foreground">Modified</span>
    <span class="text-muted-foreground/50">·</span>
    <span>4.4 MB</span>
    <span class="text-muted-foreground/50">·</span>
    <span class="inline-flex items-center gap-1 text-success"><span class="w-1.5 h-1.5 rounded-full bg-success"></span>Live</span>
  </div>
  <div class="flex gap-1">[icon buttons sm]</div>
</div>
```

---

## Console-log bar (left pane bottom)
**Used in:** Auditor left pane.
**Markup:**
```
<button class="flex items-center justify-between w-full px-3 py-2 text-xs text-muted-foreground border-t border-border bg-background hover:bg-muted/50">
  <span class="flex items-center gap-2"><svg class="lucide lucide-terminal" /> Console Logs - Modified <span class="ml-1 text-foreground font-semibold">[12]</span></span>
  <svg class="lucide lucide-chevron-down" />
</button>
```
**Notes:** Collapsible. Count badge inline next to the label.

---

## Composer (chat input bar)
**Used in:** Auditor → Chat tab, bottom of center pane.
**Markup:**
```
<div class="flex items-end gap-2 p-3 border-t border-border bg-background">
  [icon button: attach (+)]
  <textarea class="flex-1 resize-none rounded-md border border-input bg-background px-3 py-2 text-sm" placeholder="Type your message..." rows="1"></textarea>
  [primary icon button: send] [ghost icon button: more]
</div>
```
**Notes:** Send is `.ap-btn.primary.icon` and is disabled when the textarea is empty.

---

## Chat message header (above bubble)
**Used in:** Auditor → Chat tab.
**Markup:**
```
<div class="flex items-center gap-2 mb-1 text-xs text-muted-foreground">
  [pin button: hover-reveal]
  <span class="font-semibold text-foreground">Developer</span>
  <span>·</span>
  <span>May 2, 21:34</span>
  <button class="ml-auto text-xs text-muted-foreground hover:text-foreground">Restore Point</button>
</div>
```
**Notes:** "Viewing Latest Version" replaces the Restore Point button on the most-recent agent message and reads as a quiet inline label, no border.

---

## Attachment chip
**Used in:** Chat thread (inside the bubble for messages with attachments).
**Markup:**
```
<div class="inline-flex items-center gap-2 px-2 py-1.5 border border-border rounded-md bg-background hover:bg-muted/50 text-xs">
  <svg class="lucide lucide-file-video h-3.5 w-3.5 text-muted-foreground" />
  <span class="text-foreground font-medium">Modified-recording-2026-05-02.webm</span>
  <span class="text-muted-foreground">5.0 MB</span>
</div>
```
**Notes:** A row of these horizontally; sits below the bubble body. A `Download all` button (ghost, sm) sits at the row end.

---

## Status filter tab strip (right rail header)
**Used in:** Auditor → task list.
**Markup:**
```
<div role="tablist" class="flex items-center gap-1 px-2 py-1 border-b border-border overflow-x-auto">
  <button class="ap-tab active gap-1.5">All <span class="text-muted-foreground">(2762)</span></button>
  <button class="ap-tab"><svg /> <span class="text-muted-foreground">(675)</span></button>
  ...
</div>
```
**Notes:** Each filter is one `.ap-tab`. Counts trail in muted text. The first tab has a label; the rest are icon-only with their count.

---

## File tree row
**Used in:** Auditor → Files tab and Workspace tab.
**Markup:**
```
<button class="flex items-center gap-2 w-full px-2 py-1 rounded-sm hover:bg-muted/50 text-sm">
  <svg class="lucide lucide-chevron-right h-3 w-3 text-muted-foreground transition-transform" />
  <svg class="lucide lucide-folder h-3.5 w-3.5 text-muted-foreground" />
  <span class="text-foreground">apollo</span>
  <span class="ml-auto text-xs text-muted-foreground">6</span>
</button>
```
**Notes:** Indent is achieved with `pl-{n}` per nesting level. Expanded folders rotate the chevron via `data-state="open"`. Files (leaf nodes) replace the chevron with an empty 12px spacer and use `lucide-file-text` for the icon.

---

## Scene-tree row (Scene Editor tab)
**Used in:** Auditor → Scene Editor tab, left of the properties pane.
**Markup:**
```
<div class="flex items-center gap-2 px-2 py-1 rounded-sm hover:bg-muted/50 text-sm">
  <svg class="lucide lucide-chevron-down h-3 w-3 text-muted-foreground" />
  <svg class="lucide lucide-box h-3.5 w-3.5 text-primary" />
  <span class="text-foreground">_Container2</span>
  <button class="ml-auto opacity-0 group-hover:opacity-100"><svg class="lucide lucide-eye h-3.5 w-3.5 text-muted-foreground" /></button>
</div>
```
**Notes:** Same DOM shape as file-tree row; differs in icon (Phaser-style scene types) and the trailing visibility-toggle.

---

## Pinned-message panel (Pins tab)
**Used in:** Auditor → Pins tab.
**Markup:**
```
<article class="ap-card p-6 max-w-3xl">
  <header class="flex items-center gap-2 mb-3 text-xs text-muted-foreground">
    <span class="font-semibold text-foreground">Auditor</span> · <span>Apr 27, 11:40:33</span>
    <button class="ml-auto inline-flex items-center gap-1 text-foreground hover:text-primary"><svg class="lucide lucide-pin-off h-3.5 w-3.5" />Unpin</button>
  </header>
  <div class="prose prose-sm max-w-none">[long-form content]</div>
</article>
```

---

## Pagination footer (right rail bottom)
**Used in:** Auditor → task list.
**Markup:**
```
<div class="flex items-center justify-between px-4 py-3 border-t border-border text-xs">
  <span class="text-muted-foreground">Task 1 to 5 of 2748</span>
  <div class="flex items-center gap-1">
    [icon-sm button: chevron-left, disabled]
    <button class="ap-btn sm" data-active>1</button>
    [icon-sm button: chevron-right]
  </div>
</div>
```

---

## Breadcrumb / mode tabs (Create Task)
**Used in:** Create Task → Version / New Concept toggle.
**Markup:**
```
<div role="tablist" class="grid grid-cols-2 gap-0 p-1 rounded-md bg-muted h-10">
  <button class="ap-tab active">Version</button>
  <button class="ap-tab">New Concept</button>
</div>
```
**Notes:** Same `.ap-tab` primitive as the center-pane tabs, just inside a 2-cell grid container. Reuse rather than introducing a third tab class.

---

## File-upload zone (Create Task)
**Used in:** Create Task → Assets / Attachments.
**Markup:**
```
<label class="flex items-center justify-center gap-2 h-10 px-4 border border-input rounded-md cursor-pointer text-sm hover:bg-secondary text-foreground">
  <svg class="lucide lucide-upload h-4 w-4" /> Choose files...
  <input type="file" class="hidden" />
</label>
```
**Notes:** The label IS the visible button; the actual `<input>` is hidden. Same height/border treatment as other form controls so the form keeps a consistent vertical rhythm.

---

## Restore-point inline button
**Used in:** Chat thread, on every Developer message.
**Markup:**
```
<button class="ap-btn sm secondary"><svg class="lucide lucide-rotate-ccw h-3 w-3" />Restore Point</button>
```
**Notes:** Small, secondary, inline next to the timestamp. Treats restore as a "rewind" action; semantically different from a primary CTA.

---

## Avatar (header right)
**Used in:** Header.
**Markup:**
```
<button class="ap-btn ghost icon" aria-label="User menu">
  <span class="flex h-10 w-10 items-center justify-center rounded-full bg-muted text-foreground text-sm font-medium">I</span>
</button>
```
**Notes:** Apollo's avatar is a single-letter initial in a muted circle when no image is present. The button wrapper is a ghost icon button so the hover state matches the rest of the header chrome.

---

## Floating "Apply Changes" CTA (Scene Editor)
**Used in:** Auditor → Scene Editor tab, bottom-right of the preview pane.
**Markup:**
```
<button class="ap-btn primary fixed bottom-6 right-6 shadow-lg" style="background:hsl(var(--success));color:hsl(var(--success-foreground));">
  Apply Changes
</button>
```
**Notes:** Only visible when changes are pending. Uses success-green to read as "save", differentiated from the indigo "send/submit" primary buttons elsewhere.
