# Workspace marks

> Page: https://docs.flung.dev/reference/workspace-marks. Index of every page: https://docs.flung.dev/llms.txt

`@flung.dev/flungies/marks` draws a mark for a workspace, a team or an organisation from its id: a squared tile pressed with one of the brand's patterns, in a two-tone pair, with the workspace's initials on top. People get Flungies, round characters with a face; workspaces get marks, so the two never read as one another.

| Person | Their Flungie | Workspace | Its mark |
|---|---|---|---|
| `usr_8f3k2` | Ocean wobbly with crown | Northwind Studio (`ws_northwind`) | NS: Mint into sky lines |
| `usr_01hzx3k9qv` | Ink wobbly with cap, backward | Kestrel Media (`ws_k2v9d3m8qp1tnb`) | KM: Rust into butter tiles |
| `usr_7d1c0b` | Lilac classic with beanie | Lumen Labs (`ws_c4r8x2wq7j0hsm`) | LL: Ink into plum tiles |
| `usr_a` | Ocean squat with antenna | Quill Agency (`ws_p0n6t3z9b5vy2e`) | QA: Moss into ocean ripples |
| `usr_b` | Ink squat with headphones | Kettle & Co (`ws_e9j3w5r1x8kq4d`) | KC: Lilac into rose tiles |
| `flung` | Ocean tall with crown | Acme (`ws_1`) | A: Coral into berry lines |

## TL;DR

| Question | Answer |
|---|---|
| How do I install it? | `npm install @flung.dev/flungies`, the same package as the Flungies. |
| What do I give it? | The workspace's id, which never changes, and its name, for the initials. A rename changes the letters, never the mark. |
| What does it give back? | An SVG string, from `workspaceMark()`. `<WorkspaceMark>` draws it in React and `<flung-mark>` as an element. |
| Where does it run? | Anywhere JavaScript runs: browsers, Node, Cloudflare Workers, Deno and Bun. The SVG needs no DOM. |
| How many are there? | 25,200 trait sets, before the phase that shifts each pattern on top of them. |
| When is it a Flungie instead? | When it stands for a person. A mark is for a workspace, a team, an organisation or anything else that is not someone. |

## What a mark is

`@flung.dev/flungies/marks` draws workspaces. People get Flungies, which are round characters with a face. Workspaces get marks, which are squared objects, so the two never read as one another:

- **A squircle** with a 22% corner radius, never a circle.
- **One of the brand's three patterns**, embossed or debossed: tiles, lines or ripples.
- **A two-tone pair** from the Flungies palette, lit like the brand wash: the ground at the top left, turning toward the tone at the bottom right.
- **The workspace's initials** in Funnel Display at 750, in a calm zone where the pattern fades out.
- **Two tiny speed lines** in a corner, sometimes, from 64 px.

## Try it

Type a workspace's name and see its mark at every size, with the traits its id picked. It opens on Northwind Studio.

On the page, a field takes a workspace's name for the initials and an id for the mark, and draws it large, at each size from 16 to 96 px, plain, and with its light sweep.

## Install

```bash
npm install @flung.dev/flungies
```

## Use

Flungies are for people. For workspaces, teams and organisations, `@flung.dev/flungies/marks` draws a workspace mark: a squircle pressed with one of three patterns (tiles, lines or ripples), in a two-tone colour pair, with the workspace's initials on top. A person is round and a workspace is square, so the two never read as one another.

```ts
import { workspaceMark, markTraits, renderMark, markInitials, plainMark } from '@flung.dev/flungies/marks'

workspaceMark(workspace.id, { size: 32, theme: 'dark', name: workspace.name })    // an SVG string
renderMark(markTraits(workspace.id, { pattern: 'ripples' }), { size: 256, animate: true })
markInitials('Northwind Studio')                                                    // 'NS'
plainMark(workspace.id, { size: 24, name: workspace.name })                         // initials on a tint, no pattern
```

Seed with the workspace's ID and pass its name for the initials, so a rename changes the letters but not the mark. Under 24 px a mark shows one letter.

| Option | For | Default |
|---|---|---|
| `size` | Pixels. The pattern is bolder under 32 px, and the signature lines and grain appear from 64 px. | `64` |
| `theme` | `'light'` or `'dark'`. The mark keeps its colours, and gains a rim only where it would melt into the page. | `'light'` |
| `name` | The workspace's display name, for the initials. Without it, the initials come from the seed. | none |
| `initials` | `'auto'`, letters of your own, or `false` for none. | `'auto'` |
| `grain` | `false` turns the grain off. | `true` |
| `animate` | A slow light sweep across the relief, from 64 px. Hidden under `prefers-reduced-motion`. | `false` |
| `id` | The prefix for the SVG's internal ids, for a server render that a browser hydrates. | a counter |
| `overrides` | Traits to set instead of the seed's (`{ pattern: 'lines', pair: 'ocean' }`). | none |
| `salt`, `palette`, `patterns` | For other products: a salt, your own colour pairs (`{ id, label, ground, tone }`), and `{ include }` or `{ exclude }` for the patterns. | none |

### Marks on a server

```ts
import { workspaceMark } from '@flung.dev/flungies/marks'

export default {
  fetch(request: Request): Response {
    const url = new URL(request.url)
    const id = url.searchParams.get('id') ?? ''
    const name = url.searchParams.get('name') ?? undefined
    const size = Math.min(512, Math.max(16, Number(url.searchParams.get('size')) || 64))
    const theme = url.searchParams.get('theme') === 'dark' ? 'dark' : 'light'
    return new Response(workspaceMark(id, { size, name, theme }), {
      headers: { 'content-type': 'image/svg+xml', 'cache-control': 'public, max-age=86400' },
    })
  },
}
```

The initials follow the name, which can change, so cache a mark for a day rather than forever, or put the name in the URL as above.

### Marks in React and as an element

```tsx
import { WorkspaceMark } from '@flung.dev/flungies/react'

<WorkspaceMark seed={workspace.id} name={workspace.name} size={32} />
<WorkspaceMark seed={workspace.id} name={workspace.name} size={96} theme="dark" animated />
```

```ts
import { defineWorkspaceMark } from '@flung.dev/flungies/element'
defineWorkspaceMark()   // registers <flung-mark>
```

```html
<flung-mark seed="ws_8f3k2" name="Northwind Studio" size="32" theme="dark"></flung-mark>
```

The element takes the attributes `seed`, `name`, `size`, `theme`, `initials` (letters, or `none`), `salt` and `animated`. On a page that may not assign `innerHTML`, append `toSvgElement(workspaceMark(...))`, which `/marks` exports too.

Also exported from `/marks`: `MARK_TRAITS` and the tables (`MARK_PAIRS`, `MARK_PATTERNS` and the rest), `markCombinations()` (25,200 discrete trait sets), `markPalette()`, `markGeometry()` and `describeMark()`, the accessible name each SVG carries.

## Size tiers

A mark is drawn for its size: a small one has fewer, bolder features and one letter, a large one gains the signature, the grain and the sweep.

| Size | What changes |
|---|---|
| Under 24 px | One letter. |
| Under 32 px | The features are 1.55 times larger, so fewer and bolder. The relief is a gradient across each feature, with no offset walls, and the calm zone is smaller. |
| 32 px and up | The relief is three draws of one path: a shaded wall, a lit wall, and a face that wears the ground gradient turned back by the pattern's lean, so only the walls show. The letters get a soft pressed shadow. |
| 64 px and up | The signature and the grain, which is `feTurbulence` specks sized in pixels. `animate` adds the light sweep (`MARK_SWEEP_MIN`). |

The sweep is a soft band, masked to the lit walls, that crosses the tile every 9 seconds in SMIL. A `<style>` inside the SVG hides it under `prefers-reduced-motion`, which leaves the still mark.

## Colour

- **Letters** are ink or paper, whichever contrasts more with the pair's midpoint. Every pair gives at least 4:1, as a Flungie's eyes do. The mark is decorative: the name always sits beside it.
- **Walls**: the lit wall is the ground mixed toward white, and the shaded wall the midpoint mixed toward a deep violet. Dark pairs, with a midpoint luminance under 0.12, mix toward black instead.
- **A rim**: if the midpoint's contrast with the page is under 1.5, a rim is stroked round the tile, lighter on the dark page and darker on the light one. Ink gets one on dark, and Butter on light.
- **The signature** uses the brand pair, peach over sky, unless another line pair stands further from the tile in OKLab.
- **`plainMark`**, the fallback with no pattern, tints the pair's ground 68% toward white (light) or 72% toward ink (dark), and holds its letters at 4.5:1.

## The stability promise

A workspace's mark never changes, as a person's Flungie never does: every release is checked against a fixed set of workspaces and the exact SVG each one draws, and a change that would alter one ships behind an option. Only the initials follow the name, so a rename changes the letters on the same mark.

## Traits

Every trait draws from a stream of its own, seeded by the id, so overriding one never changes another. The chance is how often an id picks the option; `overrides` picks it outright.

Every pattern, colour pair, finish, scale and angle, each on the mark of Northwind Studio.

### Patterns

One of the brand's three patterns, pressed into the tile.

| Option | Id | Chance |
|---|---|---|
| Tiles | `tiles` | 37% |
| Lines | `lines` | 31% |
| Ripples | `ripples` | 31% |

### Colour pairs

A ground, a Flungies body colour, turning toward its neighbour on the wheel.

| Pair | Id | Ground | Tone | Chance |
|---|---|---|---|---|
| Peach into coral | `peach` | `#FFA584` | `#FF8A72` | 10% |
| Sky into lilac | `sky` | `#86C0FF` | `#A6ACFF` | 10% |
| Butter into peach | `butter` | `#FFD66E` | `#FFB37A` | 7.8% |
| Mint into sky | `mint` | `#8EDDB5` | `#86CDE8` | 7.8% |
| Lilac into rose | `lilac` | `#BFA4FF` | `#E6A2E6` | 7.8% |
| Coral into berry | `coral` | `#FF7E6E` | `#EE6286` | 7.8% |
| Sand into peach | `sand` | `#DDB27A` | `#E2885C` | 3.1% |
| Cloud into sky | `cloud` | `#D2D5EA` | `#93B2E8` | 3.1% |
| Ink into plum | `ink` | `#2B2834` | `#3A2F57` | 7.0% |
| Ocean into plum | `ocean` | `#3F7EDB` | `#5A64CF` | 7.0% |
| Moss into ocean | `moss` | `#4E9A73` | `#3F8A99` | 7.0% |
| Plum into berry | `plum` | `#7457C9` | `#9A4FAE` | 7.0% |
| Berry into rust | `berry` | `#D2457E` | `#D25A5C` | 7.0% |
| Rust into butter | `rust` | `#C9643B` | `#D98A3A` | 7.0% |

### Finishes

Raised or pressed: pressed features swap the lit and shaded walls.

| Option | Id | Chance |
|---|---|---|
| Embossed (raised) | `emboss` | 58% |
| Debossed (pressed) | `deboss` | 42% |

### Scales

How large the features are, and so how many fit.

| Option | Id | Chance |
|---|---|---|
| Fine | `fine` | 28% |
| Medium | `medium` | 41% |
| Bold | `bold` | 31% |

### Angles

The lean of the pattern. 14 degrees is the lean of the mark.

| Option | Id | Chance |
|---|---|---|
| 14°, the brand lean | `14` | 31% |
| −14° | `-14` | 20% |
| 0° | `0` | 16% |
| 8° | `8` | 20% |
| 24° | `24` | 14% |

### Ripple centres

Where the rings start. Ripples only.

| Option | Id | Chance |
|---|---|---|
| Centre | `centre` | 11% |
| Top left | `topLeft` | 14% |
| Top right | `topRight` | 14% |
| Bottom left | `bottomLeft` | 14% |
| Bottom right | `bottomRight` | 17% |
| Left edge | `left` | 14% |
| Bottom edge | `bottom` | 14% |

### Line rhythms

The run of capsule lengths along each row. Lines only.

| Option | Id | Chance |
|---|---|---|
| Brand | `brand` | 36% |
| Dash and dot | `dash` | 24% |
| Long throws | `long` | 24% |
| Even | `even` | 17% |

### Signatures

Two tiny speed lines in a corner, from 64 px, or none.

| Option | Id | Chance |
|---|---|---|
| None | `none` | 36% |
| Top right | `topRight` | 20% |
| Bottom left | `bottomLeft` | 16% |
| Bottom right | `bottomRight` | 16% |
| Top left | `topLeft` | 11% |

## Accessibility

A mark is an image with a name: the SVG carries `role="img"` and an `aria-label` such as "Workspace mark NS: Mint into sky lines", which `describeMark()` returns too. The workspace's name almost always sits beside it, so there it is decorative: hide it with `aria-hidden="true"` on what holds it.

The letters are ink or paper, whichever stands further from the tile, at 4:1 or more. The sweep appears from `64` px only when asked for, and a style inside the SVG hides it under `prefers-reduced-motion`.

## See also

| Doc | Why |
|---|---|
| [Flungies](https://docs.flung.dev/reference/flungies.md) | The round characters the same package draws for people |
| [Brand](https://docs.flung.dev/brand.md) | The patterns the marks are pressed with, and the brand's colours |
