SchOS/docs/branding/README.md
Nexoniarz 1754cbf1aa console: a bare ESC[m is a reset, and OSC sequences are consumed
Two ANSI bugs, both found by running fastfetch rather than by reading the
parser, and both invisible to anything that spells its escapes out in full.

ESC[m with no parameters means ESC[0m. ECMA-48 is explicit that an omitted
parameter takes its default and SGR's default is 0, and sgr() iterated its
parameter list -- which is empty in exactly that case, so the loop body never
ran and the reset was silently dropped.

Programs emit the bare form constantly. fastfetch writes "\x1b[32m1%\x1b[m", so
everything after the first coloured character stayed green forever. With a
background colour it is much worse: its palette swatch sets a white background
and resets, the reset did nothing, and the console went white-on-white and
stayed there -- filling the screen with white rectangles as it scrolled, which
looks like a corrupted framebuffer rather than one missing branch.

OSC sequences were not a state at all, so ESC ] fell through and the payload
printed as text: a hyperlinked path arrived as "Disk (]8;;file:///\]8;;\)".
Nothing here acts on an operating-system command -- there is no window title and
no hyperlink to follow -- but *discarding* one is not optional, because the
alternative is printing somebody's URL into the middle of their output. ESC \
ends it, and an ESC followed by anything else is handed back to the escape state
rather than eaten, so a malformed OSC does not swallow the sequence after it.

Verified by screendumping the framebuffer after two consecutive fastfetch runs:
identical output both times, near-white coverage down from most of the screen to
2% (the palette swatch's own white cell), and the disk line reading "Disk (/)".

Also installs docs/branding/Ascii/ascii_50.txt as /usr/share/schos/logo.txt --
Shift as characters, at the width that leaves room for an info block on an
80-column console. Installed from the branding directory rather than copied into
sysroot by hand, so there is one source.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
2026-09-12 19:38:00 +02:00

216 lines
9.2 KiB
Markdown
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.

# Branding
Three marks, three different jobs. They are not interchangeable and the
difference is not stylistic.
| | | |
|---|---|---|
| **Shift** | *the logo* | An abstract mark. Non-human, non-animal. Signs the system. |
| **Guru** | *the icon* | A pictogram. Denotes one state. Has a face; has no body. |
| **SchCotie** | *the mascot* | A character. Has a body, poses and expressions. |
The distinction that decides everything else: **a mascot has to be able to
do things.** An icon works once, at one size, in one state. A character has to
work confused, pleased, asleep and from behind — which is why it costs more and
why it is drawn last.
---
## The one constraint everything answers to
**The kernel draws its mark as a 128×128 single-channel coverage mask.**
`include/logo.h` holds no colour at all — two pixels per byte, sixteen levels of
ink — and the kernel composites it in whatever `include/theme.h` says.
So any mark that will end up there has to survive as **a solid shape in one
colour at 128 px, and be recognisable at 24**. That rules out hairlines, thin
rings and anything that depends on a gradient to read. The mark this replaced
failed on all three counts.
Colour is therefore the *last* decision, never the first. Design the silhouette,
then colour it.
---
## Shift — the logo
`shift.svg`
Three slabs, displaced: the layer diagram in
[../architecture/README.md](../architecture/README.md) as a solid object, and
the kernel's name (**SchIFT**) as a shape.
- **Any colour.** This is a fact about the pipeline, not a preference — the
coverage mask carries none, so the loader draws it in metal and the kernel in
the theme accent, from the same bytes.
- **With or without a wordmark.** Set "SchOS" beside it in **Roboto Bold**,
which is already in the tree (`ports/Roboto`), already Apache-2.0, and already
in `NOTICE`.
- Non-human and non-animal, permanently. The character work belongs to
SchCotie; a logo that starts growing a face has taken the mascot's job.
## Guru — the icon
`guru.svg`
The crash face. Mythic rather than cartoon — closer to a temple carving than a
character — square or nearly so, with an expression that stays in the
`:(` / `:|` register.
**Purple, and only purple, and only here.** `theme.h` states the rule it
enforces:
> normal states are calm and dark; only failure is loud. PSOGM keeps the
> full-bleed purple entirely to itself, which is what makes it mean something.
That purple is `PSOGM_BG #4B1D9A`, and it is deliberately **not** the accent
`#7C5CFF`. If Guru ever appears in accent violet on a splash, a sticker or a
README header, the deep purple stops meaning *the machine stopped* — and it is
the only colour in the system that means anything at all.
So: Guru does not leave the crash screen.
## SchCotie — the mascot
*Not drawn yet.*
A daemon: **the process that works while nobody is watching.** The horns are a
pun on the word; the meaning is the background job that keeps running after you
have walked away — which is `schinit` supervising, restarting what dies, awake
at 3am. Patient and watchful rather than mischievous.
Horns carry **X** — POSIX, Unix, X11 — one substitution reading three ways.
Two constraints that follow from the section above. A thin X is two diagonal
strokes and dissolves at small sizes, so it wants to be **solid wedges with the
X notched out as negative space**: the horn silhouette survives downscaling and
the X appears as you get closer. And it needs a **turnaround** — front, side,
three-quarter, matching heights on shared construction lines — because a
character drawn once at one angle only ever works at that angle.
### The licensing point, which is not optional here
**The BSD daemon is copyrighted.** Marshall Kirk McKusick holds it and the terms
are not a free licence. A character that reads as "Beastie, but purple, with X
horns" is a derivative-work argument, and this mark would be in every image
SchOS ships, beside a `NOTICE` file this project has been careful about.
The concept is not the problem. A daemon is a Greek *daimon* and a Unix
background process — neither is ownable. What belongs to Beastie is the
execution: the pitchfork, the sneakers, that red, that face, that pose. Horns, a
tail and a small imp are generic and thousands of years old.
**Draw from the idea. Do not have a picture of Beastie open while you do it.**
---
## Colour
From `include/theme.h`, which is the source of truth. Nothing here restates a
value it does not already define.
| | | |
|---|---|---|
| `SCH_BG` | `#0C0E13` | Ground. Near-black with a blue cast, because pure black reads as "switched off". |
| `SCH_FG` | `#E6E8EC` | Primary text |
| `SCH_DIM` | `#707784` | Secondary |
| `SCH_ACCENT` | `#7C5CFF` | The one accent. Shift, SchCotie, anything calm. |
| `PSOGM_BG` | `#4B1D9A` | **Failure only.** Guru's ground and nothing else's. |
## File formats
**SVG, or PNG at high resolution with no lossy compression.** Nothing else.
No JPEG anywhere — a mark is flat colour with hard edges, which is the exact
case JPEG is worst at, and the ringing it leaves around an edge is permanent.
No screenshots of marks. No re-exports of re-exports: go back to the SVG.
**SVG is the source of truth for every mark.** A raster is something generated
from it, never edited.
## The mark as characters
`Ascii/ascii_{50,68,100,150}.txt` — Shift rendered in text at four widths, named
for the column count they fit in.
`make` installs the 50-column one as `/usr/share/schos/logo.txt`, because 50 is
what leaves room for an info block beside it on an 80-column console:
```sh
fastfetch --file-raw /usr/share/schos/logo.txt
```
Installed from here rather than copied into `sysroot/` by hand, so there is one
source and the build keeps them in step.
These are a *rendering* of the mark, not a second mark. If Shift changes they
are regenerated from it; they are not edited to taste, or the two drift and the
text one wins by being the one people see in a terminal.
## What is in here, and why a raster is committed
```
shift.svg the logo, in colour
shift-mask.svg the same geometry in greys -- see below
shift-mask.png rasterised from it, committed on purpose
uberblock.svg SchFS
guru.svg the crash icon
superseded-*.png the old wordmark, kept for reference only
```
The pipeline is three stages:
```
shift-mask.svg --(inkscape)--> shift-mask.png --(make logo)--> include/logo.h
```
**Both intermediates are committed, and that is deliberate.** `inkscape` is not
a build prerequisite — see [../guides/building.md](../guides/building.md) — so a
build that required a vector rasteriser would stop working on most hosts for the
sake of a file that changes about once a year. The PNG is regenerated by hand
when the SVG changes, and `make logo` turns it into the header.
### Why the mask is a separate file from the logo
`tools/python/mklogo.py` reads ink as `(255 - luminance) * alpha`, so **tones
survive as coverage** rather than being flattened — and the relationship
inverts: *darkest here is brightest on screen*. Copying the violet fills from
`shift.svg` would light the object from below.
So `shift-mask.svg` is the same geometry in greys chosen for how the mask reads.
Two files sharing one geometry is a drift hazard; the `<desc>` in both says so.
If either is edited, edit both.
---
## Where each mark is actually drawn
| | |
|---|---|
| Loader splash | Shift, from `include/logo.h`, shaded per row by `metal()` in `boot/common/ui.c` — silver, not accent. |
| Kernel console / early boot | Shift, same mask, composited flat in a theme colour by `gfx_draw_logo`. |
| PSOGM | Guru, drawn from primitives by `draw_guru()` in `kernel/core/panic.c`. Never a bitmap: it scales with the display and costs nothing in the kernel image. |
| Serial crash report | `:(`, as text. Guru cannot be drawn in ASCII, and a mood marker in a log is not the icon. |
| SchFS | **Nowhere yet.** `uberblock.svg` has no consumer; it is waiting for `projects/schfs-linux/` to have a README worth heading. |
One trap, since it has already been stepped in: `boot/common/ui.c` includes
`logo.h`, `theme.h` and `font.h`, and the Makefile rule for the loader did not
list them. A new logo therefore did not rebuild the loader — `make` reported
nothing to do and the splash kept drawing a mask compiled months earlier. The
kernel half never showed the problem because those objects are built with
`-MD -MP` and track their own headers. **Changing anything in here means the
loader must actually relink**, and that needs `clang` and `lld-link`.
## What this does not cover
- **No trademark position.** These are marks the project uses, not marks anyone
has registered or defended.
- **No usage rules for third parties** — nothing says what someone else may do
with them. Worth writing before anything is published.
- **SchCotie does not exist.** Everything above it is a brief, not a
description.
- **Guru is drawn but not wired in.** `panic.c` still renders `:(` from
primitives, and there is a real argument for keeping it — see the note in that
file about being "legible as a mood without being a picture of anything".
- **No wordmark lockup is specified.** "Roboto Bold beside it" is not a spacing
rule, a size ratio or a clear-space margin, and it will want to be.