# rnqs.app · visual foundations v0.1

Shared identity draft for Renan Arques' projects. Use this guide when building an rnqs.app interface or adapting a project to the brand. The homepage remains the most expressive statement of the identity; interfaces use the same visual language with lighter texture and smaller headings.

## How to apply

1. Read this guide and copy [tokens.css](../tokens.css), along with the fonts and licenses from `../../assets/`. Adjust `@font-face` paths to match your project structure.
2. Set `data-theme="light"` or `data-theme="dark"` on the root element. Default to the system theme on first load and allow an explicit preference. Tokens without a selector fall back to dark.
3. Use semantic tokens inside components. `tokens.css` is the source of truth for values; this page demonstrates how they are used. When changing a value, update examples and recalculate contrast ratios.
4. Validate both themes, keyboard navigation, reduced motion, and layout down to 360 px before considering the interface ready.

```css
@import './tokens.css';
body {
  background: var(--color-bg);
  color: var(--color-text);
  font: 400 16px/1.6 var(--font-body);
}
.primary-action {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border: 1px solid var(--color-accent-text);
  border-radius: var(--radius-control);
  min-height: 44px;
  padding: 10px 16px;
  font: 600 14px/1.5 var(--font-body);
}
.primary-action:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 4px;
}
```

## Identity and colors

Preserve the `rnqs.app` spelling. The near-black blue background and Bricolage 800 come from the existing identity. Butter yellow is an evolution of the original gold, without changing the homepage.

- `--color-bg`: page background.
- `--color-surface`: panels and forms.
- `--color-elevated`: hover surface or second layer.
- `--color-text` and `--color-muted`: primary and secondary text.
- `--color-accent`: yellow fill. Use `--color-on-accent` for its text in both themes.
- `--color-accent-text`: links and highlighted text. Dark ochre in light mode; light yellow in dark mode.
- `--color-accent-soft`: subtle selection background, paired with `--color-accent-text`.
- `--color-border`: decorative dividers. For field outlines that identify inputs, use `--color-control`.
- `--color-focus`: focus outline over background or panel.
- `--color-success`, `--color-danger`, and `--color-info`: status states paired with a label or icon. Brand yellow does not automatically mean warning.

Light yellow does not work as small text on white. Keep it for button fills and use the dark tone for links. White text on yellow must also be replaced by the dark token.

Primary, secondary, accent, and status text pairs were calculated against bg and surface and exceed 4.5:1. Field borders exceed 3:1. This verifies solid pairs, not an entire interface. Re-evaluate colors over images, transparency, and new backgrounds.

## Typography

- Bricolage Grotesque 800: brand and expressive headings. On product screens, reserve it for the main title or a single highlight moment.
- Geist 400: body copy, 16 px / 1.6. Geist 500–600: labels, navigation, and buttons, 14–16 px / 1.5.
- Product headings: Geist 600, 22–32 px / 1.2. Editorial headings: Bricolage 800, 32–56 px / 1.1.
- Supporting text: 12–14 px / 1.6. Keep essential information at reading size.
- System monospace: code, values, and tokens. Avoid using it for body paragraphs.
- Limit reading paragraphs to roughly 60–70 characters per line.

The fonts are local and licensed under OFL. Copy `bricolage-grotesque-800.ttf`, `geist-latin-variable.woff2`, `OFL.txt`, and `geist-OFL.txt` when reusing them. The included Geist file covers Portuguese and Basic Latin; other languages may need additional subsets.

## Texture

The effect is ordered dithering with a 4×4 Bayer matrix, derived from the pixelated light on the homepage. The reference implementation lives in [design.js](../design.js), in `draw` and `drawAll`.

- In interfaces, limit texture to a header, panel corner, or empty state. Start at 12–20% intensity.
- By default, the texture layer spans the full horizontal width of the section. Padding and max-width belong to the content, not the texture. In a page section, the background reaches the viewport edges; in a panel, it reaches the panel edges.
- Structure the section with an absolute canvas covering its container and an inner content container with padding and max-width. Clip the effect only at the outer section boundary, never at the content boundary.
- Anchor the light center to the right edge of the usable content area. The reference uses 97% of the usable width and 45% of the section height. On wide displays, the center follows the centered content while the texture continues into outer margins and dissolves naturally.
- Compute effect position and size in usable-content coordinates, regardless of canvas width. Keep text and controls clear: the reference begins revealing pixels from 58% of the usable width.

```html
<section class="hero">
  <canvas class="pixel-field" data-anchor=".hero-content"
    data-strength="0.2" aria-hidden="true"></canvas>
  <div class="content hero-content">Content with padding and max-width</div>
</section>
```

The `data-anchor` selector must identify that section's content container. The layout reference is in [design.css](../design.css), and coordinate math is in [design.js](../design.js).

- Use ~3 px pixels, screen-aligned and unstretched.
- Keep the decorative canvas `aria-hidden="true"` and `pointer-events:none`.
- Render on resize, theme switch, or intensity adjustment. The texture stays static while reading.
- Dense screens, tables, forms, and error states can use solid backgrounds only.

## Fade outside usable bounds

When a section is wider than its max-width container and outer centering margins appear, decorative elements begin losing opacity immediately after crossing the usable content boundary. The fade distance scales with the element size rather than growing indefinitely with the viewport.

- On small screens, when the container fills the whole section, keep the texture up to the edge without extra fading. Inner padding alone does not trigger the fade. On the reference page, outer margins appear above 1536 px.
- Preserve the original opacity inside the usable area and keep the effect center anchored to the content.
- On the right, measure distance outward from the content's right edge. On the left, mirror this from the left edge.
- For this texture, the maximum fade span is 24% of the usable width. If the section edge is closer, use only that available margin. This ensures the effect ends at or before the edge without pushing visual weight into the periphery of ultrawide monitors.
- Use `alpha × (1 - t)²`, with `t` clamped between 0 and 1 across that span. Intensity drops from the very start and reaches zero smoothly. Avoid curves that preserve a noticeable plateau outside the content.
- Apply this rule to the decorative layer while preserving text, controls, and focus. For other illustrations, scale the fade span to the visual element; never rely solely on distance to the viewport edge.
- Recalculate geometry on resize. Validate narrow and ultrawide screens: the drop-off must remain visible right past the usable boundary even with wide empty margins.

The `overflowFade` function in [design.js](../design.js) handles both sides. The canvas still covers the whole section; only opacity changes outside the content.

## Space, shape, and interaction

The spacing scale starts at 4 px and covers 4, 8, 12, 16, 24, 32, 48, and 64 px. Control corners use 8 px; panels use 16 px. Start with thin borders and no shadows. Use dividers and space to organize documentation without wrapping every block in a card.

Controls have a minimum height of 44 px. Preserve visible labels, keyboard focus, and field-associated error messages. Feedback can use 160 ms; with reduced motion, use 0 ms. Avoid continuous animation in the texture.

## Scope and evolution

This foundation contains CSS tokens, documentation, and pattern examples. It is not a component library yet. Extract a component once the same solution appears in at least two projects and its requirements are well understood.

If interoperability with Figma, native tools, or multiple platforms is needed, adopt the DTCG 2025.10 format as the source and generate CSS from it. The current CSS is not a DTCG file. Avoid maintaining two catalogs of values by hand.

The save buttons on the page are local feedback demos; they do not persist data or integrate with a backend service.

## References consulted on 2026-11-12

- [Design.Systems](https://www.design.systems/): community recommendation for discussing decisions with practitioners. Recommended for fit with this project, not as a popularity ranking.
- [Design Tokens Community Group](https://www.designtokens.org/): interoperability reference; stable specification 2025.10.
- [Radix Colors: understanding the scale](https://www.radix-ui.com/colors/docs/palette-composition/understanding-the-scale): inspiration for separating backgrounds, borders, and text. This palette is custom, not an official Radix scale.
- [WCAG: contrast minimum](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html): contrast criteria for text.
- [Geist](https://vercel.com/font): complementary typeface for reading and UI.
