| name | imax-view |
| description | The house visual system for anything with a rendered appearance: artifacts, HTML pages, React components, SVG, slides, dashboards, landing pages, diagrams. Sets the frame aspect ratio, monospace type stack, type scale, spacing, palette, and the copy rules (no em dashes, no semicolons). Apply this whenever producing visual output, even when the request says nothing about styling, design, fonts, or layout, and even for quick throwaway mockups. If the output will be looked at rather than read as plain text, this skill applies. |
| when_to_use | Trigger phrases include make it look good, design this, style this, clean up the UI, build a landing page, build a dashboard, make a mockup, prototype a screen, draw a diagram, build a chart, write an artifact, build an HTML page, build a React component, make slides, make a poster. It applies just as much to requests that never mention design, such as build a quick page for this, show me this data, put together a one-pager, throw together a demo, or add a banner to the README. Reach for it before the first line of CSS rather than as a polish pass afterwards. If the output will be looked at rather than read as plain text, it qualifies. |
imax-view
A design system that treats the artifact canvas the way IMAX 15/70 treats the screen: taller than you expect, larger than you expect, and quiet everywhere except one place.
The reference is the 15-perf 70mm film format, the one that expands vertically to 1.43:1 rather than stretching sideways. Every token below traces back to something real about that format. See references/format.md for the derivations if a decision needs justifying or extending.
The four rules
- Frame first. Pick the aspect ratio before writing any other CSS. Default to 1.43:1. Do not default to 16:9.
- Type is large. Body copy starts at 18px. Nothing readable goes below 14px.
- One bright thing. The palette is near-monochrome. Accent is light bleed, not fill.
- Copy is unmarked. No em dashes, no semicolons, no hard wraps.
Frame
| Ratio | Use | Suggested canvas |
|---|
| 1.43:1 | Default. Heroes, cards, standalone artifacts, single-screen pieces. | 1100 × 769 |
| 1.90:1 | Genuinely wide content only: timelines, wide tables, comparison rails. | 1100 × 579 |
| free | Long scrolling documents. Keep --measure and the 15-col grid. | n/a |
Set it explicitly with aspect-ratio, never by accident via content height.
Below 640px, release the ratio and stack. A 1.43:1 frame on a phone is a letterbox, which is the exact opposite of the intent.
The 15-column grid
15/70 means fifteen perforations per frame. The grid is 15 columns, not 12. It reads slightly off to anyone used to Bootstrap, which is the point, and odd column counts give a true center column for free.
display: grid;
grid-template-columns: repeat(15, 1fr);
gap: var(--perf);
Type
Monospace throughout, in the Berkeley Mono lineage: squarish, terminal-derived, low stroke contrast, tall x-height. The stack degrades to whatever the OS ships, so nothing needs downloading:
--font: "Berkeley Mono", "TX-02", "Commit Mono", "JetBrains Mono",
ui-monospace, "SF Mono", Menlo, Consolas, monospace;
ui-monospace resolves to SF Mono on macOS and Cascadia Mono on Windows, both close enough in feel to carry the design.
Roles are separated by size, weight, and tracking, not by family:
| Role | Size | Weight | Tracking | Leading |
|---|
| Display | 91-137px | 500 | −0.035em | 0.92 |
| Title | 41-61px | 500 | −0.02em | 1.05 |
| Lead | 27px | 400 | −0.01em | 1.4 |
| Body | 18px | 400 | 0 | 1.65 |
| Caption | 14px | 400 | +0.01em | 1.5 |
| Eyebrow | 12px | 600 | +0.18em, uppercase | 1 |
Scale ratio is 1.5. The gap between display and body is deliberately violent, and that contrast is the cinematic register. Do not fill the middle of the scale with in-between sizes to soften it.
Measure caps at 62ch. Monospace runs wide, so longer lines stop scanning.
Numerals: font-variant-numeric: tabular-nums on anything columnar.
Copy
The words inside the frame are part of the design, so they carry rules too. Two prohibitions, both absolute:
- No em dashes. Not in headings, body copy, captions, labels, button text, alt text, tooltips, chart annotations, code comments, or commit messages. Recast the sentence instead. A period, a comma, a colon, or the word "because" almost always reads better, and none of them carry the tell.
- No semicolons. Split the clause into two sentences, or join it with a conjunction.
- No hard wraps. A paragraph is one unbroken line in the source. Let the renderer decide where it breaks.
En dashes go the same way. Numeric ranges take a plain hyphen (91-137px) or the word "to".
This covers prose only. Semicolons in CSS, JavaScript, and every other language are syntax and stay exactly where they are, and so is the line wrapping in a code block, a table, or an ASCII diagram. Reflowing those breaks them.
The hard-wrap rule is the same argument as the frame. Prose wrapped by hand to 80 columns is prose measured for a terminal, and it re-wraps wrong in every viewport that is not one. --measure already caps the line at 62ch where it renders, which is the only place the cap belongs. Wrapping the source as well fixes the break points to a width nobody is reading at, and it turns a one-word edit into a reflowed paragraph in the diff.
The rule holds in every piece the skill touches, throwaway mockups included, and it holds in the surrounding chat reply as much as in the artifact. Em dashes and semicolons are the two loudest punctuation tells of generated writing, and a system whose entire budget goes on not looking generated cannot afford either.
Palette
A projection booth, not a UI. Warm light against cold dark, because film print stock throws highlights warm and shadows cyan.
--void
--gate
--emulsion
--edge
--silver
--lamp
--halation
--cyan
The halation rule: --halation is a bleed, not a fill. It belongs in 1 to 3px edges, underlines, glows, a single active state, one number that matters. The moment it becomes a filled button background, the whole thing collapses into generic dark-mode-with-an-orange-accent. Filled surfaces use --emulsion with a --halation hairline instead.
Light: the light table
Light mode is not an inversion of dark. Inverting produces a warm cream ground with a serif-adjacent warm accent, which is the most common generated design look there is.
Instead it derives from the other half of the format: a positive print on a light table. Denser emulsion reads darker than the surround, so surfaces go down from the ground, not up. Cards are darker than the page. This is the inverse of the usual light-mode convention and it's the thing that makes the theme recognizable.
--void
--gate
--emulsion
--edge
--silver
--lamp
--halation
--cyan
The halation prohibition holds in both themes.
Choosing a theme
Do not ask the user which theme they want. A skill that opens with a question on every visual request is friction, and the answer is inferable almost every time. Resolve in this order:
- The request says so. "dark", "light", "for print", "for a deck", "for the docs site". Take it and move on.
- The output has an obvious home. Documentation, print, anything embedded in an existing light product, or long-form reading → light. Dashboards, monitoring, terminals, media, demos, hero pieces → dark.
- Otherwise: ship both. Default dark, follow
prefers-color-scheme when no theme is set, and include the .theme-toggle so the viewer decides. This is the default behavior in assets/tokens.css and costs about fifteen lines.
Ask only when the piece is a real deliverable going into a context you can't see, such as a client site or someone else's product, and the request gives no signal at all. Even then, ask once alongside other open questions, never as a standalone blocking turn.
Spacing
Named for the format, ramped hard rather than linearly:
--perf 6px grid gutter, the base unit
--frame 12px
--gate-sp 20px
--reel 36px
--act 64px
--intermission 112px section breaks only
Section breaks use --intermission and nothing smaller. Cramped vertical rhythm is what makes a dark layout feel like a terminal instead of a theater.
Signature
Every piece gets exactly one. Pick one and do not stack them.
- The expand. Hero mounts at 1.90:1 and animates to 1.43:1 over ~700ms with the content already in place. This is the actual IMAX sequence transition and it is the strongest option when motion is available.
- Perf rail. A column of 15 small notches down one frame edge,
--edge colored, marking the grid. Structural, not decorative, so align content to it.
- Frame line. A 1px
--edge border on the canvas with a soft --halation glow bleeding inward from one corner only.
Respect prefers-reduced-motion: the expand becomes a static 1.43:1 mount.
Quality floor
Assume all of this without being asked: responsive to 360px, visible keyboard focus using --halation outline, reduced motion honored, and contrast at least 4.5:1 for body text.
Contrast trap, both themes: --silver passes on --void but fails on --emulsion. Secondary text on a raised surface uses --lamp at reduced opacity, not --silver.
When to break it
- Brief specifies a look. The brief wins, always. Keep only the type scale.
- Existing codebase. Match the codebase. Do not import this into someone else's design system.
- Data density. Dashboards with 20+ metrics need the 1.90:1 frame and may drop body to 16px. Say so rather than silently shrinking.
- Print or document output. Ratios and dark ground don't transfer. Carry the type scale and measure only.
Files
assets/tokens.css: drop-in custom properties, base reset, grid, type roles. Paste into any artifact and start using the variable names.
references/format.md: where each number comes from. Read when extending the system or when a choice needs defending.