# Footers - agent guide

> Normative extract of the EchoSistema template for the page
> `/componentes/rodapes`. Copy it verbatim: tag names, props, events and classes
> are contract.
>
> Full guide (rules, tokens and every family): `/agents/echosistema-ui.md`

## Rules that apply before any line of code

- Colour only through tokens (`text-fg1`, `bg-panel`, `border-line`, `.es-i--*`); never a hex, never a Tailwind colour.
- Two axes: the intent gives the colour, the variant consumes it. Never combine them by hand.
- Visible text through `t()`; tag names, props and classes stay literal.
- A component does not fetch: it takes props and emits events.
- An icon alone inside a button needs an `aria-label`.

```vue
<footer-ecommerce :columns="COLUMNS" :legal="LEGAL" phone="+595 975 616 777"
                  email="hola@…" :note="payments" wide />
<footer-real-estate :columns="COLUMNS" :legal="LEGAL" :contacts="CONTACTS" :contact-title="…"
                    :brand="{ logo, name, to: '/' }" :image="BG" :rates="RATES" :rates-pending="pending"
                    :rates-rows="3" :subscribe="SUBSCRIBE" :note="…" :rights-text="…" @subscribe="send" />
<footer-learn :columns="COLUMNS" :legal="LEGAL"
              :cta-title="…" :cta-text="…" :cta-label="…" cta-to="/crear-cuenta" />
<footer-help-desk :columns="COLUMNS" :legal="LEGAL" :status="…" status-tone="success"
                  :hours="…" phone="…" email="…" />
<footer-landing :links="LINKS" :tagline="…" />
```

Types: `ChromeColumn { title, links }` and `ChromeLink { label, to, external? }`
(`app/data/chrome.ts`).

`<footer-real-estate>` is a DARK band in both themes (`--brand-deep`, under a
photograph when `image` is passed), so its inks are white and do not follow
the theme. Every block is optional and renders only with its data. Its own
types: `ChromeContact { key, label, href, icon, external? }` (round icon
buttons; `label` is the accessible name), `ChromeRates { title, pairLabel,
previousLabel, currentLabel, rows, note }` with `ChromeRateRow { code, sign,
previous, current, trend: 'up' | 'down' | '', change }` - ALREADY formatted, the
variant never formats a number - and `ChromeSubscribe { title, text,
placeholder, submitLabel, state: 'idle' | 'pending' | 'success' | 'error',
successMessage, errorMessage }`. The form sends nothing: it emits `subscribe`
with the address and whoever mounts it owns the request and passes `state`
back. A column link with `external: true` opens in a new tab, never through
`localePath`.

The LENGTH is the decision: the shop's is long on purpose (whoever reached the
bottom did not find what they came for); the landing page's is one band (four
columns of links are twenty ways to leave without doing the one thing the page
asks).

The copyright line comes from `runtimeEnv().legalName` - the COMPANY, never the
site's name - and is written inside the variant. Do not pass the holder as a
prop.

---

Source: `app/components/footer/*.vue`
