Skip to content
Mapping

Paint & selection

On the map, colour carries planning content — so the interaction states spend no colour at all. Numbers measured from the shipping map.

Colour is content

Zoning fills at 0.62 over the light basemap: strong enough that the colour IS the map, weak enough that boundaries and labels survive on top of it.

  • The coincidences are coincidences. Tiers 1, 2 and 4 equal --gd-success, --gd-info and --gd-danger today and are deliberately NOT aliased to them — aliasing would re-couple a red error toast to an impact-assessable parcel. Tier 3 proves it: it is #C9A21A while --gd-caution is the darker #A8850F, so an alias would silently darken every code-assessable parcel in Queensland.
  • Tiers are baked; colours are not. The pipeline writes an integer 0–4 per parcel and the tier→colour step is a runtime match. Re-tuning the palette costs a rebuild, never a re-bake of a council's tiles.
  • Published fills — a council's zone palette, the flood bands, ShapingSEQ's footprint — are not in the design system. They are facts about a publisher and live in the spec's colour registry with their provenance attached.
0 Not yet mapped
1 No approval
2 Building approval
3 Council approval (code)
4 Council approval (impact)
The assessment rampTier 0 is neutral by obligation: an unassessed parcel must not borrow a colour that asserts something.

The cartography group

The whole of it — read from the same TypeScript that generates tokens.css, so this table cannot describe a palette the map does not have. Each row shows light then dark.

cartography
--gd-cartography-assessment-0#B9BCC4#B9BCC4

tier 0 — not codified, or not applicable. Neutral by obligation: an unassessed parcel must not borrow a colour that asserts something

--gd-cartography-assessment-1#1B8A4C#1B8A4C

tier 1 — no approval needed. Equals --gd-success TODAY BY COINCIDENCE; never alias it

--gd-cartography-assessment-2#2F6FB0#2F6FB0

tier 2 — building approval (a certifier, not council). Coincides with --gd-info; never alias it

--gd-cartography-assessment-3#C9A21A#C9A21A

tier 3 — council approval, code assessed. DOES NOT equal --gd-caution (#A8850F): aliasing would darken every code-assessable parcel

--gd-cartography-assessment-4#C43D3D#C43D3D

tier 4 — council approval, impact assessed. Coincides with --gd-danger; never alias it

--gd-cartography-assessment-0-line#696D77#B9BCC4

tier 0 casing — the darker stroke for an unassessed parcel

--gd-cartography-assessment-1-line#15703D#5BD08B

tier 1 stroke — also the pass outline in the 3D scene, where a 2.2px line needs the ink rather than the fill

--gd-cartography-assessment-2-line#285F96#7FB3E6

tier 2 stroke

--gd-cartography-assessment-3-line#7F6508#EAB94D

tier 3 stroke

--gd-cartography-assessment-4-line#A83232#E97B7B

tier 4 stroke — the fail outline in the 3D scene

--gd-cartography-parcel-line#C2C8D2#C2C8D2

the cadastre hairline between parcels. At 0.5px over every parcel in view this is the highest-frequency line on the map, so it sets the texture of the whole fabric — dark enough to read the subdivision pattern, light enough never to compete with a road or the fill beneath it

--gd-cartography-building#E8E9ED#E8E9ED

existing building massing, extruded from LiDAR. A warm near-white, not pure white: the layer is semi-transparent so a parcel's fill still reads through, and pure white picks up a cold tint from whatever is beneath it

--gd-cartography-massing#17A6A0#17A6A0

GRIDD's generated best-fit massing

--gd-cartography-massing-alt#0F7D78#0F7D78

the alternating storey shade, so a stack of levels is legible rather than one fused block

--gd-cartography-easement#8A7AB5#8A7AB5

a registered easement's fill. A title fact, not a hazard — which is what the dashed edge says

--gd-cartography-easement-line#6B5A9E#6B5A9E

the easement's dashed edge

--gd-cartography-basemap-ground#F8F7F7#22242B

the basemap ground plane — the paper the cadastre is drawn on

--gd-cartography-basemap-road#BCC8D5#3A3F4A

road fill. Deliberately heavier than the cadastre hairline: a road is a place you can go, a boundary is not

--gd-cartography-basemap-park#FFFFFF#282B33

parks and reserves. White in the light, NOT green: a green basemap park collides with the zone palette, which already uses light greens to mean specific things (sport & recreation, rural, open space). Basemap green under those reads as a zone the lot does not have

--gd-cartography-basemap-water#A2D8EC#1E3A47

rivers, creeks and the bay — the one basemap feature that stays recognisably itself in both themes

--gd-cartography-basemap-label#5C6470#9AA3B0

street names — the basemap's working label

--gd-cartography-basemap-label-strong#4A525E#C2C9D4

suburb and town names — the label that anchors the view

--gd-cartography-basemap-label-halo#FFFFFF#101116

the halo behind a basemap label. It is the GROUND's colour, not a colour of its own: its whole job is to punch the label's own paper out from under it where the label crosses the parcel fabric

--gd-cartography-utility-water#12809C#12809C

water main

--gd-cartography-utility-sewer#8A6A2B#8A6A2B

sewer main

--gd-cartography-utility-storm#708B96#708B96

stormwater main

The fills are the same value in both themes on purpose. --gd-surface-map is charcoal rather than black precisely so a parcel's fill keeps the relationship to its ground that it has in daylight. Only the strokes fork, because a hairline has to hold against its own backdrop.

The palette as values

A MapLibre paint spec cannot read a CSS custom property — var(--gd-cartography-assessment-3) inside one is a parse error, not a colour. So the map takes the same tokens as JavaScript, from @gridd/ui/cartography.

tierFill(tier)
0#B9BCC41#1B8A4C2#2F6FB03#C9A21A4#C43D3D
tierLine(tier)
0#696D771#15703D2#285F963#7F65084#A83232
fabric()
parcelLine#C2C8D2building#E8E9ED
massing()
a#17A6A0b#0F7D78
services()
easement#8A7AB5easementLine#6B5A9Ewater#12809Csewer#8A6A2Bstorm#708B96
Called at renderLight values. Theme is a parameter, not a second palette: tierLine(4) is #A83232 and tierLine(4, "dark") is #E97B7B.

The tier match

["match",["get","tier"],0,"#B9BCC4",1,"#1B8A4C",2,"#2F6FB0",3,"#C9A21A",4,"#C43D3D","#B9BCC4"]
  • That is the real output of tierMatchExpression("tier"), built in the package rather than at the call site because the fallback matters: an unbaked or unknown tier must land on tier 0's neutral, never on a colour that asserts an assessment nobody computed.
  • Every accessor resolves through token(), the same model that generates tokens.css. There is one source and this is an accessor, not a mirror — which is what stops the canvas and the stylesheet disagreeing.
  • token() throws on an unknown name rather than returning a fallback, because a silent fallback in a paint spec is a wrong colour on a map that nobody notices for a month.
  • In a template, never import from here. Use var(--gd-cartography-*), so a theme change stays a theme change.

Hover & selection

Hover is a line. Selection is a line. A fill would sit on top of the zoning colour — the one thing the map exists to show.

Rest
Hover
Selected
The three statesRest · hover (2 px ink) · selected (2.6 px accent + a 0.05 wash). The fill never changes — that is the rule.
  • Hover — a 2 px near-black stroke via feature-state; the fill does not change. On the region view, where there is no zoning to hide, an LGA may wash at 0.1.
  • Selected — a 2.6 px accent stroke (#4740DB), plus a 0.05 accent wash so faint it is presence rather than paint.
  • The cursor is the third signal: pointer over a parcel, default elsewhere — hit-tested on the same layer the hover strokes.
  • Subdivision cells alternate 0.16 / 0.28 fills so adjacent proposed lots separate without introducing a second hue.

Overlays & easements

A constraint is an area with an honest edge — translucent enough to overlap, outlined enough to end somewhere definite.

Zoning 0.62
Easement 0.35
Footprint 0.32
Focus wash 0.05
The opacity ladderOne hue at the map's own opacities, over the basemap ground — zoning is the loudest thing, a wash is barely there.
  • Constraint overlays carry their own per-layer fill opacity around a third — two hazards overlapping must both stay legible, and the darker sum is the intersection.
  • Registered easements: 0.35 fill with a dashed 1.6 px edge ([2, 1.6]) — a title fact, not a hazard, and the dash is what says so.
  • The regional urban footprint sits at 0.32 and exists only below the council gate — context for choosing, never competing with a council's own layers.
  • The layers panel's swatches take the map's ACTUAL colours — data, not tokens — which is why those literals are marked gd-colour-ok in the docs rather than tokenised (Layers panel).

The basemap

The paper, and the only part of the cartography palette that fully forks between themes — because the paper is exactly the thing that should change when the lights go out.

The shipped map repaints CARTO Positron rather than using it as it comes. These seven values are returned together by basemap(theme) on purpose: they are a measured set, not seven independent choices. Swap one and you have broken the pair it was measured against.

LightDark
The paperThe plane the cadastre is drawn on. Charcoal in the dark, not black: the fills above it are translucent and were tuned against a light-ish ground.
RoadsDeliberately DARKER than the ground. Upstream Positron draws white roads on near-white land — about 1.05:1, effectively invisible — and inverting that polarity is the whole reason the retune exists.
ParksWhite in the light, not green. A green basemap park collides with the zone palette, which already uses light greens to mean specific things; green under those reads as a zone the lot does not have.
WaterThe one basemap feature that stays recognisably itself in both themes.
Street namesPositron's own ink is ~3.3:1 on this ground, under the floor. This clears 4.5:1 on the ground token above.
Suburb namesThe label that anchors the view — the darker of the pair in the light theme, the lighter in the dark. In both, the one that wins.
Label haloThe GROUND's colour, not a colour of its own: its job is to punch the label's own paper out from under it where it crosses the parcel fabric.
  • Content does not fork; the paper does. Every value above this section holds across themes so an assessment tier means the same thing at midnight as at noon. The basemap is the deliberate opposite.
  • Never setStyle to change theme. It tears down every source and layer — the parcel fabric, the selection, the 3D scene — and reloads the tiles behind them. setPaintProperty swaps the colours in place and the map does not blink.
  • Every layer id is third-party, not an API. CARTO can rename them upstream, so each call is guarded — but a silent degrade to plain Positron reads as a styling whim rather than a broken dependency, so the app counts the misses and reports when more than half are gone.

Navigate

Esc