# RedFox — Sistema de diseño Este archivo es la versión legible por máquina del brandbook de RedFox (https://redfoxdev.com/brandbook). Es el mismo contenido que la página, en texto plano, para poder pegárselo a un asistente o enlazarlo desde una herramienta. Se genera desde docs/design.md y docs/ui-patterns.md en el repositorio del sitio, así que no puede quedar desfasado respecto de la página. El sitio es en español y para LATAM. Todo material de marca se escribe en español. --- # Design System — RedFox > The canvas is black, the content is white, and colour appears only to identify a service. > Archivo says things to people; Space Mono labels data. Nothing is rounded, nothing is gradient, > and no button is ever coloured. --- ## Status — read this first **This file is the design system.** It is not a description of something else — it is the record every page is audited against, and both `/brandbook` (for people) and `/brandbook.md` (for assistants and tooling) are rendered from it. If a page disagrees with this file, the page is wrong. The black system replaced the navy/red one across all 23 route templates in six gated waves, tracked in `docs/plan-rebrand-migration.md`. The exploration it was designed in (`/rebrand-test`, `components/rebrand/`) was deleted in Wave 6 once its components were promoted; nothing references it any more. The navy-era token aliases are gone too — `grep` for `brand-red` or `brand-navy` returns zero. Every route is migrated, `/lp/*` included. The grep for navy-era values returns zero across `app`, `components` and `lib`. **Changing this file changes what the public brandbook says.** Both surfaces rebuild from it, so a careless edit ships. Keep the values in step with `app/globals.css`. --- ## Confirmed vs. Estimated Values | Value | Status | |-------|--------| | Canvas `#000000`, surface `#0B0B0B`, panel `#141414` | ✅ Confirmed — shipped tokens | | Text scale `#FFFFFF` / `#A1A1AA` / `#71717A` | ✅ Confirmed — shipped tokens | | Five service accents (see §2) | ✅ Confirmed — shipped tokens | | Hairline `rgba(255,255,255,0.08)` / strong `0.16` | ✅ Confirmed — shipped tokens | | Archivo (display + body) · Space Mono (utility) | ✅ Confirmed — `app/layout.tsx` | | Border radius `0` everywhere | ✅ Confirmed — brandbook ch. 05 | | No gradients, no shadows | ✅ Confirmed — brandbook ch. 03, 05 | | Container `max-w-[1200px]`, gutter inside | ✅ Confirmed — `components/layout/Container.tsx` | | CTA white-on-black, never coloured | ✅ Confirmed — brandbook ch. 03, 08 | | Photography roles and treatment | ✅ Confirmed — brandbook ch. 06 | | Exact type sizes per breakpoint, section padding | `~` Estimated from the built components | | Long-form body colour `--color-dim` on black (§11 Template C) | ✅ Confirmed — Wave 4, measured against WCAG | | Long-form measure, leading, prose scale (§11 Template C) | `~` Estimated — written in Wave 4, tuned against the live articles | | Form and input spec (§14) | `~` Estimated — written in Wave 5 ahead of the three forms | | Accessible error state (§14) | ✅ Confirmed — `aria-invalid` / `aria-describedby` / `role="alert"` shipped in Wave 5 | --- ## 1. Visual Theme & Atmosphere RedFox looks like an instrument panel, not a brochure. The page is pure black — not navy, not charcoal — and everything on it is a hairline, a white word or a number. The restraint is the argument: a company that builds the system a business runs on should look like a system, and systems do not decorate themselves. The single rule that governs everything: **colour identifies, it never decorates.** Five accents exist, one per service, and each appears only to say which service you are reading about. Red is one of those five — the accent for Inteligencia Artificial — and the logo. It is no longer *the* brand colour, and it never appears on a button. Structure is carried by line and surface rather than by colour or shadow. Sections are separated by a 1px hairline at 8% white, never by a background change. Cards are not cards: they are cells in one slab, divided by seams, sharing borders rather than floating apart. Nothing has a rounded corner and nothing casts a shadow. Type does the hierarchy, and Space Mono marks the difference between something a person reads and something a machine would read. **Key characteristics:** - Pure black `#000000` canvas on every page, including long-form reading surfaces - Five service accents, used as a 2px bar, an icon, or a diagram branch — nothing else - Primary CTA is white-on-black; secondary is a 1px white outline. Never a coloured button - Zero border radius on every component, without exception - Zero gradients. The one surviving `linear-gradient` in the codebase is the marquee `mask-image` - Zero shadows on content; depth is suggested by hairline and surface only - Archivo carries display *and* body; Space Mono carries labels, counts and durations only - Sections separated by a hairline, never by an alternating background - Photography is always desaturated so the only colour on a page stays the service accent --- ## 2. Color Palette & Roles ### Base | Token | Value | Role | |---|---|---| | `--color-canvas` | `#000000` | Page background, everywhere | | `--color-surface` | `#0B0B0B` | Lifted sections and cells | | `--color-surface-2` | `#141414` | Panels and menus sitting on a surface | | `--color-ink` | `#FFFFFF` | Headings, figures, primary CTA | | `--color-dim` | `#A1A1AA` | Body copy and descriptions | | `--color-faint` | `#71717A` | Metadata, eyebrows, footnotes | | `--color-hairline` | `rgba(255,255,255,0.08)` | Section rules, cell seams | | `--color-hairline-strong` | `rgba(255,255,255,0.16)` | Outline buttons, emphasis rules | ### Service accents Red is one of five. It is not the brand accent and it does not lead. | Service | Token | Value | Icon (Phosphor, duotone) | |---|---|---|---| | Consultoría | `--color-svc-consultoria` | `#B168F9` | `Compass` | | Inteligencia Artificial | `--color-svc-ia` | `#FF3B5C` | `Brain` | | Automatización | `--color-svc-automatizacion` | `#FFA23C` | `Lightning` | | Desarrollo | `--color-svc-desarrollo` | `#7C9CFF` | `Code` | | Data | `--color-svc-data` | `#3DE0A5` | `ChartLineUp` | ### Discipline of colour (brandbook ch. 03) - **Do** use an accent for the service mark (a 2px bar), the service icon, or a diagram branch. - **Do** keep it to at most two appearances of colour per card or block. - **Don't** put colour on a button. The primary CTA is white on black, always — including IA. - **Don't** put colour on text that has to be read, and never on a section background. - **Don't** put colour in a gradient. There are no gradients in this brand. ### The accent rule on a service page (brandbook ch. 07) Inside a service page the only accent that appears is that service's own. The other four return only at the end, in "Cómo se conecta", when the page offers somewhere to go next. The reader has already chosen; the accent now confirms where they are standing rather than distinguishing between five options. ### Red, specifically Red survives in three places: the logo mark (`#DD172F`, unchanged — the mark itself is never recoloured or turned white), the IA accent `#FF3B5C`, which is a brighter red tuned for a pure-black ground, and the homepage hero's scattered accent dots, which are the logo red rather than any service colour. The hero is the one standing exception to "colour never goes on a section background"; do not read it as licence for a second one. The logo ships in two files, both with the same red mark. `redfox-logo.svg` sets the wordmark in white and is the default; `redfox-logo-light.svg` sets it in black for white and printed grounds. The **mark** is what never changes — the wordmark follows its background. ### Semantic There is no separate semantic palette. Validation errors use the IA accent `#FF3B5C`; success and warning states are carried by copy and by a hairline state change, not by a colour chip. ### Gradients None **as colour**. Three gradients exist in the codebase and all three are masks or textures, never a fill a visitor reads as colour: - `.rb-mask-x` — the edge mask on the client-logo marquee. - `ChipAnimation`'s `radialGradient` — an SVG opacity mask fading its dot grid. - The homepage hero's `FADE` and its dot-grid `radial-gradient` — a mask and a 1px dot texture. Anything else is a defect. A gradient that carries colour, or that fills a panel, is the pattern this rule exists to stop — `components/lp/BeforeAfter.tsx` shipped one briefly and it was removed. --- ## 3. Typography Rules ### Font families - **Archivo** — display *and* body. One family, separated by weight and size rather than by a second typeface. Loaded in `app/layout.tsx`, exposed as `--font-heading` and `--font-sans`. - **Space Mono** (400, 700) — utility only. Loaded as `--font-mono`, applied through `.rb-meta` and `.rb-num`. - No third family, ever. ### The mono rule Space Mono is for anything a machine would read: service names, counts, durations, dates, section eyebrows, footnotes, figures. **Prose is never mono.** A paragraph, a heading, a sentence of any kind is Archivo. This is the single typographic rule that gets broken most easily and it is not negotiable. ```tsx // Machine-read — mono

Precio fijo por proyecto · Primer resultado antes de 30 días

+40
// Prose — Archivo, never mono

Construimos el sistema que sí funciona.

``` ### Type scale | Role | Size | Weight | Line height | Tracking | Notes | |---|---|---|---|---|---| | Display hero | 40 / 52 / 60px | 700 | 1.05 | −0.035em | Mobile → sm → lg | | H1 page | 44 / 64 / 76px | 700 | 1.02 | −0.035em | Brandbook cover scale | | H2 section | 30 / 38px | 700 | 1.15 | −0.025em | | | H3 | 24 / 28px | 600 | 1.2 | −0.022em | | | Statement | 26 / 32px | 600 | 1.3 | −0.022em | A positioning line, not a heading | | Card title | 19px | 600 | 1.3 | 0 | | | Body large | 17px | 400 | 1.65 | 0 | Hero and chapter intros | | Body | 16px | 400 | 1.6–1.65 | 0 | | | Body small | 14px | 400 | 1.6 | 0 | Cell descriptions | | Meta (`.rb-meta`) | 11px | 400 | 1.5 | 0.08em | UPPERCASE, Space Mono | | Figure (`.rb-num`) | 17–28px | 700 | 1.0–1.2 | 0 | Space Mono, tabular | | Button label | 14px | 600 | 1 | 0 | | ### Typography principles - Negative tracking is written in `em`, never `px`, so it scales with the size. - Headings are white; body copy is `--color-dim`; metadata is `--color-faint`. Three steps, no more. - **No italic `` in headings.** The italic key word was the navy brand's signature move and is not part of this system. The base-layer rule in `globals.css` survives only until the last unmigrated page stops emitting it, and is marked as a Wave 6 removal. - Eyebrows are `.rb-meta` preceded by a 24px hairline, not a coloured label. - Body copy never goes below `line-height: 1.6`. --- ## 4. Component Stylings ### Buttons **Primary CTA — white on black** - Background `#FFFFFF`, label `#000000`, 14px / weight 600 - Padding `14px 24px`, **radius `0`**, no border, no shadow - Hover: `filter: brightness(0.9)`; active: `scale(0.98)`; transition 150ms - One primary CTA per section. Everything else is an outline or a link. **Secondary — outline, with the A1 wipe** - Transparent ground, `1px solid #FFFFFF`, label white 14px / weight 600 - Padding `14px 24px`, radius `0` - Hover: a white fill wipes in from the left (`scaleX(0 → 1)`, 300ms) and the label inverts to black 80ms behind it. Implemented by `.rb-btn-wipe` + `__fill` + `__label` in `globals.css`. **Text link — with the F3 drawn underline** - White 14px, optional `→` that shifts `translateX(4px)` on hover - `.rb-link-draw` + `.rb-link-draw__line`: a 1px rule draws from the left in 280ms and retracts to the right on leave. Use `--inset` for links that carry horizontal padding, such as nav items. There is no coloured button in this system. Not for IA, not for errors, not for anything. ### Cells and slabs Cards do not float. A group of related cells is one slab: a container with a hairline border whose background is the hairline colour, and children on `--color-canvas` separated by `gap-px`, so the seams *are* the gaps. ```tsx
``` - Padding `24–36px`, radius `0`, no shadow - Hover: `background: rgba(255,255,255,0.035)`, 150ms. No lift, no border glow. - The service mark on a cell is a `2px × 16px` bar in the service accent that grows to 24px on hover. Never a dot, never a loose icon. ### Navigation - Sticky, `h-16`, `background: rgba(0,0,0,0.72)` with `backdrop-blur-xl`, bottom hairline - Logo left at `h-6`, links in Archivo 14px white with the F3 drawn underline - Services dropdown: panel on `--color-surface-2`, `--color-hairline-strong` border, each row an accent-coloured duotone icon + service name + outcome - Right CTA is white-on-black. Nav labels say **"Servicios"** — never "Módulos"; see `lessons.md`. ### Inputs **Specified in §14.** A field is a rectangle one surface step above its ground, with a `--color-hairline-strong` edge that escalates to `--color-faint` on hover and `--color-ink` on focus. Radius `0`, no ring, no glow, no colour — except the error state, which is the one place in this system where colour is not a service mark. Full spec, including the accessible error state and form layout, in §14. ### Eyebrow / meta label `.rb-meta` in `--color-faint`, preceded by a `1px × 24px` rule in `--color-hairline-strong`. No pill, no background, no colour. ### Image treatment - Every photograph gets `filter: grayscale(1) contrast(1.08) brightness(0.88)` (`.rb-img`), so the only colour left on the page is the service accent. `.rb-img-raw` exists to demonstrate the untreated state in the brandbook and must not ship on a real page. - **Photography only.** `.rb-img` applies to the three photographic roles in §12, not to every image. **Product UI screenshots are exempt** — on `/productos` the screenshot *is* the thing being sold, and desaturating it hides the product's own interface. Diagrams, logos and screenshots keep their own colour. If an image is a picture of the world, it gets `.rb-img`; if it is a picture of a screen, it does not. - Text over a photo only with a 55% black scrim, and only on an already-treated image. - Always `next/image`, never a bare ``. - No rounding, no shadow. --- ## 5. Icon System - **Package:** `@phosphor-icons/react`, weight **`duotone`**, always. Never regular, bold, thin or fill. - **Size:** 24–32px on cells and panels, 22–26px inline. - **Colour:** a service icon carries its service accent. Every other icon inherits the text colour. - Icons are always paired with a label — never decorative background art. Service icon assignments are in §2. `lib/servicios-config.ts` is the machine-readable source and wins over this table. --- ## 6. Layout Principles ### Container — one constant ```ts export const CONTAINER = "mx-auto w-full max-w-[1200px] px-5 sm:px-8 lg:px-10"; ``` There is exactly one container in the system, and **the gutter lives inside the max-width box.** Putting the gutter on an outer wrapper shifts the content edge by the gutter width and knocks every row out of alignment with the header — that is the live site's existing bug, where the logo sits 40px to the right of the H1 and it worsens on wider screens. Never wrap `CONTAINER` in another padded element. ### Spacing - Base unit 4px; the working scale is `4 / 8 / 12 / 16 / 20 / 28 / 36 / 48 / 80 / 112px` - Section vertical padding `80px` mobile → `112px` desktop (`py-20 lg:py-28`) - Cell padding `24–36px`; grid gaps are `gap-px` where cells share seams, `16–36px` otherwise ### Section separation Sections are separated by a **1px hairline at 8% white**, never by a background change. There is no A/B background alternation in this system — the whole page is black. A section may sit on `--color-surface` when it genuinely needs to lift, and that is the exception, not a rhythm. ### Section chrome — `Section`, and when not to use `RevealContent` Every section is built from `components/shared/Section.tsx`, which carries the container gutter and the D3 drawn rule. A page's first section takes `flush` — a hero draws no rule above it. Do not hand-roll `
`; that produces a second, slightly different rhythm. **`RevealContent` sets `initial={{ opacity: 0 }}`.** Content inside it is therefore invisible in the server-rendered HTML and only appears after hydration and an intersection. That is acceptable for a section the reader scrolls to. It is **not** acceptable for: - **Any `

` or hero copy.** The most important element on the page must not depend on JS. - **Link grids that are a crawl path** — the blog index, related services. These carry internal link equity and must render at full opacity with or without JS. The rule of thumb: if it is above the fold, or if a crawler following links is the point, render it plainly. `prefers-reduced-motion` already renders everything fully, so this only affects the JS-disabled and pre-hydration cases — which are exactly the ones that matter for the H1. ### Border radius **`0px`. Every component, no exception.** There is no radius scale. Tailwind's `rounded-*` utilities should not appear in migrated files; `rounded-none` is used only where a third-party default has to be overridden. ### Depth No shadows on content. Depth is suggested by the hairline and by the three-step surface scale (`canvas → surface → surface-2`). The one shadow in the system is on the nav dropdown, where a menu genuinely floats over the page. --- ## 7. Depth & Elevation | Level | Treatment | Use | |---|---|---| | 0 — flat | nothing | Everything by default | | 1 — seam | `1px` hairline at 8% white | Section rules, cell seams | | 2 — surface | `--color-surface` `#0B0B0B` | A section that needs to lift off the canvas | | 3 — panel | `--color-surface-2` `#141414` + `--color-hairline-strong` | Menus, overlays | | 4 — floating | `0 24px 64px rgba(0,0,0,0.8)` | Nav dropdown only | No `box-shadow` on a card, an image, a button or an input. --- ## 8. Micro-Interactions & Motion Motion explains a relationship or it does not happen. Nothing moves to set a mood. (Brandbook ch. 09.) | Name | Spec | |---|---| | Entrance | `opacity 0 → 1` with 20px rise, 450ms ease-out, once per element | | Stagger | 80–100ms between siblings, never more than five staggered items | | D3 — drawn rule | The section's own top hairline draws `scaleX(0 → 1)` in 300ms; content follows at +180ms in 250ms. No extra element is added — the line that already separates the section is simply drawn | | E3 — masked headline | Each headline line rises from behind its own `overflow-hidden` mask, 600ms, `cubic-bezier(0.16, 1, 0.3, 1)` | | A1 — button wipe | White fill wipes in from the left, 300ms; label inverts 80ms behind it | | A3 — brackets | 9px hairline corner brackets fade and settle inward, 180ms | | B1 — focus row | Hovering one cell drops its siblings to `opacity: 0.35`, 220ms | | C1 — diagram hover | Hovering a branch dims the others to 22% | | F2 — reading meter | The service bar lightens the active service in 200ms as you read | | F3 — link underline | 1px rule draws from the left in 280ms, retracts to the right on leave | | Diagram pulse | Branches draw on load and a pulse travels them — the only looping animation on the site | | Reduced motion | `prefers-reduced-motion: reduce` sets `animation: none` globally; every Framer component renders in its final state | Transforms and opacity only. No animated colour, no animated layout. **Known limitation:** the D3 rule replaced the static `.rb-divider` border with an animated one, so without JavaScript or before hydration the section hairlines are missing. Cosmetic, accepted. The fix — keep the static border and animate a white line over it — costs one element per section and is available if the polish pass wants it. --- ## 9. Do's and Don'ts ### Do - Use `#000000` as the page background — pure black, on every page including the blog - Use a service accent only as a mark, an icon or a diagram branch, at most twice per block - Keep every CTA white-on-black, and every secondary a 1px white outline - Set every machine-read string in Space Mono via `.rb-meta` / `.rb-num` - Separate sections with a 1px hairline at 8% white - Build groups of cells as one slab with `gap-px` seams, sharing borders - Put the gutter inside the 1200px box, using the single `CONTAINER` constant - Desaturate every photograph with `.rb-img` before it goes on a page — photographs only, never product UI screenshots (see §4) - Use the photography roles in order: Operación real → Materia → Retrato ### Don't - Don't use navy `#0A0E1A`, `#0D1220` or the light `#F0F0F0` surface — all three are retired - Don't colour a button, including for Inteligencia Artificial - Don't set a paragraph, a heading or any prose in Space Mono - Don't use `` italic in a heading — that was the navy brand, not this one - Don't round a corner. Radius is `0`, everywhere - Don't add a gradient. The marquee `mask-image` is the only one that survives - Don't add a `box-shadow` to a card, image, button or input - Don't alternate section backgrounds — the page is one black canvas - Don't put two photography directions on the same page, and never a photo behind a form or a data block - Don't label navigation, buttons or headings "Módulos". The client-facing word is **"Servicios"**; the operating-system metaphor is only ever used inside a sentence that explains it (`lessons.md`) --- ## 10. Responsive Behavior | Name | Width | Key changes | |---|---|---| | Mobile | <640px | 1-col, gutter 20px, section padding 80px, display hero 40px | | Small | 640–1024px | 2-col grids, gutter 32px, display hero 52px | | Desktop | >1024px | Full multi-col, gutter 40px, 1200px box, display hero 60px | - Navigation collapses to a full-screen black overlay; links stack, services expand inline - Slabs collapse to 1-col; the `gap-px` seams become horizontal rules automatically - The system diagram is desktop-only; below `lg` it degrades to a row of accent-marked service chips - `.rb-claims` writes its own seams in CSS rather than swapping Tailwind padding classes, because `pl-0` and `pl-4` on one element resolve by **stylesheet order, not class order**, and silently indented a cell. Where two utilities could collide, write the CSS --- ## 11. Page Templates ### Template A — Homepage ``` 1. Nav sticky, rgba(0,0,0,0.72) + blur, bottom hairline 2. Hero eyebrow → masked H1 → body → CTA pair → claims panel | system diagram 3. Client logos marquee, .rb-mask-x edge mask 4. Services slab 5 cells, one slab, accent mark + duotone icon per cell 5. Diagnóstico the offer, stated plainly 6. Cómo trabajamos numbered steps 7. Por qué RedFox cells with hairline seams 8. Herramientas logo strip 9. Cierre one statement, one white CTA 10. Footer ``` Every section from 3 onward carries a D3 drawn rule as its top hairline. ### Template B — Service page (brandbook ch. 07, in this order, always) ``` 01 Encabezado breadcrumb · icon · name · promise; diagram at right with this branch lit and the others at 22% 02 El problema the pain in the client's words + three symptoms they recognise 03 Qué incluye three deliverables in one slab with seams 04 Evidencia one full-bleed photograph of real operations, black scrim 05 Cómo se conecta the two services it combines with most — the other accents return here 06 Preguntas real objections answered plainly, then one white CTA ``` - Only this service's accent appears before step 05. - The service bar stays pinned to the service you are reading (F2 reading meter). - Delivery window and starting scope sit together under the CTA, in mono. - **No prices on a service page.** Pricing lives in the proposal; the page shows "alcance de arranque" instead. ### Template C — Long-form reading (blog, articles) The blog is the only place on this site where someone reads 1,500 words instead of scanning a section, and it is now black like everything else — the `#F0F0F0` light surface is retired. Every value below exists to answer one question: what does the rest of this system have to do differently when the reader stays on the page for six minutes instead of six seconds? ``` 01 Encabezado back link · H1 · eyebrow (vertical) + year in mono 02 Portada one treated photograph at the reading measure 03 Cuerpo the article, one 660px column 04 Servicios the related services slab — the internal links 05 Cierre one white CTA 06 Footer ``` #### The reading column | Value | Setting | Why | |---|---|---| | Measure | `max-w-[660px]` ≈ **68–72 characters** | Below ~55 the eye jumps too often; above ~80 it loses the line on the return sweep. 660px is the same number at 18px Archivo | | Column | One, centred. Title, cover and body share it | Two widths inside one article make the left edge move as you scroll, which reads as a layout bug | | Section padding | `py-14 lg:py-20` | Shorter than the marketing `py-20 lg:py-28`. A reader who came for the text should not have to scroll past a landing-page gap first | #### Body copy | Value | Setting | Why | |---|---|---| | Size | **18px**, every breakpoint (`prose-lg`) | Marketing body is 16–17px because it is scanned next to a heading. Read continuously, 16px on black is small; the measure narrows on mobile instead of the type shrinking | | Line height | **1.78** | Marketing copy floors at 1.6. Long-form on a dark ground needs more: each line is a bright band on black, and tight leading makes consecutive bands interfere. 1.75–1.8 is the working range | | Paragraph spacing | **24px** (`1.33em`), no indent | Larger than the leading, so a paragraph break is visible without a rule or an indent | | Weight | 400. `` is 600 in `--color-ink` | A bolder base weight blooms on black. Emphasis comes from colour stepping up to white, not from more ink | | Tracking | `0` | Negative tracking is a display move. At 18px it closes the counters and slows reading | #### Body colour — the one value that is not white **Body copy is `--color-dim` `#A1A1AA`, not `--color-ink`.** `#FFFFFF` on `#000000` is a **21:1** contrast ratio. That is not "maximum legibility", it is the condition that produces halation: on an emissive screen the white glyphs bleed into the black counters, the stems thicken visually, and after a few hundred words the reader is tired without being able to say why. The effect is invisible in a screenshot and only shows up in the reading, which is exactly why this has to be written down rather than judged by eye. `#A1A1AA` on black measures **8.2:1** — above WCAG AAA for body text (7:1), with roughly 60% of the luminance of pure white. It is also already the system's body colour (§3), so long-form does not need a token of its own. - Body, list items, captions, table cells → `--color-dim` - Headings, ``, links, blockquote text → `--color-ink`. Short bursts; white is the contrast step that marks them, and no burst is long enough to fatigue - Metadata, markers, counters, rules → `--color-faint` Three steps, same as everywhere else. Long-form does not get a fourth. #### Heading scale inside an article Article headings are **smaller than section headings**. An H2 in a landing section announces a new subject to someone scanning; an H2 in an article interrupts someone already reading, and only has to be findable, not loud. | Role | Size | Weight | Tracking | Space above | Colour | |---|---|---|---|---|---| | H1 (article title) | 34 / 46px | 700 | −0.03em | — | `ink` | | H2 | 30px | 700 | −0.025em | `1.87em` (≈56px) | `ink` | | H3 | 24px | 600 | −0.02em | `1.6em` (≈38px) | `ink` | | H4 | 18px | 600 | 0 | `1.6em` | `ink` | Space above a heading is always about three times the space below it — a heading belongs to the text under it, not to the paragraph it follows. No `` italic in any of them (§3). #### Links inside prose A prose link cannot use the F3 drawn underline. F3 draws on hover, and a link that is indistinguishable from body text until the pointer reaches it is not a link — in a 1,500-word article that is dozens of links a reader never learns are there. F3 also needs a nested `` element, which Markdown-rendered anchors do not have. So, in prose only: - Link text is `--color-ink` (white against `--color-dim` body — the colour step is the first signal) - **1px underline in `--color-hairline-strong`**, `text-underline-offset: 3px`, always visible - On hover/focus the underline goes to solid `--color-ink` in 150ms. The rule brightens, it does not appear `rb-link-draw` stays the treatment for every link we author the markup for: the back link, the card links, the related-services links, nav and footer. Prose is the exception, and it is the only one. #### Lists, quotes, rules - **Bulleted list:** `list-style: square` — this system has no rounded shapes, and that includes a bullet. Marker in `--color-faint`, `1.5em` indent, `0.6em` between items - **Numbered list:** counters in **Space Mono** via `--color-faint`. A list index is machine-read (§3), and tabular figures keep double digits aligned - **Blockquote:** 1px left rule in `--color-hairline-strong` (never a service accent — a quote is not a service), `20px` padding, text `--color-ink` at 19px/1.6, **not italic**, no quote glyph - **`
`:** a full-measure hairline at 8% white with `3em` above and below. It is the D3 rule standing still #### Code and captions - **Inline code:** Space Mono `0.875em`, `--color-ink`, on `--color-surface-2`, `2px 6px` padding, radius `0`, no backtick glyphs - **Code block:** `--color-surface` ground, 1px `--color-hairline` border, radius `0`, 14px/1.6 mono, horizontal scroll rather than wrapping. Never the accent-coloured code of the navy era - **Images in prose and the cover:** `.rb-img` treatment like every other photograph, radius `0` - **Caption:** `.rb-meta` in `--color-faint`, `12px`, centred under the image #### What long-form does *not* change The measure, the leading and the body colour are the only concessions. Section padding, the hairline dividers, the D3 rules, the white-on-black CTA, the zero radius and the mono rule are identical to every other page. A reading surface that invents its own chrome stops looking like the same site two scrolls in. --- ## 12. Photography Three roles, in a fixed order of preference. Never all three on one page, and never two directions on one page. ### 1 — Operación real (primary) Documentary photography of a client's actual operation: warehouses, plants, production floors, offices in use. People working, not people posing. It is the only direction that supplies proof rather than texture. - **Use:** case studies · service pages · blog headers - **Do:** real scenes shot on site with the mess that is already there; wide framing that shows the whole system; people with their backs turned or absorbed in the task - **Don't:** stock of people smiling at a camera in a meeting room; screens with fake dashboards composited on; any frame where the work looks clean and quiet - **Cost:** requires site access and written permission. That cost is real, and it is why the second direction exists ### 2 — Materia (support) Macro of material, machine and industrial texture. Used where no operations photo exists and the text needs a pause. Never competes with Operación real on the same page — it replaces it when there isn't one. - **Use:** section breaks · quote grounds · resource covers - **Do:** one material per frame, very tight crop; high contrast with real black in the shadows; large and full-bleed, never icon-sized - **Don't:** 3D renders, particles, polygon meshes, generic "AI" imagery; textures whose own colour competes with the accents; the same texture in two adjacent sections - **Cost:** stock or a short in-house shoot. The cheap fallback, not the first choice ### 3 — Retrato (reserved) Team and client portraits on black. Only where the person is the subject. - **Use:** sobre nosotros · testimonials · author bylines - **Do:** continuous black ground with no set behind it; a single hard light source; consistent framing across the whole series - **Don't:** light or coloured grounds; mixing our own portraits with stock people; saturated clothing that survives the treatment - **Cost:** requires a directed shoot. Without one, the section runs without a portrait ### Placement - One photograph per service page, full-bleed, as a cut between sections - Text over a photo only with a 55% black scrim on an already-treated image - Never a photo behind a data block or a form > The nine photos under `public/rebrand/img/` are Unsplash material used only to prove the > treatment. None are ours and **none may be published.** Wave 6 deletes them. --- ## 13. Voice Direct and concrete, with no brochure adjectives. We write like someone who has already stood in the client's operation. | Instead of | Write | Why | |---|---|---| | "Soluciones innovadoras de transformación digital de última generación." | "Construimos el sistema que refleja cómo ya trabajas." | Name what we do, not the category we get filed under | | "Contáctanos para conocer más sobre nuestros servicios." | "Cuéntanos el problema. En 30 minutos sabemos si podemos ayudarte." | Say what happens after the click, and how long it takes | | "Precios competitivos adaptados a tus necesidades." | "Precio fijo por proyecto, no por hora. Alcance escrito antes de empezar." | A figure or a verifiable rule beats an adjective | **Vocabulary rule.** "Cada servicio es un módulo del sistema operativo de tu empresa" is fine — the metaphor lives inside a sentence that explains it. "Módulos" as a nav label, a button or a heading is not: without the explaining sentence the client does not know what a module is. Client-facing label is always **"Servicios"**. See `lessons.md`. --- ## 14. Forms and Inputs A form is the only place on this site where the visitor writes instead of reads, and it is the only place where the system has to admit that something went wrong. Everything below exists to answer two questions the rest of the document never asks: what does a rectangle look like when a person is allowed to type into it, and what does this brand do when the answer is rejected. Written in Wave 5, ahead of the three forms, for the same reason §11 Template C was written ahead of the article template: three forms built against three improvised input styles is the failure this ordering prevents. ### The one exception to the colour rule §2 says colour identifies a service and never decorates. **The error state is the exception**, and it is the only one. An invalid field is bordered in `--color-svc-ia` `#FF3B5C` and its message is set in the same value. This is deliberate: the IA accent is already the system's declared validation colour (§2 Semantic), and an error a user cannot find is worse than a stretched rule. Colour is the *second* signal — `aria-invalid` and the message text are the first. Nothing else in a form is coloured: not the submit, not a selected option, not a success state. ### The text input | Property | Value | |---|---| | Height | `46px` — `12px 14px` padding on 15px/1.5 text | | Type | Archivo 15px, weight 400, `--color-ink`. Placeholder `--color-faint` | | Ground | One step above the field's ground: `--color-surface` on canvas, `--color-surface-2` on a surface panel | | Border | `1px solid var(--color-hairline-strong)` | | Radius | `0`. No shadow, no inner shadow, no ring | | Hover | `border-color: var(--color-faint)`, 150ms | | Focus | `border-color: var(--color-ink)` **plus** the global square 2px white `:focus-visible` outline at `2px` offset, already in `globals.css` | | Transition | `border-color 150ms` only. Never an animated background | The border escalates in three steps — `hairline-strong → faint → ink` — and each step is an existing token. A field never grows a coloured focus ring; the navy era's `ring-1 ring-brand-red/30` is retired along with the colour it used. ### Textarea The text input's box, with `min-height: 120px` (4 rows), `line-height: 1.6`, and `resize: vertical` — never `resize: none`, because a person writing 400 words should be able to see them, and never `both`, because horizontal resize breaks the column. ### Select The text input's box with `appearance: none`, `padding-right: 40px`, and a 16px chevron in `--color-faint` pinned `14px` from the right edge, `pointer-events: none`. The native option list cannot be styled beyond ground and colour, so each `