diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cbf235..e494e39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Added — Design System (v1) +- Opt-in design system at `docs/public/design-system/v1/` — plain CSS + tokens using ITK Dev teal/cyan brand palette +- Tokens for colors, typography (Inter), spacing, radii, shadows, transitions +- Components: buttons, badges, cards, form inputs, tables, modal, sidebar nav, stat cards, alerts +- Live playground at `/research-projects/design-system/v1/playground.html` +- VitePress documentation pages (Overview, Tokens, Components, Usage) and top-nav entry + +### Changed — Design System (v1.1, aarhus.dk relation + data viz) +- Added aarhus-inspired pink accent (`#ee0043`) and coral (`#ff5f31`), pastel surface utilities (mint, cream, pale-blue, pale-pink, pale-aqua, coral), and `--ds-radius-pill` / `--ds-radius-2xl` +- Warmed body background to `#f5f4f2` and text to `#202423` to harmonize with aarhus.dk without copying it +- New component variants: `btn-accent`, `btn-pill`, `card-soft`, `hero`, `quick-link`, `sparkline` +- New viz helpers at `design-system/v1/viz/` — Chart.js theme (palette defaults), Leaflet theme CSS, `dsMakePin` / `dsHeatmap` / `dsCluster` overlay helpers +- New docs pages: `/projects/design-system/diagrams` (Mermaid examples) and `/projects/design-system/data-viz` (Chart.js, Leaflet, sparklines) +- Playground expanded with pastel swatches, pill/accent buttons, hero banner, quick-link tiles, three themed Chart.js charts, a Leaflet map with pins + heatmap, and sparklines in a table + ### Added — Opkrævningsoverblik Project - Consolidated municipal charges overview prototype for Aarhus Kommune citizens - Interactive mock with login, dashboard, status indicator, charge list, filtering, and 5-year history chart diff --git a/CLAUDE.md b/CLAUDE.md index 6fd3d01..cf58e87 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,6 +23,8 @@ docs/index.md # Landing page (VitePress home layo docs/about.md # About ITKdev Research docs/public/robots.txt # SEO control (noindex) docs/public/projects//mocks/ # Interactive HTML prototypes (static assets) +docs/public/design-system/v1/ # Shared opt-in design system (tokens + components) +docs/projects/design-system/ # Design system documentation pages docs/projects// # Each research project index.md # Main report / overview mocks.md # Mocks listing page @@ -62,6 +64,20 @@ Taskfile.yml # Task automation (dev, build, lint - Site has `noindex, nofollow` meta tags and `robots.txt` to prevent crawling - Home page feature cards automatically show "Last edited" dates from git history +## Design system (opt-in) + +Shared visual language for new prototypes. Lives at `docs/public/design-system/v1/` and is served as static assets. + +- **Opt in** from a mock's HTML: + ```html + +
...
+ ``` +- **Scope**: all classes are nested under `.ds` to prevent leakage. +- **Versioning**: pinned at `v1/`; breaking changes ship as `v2/` without touching `v1/`. +- **Docs**: see `/projects/design-system/` (Overview, Tokens, Components, Usage) and the live playground at `/research-projects/design-system/v1/playground.html`. +- **Do not retrofit** existing prototypes. Skip the system for prototypes that mimic an external product (`deltag-aarhus`) or test other palettes (`wcag-contrast-checker`). + ## Password-protecting a project Add frontmatter to every markdown file in the project: diff --git a/docs/.vitepress/sidebar.mts b/docs/.vitepress/sidebar.mts index f277088..04079cf 100644 --- a/docs/.vitepress/sidebar.mts +++ b/docs/.vitepress/sidebar.mts @@ -88,6 +88,20 @@ const opkraevningsoverblik: DefaultTheme.SidebarItem[] = [ }, ] +const designSystem: DefaultTheme.SidebarItem[] = [ + { + text: 'Design System', + items: [ + { text: 'Overview', link: '/projects/design-system/' }, + { text: 'Tokens', link: '/projects/design-system/tokens' }, + { text: 'Components', link: '/projects/design-system/components' }, + { text: 'Diagrams', link: '/projects/design-system/diagrams' }, + { text: 'Data viz', link: '/projects/design-system/data-viz' }, + { text: 'Usage', link: '/projects/design-system/usage' }, + ], + }, +] + export function sidebar(): DefaultTheme.Sidebar { return { '/projects/climate-nudging/': climateNudging, @@ -98,11 +112,13 @@ export function sidebar(): DefaultTheme.Sidebar { '/projects/deltag-aarhus-timeline/': deltagAarhusTimeline, '/projects/book-aarhus/': bookAarhus, '/projects/opkraevningsoverblik/': opkraevningsoverblik, + '/projects/design-system/': designSystem, } } export function nav(): DefaultTheme.NavItem[] { return [ + { text: 'Design System', link: '/projects/design-system/' }, { text: 'About', link: '/about' }, ] } diff --git a/docs/projects/design-system/components.md b/docs/projects/design-system/components.md new file mode 100644 index 0000000..be5bfc3 --- /dev/null +++ b/docs/projects/design-system/components.md @@ -0,0 +1,239 @@ +**Project:** ITK Dev Design System + +# Components + +All components render correctly inside a `.ds` container. See the live +gallery below for rendered examples — this page documents the API. + +Open live playground ↗ + +## Buttons + +```html + + + + + + +``` + +Sizes: add `btn-sm` or `btn-lg`. + +Shape: add `btn-pill` for fully rounded corners. Combines with any variant. + +```html + + +``` + +## Badges + +```html +Default +Primary +Success +Warning +Danger +Info +``` + +## Cards + +```html +
Default card
+
Stronger border
+
Shadow, no border
+ +
+
Title
+

Body

+ +
+``` + +## Form fields + +```html +
+ + + Use your full name. +
+ + + +``` + +Error state: add `style="border-color: var(--ds-color-danger);"` to the +input, plus a ``. + +## Tables + +```html +
+ + + + + +
ProjectStatus
Climate NudgingActive
+
+``` + +Modifiers: `table-zebra` alternates row backgrounds; `table-hover` adds +hover highlighting. + +## Modal + +```html + +``` + +Toggle visibility from your own JS — the design system ships CSS only. + +## Sidebar nav + +```html + +``` + +## Stat / metric card + +```html +
+
Active users
+
1.248
+
▲ 12%
+
+``` + +`stat-trend-up` (green) and `stat-trend-down` (red) indicate direction. + +## Alerts + +```html +
Info message
+
Success message
+
Warning message
+
Error message
+``` + +## Layout primitives + +- `.ds-container` — centered, max-width 1200px +- `.ds-stack` — vertical rhythm between children (16px); `ds-stack-sm` / + `ds-stack-lg` for tighter/looser spacing +- `.ds-cluster` — horizontal row, wraps, 12px gap +- `.ds-grid` — auto-fit grid, 240px minimum column width + +## Line icons + +A shared SVG sprite at `design-system/v1/icons.svg`. Reference any icon with ``. Sized via CSS class, tinted via `currentColor`. + +```html + + + + + +``` + +Sizes: default (`1.25em`), `ds-icon-lg` (`1.75em`), `ds-icon-xl` (`2.25em`). + +**Available icons**: `home`, `search`, `bell`, `user`, `users`, `calendar`, `calendar-check`, `folder`, `inbox`, `dashboard`, `chart`, `settings`, `car`, `school`, `vote`, `alert`, `trash`, `leaf`, `bike`, `plus`, `arrow-right`, `edit`, `check`, `more`, `export`, `map-pin`, `building`. + +See the playground for visual reference. Prefer these over emoji — emoji render inconsistently across platforms and don't inherit text color. + +## Aarhus-inspired extensions + +The following components carry the aarhus.dk visual relation — pastel +surfaces, softer shapes, pink accent. Use them to signal "same municipal +family" in prototypes that benefit from a warmer, more citizen-facing tone. + +### Surface utilities + +Pastel backgrounds you can apply to any element. Pair with `.card-soft`, +`.hero`, or plain `
`. + +```html +
Mint
+
Cream
+
Pale blue
+
Pale pink
+
Pale aqua
+
Coral
+``` + +### Soft card + +Larger radius (24px), no border. Meant to sit on a pastel surface or a +warm body background. + +```html +
+

Friendly tone

+

Softer shape for citizen-facing content.

+
+``` + +### Hero banner + +Full-width promotional section with a big heading and an optional search +row. Add any surface utility for the background. + +```html +
+

Hvad leder du efter?

+

Find services, høringer og aktuelle sager.

+ +
+``` + +### Quick-link tile + +Iconed service shortcut — hover lift, rounded icon bubble. + +```html + + 🚗 + Parkering + Zoner, tilladelser, betaling + +``` + +### Sparkline + +CSS-sized, `currentColor`-tinted SVG. Put it in a table cell or next to +a stat. Tint by setting `color` on the parent (or via +`style="color: var(--ds-color-accent)"`). + +```html + + + + +``` diff --git a/docs/projects/design-system/data-viz.md b/docs/projects/design-system/data-viz.md new file mode 100644 index 0000000..0924ffc --- /dev/null +++ b/docs/projects/design-system/data-viz.md @@ -0,0 +1,157 @@ +**Project:** ITK Dev Design System + +# Data viz + +For interactive charts, graphs, and maps inside prototype HTML files. +The design system ships thin theme/helper layers on top of established +libraries — Chart.js for charts, Leaflet for maps, pure SVG for +sparklines. No npm dependencies added; libraries are CDN-loaded. + +See live examples in playground ↗ + +## Charts — Chart.js + +`chart-theme.js` sets Chart.js global defaults to the ITK palette +(teal → pink → coral → cyan → green → sage → lime → teal-dark). Datasets +with no `backgroundColor` pick up a color automatically in that order. + +```html + + + + +
+ +
+ + +``` + +Supported out of the box: bar, line, doughnut, pie, radar, polarArea, +bubble, scatter. For pie and doughnut charts, the palette is spread +across individual data points. + +## Maps — Leaflet + +`leaflet-theme.css` themes controls, popups, and attribution. +`leaflet-overlays.js` provides three helpers. + +```html + + + + + + + +
+
+
+ + +``` + +### Pin colors + +Pass `color` to `dsMakePin()`: + +| Value | Resulting color | +|---|---| +| (none) | primary (teal) | +| `"accent"` | pink | +| `"success"` | green | +| `"warning"` | yellow | +| `"danger"` | red | + +### Heatmap gradient + +Default gradient runs teal → cyan → coral → pink — ITK brand crossed with +the aarhus.dk accent. Override with a `gradient` option if your data +tells a different story: + +```js +dsHeatmap(points, { + gradient: { 0.3: "#89bd23", 0.6: "#f5b800", 1.0: "#e44930" }, +}); +``` + +### Clustering + +Load `leaflet.markercluster` and use `dsCluster()`: + +```html + + +``` + +```js +const group = dsCluster([ + { lat: 56.1572, lng: 10.2107, popup: "Rådhuset" }, + { lat: 56.1539, lng: 10.2006, color: "accent", popup: "Aros" }, + // ...many more +]); +group.addTo(map); +``` + +## Sparklines — pure SVG + +For inline micro-charts in table cells or next to stats. No library. + +```html + + + + +``` + +Size via the container (default 80×24). Tint by setting `color` on the +parent — `color: var(--ds-color-accent)` turns it pink. + +## Why these libraries + +- **Chart.js** is already used in the `opkraevningsoverblik` mock (same + version, 4.4.7). Familiar, zero-config, ~80KB gzipped. +- **Leaflet** is already used in the `deltag-aarhus` mock. Open source, + works with OpenStreetMap tiles, well-supported plugin ecosystem + (heatmap, clustering, routing). +- **Sparklines as SVG** — no dependency justifies itself when 10 lines + of inline markup achieves the same outcome. + +## The aarhus.dk connection + +Palettes and overlays deliberately echo aarhus.dk's visual language +(pink accent, pastel surfaces in dashboards, teal → pink heatmap +gradient) without copying the site. Prototypes using the design system +should read as "from the same family" at a glance. diff --git a/docs/projects/design-system/diagrams.md b/docs/projects/design-system/diagrams.md new file mode 100644 index 0000000..f0fdbf9 --- /dev/null +++ b/docs/projects/design-system/diagrams.md @@ -0,0 +1,123 @@ +**Project:** ITK Dev Design System + +# Diagrams + +Mermaid is wired into VitePress via `vitepress-plugin-mermaid`. Use it +inside any research project's Markdown for flowcharts, sequence diagrams, +gantt charts, and more. + +::: info Tip +Diagrams live in Markdown, not in prototypes. For interactive charts +inside mock HTML files, see [Data viz](/projects/design-system/data-viz). +::: + +## Flowchart + +```mermaid +flowchart LR + A[User request] --> B{Authenticated?} + B -->|Yes| C[Load dashboard] + B -->|No| D[Redirect to login] + C --> E[Show personalised feed] + D --> F[MitID] + F --> C +``` + +## Sequence diagram + +```mermaid +sequenceDiagram + autonumber + participant Citizen + participant Portal + participant Backend + participant Notifier + + Citizen->>Portal: Submit hearing response + Portal->>Backend: POST /hearings/42/responses + Backend-->>Portal: 201 Created + Portal-->>Citizen: Confirmation screen + Backend->>Notifier: Queue email receipt + Notifier-->>Citizen: Email with reference +``` + +## State diagram + +```mermaid +stateDiagram-v2 + [*] --> Draft + Draft --> InReview: submit + InReview --> Approved: approve + InReview --> Draft: request changes + Approved --> Published: publish + Published --> Archived: archive + Archived --> [*] +``` + +## Gantt + +```mermaid +gantt + title Project timeline + dateFormat YYYY-MM-DD + section Research + User interviews :a1, 2026-02-01, 14d + Synthesis :after a1, 7d + section Design + Wireframes :2026-02-22, 10d + Prototyping :2026-03-04, 14d + section Build + Backend API :2026-03-18, 21d + Frontend :2026-03-25, 21d +``` + +## Pie + +```mermaid +pie title Traffic sources + "Organic" : 42 + "Direct" : 28 + "Referral" : 18 + "Campaign" : 12 +``` + +## ER diagram + +```mermaid +erDiagram + CITIZEN ||--o{ RESPONSE : submits + HEARING ||--o{ RESPONSE : receives + HEARING { + int id + string title + date deadline + } + RESPONSE { + int id + int hearing_id + int citizen_id + text content + } + CITIZEN { + int id + string name + string mitid + } +``` + +## Theming + +Mermaid respects VitePress's light/dark mode automatically. For +per-diagram tweaks, start the code block with `%%{init: ...}%%`: + +````markdown +```mermaid +%%{init: { "theme": "base", "themeVariables": { + "primaryColor": "#007ba6", + "primaryTextColor": "#fff", + "lineColor": "#495057" +}}}%% +flowchart LR + A --> B +``` +```` diff --git a/docs/projects/design-system/index.md b/docs/projects/design-system/index.md new file mode 100644 index 0000000..49fe630 --- /dev/null +++ b/docs/projects/design-system/index.md @@ -0,0 +1,61 @@ +**Project:** ITK Dev Design System + +# Design System + +A shared, opt-in visual language for ITKdev Research prototypes. Plain CSS ++ design tokens, no build step, no framework. + +::: info Opt in +This design system is **opt-in**. Existing prototypes that match an +external product (like `deltag-aarhus`) or test other palettes (like +`wcag-contrast-checker`) should not include it. +::: + +## Quick start + +Add one stylesheet to your mock's HTML, then wrap your UI in a `.ds` +container: + +```html + + +
+ +
+``` + +The `.ds` wrapper scopes every style — nothing leaks to the rest of the +page, so you can safely mix this with Tailwind or other frameworks. + +## What's in it + +- **[Tokens](/projects/design-system/tokens)** — colors, typography, spacing, radii, shadows. +- **[Components](/projects/design-system/components)** — buttons, cards, badges, form inputs, tables, modals, sidebar nav, stat cards, alerts. +- **[Usage](/projects/design-system/usage)** — how to opt in, versioning, extension guidance. + +## Live playground + +Open playground ↗ + +Every component variant, rendered with the ITK Dev palette on a single +scrollable page. + +## Example pages + +The same components, assembled into realistic layouts: + +Citizen-facing webpage ↗ +Admin app dashboard ↗ + +Each example links to the others via a demo nav at the top, so you can +compare patterns side-by-side. + +## Branding + +The design system uses ITK Dev's teal and cyan as its primary palette, +derived from the logo: + +- **Teal** `#007BA6` — primary actions, links, focus rings +- **Cyan** `#00B5C9` — secondary accent, info states +- **Green** `#008D3D` — success +- **Red** `#E44930` — danger diff --git a/docs/projects/design-system/tokens.md b/docs/projects/design-system/tokens.md new file mode 100644 index 0000000..a7049ed --- /dev/null +++ b/docs/projects/design-system/tokens.md @@ -0,0 +1,135 @@ +**Project:** ITK Dev Design System + +# Tokens + +All values live in [`tokens.css`](https://github.com/itk-dev/research-projects/blob/main/docs/public/design-system/v1/tokens.css) +as CSS custom properties. Reference them by name — never hardcode hex +values in components. + +## Colors + +### Brand — teal (primary) + +| Token | Hex | +|---|---| +| `--ds-teal-50` | `#e6f2f6` | +| `--ds-teal-100` | `#cce4ed` | +| `--ds-teal-500` | `#007ba6` (primary) | +| `--ds-teal-600` | `#00698e` (hover) | +| `--ds-teal-700` | `#005876` (active) | + +### Brand — cyan (secondary) + +| Token | Hex | +|---|---| +| `--ds-cyan-400` | `#00b5c9` | +| `--ds-cyan-500` | `#00a5cd` | + +### Brand — supporting + +| Token | Hex | Intent | +|---|---|---| +| `--ds-green-500` | `#008d3d` | success | +| `--ds-red-500` | `#e44930` | danger | +| `--ds-yellow-500` | `#f5b800` | warning | +| `--ds-lime-500` | `#89bd23` | accent | +| `--ds-sage-500` | `#73bc99` | accent | + +### Accent — aarhus.dk relation + +Pink and coral borrowed from aarhus.dk. Use the pink for +high-visibility secondary CTAs (`.btn-accent`) and the coral sparingly +for warm highlights. + +| Token | Hex | Intent | +|---|---|---| +| `--ds-pink-500` | `#ee0043` | aarhus accent, `--ds-color-accent` | +| `--ds-pink-100` | `#fddce6` | soft pink background | +| `--ds-coral-500` | `#ff5f31` | warm accent | +| `--ds-coral-100` | `#ffe1d7` | soft coral background | + +### Pastel surfaces + +Soft section backgrounds — the visual tell that connects prototypes to +the aarhus.dk look. Use on `.card-soft`, `.hero`, or any section. + +| Token | Hex | +|---|---| +| `--ds-surface-mint` | `#aeead9` | +| `--ds-surface-cream` | `#fef4c1` | +| `--ds-surface-pale-blue` | `#ebeffb` | +| `--ds-surface-pale-pink` | `#f1dede` | +| `--ds-surface-pale-aqua` | `#daedf3` | +| `--ds-surface-coral` | `#ffd7c4` | + +### Grayscale + +`--ds-gray-50` through `--ds-gray-900`, plus `--ds-white` and `--ds-black`. + +### Semantic aliases + +Prefer semantic tokens in component styles — they adapt if the palette +shifts. + +| Token | Maps to | +|---|---| +| `--ds-text-primary` | `--ds-gray-900` | +| `--ds-text-secondary` | `--ds-gray-700` | +| `--ds-text-muted` | `--ds-gray-600` | +| `--ds-text-link` | `--ds-teal-600` | +| `--ds-bg-page` | `--ds-gray-50` | +| `--ds-bg-surface` | `--ds-white` | +| `--ds-bg-subtle` | `--ds-gray-100` | +| `--ds-border-default` | `--ds-gray-300` | +| `--ds-border-focus` | `--ds-teal-500` | +| `--ds-color-primary` | `--ds-teal-500` | +| `--ds-color-success` | `--ds-green-500` | +| `--ds-color-warning` | `--ds-yellow-500` | +| `--ds-color-danger` | `--ds-red-500` | +| `--ds-color-info` | `--ds-cyan-500` | +| `--ds-color-accent` | `--ds-pink-500` | + +## Typography + +- **Font family**: Inter, loaded from Google Fonts with system fallbacks. +- **Monospace**: `ui-monospace` stack for code. + +Size scale: `--ds-fs-xs` (12px) → `--ds-fs-5xl` (48px), in steps that +cover body, heading, and display sizes. + +Weights: `--ds-fw-regular` (400), `--ds-fw-medium` (500), +`--ds-fw-semibold` (600), `--ds-fw-bold` (700). + +Line heights: `--ds-lh-tight` (1.25), `--ds-lh-snug` (1.4), +`--ds-lh-body` (1.5), `--ds-lh-loose` (1.7). + +## Spacing + +4px base scale: `--ds-space-1` (4px) through `--ds-space-8` (64px). + +| Token | Value | +|---|---| +| `--ds-space-1` | 4px | +| `--ds-space-2` | 8px | +| `--ds-space-3` | 12px | +| `--ds-space-4` | 16px | +| `--ds-space-5` | 24px | +| `--ds-space-6` | 32px | +| `--ds-space-7` | 48px | +| `--ds-space-8` | 64px | + +## Radii + +`--ds-radius-sm` (3px), `--ds-radius-md` (6px), `--ds-radius-lg` (10px), +`--ds-radius-xl` (16px), `--ds-radius-2xl` (24px), `--ds-radius-pill` +(fully rounded), `--ds-radius-full` (alias for `pill`). + +## Shadows + +`--ds-shadow-sm`, `--ds-shadow-md`, `--ds-shadow-lg`, and +`--ds-shadow-focus` for focus rings. + +## Transitions + +`--ds-transition-fast` (120ms), `--ds-transition` (180ms), +`--ds-transition-slow` (300ms) — all `ease-out`. diff --git a/docs/projects/design-system/usage.md b/docs/projects/design-system/usage.md new file mode 100644 index 0000000..c92d0a9 --- /dev/null +++ b/docs/projects/design-system/usage.md @@ -0,0 +1,81 @@ +**Project:** ITK Dev Design System + +# Usage + +## Opting in + +Add one `` to your mock's HTML, then wrap your UI in `.ds`: + +```html + + +
+ +
+``` + +The `.ds` scope prevents the stylesheet from bleeding into surrounding +elements. This matters when a prototype mixes the design system with +Tailwind, an embedded iframe, or another framework. + +## When to use it + +**Use it** when: + +- You're building a new prototype from scratch. +- The prototype represents an ITKdev-authored tool or concept (not an + external product clone). +- You want to ship quickly without re-inventing buttons, modals, and tables. + +**Skip it** when: + +- The prototype must match an external product's visual language (like + `deltag-aarhus` mimicking the real Aarhus Kommune portal). +- The prototype's purpose is to test or showcase other palettes (like + `wcag-contrast-checker`). +- The prototype is highly stylized and the shared look would work against + the concept. + +Existing prototypes are intentionally not retrofitted. + +## Versioning + +The stylesheet is served from a versioned folder: +`/research-projects/design-system/v1/`. + +- **Non-breaking changes** (new components, new tokens, bug fixes) land in + `v1/` directly. +- **Breaking changes** (renamed tokens, removed classes) ship as a new + `v2/` folder. Prototypes linked to `v1/` keep working unchanged. + +Pin your prototype to the version you built against. + +## Extending the system + +If your prototype needs a variant that isn't covered, first consider +whether the need is general enough to add to `components.css`. If yes, +open a PR with the new variant + a playground entry. If not, add local +styles in your mock's own ` + + + +
+
+ Design system eksempel + +
+
+ +
+ + + + + +
+ + +
+
Oversigt / Dashboard
+
+ + + +
+ + +
+ +
+
+

Dashboard

+

Velkommen tilbage, Jesper. Her er et overblik over aktuelle sager.

+
+
+ + +
+
+ + +
+
+
Åbne sager
+
248
+
▲ 12% vs sidste uge
+
+
+
Behandlingstid
+
4.2 d
+
▼ 0.6 d
+
+
+
Borgertilfredshed
+
92%
+
▲ 3%
+
+
+
Aktive høringer
+
12
+
3 slutter i uge 17
+
+
+ + +
+
+
+ Sagsbehandling — sidste 6 uger + På plan +
+ +
+ +
+
+ Seneste aktivitet + Alle → +
+
    +
  • + + Sag #4821 lukketByggesag, Trøjborg + 5 min +
  • +
  • + + Ny kommentarHøring: Byrum i Aarhus C + 22 min +
  • +
  • + + 3 nye sager modtagetVia kontaktformular + 1 t +
  • +
  • + + Høring udløber snartKlimaplan 2030 — 2 dage + 3 t +
  • +
  • + + Ny borger oprettetFlyttemelding godkendt + I går +
  • +
+
+
+ + +
+
+ Seneste sager + 248 i alt +
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDEmneBorgerStatusTrendFrist
#4821Byggesag — ombygningLars HansenLukket + + + + +
#4820Høring: Byrum Aarhus CÅben + + + + + 15. maj
#4819FlyttemeldingMette SørensenAfventer dok. + + + + + 26. apr
#4818ParkeringstilladelseAli MahmoudNy + + + + + 30. apr
#4817Klage — renovationSofia BergEskaleret + + + + + I dag
+
+
+ +
+
+
+ + + + + + + + diff --git a/docs/public/design-system/v1/examples/website.html b/docs/public/design-system/v1/examples/website.html new file mode 100644 index 0000000..6d14185 --- /dev/null +++ b/docs/public/design-system/v1/examples/website.html @@ -0,0 +1,502 @@ + + + + + +Eksempel: Offentlig webside — ITK Dev Design System + + + + + + +
+
+ Design system eksempel + +
+
+ +
+
+ + + ITKdev + + + +
+
+ + +
+
+ + + Nyt: Klimaplan 2030 + +

Aarhus — for alle, af os alle.

+

Find services, høringer, arrangementer og aktuelle sager — samlet ét sted. Giv din mening til kende og vær med til at forme byen.

+ +
+
+ +
+ + +
+
+

Populære services

+ + Se alle + + +
+ +
+ + +
+
+

Aktuelt

+ + Alle nyheder + + +
+ +
+ + +
+
+

Kommunen i tal

+
+
+
+
Indbyggere
+
355.094
+
+ + 0.8% vs 2024 +
+
+
+
Aktive høringer
+
12
+
3 slutter i denne uge
+
+
+
CO₂ pr. indbygger
+
4.2 t
+
+ + 12% vs 2024 +
+
+
+
Åbne sager
+
2.418
+
+ + 4% +
+
+
+
+ +
+ + +
+
+
+
Kampagne · maj 2026
+

Cykl til arbejde — vind præmier.

+

Deltag i maj-udfordringen og tæl dine kilometer. Bliv en del af en bevægelse, der gør Aarhus grønnere og sundere.

+ + Tilmeld dig nu + + +
+
+ +
+
+
+ + + + + diff --git a/docs/public/design-system/v1/icons.svg b/docs/public/design-system/v1/icons.svg new file mode 100644 index 0000000..0bd5608 --- /dev/null +++ b/docs/public/design-system/v1/icons.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/design-system/v1/index.css b/docs/public/design-system/v1/index.css new file mode 100644 index 0000000..dff672c --- /dev/null +++ b/docs/public/design-system/v1/index.css @@ -0,0 +1,9 @@ +/* ITK Dev Design System — v1 + Single-file entry point. Opt in from a prototype with: + + Then wrap your UI in a .ds container: +
...
*/ + +@import url("./tokens.css"); +@import url("./base.css"); +@import url("./components.css"); diff --git a/docs/public/design-system/v1/playground.html b/docs/public/design-system/v1/playground.html new file mode 100644 index 0000000..e5b0d10 --- /dev/null +++ b/docs/public/design-system/v1/playground.html @@ -0,0 +1,587 @@ + + + + + +ITK Dev Design System — Playground (v1) + + + + + + + + + + +
+ +
+

Color tokens

+

Brand teal is primary; cyan is the secondary accent.

+
+
+
Teal 500
+
#007BA6
+
+
+
Cyan 400
+
#00B5C9
+
+
+
Green 500
+
#008D3D
+
+
+
Red 500
+
#E44930
+
+
+
Lime 500
+
#89BD23
+
+
+
Sage 500
+
#73BC99
+
+
+
+ +
+

Line icons

+

SVG sprite at ./icons.svg. Reference with <use href="./icons.svg#name"/>. Sized via CSS, tinted via currentColor.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+

Typography

+
+

Heading 1 — The quick brown fox

+

Heading 2 — The quick brown fox

+

Heading 3 — The quick brown fox

+

Heading 4 — The quick brown fox

+

Body text — The quick brown fox jumps over the lazy dog. 1234567890.

+ Small — The quick brown fox jumps over the lazy dog. +
+
+ +
+

Buttons

+

Variants × sizes. Add btn-sm or btn-lg for sizing.

+
+ + + + + + +
+
+ + + +
+
+ +
+

Badges

+
+ Default + Primary + Success + Warning + Danger + Info +
+
+ +
+

Cards

+
+
+

Default card

+

Subtle border, no shadow. Good for nested content.

+
+
+

Bordered card

+

Stronger border for higher contrast.

+
+
+

Elevated card

+

Shadow, no border — floats off the surface.

+
+
+
With header
+

Content body between header and footer.

+ +
+
+
+ +
+

Form fields

+
+
+ + + Use your full name. +
+
+ + +
+
+ + +
+
+ + + Please enter a valid email address. +
+
+ + +
+
+
+ +
+

Table

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProjectStatusOwnerBudget
Climate NudgingActiveTeam A120.000 kr
Book AarhusReviewTeam B85.000 kr
OpkrævningsoverblikDraftTeam C60.000 kr
+
+
+ +
+

Alerts

+
+
Info: This is an informational callout.
+
Success: Your changes have been saved.
+
Warning: This action cannot be undone.
+
Error: Something went wrong.
+
+
+ +
+

Metric cards

+
+
+
Active users
+
1.248
+
▲ 12% vs last week
+
+
+
CO₂ saved
+
42 kg
+
▲ 8%
+
+
+
Response time
+
312 ms
+
▼ 4% (slower)
+
+
+
+ +
+

Sidebar nav

+
+ +
+

Dashboard

+

Page content sits next to the sidebar.

+
+
+
+ +
+

Modal

+

Click to open a demo modal. Press Escape or click the backdrop to close.

+ + + + + +
+ +
+

Aarhus-inspired surfaces

+

Pastel backgrounds borrowed from aarhus.dk, usable on sections, cards, and heroes.

+
+
+ Mint +
.surface-mint
+
+
+ Cream +
.surface-cream
+
+
+ Pale blue +
.surface-pale-blue
+
+
+ Pale pink +
.surface-pale-pink
+
+
+ Pale aqua +
.surface-pale-aqua
+
+
+ Coral +
.surface-coral
+
+
+
+ +
+

Pill & accent buttons

+

Pink accent signals the aarhus.dk relation; pill shape softens hierarchy.

+
+ + + + + +
+
+ +
+

Hero banner

+
+

Hvad leder du efter?

+

Find information om kommunens services, borgerinddragelse og aktuelle sager.

+ +
+
+ +
+

Quick-link tiles

+

Service shortcuts — compact, iconed, with hover lift.

+ +
+ +
+

Charts (Chart.js)

+

Datasets auto-pick up the ITK palette via chart-theme.js — no per-chart color config.

+
+
+
+
+
+
+ +
+

Sparklines in a table

+
+ + + + + + + + + + + + + + + + + + + + + +
Project7-day trendTotal
Visitors + + + + + 12.408
Bookings + + + + + 428
Errors + + + + + 3
+
+
+ +
+

Map with pins + heatmap (Leaflet)

+

Centered on Aarhus city hall. Pins use dsMakePin(); heatmap uses dsHeatmap() with the default teal → pink gradient.

+
+
+ +
+ + + + + + + + + + + + + + diff --git a/docs/public/design-system/v1/tokens.css b/docs/public/design-system/v1/tokens.css new file mode 100644 index 0000000..42f1c01 --- /dev/null +++ b/docs/public/design-system/v1/tokens.css @@ -0,0 +1,176 @@ +/* ITK Dev Design System — Design Tokens (v1) + Custom properties only. Consumed via index.css. + Brand palette derived from the ITK Dev logo. */ + +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"); + +:root { + /* Brand — Teal (primary) */ + --ds-teal-50: #e6f2f6; + --ds-teal-100: #cce4ed; + --ds-teal-200: #99c9db; + --ds-teal-300: #66aec9; + --ds-teal-400: #3393b6; + --ds-teal-500: #007ba6; /* primary */ + --ds-teal-600: #00698e; + --ds-teal-700: #005876; + --ds-teal-800: #00475e; + --ds-teal-900: #003647; + + /* Brand — Cyan (secondary) */ + --ds-cyan-100: #cceff3; + --ds-cyan-300: #66d2dd; + --ds-cyan-400: #00b5c9; + --ds-cyan-500: #00a5cd; + --ds-cyan-700: #007b9b; + + /* Brand — supporting hues */ + --ds-green-100: #cce8d8; + --ds-green-500: #008d3d; /* success */ + --ds-green-700: #006a2d; + --ds-lime-500: #89bd23; + --ds-sage-500: #73bc99; + --ds-red-100: #fbdad5; + --ds-red-500: #e44930; /* danger */ + --ds-red-700: #b3371f; + --ds-yellow-100: #fff3c4; + --ds-yellow-500: #f5b800; /* warning */ + --ds-yellow-700: #b38600; + + /* Accent — aarhus.dk relation (pink + coral) */ + --ds-pink-100: #fddce6; + --ds-pink-500: #ee0043; + --ds-pink-700: #b80134; + --ds-coral-100: #ffe1d7; + --ds-coral-500: #ff5f31; + --ds-coral-700: #cc4820; + + /* Pastel surfaces — aarhus.dk-inspired section backgrounds */ + --ds-surface-mint: #aeead9; + --ds-surface-cream: #fef4c1; + --ds-surface-pale-blue: #ebeffb; + --ds-surface-pale-pink: #f1dede; + --ds-surface-pale-aqua: #daedf3; + --ds-surface-coral: #ffd7c4; + + /* Grayscale */ + --ds-white: #ffffff; + --ds-gray-50: #f8f9fa; + --ds-gray-100: #f1f3f5; + --ds-gray-200: #e9ecef; + --ds-gray-300: #dee2e6; + --ds-gray-400: #ced4da; + --ds-gray-500: #adb5bd; + --ds-gray-600: #868e96; + --ds-gray-700: #495057; + --ds-gray-800: #343a40; + --ds-gray-900: #212529; + --ds-black: #0f1114; + + /* Semantic — text */ + --ds-text-primary: #202423; + --ds-text-secondary: var(--ds-gray-700); + --ds-text-muted: var(--ds-gray-600); + --ds-text-inverse: var(--ds-white); + --ds-text-link: var(--ds-teal-600); + --ds-text-link-hover: var(--ds-teal-700); + + /* Semantic — surfaces */ + --ds-bg-page: #f5f4f2; + --ds-bg-surface: var(--ds-white); + --ds-bg-subtle: var(--ds-gray-100); + --ds-bg-muted: var(--ds-gray-200); + --ds-bg-inverse: var(--ds-gray-900); + + /* Semantic — borders */ + --ds-border-default: var(--ds-gray-300); + --ds-border-subtle: var(--ds-gray-200); + --ds-border-strong: var(--ds-gray-500); + --ds-border-focus: var(--ds-teal-500); + + /* Semantic — status */ + --ds-color-primary: var(--ds-teal-500); + --ds-color-primary-hover: var(--ds-teal-600); + --ds-color-primary-active: var(--ds-teal-700); + --ds-color-primary-soft: var(--ds-teal-50); + + --ds-color-success: var(--ds-green-500); + --ds-color-success-soft: var(--ds-green-100); + --ds-color-warning: var(--ds-yellow-500); + --ds-color-warning-soft: var(--ds-yellow-100); + --ds-color-danger: var(--ds-red-500); + --ds-color-danger-soft: var(--ds-red-100); + --ds-color-info: var(--ds-cyan-500); + --ds-color-info-soft: var(--ds-cyan-100); + --ds-color-accent: var(--ds-pink-500); + --ds-color-accent-hover: var(--ds-pink-700); + --ds-color-accent-soft: var(--ds-pink-100); + + /* Typography */ + --ds-font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", + Roboto, "Helvetica Neue", Arial, sans-serif; + --ds-font-family-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, + "Cascadia Mono", "Liberation Mono", Consolas, monospace; + + --ds-fs-xs: 0.75rem; /* 12 */ + --ds-fs-sm: 0.875rem; /* 14 */ + --ds-fs-base: 1rem; /* 16 */ + --ds-fs-lg: 1.125rem; /* 18 */ + --ds-fs-xl: 1.25rem; /* 20 */ + --ds-fs-2xl: 1.5rem; /* 24 */ + --ds-fs-3xl: 1.875rem; /* 30 */ + --ds-fs-4xl: 2.25rem; /* 36 */ + --ds-fs-5xl: 3rem; /* 48 */ + + --ds-fw-regular: 400; + --ds-fw-medium: 500; + --ds-fw-semibold: 600; + --ds-fw-bold: 700; + --ds-fw-black: 800; + + --ds-lh-tight: 1.25; + --ds-lh-snug: 1.4; + --ds-lh-body: 1.5; + --ds-lh-loose: 1.7; + + /* Spacing — 4px base scale */ + --ds-space-0: 0; + --ds-space-1: 0.25rem; /* 4 */ + --ds-space-2: 0.5rem; /* 8 */ + --ds-space-3: 0.75rem; /* 12 */ + --ds-space-4: 1rem; /* 16 */ + --ds-space-5: 1.5rem; /* 24 */ + --ds-space-6: 2rem; /* 32 */ + --ds-space-7: 3rem; /* 48 */ + --ds-space-8: 4rem; /* 64 */ + + /* Radii */ + --ds-radius-sm: 2px; + --ds-radius-md: 4px; + --ds-radius-lg: 6px; + --ds-radius-xl: 10px; + --ds-radius-2xl: 14px; + --ds-radius-pill: 9999px; + --ds-radius-full: 9999px; + + /* Shadows */ + --ds-shadow-sm: 0 1px 2px rgb(0 0 0 / 6%); + --ds-shadow-md: 0 2px 6px rgb(0 0 0 / 8%), 0 1px 2px rgb(0 0 0 / 4%); + --ds-shadow-lg: 0 8px 24px rgb(0 0 0 / 10%), 0 2px 6px rgb(0 0 0 / 6%); + --ds-shadow-focus: 0 0 0 3px rgb(0 123 166 / 30%); + + /* Layout */ + --ds-container-max: 1200px; + + /* Transitions */ + --ds-transition-fast: 120ms ease-out; + --ds-transition: 180ms ease-out; + --ds-transition-slow: 300ms ease-out; + + /* Z-index scale */ + --ds-z-dropdown: 100; + --ds-z-sticky: 200; + --ds-z-overlay: 900; + --ds-z-modal: 1000; + --ds-z-toast: 1100; +} diff --git a/docs/public/design-system/v1/viz/README.md b/docs/public/design-system/v1/viz/README.md new file mode 100644 index 0000000..38b6e02 --- /dev/null +++ b/docs/public/design-system/v1/viz/README.md @@ -0,0 +1,96 @@ +# Data viz helpers + +Theme-aware wrappers for the three data-viz libraries prototypes +typically need. Everything is CDN-loaded in the prototype HTML; the +design system ships only thin theme/helper layers. + +## Charts — Chart.js 4 + +```html + + + + +
+ +
+ + +``` + +`chart-theme.js` sets Chart.js global defaults (font, colors, gridlines, +tooltip) and auto-applies the ITK palette (teal → pink → coral → cyan → +green → sage → lime → teal-dark) in order when a dataset has no +`backgroundColor`. For pie/doughnut charts, the palette is spread across +data points. + +## Maps — Leaflet 1.9 + +```html + + + + + + + +
+
+
+ + +``` + +The heatmap default gradient runs teal → cyan → coral → pink, which +telegraphs both the ITK brand and the aarhus.dk relation in a single +overlay. + +## Sparklines — pure SVG + +```html + + +
+ + + + +
+``` + +`color: currentColor` — set the parent's `color` to tint the line (e.g. +`style="color: var(--ds-color-accent);"` for a pink sparkline). + +## Files + +- `chart-theme.js` — Chart.js global defaults + palette plugin +- `leaflet-theme.css` — themed Leaflet controls, popups, pins, clusters +- `leaflet-overlays.js` — `dsMakePin`, `dsHeatmap`, `dsCluster` helpers diff --git a/docs/public/design-system/v1/viz/chart-theme.js b/docs/public/design-system/v1/viz/chart-theme.js new file mode 100644 index 0000000..3011896 --- /dev/null +++ b/docs/public/design-system/v1/viz/chart-theme.js @@ -0,0 +1,83 @@ +/* ITK Dev Design System — Chart.js theme (v1) + Include AFTER Chart.js on the page. Sets global defaults so every + Chart.js chart inherits the ITK palette, font, and muted gridlines. + Usage: + + +*/ +(function () { + if (typeof Chart === "undefined") { + console.warn("[ds-chart-theme] Chart.js not loaded yet"); + return; + } + + // Palette rotation — teal primary, pink/coral accents signal aarhus relation, + // then supporting hues for high-cardinality data. + var palette = [ + "#007ba6", // teal-500 (primary) + "#ee0043", // pink-500 (accent) + "#ff5f31", // coral-500 + "#00b5c9", // cyan-400 + "#008d3d", // green-500 + "#73bc99", // sage-500 + "#89bd23", // lime-500 + "#00698e", // teal-600 + ]; + + Chart.defaults.font.family = + '"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'; + Chart.defaults.font.size = 13; + Chart.defaults.color = "#495057"; // gray-700 + Chart.defaults.borderColor = "#e9ecef"; // gray-200 + + Chart.defaults.elements.bar.borderRadius = 4; + Chart.defaults.elements.line.tension = 0.3; + Chart.defaults.elements.point.radius = 3; + Chart.defaults.elements.point.hoverRadius = 5; + + Chart.defaults.plugins.legend.labels.boxWidth = 12; + Chart.defaults.plugins.legend.labels.boxHeight = 12; + Chart.defaults.plugins.legend.labels.padding = 16; + + Chart.defaults.plugins.tooltip.backgroundColor = "rgba(32,36,35,0.95)"; // text-primary + Chart.defaults.plugins.tooltip.titleFont = { weight: "600" }; + Chart.defaults.plugins.tooltip.padding = 10; + Chart.defaults.plugins.tooltip.cornerRadius = 6; + + // Auto-apply palette when datasets don't specify colors. + var originalInit = Chart.prototype.update; + Chart.register({ + id: "ds-palette", + beforeUpdate: function (chart) { + chart.data.datasets.forEach(function (ds, i) { + var color = palette[i % palette.length]; + if (ds.backgroundColor == null) { + if (chart.config.type === "line") { + ds.backgroundColor = hexToRgba(color, 0.15); + ds.borderColor = color; + ds.pointBackgroundColor = color; + } else if (chart.config.type === "pie" || chart.config.type === "doughnut") { + // Spread palette across data points for categorical charts. + ds.backgroundColor = ds.data.map(function (_, j) { + return palette[j % palette.length]; + }); + } else { + ds.backgroundColor = color; + ds.borderColor = color; + } + } + }); + }, + }); + + function hexToRgba(hex, alpha) { + var h = hex.replace("#", ""); + var r = parseInt(h.substring(0, 2), 16); + var g = parseInt(h.substring(2, 4), 16); + var b = parseInt(h.substring(4, 6), 16); + return "rgba(" + r + "," + g + "," + b + "," + alpha + ")"; + } + + // Expose palette for manual use. + window.dsChartPalette = palette; +})(); diff --git a/docs/public/design-system/v1/viz/leaflet-overlays.js b/docs/public/design-system/v1/viz/leaflet-overlays.js new file mode 100644 index 0000000..dce650c --- /dev/null +++ b/docs/public/design-system/v1/viz/leaflet-overlays.js @@ -0,0 +1,85 @@ +/* ITK Dev Design System — Leaflet overlay helpers (v1) + Requires Leaflet (and leaflet.heat for heatmaps, leaflet.markercluster + for clusters) to be loaded first. + + API: + dsMakePin(lat, lng, { color, label, popup }) + dsHeatmap(points, { radius, blur, gradient }) + dsCluster(points, { popup }) + + All return Leaflet layers — call .addTo(map) to render. +*/ +(function () { + if (typeof L === "undefined") { + console.warn("[ds-leaflet-overlays] Leaflet not loaded yet"); + return; + } + + function dsMakePin(lat, lng, opts) { + opts = opts || {}; + var variant = opts.color ? " ds-pin-" + opts.color : ""; + var label = opts.label ? '' + opts.label + "" : ""; + var html = + '
' + + '
' + + label + + "
"; + + var icon = L.divIcon({ + html: html, + className: "", // suppress Leaflet's default icon styles + iconSize: [28, 36], + iconAnchor: [14, 36], // point at the tip + popupAnchor: [0, -32], + }); + + var marker = L.marker([lat, lng], { icon: icon }); + if (opts.popup) marker.bindPopup(opts.popup); + return marker; + } + + // ITK teal → aarhus pink gradient (signals brand + relation in one stroke) + var defaultHeatGradient = { + 0.2: "#007ba6", + 0.4: "#00b5c9", + 0.6: "#ff5f31", + 0.8: "#ee0043", + 1.0: "#b80134", + }; + + function dsHeatmap(points, opts) { + if (typeof L.heatLayer !== "function") { + console.warn("[ds-leaflet-overlays] leaflet.heat plugin not loaded"); + return null; + } + opts = opts || {}; + return L.heatLayer(points, { + radius: opts.radius != null ? opts.radius : 25, + blur: opts.blur != null ? opts.blur : 18, + maxZoom: opts.maxZoom != null ? opts.maxZoom : 17, + gradient: opts.gradient || defaultHeatGradient, + }); + } + + function dsCluster(points, opts) { + if (typeof L.markerClusterGroup !== "function") { + console.warn("[ds-leaflet-overlays] leaflet.markercluster plugin not loaded"); + return null; + } + opts = opts || {}; + var group = L.markerClusterGroup(); + points.forEach(function (p) { + var m = dsMakePin(p.lat, p.lng, { + color: p.color, + label: p.label, + popup: p.popup, + }); + group.addLayer(m); + }); + return group; + } + + window.dsMakePin = dsMakePin; + window.dsHeatmap = dsHeatmap; + window.dsCluster = dsCluster; +})(); diff --git a/docs/public/design-system/v1/viz/leaflet-theme.css b/docs/public/design-system/v1/viz/leaflet-theme.css new file mode 100644 index 0000000..85183bb --- /dev/null +++ b/docs/public/design-system/v1/viz/leaflet-theme.css @@ -0,0 +1,108 @@ +/* ITK Dev Design System — Leaflet theme (v1) + Include AFTER the Leaflet base CSS. Themes controls, popups, and + attribution with ITK tokens. Load leaflet-overlays.js for pin/heatmap + helpers. */ + +.leaflet-container { + font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font-size: 13px; +} + +/* Zoom + controls */ +.leaflet-bar { + border: 0; + border-radius: var(--ds-radius-md, 6px); + box-shadow: var(--ds-shadow-md, 0 2px 6px rgb(0 0 0 / 8%)); + overflow: hidden; +} + +.leaflet-bar a, +.leaflet-bar a:hover { + background: #fff; + color: var(--ds-color-primary, #007ba6); + border-bottom-color: var(--ds-border-subtle, #e9ecef); +} + +.leaflet-bar a:hover { + background: var(--ds-color-primary-soft, #e6f2f6); +} + +/* Popups */ +.leaflet-popup-content-wrapper { + border-radius: var(--ds-radius-lg, 10px); + box-shadow: var(--ds-shadow-lg, 0 8px 24px rgb(0 0 0 / 10%)); + padding: 0; +} + +.leaflet-popup-content { + margin: 12px 16px; + line-height: 1.5; + color: var(--ds-text-primary, #202423); +} + +.leaflet-popup-content h4 { + margin: 0 0 4px; + font-size: 14px; + font-weight: 600; +} + +.leaflet-popup-tip { box-shadow: none; } + +/* Attribution */ +.leaflet-control-attribution { + background: rgba(255, 255, 255, 0.85); + color: var(--ds-text-muted, #868e96); + font-size: 11px; + padding: 2px 6px; + border-radius: var(--ds-radius-sm, 3px); +} + +.leaflet-control-attribution a { color: var(--ds-color-primary, #007ba6); } + +/* DS pins — created by dsMakePin() in leaflet-overlays.js */ +.ds-pin { + width: 28px; + height: 36px; + position: relative; + filter: drop-shadow(0 2px 4px rgb(0 0 0 / 25%)); +} + +.ds-pin-bubble { + width: 28px; + height: 28px; + border-radius: 50% 50% 50% 0; + background: var(--ds-color-primary, #007ba6); + transform: rotate(-45deg); + border: 2px solid #fff; +} + +.ds-pin-label { + position: absolute; + inset: 0 0 auto 0; + margin-top: 4px; + text-align: center; + color: #fff; + font-size: 12px; + font-weight: 600; + line-height: 24px; + pointer-events: none; +} + +.ds-pin.ds-pin-accent .ds-pin-bubble { background: var(--ds-color-accent, #ee0043); } +.ds-pin.ds-pin-success .ds-pin-bubble { background: var(--ds-color-success, #008d3d); } +.ds-pin.ds-pin-warning .ds-pin-bubble { background: var(--ds-color-warning, #f5b800); } +.ds-pin.ds-pin-danger .ds-pin-bubble { background: var(--ds-color-danger, #e44930); } + +/* Marker cluster theming — used when leaflet.markercluster is loaded */ +.marker-cluster-small, +.marker-cluster-medium, +.marker-cluster-large { + background: rgba(0, 123, 166, 0.25); +} +.marker-cluster-small div, +.marker-cluster-medium div, +.marker-cluster-large div { + background: var(--ds-color-primary, #007ba6); + color: #fff; + font-weight: 600; +}