Skip to main content
Compendium / Pillars & Roles / Comparison / Pillar Compass
#024

Pillar Compass

A 4-point cartographer-style compass placing the pillars at the cardinal directions.

STABLE
#svg #real-content #dark-mode-tested
Live
Survey Instrument
Bearing 360°
N · DO CO S · DE GO
Spec

Intent

Render the four pillars as cardinal directions on a surveyor's compass. Reinforces the framework's spatial completeness — pick a direction, get a pillar.

Acceptance Criteria

  • [ ] North/East/South/West labelled with pillars
  • [ ] Compass rose centred with crosshair + ordinal letters
  • [ ] Each label carries the pillar's accent colour
  • [ ] Does not require JS — pure SVG render

Constraints

  • Pure SVG
  • Theme-aware via tokens
  • No hex literals in brand-colour slots
  • ≤ 150 lines body
// pillar-compass.astro
---
import type { CompendiumMeta } from '../../../data/types';

export const meta: CompendiumMeta = {
  id: 24,
  slug: 'pillar-compass',
  name: 'Pillar Compass',
  category: 'pillars-roles',
  subcategory: 'comparison',
  description: 'A 4-point cartographer-style compass placing the pillars at the cardinal directions.',
  spec: `## Intent
Render the four pillars as cardinal directions on a surveyor's compass. Reinforces the framework's spatial completeness — pick a direction, get a pillar.

## Acceptance Criteria
- [ ] North/East/South/West labelled with pillars
- [ ] Compass rose centred with crosshair + ordinal letters
- [ ] Each label carries the pillar's accent colour
- [ ] Does not require JS — pure SVG render

## Constraints
- Pure SVG
- Theme-aware via tokens
- No hex literals in brand-colour slots
- ≤ 150 lines body`,
  tags: ['svg', 'real-content', 'dark-mode-tested'],
  status: 'stable',
  health: { ics: 80, a11y: 'aa', themed: true, animated: false },
};
---

<div data-this-component class="w-full bg-paper text-black border-4 border-black shadow-nb-sm p-3 overflow-hidden">
  <div class="flex items-center justify-between mb-1 gap-2">
    <div class="font-mono text-[9px] uppercase tracking-[0.25em] opacity-60 truncate">Survey Instrument</div>
    <div class="font-mono text-[9px] uppercase tracking-[0.25em] opacity-60 shrink-0">Bearing 360°</div>
  </div>

  <svg viewBox="0 0 240 240" class="w-full max-w-[280px] mx-auto block" aria-label="Pillar compass: DO north, CO east, DE south, GO west" role="img">
    <circle cx="120" cy="120" r="100" stroke="var(--color-ink)" stroke-width="4" fill="var(--color-paper)" />
    <circle cx="120" cy="120" r="84"  stroke="var(--color-ink)" stroke-width="2" fill="none" stroke-dasharray="3 3" opacity="0.4" />

    {Array.from({ length: 36 }).map((_, i) => {
      const a = (i * 10) * Math.PI / 180;
      const x1 = 120 + Math.cos(a) * 96;
      const y1 = 120 + Math.sin(a) * 96;
      const x2 = 120 + Math.cos(a) * (i % 9 === 0 ? 84 : 90);
      const y2 = 120 + Math.sin(a) * (i % 9 === 0 ? 84 : 90);
      return <line x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--color-ink)" stroke-width={i % 9 === 0 ? 2 : 1} />;
    })}

    <line x1="120" y1="30" x2="120" y2="210" stroke="var(--color-ink)" stroke-width="2" />
    <line x1="30" y1="120" x2="210" y2="120" stroke="var(--color-ink)" stroke-width="2" />

    <polygon points="120,40 110,120 130,120" fill="var(--color-do)" stroke="var(--color-ink)" stroke-width="3" />
    <polygon points="200,120 120,110 120,130" fill="var(--color-co)" stroke="var(--color-ink)" stroke-width="3" />
    <polygon points="120,200 110,120 130,120" fill="var(--color-de)" stroke="var(--color-ink)" stroke-width="3" />
    <polygon points="40,120 120,110 120,130" fill="var(--color-go)" stroke="var(--color-ink)" stroke-width="3" />

    <circle cx="120" cy="120" r="10" fill="var(--color-paper)" stroke="var(--color-ink)" stroke-width="3" />

    <g font-family="Inter, sans-serif" font-weight="900">
      <rect x="96" y="4" width="48" height="22" fill="var(--color-do)" stroke="var(--color-ink)" stroke-width="3" />
      <text x="120" y="20" text-anchor="middle" font-size="12" fill="var(--color-ink)">N · DO</text>

      <rect x="206" y="109" width="30" height="22" fill="var(--color-co)" stroke="var(--color-ink)" stroke-width="3" />
      <text x="221" y="125" text-anchor="middle" font-size="11" fill="var(--color-ink)">CO</text>

      <rect x="96" y="214" width="48" height="22" fill="var(--color-de)" stroke="var(--color-ink)" stroke-width="3" />
      <text x="120" y="230" text-anchor="middle" font-size="12" fill="var(--color-ink)">S · DE</text>

      <rect x="4" y="109" width="30" height="22" fill="var(--color-go)" stroke="var(--color-ink)" stroke-width="3" />
      <text x="19" y="125" text-anchor="middle" font-size="11" fill="var(--color-ink)">GO</text>
    </g>
  </svg>
</div>