Reference

Design system

Every value below is parsed from src/styles/tokens.css at build time, so this page cannot drift from the stylesheet. Components consume semantic tokens only, never the raw ramps.

01

Colour

Raw ramps

Layer 1. Reference these only when defining a semantic alias.

  • --neutral-0#ffffff
  • --neutral-25#fdfcfd
  • --neutral-50#faf9fa
  • --neutral-100#f3f1f3
  • --neutral-200#e7e4e7
  • --neutral-300#d3ced2
  • --neutral-400#a9a3a8
  • --neutral-500#7e777d
  • --neutral-600#605a5f
  • --neutral-700#464146
  • --neutral-750#3c383c
  • --neutral-800#2d292c
  • --neutral-825#292527
  • --neutral-850#1c191b
  • --neutral-900#171416
  • --neutral-950#100e0f
  • --neutral-975#0b0a0b
  • --brand-100#ffe4f2
  • --brand-200#ffc2e0
  • --brand-300#fb8ec4
  • --brand-400#f5459f
  • --brand-500#e5007dHSLU corporate magenta
  • --brand-600#c00068
  • --brand-700#9b0054
  • --brand-800#6e003b
  • --brand-850#5c0033
  • --brand-900#2e0019

Semantic aliases

Layer 2. The only colours a component may use.

  • --color-bgvar(--neutral-50)page background
  • --color-bg-subtlevar(--neutral-100)alternating section band
  • --color-surfacevar(--neutral-0)card and panel fill, lifts off the page
  • --color-surface-sunkenvar(--neutral-100)inset wells, meters, code
  • --color-bordervar(--neutral-200)hairlines, dividers, card edges
  • --color-border-strongvar(--neutral-300)interactive edges, inputs
  • --color-textvar(--neutral-900)body copy and headings
  • --color-text-mutedvar(--neutral-600)secondary copy, dates, captions
  • --color-text-subtlevar(--neutral-500)eyebrows, meta, disabled
  • --color-text-inversevar(--neutral-25)copy on ink fills
  • --color-accentvar(--brand-600)accent *text*: links, emphasis
  • --color-accent-strongvar(--brand-700)accent text, hovered
  • --color-accent-fillvar(--brand-500)brand fill: buttons, rules, meters
  • --color-accent-fill-hovervar(--brand-600)brand fill, hovered
  • --color-accent-contrastvar(--neutral-25)copy on a brand fill
  • --color-accent-mutedvar(--brand-200)decorative marks and hairlines
  • --color-accent-softvar(--brand-100)accent tint backgrounds
  • --color-inkvar(--neutral-900)inverted surfaces, ink buttons, footer
  • --color-focusvar(--brand-500)focus ring
  • --color-selectionvar(--brand-200)::selection background
  • --color-scrimrgb(0 0 0 / 78%)gradient over video and photo
  • --color-on-mediavar(--neutral-0)copy burned over media

Themes

The same markup under both themes. Dark mode reassigns aliases in one block and followsprefers-color-scheme, with data-theme as an override hook.

Light

Body copy on paper, with an accent link anda highlight.

Tag

Dark

Body copy on ink, with an accent link anda highlight.

Tag

02

Typography

Families

One family: Archivo, self-hosted by Astro's font pipeline. Hierarchy comes from weight (400 to 900) and size, never from a second typeface. --family-display is an alias so components can say what they mean.

  • --family-display
  • --family-sans
  • --family-mono

Scale

Fluid between 360px and 1280px viewports.

  • --text-2xs0.625rem10px: micro-labels, mark captions
  • --text-xs0.75rem12px: nav, eyebrows, tag text
  • --text-sm0.8125rem13px: meta, dates, bio copy
  • --text-base0.9375rem15px: UI default
  • --text-mdclamp(0.9375rem, 0.9rem + 0.2vw, 1.0625rem)body copy
  • --text-lgclamp(1.0625rem, 1rem + 0.35vw, 1.25rem)lead paragraphs
  • --text-xlclamp(1.25rem, 1.14rem + 0.55vw, 1.625rem)card titles
  • --text-2xlclamp(1.5rem, 1.3rem + 1vw, 2.125rem)sub-heads
  • --text-sectionclamp(2rem, 1rem + 4.2vw, 3.5rem)uppercase section titles
  • --text-3xlclamp(2rem, 1.4rem + 2.6vw, 3.25rem)page titles
  • --text-displayclamp(2.75rem, 0.4rem + 9.4vw, 7.5rem)hero headline

Leading, tracking, weight

  • --leading-none1
  • --leading-display0.88stacked hero lines, set solid
  • --leading-tight1.05section titles
  • --leading-snug1.2headings
  • --leading-normal1.5UI text
  • --leading-relaxed1.6long-form prose
  • --tracking-display-0.038emhero, Black weight
  • --tracking-tight-0.028emsection titles
  • --tracking-snug-0.015emheadings
  • --tracking-normal0em
  • --tracking-wide0.04em
  • --tracking-caps0.11emuppercase labels
  • --weight-regular400
  • --weight-medium500
  • --weight-semibold600
  • --weight-bold700
  • --weight-black900display type only

Eyebrow · uppercase, tracked

Marketing+

Section title

Lead paragraph: sets up a section in one breath, sits at --text-lg in muted ink.

Body copy at --text-md on a --measure of 64 characters. Numbers such as CHF 50,000 and 2023–2026 use tabular figures so table rows and date rails never shift.

03

Space and layout

Space · 4px grid

  • --space-3xs0.25rem4px
  • --space-2xs0.5rem8px
  • --space-xs0.75rem12px
  • --space-s1rem16px
  • --space-m1.5rem24px
  • --space-l2rem32px
  • --space-xl3rem48px
  • --space-2xl4rem64px
  • --space-3xl6rem96px
  • --space-4xl8rem128px
  • --space-sectionclamp(3.5rem, 8vw, 7rem)vertical section rhythm

Layout

  • --measure64chmax prose line length
  • --width-narrow46rem
  • --width-content62rem
  • --width-wide78rem
  • --gutterclamp(1.25rem, 5vw, 4rem)

Shape

  • --radius-xs2px
  • --radius-sm4px
  • --radius-md8px
  • --radius-lg14px
  • --radius-pill999px
  • --border-hairline1px
  • --border-thick2px

Elevation

  • --shadow-sm
  • --shadow-md

Motion

  • --duration-fast120ms
  • --duration-base200ms
  • --duration-slow360ms
  • --ease-outcubic-bezier(0.22, 1, 0.36, 1)
  • --ease-in-outcubic-bezier(0.65, 0, 0.35, 1)
  • --ring-width2px
  • --ring-offset2px

04

Primitives

Button

Renders <a> with href, otherwise<button>. Three variants, three sizes.

Link button

Tag

Non-interactive label. Neutral for tools, accent for emphasis.

NeutralAccentOutlineSmallSmall accentLarge accent

Card

Three tones, an optional accent rule, and whole-card linking when givenhref.

Surface, default padding.

Subtle, small padding.

Accent tint.

Interactive, with rule. Hover me.

Stat

Headline metric in the display face, tabular figures.

70+

Events delivered

Across Swiss sections

CHF 50k

Budget per event

3.3

Profitability index

Launch campaign

LevelBar

CEFR proficiency. Label and level text carry the meaning; the pips are decorative.

English

C2

German

B2

Polish

A2

Ukrainian

Native

TimelineEntry

Period rail plus substance. Bullets are authored in the slot.

Jun 2023 – Jun 2026

Switzerland

National Event Manager

ESN Switzerland

  • Planned and delivered 70+ events across Swiss university sections.
  • Led multinational teams for events with 300+ participants.

PartnerWall

Linked chips for sponsors and stakeholders. Each chip shows the brand's own unmodified mark, or the partner's name when no licence-clean asset exists. Marks stay on a light plate in both themes: recolouring a trademark is what guidelines forbid.

Nav and Footer

Both render once per page from Layout.astro: the bar at the top of this page and the closing band below are the live instances. Neither takes page-level props beyond its link list.

05

Utilities

These helpers cover layout and typographic roles so components stay free of one-off wrappers. Anything with state or variants belongs in src/components/ui/ instead.

.container
Centred measure and gutter. data-width="narrow | wide".
.stack
Vertical rhythm; override --stack-gap.
.cluster
Wrapping horizontal group; override --cluster-gap.
.grid
Auto-fit columns; override --grid-min and --grid-gap.
.prose / .lead
Long-form measure and paragraph spacing.
.eyebrow / .meta
Section labels and secondary text.
.visually-hidden
Screen-reader-only text; stays visible on focus.
data-numeric
Tabular figures for dates, budgets and metrics.
.display
Hero voice: Black, uppercase, set solid. Once per page.
.section-title
The same voice one register down; applied by Section.
.eyebrow[data-size="xs"]
10px micro-label for mark grids and column captions.