# site-customization Specification

## Requirements

### Requirement: Configurable brand palette settings

The system MUST expose site settings for the key brand palette tokens with the current brand values
as defaults: `color_primary` (`#2C2F31`), `color_primary_hover` (`#1A1C1D`), `color_base`
(`#F4F3F1`), `color_section_alt` (`#E6E7E8`), `color_accent` (`#B09B82`), `color_accent_strong`
(`#7A6A5A`) and `color_ink` (`#1A1C1D`). The settings MUST be seeded and persisted through
`SettingsService`.

#### Scenario: Palette defaults are seeded

- GIVEN the `SiteSettingSeeder` runs
- WHEN the palette settings are read
- THEN each palette key exists
- AND `color_primary` is `#2C2F31` and `color_accent` is `#B09B82`

### Requirement: Runtime CSS variable overrides

The public layout MUST render a `<style id="brand-overrides">` element in `<head>` AFTER the Vite
CSS link. The block MUST declare one `:root` custom property per palette setting that is set, mapping
each setting to its CSS variable (`color_primary` → `--color-brand-900`, `color_primary_hover` →
`--color-brand-950`, `color_base` → `--color-brand-50`, `color_section_alt` → `--color-brand-100`,
`color_accent` → `--color-accent-500`, `color_accent_strong` → `--color-accent-700`, `color_ink` →
`--color-brand-950`). Only variables whose setting is set SHALL be emitted. A value that is not a
valid `#RGB`/`#RRGGBB` hex SHALL fall back to that token's default.

#### Scenario: Set values are emitted as CSS variables

- GIVEN `color_primary` is `#123456` and `color_accent` is `#ABCDEF`
- WHEN a public page renders
- THEN the `<style id="brand-overrides">` block contains `--color-brand-900: #123456`
- AND it contains `--color-accent-500: #ABCDEF`
- AND the style element appears after the Vite CSS link

#### Scenario: Unset variables are omitted

- GIVEN `color_accent_strong` has no value
- WHEN a public page renders
- THEN the override block does not contain `--color-accent-700`

#### Scenario: Invalid hex falls back to the default

- GIVEN `color_primary` is `not-a-color`
- WHEN the overrides are resolved
- THEN `--color-brand-900` resolves to the default `#2C2F31`

### Requirement: Filament panel primary color from settings

The Filament admin panel MUST use the `panel_color_primary` setting (default `#2C2F31`) as its
primary color. Reading the setting MUST NOT fail when the settings table is unavailable (for example
during migrations).

#### Scenario: Custom panel color is applied

- GIVEN `panel_color_primary` is `#B09B82`
- WHEN the admin panel is built
- THEN the panel primary color is the one derived from `#B09B82`

#### Scenario: Panel building is safe without a database

- GIVEN the settings source throws because the database is not ready
- WHEN the panel is built
- THEN it falls back to the default primary `#2C2F31`
- AND no exception escapes

### Requirement: Activatable brochure section

The system MUST expose brochure settings: `brochure_enabled` (default `false`), `brochure_title`
(default "Descarga nuestro brochure"), `brochure_description`, `brochure_file` (public disk path) and
`brochure_cta_label` (default "Descargar brochure"). A reusable `<x-brochure>` section component
SHALL render ONLY when `brochure_enabled` is true AND the configured file exists on the public disk.
When rendered, it MUST show the title, the description (when set) and a download button linking to
the file with the `data-track="brochure_download"` attribute. The section MUST NOT render when the
file is missing, keeping the link 404-safe.

#### Scenario: Disabled brochure is hidden

- GIVEN `brochure_enabled` is false and a file is configured
- WHEN the home page renders
- THEN the brochure section is not present

#### Scenario: Enabled brochure with a missing file is hidden

- GIVEN `brochure_enabled` is true and `brochure_file` points to a file that does not exist
- WHEN the home page renders
- THEN the brochure section is not present

#### Scenario: Enabled brochure renders the download

- GIVEN `brochure_enabled` is true, a PDF exists on the public disk and the title, description and
  CTA label are set
- WHEN the home page renders
- THEN the section shows the title, the description and the CTA label
- AND it contains a download link to the file with `data-track="brochure_download"`

### Requirement: Admin management of customization settings

The `ManageSiteSettings` Filament page MUST provide a palette section with color pickers and hex
validation plus a contrast helper note, and a Brochure section with an enable toggle, text fields
and a PDF `FileUpload` (public disk, max ~20MB). Saving MUST persist the values through
`SettingsService`. The palette and brochure settings MUST also be part of the panel hydration.

#### Scenario: The new sections render

- GIVEN an authenticated administrator
- WHEN they open the site settings page
- THEN the palette section and the brochure section are present

#### Scenario: Palette settings are saved

- GIVEN an authenticated administrator on the settings page
- WHEN they submit `color_primary` = `#123456` and `panel_color_primary` = `#654321`
- THEN both settings are persisted

#### Scenario: Brochure settings and PDF are saved

- GIVEN an authenticated administrator on the settings page
- WHEN they enable the brochure, fill the title and upload a PDF
- THEN `brochure_enabled` is true, the title is persisted and `brochure_file` holds the stored path
