| 1 | # Whale Teams TUI — archived portrait-art reference |
| 2 | |
| 3 | > **Status — retired reference, not current brand authority.** This record |
| 4 | > preserves the removed hand-drawn portrait/crown treatment for historical |
| 5 | > comparison. Do not use its `▚△▞` treatment as a Codewhale mark or infer that |
| 6 | > `underwater.rs` renders it. The canonical mark is a raster asset and has no |
| 7 | > approved ASCII or block-glyph substitute. |
| 8 | |
| 9 | How the former Signal Cut mascots became terminal glyph art. The remaining |
| 10 | live runtime contract (role → species, state → evidence, inks) is |
| 11 | [`WHALE_TEAMS_TUI.md`](WHALE_TEAMS_TUI.md); this file is historical drawing |
| 12 | evidence only, not a specification for the startup hero or roster. |
| 13 | |
| 14 | Source of truth (CWC repo, read-only from here): |
| 15 | `docs/design/whale-teams/VISUAL-BRIEF.md`, the Signal Cut concept boards and |
| 16 | the six-role × six-state avatar matrix beside it, and the runtime contract |
| 17 | `apps/web/lib/product/whale-identity.ts`. Nothing is copied; the terminal art |
| 18 | is authored fresh from the same silhouette grammar. |
| 19 | |
| 20 | ## What the mascots actually say |
| 21 | |
| 22 | Read off the matrix and the working keyframes: |
| 23 | |
| 24 | - **Head at the left**, blunt or beaked nose, eye well forward. |
| 25 | - **Gold upper body, ink lower body**, with the role accent on the flipper. |
| 26 | - **Swept dorsal fin** about a third of the way back on an arched back. |
| 27 | - **The tail is attached.** A short tail stock leaves the body and rises |
| 28 | straight into the two-lobe fluke; the fluke sits *above* the body line. |
| 29 | - **One cyan cut** rides the belly. Cyan is the only water colour. |
| 30 | - **Working** adds bounded cyan wake dots *behind* the tail — never a change |
| 31 | of pose, expression, or scale. |
| 32 | |
| 33 | ## (a) Historical empty-state portrait |
| 34 | |
| 35 | Former `crates/tui/src/tui/underwater.rs` idle-art constants. The current |
| 36 | startup hero no longer uses this artwork and does not approximate the canonical |
| 37 | raster mark. |
| 38 | |
| 39 | ``` |
| 40 | ˚ |
| 41 | ▗▄▄▟▄▄▄▄▄▖ ▚△▞ |
| 42 | ▐█·████████▙▄▄▞ |
| 43 | ▝▀▀▀▀▀▀▀▀▘ |
| 44 | ``` |
| 45 | |
| 46 | uwu variant — same skeleton, one body cell shorter, blush and sparkle: |
| 47 | |
| 48 | ``` |
| 49 | ˚✦ |
| 50 | ▗▄▄▟▄▄▄▄▖ ▚△▞ |
| 51 | ▐█░·░█████▙▄▄▞ |
| 52 | ▝▀▀▀▀▀▀▀▘ |
| 53 | ``` |
| 54 | |
| 55 | What changed against the previous mark, and why: |
| 56 | |
| 57 | | Before | After | Reason | |
| 58 | | --- | --- | --- | |
| 59 | | Fluke `▚△▞` floated six columns clear of the body, one column off the stock | The fluke's notch `△` sits directly above the rising stock tip `▞` | The mascots' tail is attached and rises out of the body; a detached fluke reads as debris | |
| 60 | | `▙━━━━▞` — a four-cell rule leaving the flank at eye height | `▙▄▄▞` — the stock stays body mass and falls away before it rises | A long thin horizontal bar reads as a spear; the hero now uses no rule glyph at all | |
| 61 | | Flat rectangular back | `▗▄▄▟▄▄▄▄▄▖` — swept dorsal at ~35 % of the body | Dorsal fin is the roster's strongest shared silhouette cue | |
| 62 | | Belly closed in gold | Belly row is the **cyan current cut** | The mark's second colour finally appears; gold back over ink/cyan belly matches the mascots | |
| 63 | | 24 columns wide | 17 columns | Quieter at 60 columns; leaves the composer the room | |
| 64 | |
| 65 | The glyph vocabulary is deliberately the same one `whales::art` uses for the |
| 66 | six role portraits (`▗▄…▖` back, `▐█…▙` body, `▝▀…▘` belly, `▄` stock, |
| 67 | `▚△▞` crown fluke), so the hero and the `/fleet` roster are one animal at two |
| 68 | scales. Every glyph has a `glyphs::ascii_fallback` entry; with |
| 69 | `CODEWHALE_ASCII_SAFE=1` the hero narrows to |
| 70 | |
| 71 | ``` |
| 72 | o |
| 73 | .########. \^/ |
| 74 | |#.###########/ |
| 75 | .########. |
| 76 | ``` |
| 77 | |
| 78 | ## (b) Six role badges |
| 79 | |
| 80 | Already shipped — no new work in this pass. `whales::badge` renders a two-cell |
| 81 | species badge (feature glyph in the role accent + body cell) on |
| 82 | `/fleet` roster rows (`views/fleet_roster.rs`) and sub-agent worker rows |
| 83 | (`views/mod.rs`, `SubAgentsView`). Six full block-art whales in a list row was |
| 84 | never the plan; the badge plus the name and state word carries the identity. |
| 85 | The one open consumer named in `WHALE_TEAMS_TUI.md` is the Fleet setup role |
| 86 | pane. |
| 87 | |
| 88 | ## (c) State → the TUI's existing status vocabulary |
| 89 | |
| 90 | Also already shipped in `whales.rs`; restated here so the art has one home. |
| 91 | |
| 92 | | Signal Cut state | TUI cue | Evidence | |
| 93 | | --- | --- | --- | |
| 94 | | Resting | level float, no wake | completed child, idle/done session | |
| 95 | | Thinking | two cyan ticks over the head, badge `˚` | queued / starting / model wait | |
| 96 | | Working | bounded cyan wake under the tail, badge `·`/`˚` 4-frame 720 ms loop | running / running-tool receipt | |
| 97 | | Waiting for you | Signal Gold ring at the head, badge `◆` | pending question or approval | |
| 98 | | Blocked | still, nose against a vertical ink bar, badge `▌` | failed / budget exhausted | |
| 99 | | Offline | open outline, drained fill, badge `░` | cancelled | |
| 100 | |
| 101 | The hero is a **resting** whale and claims nothing: it renders only in the |
| 102 | empty state, carries no state cue, and its caustic sweep is decoration bound |
| 103 | to the motion policy, not a runtime signal. Glyph is always paired with a |
| 104 | word elsewhere; the hero has no word because it has no state. |
| 105 | |
| 106 | ## (d) Colorways → themes |
| 107 | |
| 108 | Only **Signal Classic** is represented. The hero resolves its inks through the |
| 109 | live `UiTheme`: gold body from `accent_action` (Signal Gold `#F6C453` on the |
| 110 | whale theme), and the spout and belly cut from |
| 111 | `whales::WhaleInk::from_theme(..).current` — brand cyan `#48D7FF` lifted to the |
| 112 | secondary-chrome contrast floor against the theme surface. That is a change: |
| 113 | the spout previously took each theme's `accent_secondary`. Using the Whale |
| 114 | Teams ink means the empty-state hero and the `/fleet` portraits speak the same |
| 115 | cyan in every theme, and light themes stay legible. |
| 116 | |
| 117 | `uwu` keeps its own art variant and its sakura eye/blush channel. |
| 118 | |
| 119 | Deep Current, Reef Shift, and Night Signal are **deferred**. They are colour |
| 120 | variation only — never role or state meaning — so a terminal that already |
| 121 | derives every ink from the active theme gains nothing from a second colour |
| 122 | axis. Revisit only if the TUI grows a whale-specific theme picker. |
| 123 | |
| 124 | `scripts/preview-whale-art.py` renders this comparison in true colour, in |
| 125 | plain text (`docs/design/whale-art-preview.txt`), and as a terminal-cell PNG |
| 126 | (`docs/design/whale-art-preview.png`). It reads the art constants straight out |
| 127 | of `underwater.rs`, so the preview cannot drift from the build. |
| 128 | |
| 129 | ## Not represented |
| 130 | |
| 131 | The four-frame working loop on the hero (it is a resting mark), the ambient |
| 132 | cameo glyphs in `ambient_life.rs`, `notifications.rs` `TITLE_WHALE_FRAMES`, the |
| 133 | legacy WhalePet atlas, and any raster asset. |
| 134 |