# De Stijl Neoplastic

굵은 순흑 수직·수평 선이 화면을 비대칭 직사각형 면으로 분할하고, 소수의 면만 순수 삼원색으로 채우는 1917년 신조형주의 스타일 — 모션은 없다.

- taxonomy: de-stijl · neoplasticism, mondrian, primary-colors, thick-black-rules, asymmetric-planes, static-composition · complexity=medium
- page types: landing, portfolio, marketing, editorial
- best for: 디자인 스튜디오·갤러리·아트 프로젝트 랜딩, 포트폴리오·전시 아카이브, 대담한 브랜드 매니페스토·캠페인 페이지
- avoid for: 데이터 밀도가 높은 대시보드·관리 도구, 긴 본문 위주의 문서·블로그, 부드러운 감성·파스텔 톤이 필요한 서비스
- provenance: authored (design-diversity 팩 'web-de-stijl-neoplastic' (MIT) 각색) — confidence: colors=manual, typography=manual, spacing=manual, motion=manual, layout=manual

## Design rules

# De Stijl Neoplastic

## Overview
1917 Neoplasticism (Mondrian, Rietveld) as a website. Thick pure-black vertical and horizontal rules divide the whole viewport into asymmetric rectangular planes; most planes stay white, and only a few are filled with pure primary red, yellow, or blue. There are no diagonals, no curves, no shadows, and no motion — the composition is completely static. You know it's this style when every division is a thick orthogonal black line and color appears only as a sparse plane fill.

## Colors & Roles
Canonical mode is **light**: white canvas (`background`), near-black `foreground`/`border` (#1A1A1A → oklch 0.218), and exactly three chromatics — `primary` red (oklch 0.577 0.234 28), `secondary` yellow (oklch 0.883 0.181 94.5), `accent` blue (oklch 0.439 0.146 255.3). No other hue is ever allowed — no purple, green, orange, or pastels. Color fills a minority of planes; the rest are white. Text is black on white (~16:1, AAA) or white/black on color planes (keep ≥4.5:1: white on red/blue, black on yellow). The dark mode is an authored inversion of the same system: the canvas becomes the pack's black, rules and text become white, primaries stay identical, and motion stays banned.

## Typography Rules
Two Google Fonts. Display: **Archivo Black** (single weight 400), uppercase, `clamp(2.4rem, 5vw, 4.6rem)`, line-height 1.0, letter-spacing −0.01em — a geometric grotesque. Body: **Archivo** 500, 1rem, line-height 1.5, measure 56–66ch. Labels/meta: Archivo 700, 0.75rem, uppercase, letter-spacing 0.12em. Text sits horizontally inside planes only — rotated or diagonal text is forbidden.

## Layout Principles
Full-bleed plane composition — no content max-width (1280px desktop reference; breakpoints 768px / 1120px). Build with CSS Grid: unequal `fr` tracks, and thick black gaps (8–12px primary rules, 6px secondary) acting as the dividing lines — typically a black container background showing through `gap`. Plane sizes are deliberately unequal (one large white plane balanced against smaller color planes), but rule thickness and plane padding (`clamp(24px, 3vw, 48px)`) stay uniform.

**The resolved grid is non-negotiable**: every plane — white ones included — must be sealed on all sides by black rules (viewport edge excepted) and interlock with its neighbors so the planes tile the screen with no gaps. An unbounded empty white region is a dead void; a small color square floating alone in white space is a failure. Verify: no empty grid cells, every cell boundary carries a black rule.

## Depth & Elevation
None. Zero shadows, zero gradients, zero blur, zero noise. The composition is perfectly flat; thick black rules are the only structural device.

## Shapes
0px radius everywhere — right angles only. No rounded corners, no curves, no diagonals. Icons, if needed at all, are crafted from rectangles and straight lines (black or primary-colored); generic icon sets and emoji are banned. Images fill rectangular planes edge-to-edge (radius 0) and are separated from neighbors by thick black borders.

## Component Stylings
- **Button**: red or blue rectangular plane + thick black border (4–6px), Archivo Black uppercase, padding 14px 32px, radius 0. Hover swaps the fill instantly (0ms) to another primary or inverts to black — no transition.
- **Card / plane**: rectangle with thick black border, white or primary-filled. Padding `clamp(24px,3vw,48px)`, 16px title↔body gap, text anchored top-left or bottom-left — no dead space inside a plane.
- **Nav**: one horizontal white plane at the top with an 8px black bottom rule; Archivo Black wordmark left, menu items right as labels inside small yellow/blue planes, black line separators between items.
- **Color block**: an empty plane filled with pure red/yellow/blue is a legitimate compositional component — but it must share black rules with adjacent planes, never float.
- **Image plane**: real image or a legitimate color/white plane — never a gray "image placeholder" box.

## Motion
None — `motion: none` is the identity. No scroll-entrance animations, no hover movement or scaling, no fades/slides/draws. The only permitted interaction is an instant (0ms, no transition) color swap of a plane on hover — a blink, not an animation. `prefers-reduced-motion` needs no handling; nothing moves.

## Do's and Don'ts
**Do:** divide the full screen into asymmetric rectangles with uniform thick black rules; keep most planes white and color only a few; interlock every plane so the grid resolves with no voids; keep padding and rule thickness consistent.
**Don't:** use circles, triangles, or diagonals (that's Bauhaus territory); use any hue beyond red/yellow/blue; use gradients, shadows, radius, or emoji; add any transition animation; thin the black rules below 6px; fill every plane with color; make the division even and regular — that regresses to a generic grid site.

## Responsive Behavior
Breakpoints at 768px and 1120px. The plane composition re-flows: unequal columns stack into fewer tracks on mobile while every plane stays sealed by black rules — the resolved-grid rule applies at every width. Display type scales via `clamp()`. Never let stacking produce an unbounded white void.

## Agent Prompt Guide
> Build this in the 'De Stijl Neoplastic' style: divide the entire viewport into asymmetric rectangles using thick pure-black rules (8–12px primary, 6px secondary) as CSS Grid gaps over a black container; leave most planes white and fill only a few with pure primary red, yellow, or blue; seal every plane on all sides with black rules — no unbounded voids, no floating color squares; Archivo Black uppercase display type, Archivo 500 body; zero radius, zero shadows, zero curves; completely static — hover may only swap a plane's fill instantly (0ms).

## Known Gaps / Confidence
Adapted from the MIT-licensed design-diversity pack `web-de-stijl-neoplastic` — an authored spec, not measured from a live site, so all confidence fields are `manual`. All chromatic values trace to the pack's tokens.json (#E30613 / #FFD500 / #0050A0 / #1A1A1A on #FFFFFF), converted to OKLCH; neutral tonal steps (muted, chart-5) and the entire dark mode are authored derivations noted in `tokens.colors.notes`. The light mode is canonical.


## Tokens (theme.css — use these values verbatim, do not re-derive)

```css
/* De Stijl Neoplastic — theme.css (generated, do not edit) */
:root {
  --radius: 0px;
  --radius-selector: 0px;
  --radius-field: 0px;
  --font-sans: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --font-display: 'Archivo Black', 'Arial Black', Helvetica, sans-serif;
  --spacing: 8px;
  --shadow: 0px 1px 2px 0px color-mix(in oklab, oklch(0 0 0) 0%, transparent);
  --ks-display-weight: 400;
  --ks-display-tracking: -0.01em;
  --background: oklch(1 0 0);
  --foreground: oklch(0.218 0 0);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.218 0 0);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.218 0 0);
  --primary: oklch(0.577 0.234 28.0);
  --primary-foreground: oklch(1 0 0);
  --secondary: oklch(0.883 0.181 94.5);
  --secondary-foreground: oklch(0.218 0 0);
  --muted: oklch(0.96 0 0);
  --muted-foreground: oklch(0.4 0 0);
  --accent: oklch(0.439 0.146 255.3);
  --accent-foreground: oklch(1 0 0);
  --destructive: oklch(0.577 0.234 28.0);
  --destructive-foreground: oklch(1 0 0);
  --border: oklch(0.218 0 0);
  --input: oklch(0.218 0 0);
  --ring: oklch(0.439 0.146 255.3);
  --chart-1: oklch(0.577 0.234 28.0);
  --chart-2: oklch(0.439 0.146 255.3);
  --chart-3: oklch(0.883 0.181 94.5);
  --chart-4: oklch(0.218 0 0);
  --chart-5: oklch(0.65 0 0);
}

.dark {
  --background: oklch(0.218 0 0);
  --foreground: oklch(1 0 0);
  --card: oklch(0.218 0 0);
  --card-foreground: oklch(1 0 0);
  --popover: oklch(0.218 0 0);
  --popover-foreground: oklch(1 0 0);
  --primary: oklch(0.577 0.234 28.0);
  --primary-foreground: oklch(1 0 0);
  --secondary: oklch(0.883 0.181 94.5);
  --secondary-foreground: oklch(0.218 0 0);
  --muted: oklch(0.28 0 0);
  --muted-foreground: oklch(0.85 0 0);
  --accent: oklch(0.439 0.146 255.3);
  --accent-foreground: oklch(1 0 0);
  --destructive: oklch(0.577 0.234 28.0);
  --destructive-foreground: oklch(1 0 0);
  --border: oklch(1 0 0);
  --input: oklch(1 0 0);
  --ring: oklch(0.883 0.181 94.5);
  --chart-1: oklch(0.577 0.234 28.0);
  --chart-2: oklch(0.439 0.146 255.3);
  --chart-3: oklch(0.883 0.181 94.5);
  --chart-4: oklch(1 0 0);
  --chart-5: oklch(0.65 0 0);
}
```

## Golden example (exemplar.html — match this structure and token usage)

```html
<!-- Golden snippet for "De Stijl Neoplastic". Fragment — assumes the style's CSS variables
     (--background, --foreground, --primary, --secondary, --accent, --border, --radius,
     --font-sans, --font-display, ...) are in scope. Tokens only; no literal colors.
     The black dividing rules are the container's --foreground background showing through grid gaps. -->
<section style="background:var(--foreground); color:var(--foreground); font-family:var(--font-sans); border:10px solid var(--foreground);">

  <!-- Nav plane: white strip sealed by the thick rule below it -->
  <header style="display:flex; align-items:stretch; background:var(--background); border-bottom:10px solid var(--border); margin-bottom:0;">
    <span style="font-family:var(--font-display); font-size:1.25rem; text-transform:uppercase; letter-spacing:-0.01em; padding:14px 24px;">Stijl</span>
    <span style="margin-left:auto; display:flex;">
      <a href="#" style="background:var(--secondary); color:var(--secondary-foreground); border-left:6px solid var(--border); padding:14px 20px; font-size:.75rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; text-decoration:none;">Werk</a>
      <a href="#" style="background:var(--accent); color:var(--accent-foreground); border-left:6px solid var(--border); padding:14px 20px; font-size:.75rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; text-decoration:none;">Manifest</a>
    </span>
  </header>

  <!-- Hero: asymmetric interlocked planes; black rules = 8px gaps over the black container -->
  <div style="display:grid; grid-template-columns:3fr 1.1fr; grid-template-rows:auto auto; gap:8px; background:var(--foreground);">

    <!-- Large white plane (spans both rows) -->
    <div style="grid-row:1 / 3; background:var(--background); padding:clamp(24px,3vw,48px); display:flex; flex-direction:column; justify-content:flex-end;">
      <p style="margin:0 0 16px; font-size:.75rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;">1917 — Neoplasticism</p>
      <h1 style="margin:0 0 16px; font-family:var(--font-display); font-weight:400; font-size:clamp(2.4rem,5vw,4.6rem); line-height:1.0; letter-spacing:-0.01em; text-transform:uppercase;">
        Line,<br>plane,<br>primary.
      </h1>
      <p style="margin:0 0 24px; max-width:56ch; font-size:1rem; font-weight:500; line-height:1.5;">
        The screen is divided by thick black rules into unequal rectangles. Most stay white; a few carry pure color. Nothing moves.
      </p>
      <a href="#" style="align-self:flex-start; border-radius:var(--radius); background:var(--primary); color:var(--primary-foreground); border:5px solid var(--border); padding:14px 32px; font-family:var(--font-display); font-size:.9rem; text-transform:uppercase; letter-spacing:-0.01em; text-decoration:none;"
         onmouseover="this.style.background='var(--accent)'" onmouseout="this.style.background='var(--primary)'">
        Enter
      </a>
    </div>

    <!-- Tall blue plane -->
    <div style="background:var(--accent); min-height:200px;"></div>

    <!-- Yellow plane + small white plane, interlocked -->
    <div style="display:grid; grid-template-columns:1.6fr 1fr; gap:8px; background:var(--foreground);">
      <div style="background:var(--secondary); min-height:96px;"></div>
      <div style="background:var(--background);"></div>
    </div>
  </div>

  <!-- Footer strip: three unequal planes, one colored -->
  <div style="display:grid; grid-template-columns:1.4fr 1fr 0.7fr; gap:8px; background:var(--foreground); border-top:8px solid var(--border);">
    <div style="background:var(--background); padding:16px 24px; font-size:.75rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;">Composition No. 1</div>
    <div style="background:var(--background); padding:16px 24px; font-size:.75rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--muted-foreground);">No curves. No motion.</div>
    <div style="background:var(--primary);"></div>
  </div>
</section>
```

## Apply

- shadcn project: `npx shadcn@latest add https://web.ggum.uk/styles/r/de-stijl.json` — installs the tokens above into globals.css, then use semantic classes (bg-background, text-primary, …) only.
- other stack: paste the theme.css block above into your global stylesheet and style everything via `var(--…)` references.
- single HTML/artifact: embed the theme.css block in a `<style>` tag and follow the exemplar's markup pattern.
- dark mode: toggle the `.dark` class (both variants are in the tokens above).
- before finishing: re-check every Don't in the Design rules section above against your output.
