# Encoding and shared design guide

## UTF-8 end to end

Use UTF-8 without BOM for PHP/HTML/JS/CSS source. For HTML responses send `header('Content-Type: text/html; charset=UTF-8');` before output and place `<meta charset="UTF-8">` near the beginning of the document head. Preserve session, redirect and cache logic. CSV, JSON, PDF and image endpoints need their own content types.

After a successful MySQLi connection and before queries/escaping, use a checked `$conn->set_charset('utf8mb4')` call. PDO MySQL should include `charset=utf8mb4` in its DSN. Connection settings configure transport; they do not convert existing columns or repair damaged records.

For plain text in HTML, use `htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')`. Substitute handling prevents a malformed string from disappearing, but does not repair the source. Do not double-escape intended trusted HTML or transform passwords.

## Findings from the supplied audit

The file scan covered 231 direct files and reported 113 heuristic findings; it was not cut off by its scan limit, but it omitted nested folders and skipped some large files. Findings include comments, examples and old unused scripts. The audit can flag itself because it contains encoding examples.

The database report was labeled directory. Its audit connection used utf8mb4; the database default was utf8. `2007_rdir` had 55 utf8 text columns; `WhereUser` had 31 utf8mb4 text columns. Several ancillary/copy tables retained latin1 or utf8. No record contents were scanned, and this report does not certify every application connection.

The uploaded `regionalwebsite/theworld.php` had exactly one invalid UTF-8 byte: Windows-1252 `0x96` between Kazakhstan and Uzbekistan on line 121, inside an old commented section. It also lacked explicit HTML charset declarations and an explicit charset on its new connection. That inspection did not deliver a patched file and does not explain unrelated question marks on the club editor.

## Repair workflow

Back up original bytes and inspect a few affected values with their declared charset, primary key and HEX representation. Separate incorrect display decoding, genuine Latin-1 text, UTF-8 bytes mislabeled as Latin-1, already stored mojibake and irreversible replacement characters.

Do not blanket-convert tables or replace every `â` or `Ã`: these characters can be legitimate. Test schema changes on staging, including indexes, unique constraints, foreign keys, collation support and locks. Preview per-record repairs with old/new values and require the old value still to match before update. Preserve rollback data.

Use `/siteadmin/encoding.php` to gather reports. It reads metadata/source; it does not make those repairs. Obtain the latest active source files before changing headers so newer feature fixes survive.

## Shared design and accessibility

Use the root header and current stylesheet. Include the Where menu after the header for account/report pages. Keep page-specific CSS scoped to a unique container/class to avoid changing menus on unrelated sections. Prefer root-relative links for shared assets and explicit `__DIR__`-based PHP includes.

Use one meaningful page heading, descriptive labels, visible keyboard focus, understandable error/empty states and accurate alt text. For the lightbox, preserve the original image link as fallback and return focus to the thumbnail on close. Wide rankings may keep their existing scrollable containers; a new site-wide table-wrapper rollout was deferred.

Public pages can use public caching only when their response is identical for all visitors and contains no session-specific navigation/data. A shared header that varies with login status changes that assumption. The kennel leaderboard uses private/no-store caching. Do not indiscriminately remove session initialization or apply public cache headers across the site.

References: [PHP charset API](https://www.php.net/manual/en/mysqli.set-charset.php) and [MySQL column charset conversion](https://dev.mysql.com/doc/refman/8.4/en/charset-conversion.html).

## Certificate rendering

The new PDF embeds DejaVu Sans regular/bold fonts supplied in certificate-fonts.
Measured text widths keep names and detail lines within the page. The renderer
still converts text to Windows-1252 before PDF output; embedding a Unicode-capable
font alone does not make this generator fully Unicode. Do not describe it as
supporting every script. CSV remains UTF-8.

Continents have explicit text labels and a pending state; never communicate
club membership with colour alone. Keep the club names consistent across map,
milestones, certificate, CSV and guides.
