Skip to content
zebrania.edu.pl

§ brand

Visual
identity.

Brand, colors, and typography for Zebrania.edu.pl — design system "A". Paste this address to an AI agent to keep pages, decks, and graphics consistent with the product.

https://zebrania.edu.pl/brand one page, made to copy from

§ 01 principles

Design principles

Five rules that settle every trade-off. Check them before you add a color, a shadow, or a new component.

01

Light by default, warm neutrals

The canvas is a warm white, never pure #fff or #000. Dark mode is derived from the same tokens via light-dark() — not a separate design. Sections stay legible and information-dense, with no dark "brand moments".

02

Moss for accent, olive for the button

Accent is split by role: moss (#82b842) colors links, chips, and active states; the CTA fill is a separate, deep olive (#4f7a12) with white text. Mid-tone greens sit in a contrast dead zone — neither black nor white text reads well on them.

03

Utilitarian minimalism

1px hairline borders plus a subtle elevation shadow — not either/or. 6px radius. One bordered surface per group of content; cards never nest inside cards.

04

Space Grotesk on display, Geist at work

Headings carry Space Grotesk. Body text and UI — Geist. Codes, addresses, and identifiers — Geist Mono. No other typeface enters the system.

05

Status kept separate from accent

Success, error, and warning have their own semantic tokens — the status green is a different green from the brand moss. Accent never doubles as a status message.

§ 02 neutrals

Canvas, surfaces, and text

Neutrals are warm — never pure #fff/#000. Every token declares a light-dark() pair; dark mode is the same tokens, not a separate palette.

--color-canvas
#faf9f8 · dark #14110d
Page canvas — warm white, never pure #fff
--color-surface
#ffffff · dark #1c1917
Cards, panels, raised surfaces
--color-border
#e7e2da · dark #34302a
1px borders — always thin, darkened rather than thickened
--color-ink
#1c1a17 · dark #f5f2ec
Primary text — warm black
--color-muted
#57534e · dark #a8a29a
Secondary text, metadata (≥4.5:1 on canvas)

§ 03 accent

Moss and olive — accent split by role

Moss colors tints and text; the CTA fill is a separate, deep olive with white text. This section exists because on mid-tone green, neither black nor white text reaches 4.5:1.

--color-accent
#82b842 · dark #9bcd5a
Moss — tints, chips, focus rings, active navigation. Never as a large fill.
--color-accent-strong
#4f7a12 · dark #b7e07a
Accent as text — links and highlights, safe for contrast
--color-accent-fill
#4f7a12 · both themes
Primary CTA fill — deep olive, dark in both themes
--color-accent-fill-strong
#3f6310 · both themes
CTA hover state
--color-accent-fg
#ffffff · both themes
Text on the CTA fill — always white
--color-success
#1a7f37 · dark #3fb950
Confirmations, completed states
--color-danger
#cf222e · dark #f85149
Errors, destructive actions
--color-warning
#b45309 · dark #d29922
Warnings, pending states

§ 04 typography

Space Grotesk on display, Geist at work

Three typefaces, three roles. Headings — Space Grotesk. Body text and UI — Geist. Class names, addresses, and identifiers — Geist Mono.

display · Space Grotesk

Aa Bb 123

var(--font-display)
h1–h6, hero headings

body · Geist

Aa Bb 123

var(--font-sans)
text, forms, navigation

mono · Geist Mono

Aa Bb 123

var(--font-mono)
class names, addresses, tokens
type scale
text-xs
The quick brown fox jumps
12px · Metadata, captions, footnotes
text-sm
The quick brown fox jumps
14px · Secondary text, card descriptions
text-base
The quick brown fox jumps
16px · Body text
text-lg
The quick brown fox jumps
18px · Intro paragraph
text-xl
The quick brown fox jumps
20px · Card heading
text-3xl
The quick brown fox jumps
30px · Section heading (mobile)
text-4xl
The quick brown fox jumps
36px · Section heading (desktop)
text-5xl
The quick brown fox jumps
48px · Hero heading (mobile)
text-7xl
The quick brown fox jumps
72px · Hero heading (desktop)

§ 05 components

Component patterns

Patterns used across the whole site. Copy them literally — do not invent new affordances for known tasks.

brand mark — the zebra

16px

24px

32px

64px

on fill

zebrania.edu.pl

lockup

One mark on every surface: favicon, site nav, app shell, help site, printed join poster and og-image (GH-2419). It is a single /favicon.svg, kept byte-identical in apps/www, apps/web and apps/help because the three build independently — change one, change all three. The hero's slot grid is a product motif, not the mark, and never stands in for it. Derived from the Noto Emoji zebra (Apache-2.0) with the viewBox cropped to the artwork so the whole animal fills the frame at 16px.

buttons — Button component

sm md lg primary
secondary
ghost
danger
danger-fill
success
loading
disabled
fullWidth
Action link Destructive link

Variants named by code: primary (olive CTA), secondary (outline), ghost (no fill), danger (destructive outline), danger-fill (full destructive CTA), success. Scale sm/md/lg plus loading/disabled/fullWidth states. Rendered with the real Button component — a twin of the app's (ADR-104), same tokens and classes.

icons — Icon component + registry

reserved
mine
disabled
conflict
ownDuty
pending
dismiss
warning
tip
dot

Names are intents (what the icon means), not shapes — swapping a glyph is one line in registry.ts, never at the call sites (GH-2006). Icons inherit color via currentColor and size via font-size. A twin of the app's (ADR-104).

chips and badges

Homeroom Active Pending Draft CODE-4A7

Role chip: moss tint /10 with a /30 border. Statuses: semantic-token tints /15. Codes (classes, tokens): Geist Mono on canvas with a border. Relationship context is always a label — never a role switcher (ADR-094 § 3).

top navigation bar

zebrania.edu.pl pl en Log in

The brand mark is the zebra — one mark across the marketing site, the app, the help site and the printed join poster (GH-2419). The active section reads as a filled slot, not an underline. Bar height and section scroll-margin read the same --site-nav-h token, and the slot corner radius is --radius-slot (2px, deliberately not --radius-xs). Log in carries secondary weight: the page's single filled accent button belongs to the hero's register CTA (GH-2246).

paginated table

Student Class Status Actions
Emma Clark 4a Active Edit
James Wilson 4a Pending Edit
Olivia Bennett 4b Draft Edit
1–3 of 24 Per page: 10 ▾
1 2 3 ›

Headers: mono, uppercase, --color-muted on canvas. Even rows: canvas tint /60. Pager inside the table card: count, page-size choice (user preference), and page buttons — the active page uses the CTA fill. Long content truncates with a tooltip — never wraps.

form — fields, switch, segments

Full name Emma Clark Visible to the class homeroom teacher.
Email address emma@example Enter a valid email address.
Email notifications Booking confirmations and reminders. Subject Teacher

Fields: bordered surface, moss focus ring. Error: outline plus --color-danger message. Switch: 999px track, checked uses the CTA fill. Segments: active one on a surface with a subtle shadow.

overlays and states — modal, toast, menu, empty state

✓ 2 3

New event

Step 2 of 3 — choose meeting times.
Back Next
Booking confirmed
Edit Duplicate Delete…

No events yet

Create your first meeting to see it here.

Modal: header/body/footer split by hairlines; wizard steps in the header; shadows only on overlays. Toast: inverted (--color-ink background, --color-canvas text), moss checkmark. Destructive menu items — --color-danger, always routed through the shared confirmation dialog. Empty state: dashed border.

navigation — rail and breadcrumbs

Classes 4a Emma Clark
School Dashboard Meetings 3 My children EC Emma (4a)

One left rail, no top bar (ADR-094 § 2). Active item: moss tint plus a --color-accent-strong icon. Groups labeled in mono uppercase. Children shown as initials avatars in a moss tint. Breadcrumbs for multi-level areas (Classes › 4a › Student): earlier levels clickable in --color-muted, the current level bold; one shared drill-down path for every entry point.

slot grid card — the product motif

Open House

Class 3B · March 15

7/16
✓
8:15
●
8:45
9:00
✓
⏰
9:45
●
10:15
—
10:45
🔒
11:15
●
11:45
  • Free — bordered surface, moss tint on hover
  • ✓ My booking — CTA fill · ● Booked by others — canvas
  • — Disabled · ⏰ Conflict between children (blocked) · 🔒 Own duty (stripes)

Non-bookable states explain themselves on click — an icon is never the sole carrier of meaning (ADR-094 § 4).

shell states — WakeIndicator, ShellNotice

The app is starting up

It had gone to sleep and is waking back up. This usually takes a few seconds.

WakeIndicator — role="status", aria-live="polite"

The app is starting up

It had gone to sleep and is waking back up. This takes a few seconds — please try again.

ShellNotice — role="alert"

The menu could not be loaded

The page itself is fine — only the navigation failed to load. Try again in a moment.

ShellNotice — role="alert"

Pending and failure states for the streamed app shell (ADR-122, GH-2416). WakeIndicator renders in the pending branch of the shell's {#await} while the backend wakes — a 600ms CSS reveal delay keeps a warm load from flashing it at all. ShellNotice covers the two terminal outcomes a streamed load cannot hand to +error.svelte: waking, and failed — Retry re-runs only the shell load, not the page beneath it.

§ 06 rules

Do and don't

A quick cheat sheet. When in doubt, pick the pattern already used on the homepage.

✓ do

  • Keep the light canvas (--color-canvas) as the default; dark mode only through light-dark() tokens.
  • Paint the primary CTA with the olive fill (--color-accent-fill) and white text (--color-accent-fg).
  • Use moss (--color-accent) only as a tint: /10–/15 backgrounds, chips, focus rings, active navigation.
  • Border card edges with a thin hairline (--color-border) and a 6px radius.
  • Set headings in Space Grotesk, body text in Geist, codes and addresses in Geist Mono.
  • Signal states with semantic tokens: --color-success, --color-danger, --color-warning.

✗ don't

  • Do not put dark text on a green fill — that is the rejected emerald variant with weak contrast.
  • Do not use pure #fff or #000 — neutrals are always warmed.
  • Do not fill large surfaces with moss; the accent is a spotlight, not paint.
  • Do not introduce new accent hues — moss, olive, and the status tokens are the full set.
  • Do not nest rounded cards inside cards; one bordered surface per group of content.
  • Do not build dark sections "for effect" — hierarchy is carried by typography and spacing, not a background inversion.

§ 07 for ai agents

Machine summary

Paste this block into an agent prompt to anchor the design decisions. Kept brief — the agent will infer the rest from this page.

prompt anchor
Design system: Zebrania.edu.pl ("system A", ADR-094)
Reference: https://zebrania.edu.pl/brand

Stack      Astro / SvelteKit + Tailwind CSS v4. Tokens as CSS variables
           in @theme, themed via light-dark() + [data-theme].
Fonts      Space Grotesk (display) · Geist (body/UI) · Geist Mono (codes).
Mood       Light-first, warm, dev-tool minimalist. Product for Polish
           schools — calm and trustworthy, not flashy.

Palette (light · dark)
  --color-canvas        #faf9f8 · #14110d   page canvas (warm, never #fff)
  --color-surface       #ffffff · #1c1917   cards, panels
  --color-border        #e7e2da · #34302a   1px hairlines
  --color-ink           #1c1a17 · #f5f2ec   primary text
  --color-muted         #57534e · #a8a29a   secondary text
  --color-accent        #82b842 · #9bcd5a   moss tint — links, chips, focus
  --color-accent-strong #4f7a12 · #b7e07a   accent-as-text
  --color-accent-fill   #4f7a12 (both)      primary CTA fill (deep olive)
  --color-accent-fg     #ffffff (both)      text on CTA fill
  --color-success       #1a7f37 · #3fb950
  --color-danger        #cf222e · #f85149
  --color-warning       #b45309 · #d29922

Brand mark (canonical, GH-2419)
  the zebra · /favicon.svg · one mark on every surface, no variants
  copies: apps/www/public · apps/web/src/lib/assets · apps/help
          byte-identical, no shared package — change one, change all three
  uses:   favicon · site nav · app shell · help site · join poster · og-image
  never   a second mark, a wordmark-only lockup, or the 🦓 emoji as a stand-in
  source  Noto Emoji U+1F993 (Apache-2.0), viewBox cropped to artwork bbox

Primary CTA
  bg: --color-accent-fill · text: --color-accent-fg (white) · bold
  radius: 6px · hover: --color-accent-fill-strong (#3f6310)

Chip / badge
  bg: accent at 10–15% opacity · text: --color-accent-strong · pill radius

Headline
  font: Space Grotesk · weight 700–800 · color: --color-ink

Body / UI
  font: Geist · 16px base · secondary text: --color-muted

Components (patterns from mockup "A", ADR-094 § 5)
  table    mono-uppercase headers on canvas · zebra rows (canvas/60)
           truncate + tooltip, never wrap
           pager inside the card: count · page-size select · page buttons
  chip     pill · role: accent/10 + accent/30 border · status: token/15
  switch   999px track · checked = --color-accent-fill
  modal    header/body/footer split by hairlines · wizard steps in header
           shadows on overlays ONLY (modal, toast, menus)
  toast    inverted: --color-ink bg, --color-canvas text, moss check
  ctxmenu  destructive items in --color-danger, routed via confirm dialog
  empty    dashed border on surface
  navrail  single left rail, no top bar · active = accent/10 tint
           child avatars: initials in moss tint
  crumbs   drill-down areas only (Klasy › 4a › Uczeń) · prior levels
           clickable in --color-muted · current level bold ink
  booking  slot states: free/mine/reserved/disabled/conflict/own-duty
           non-bookable states explain on click, icon never sole carrier
  shell    WakeIndicator (role=status, aria-live=polite, 600ms reveal
           delay) for the pending branch of the streamed shell load;
           ShellNotice (role=alert, waking/failed variants, Retry) for
           its two terminal outcomes (ADR-122, GH-2416)

Rules
  1 Light-first. Dark mode only via light-dark() tokens — never a redesign.
  2 Accent split by role: moss = tint/text, deep olive = CTA fill.
    Never dark text on a green fill (mid-green contrast dead zone).
  3 Warm neutrals only — no pure #fff/#000, no cool grays.
  4 1px hairline borders + subtle elevation shadow · radius 6px.
  5 Status colors are separate semantic tokens, never the brand accent.
  6 No new accent hues. Moss + olive + status tokens are the full set.
  7 One mark everywhere — the zebra. The hero's slot grid is a product
    motif, not the mark; it never stands in for the brand mark.