diff --git a/ASSETS.md b/ASSETS.md
index d451fee..2d10a6d 100644
--- a/ASSETS.md
+++ b/ASSETS.md
@@ -9,9 +9,9 @@ mas ainda sem versão no nome das pastas dos ficheiros hand-vendored.
| Biblioteca | Versão | Caminho | Usado em |
|------------------------|--------|----------------------------------------|----------------------|
| Bootstrap | 5.3.3 | `assets/vendor/bootstrap5/` | Site público + backoffice (unificado 25/09) |
-| Bootstrap Icons | — | `assets/vendor/bootstrap-icons/` | Backoffice |
+| Bootstrap Icons | — | `assets/vendor/bootstrap-icons/` | Backoffice (agora carregado do pacote partilhado `bootstrap-icons` 1.13.1; esta cópia só como recurso) |
| jQuery | 3.7.1 | `assets/vendor/jquery/jquery-3.7.1.min.js` | Site público + backoffice (deduplicado 25/09) |
-| Font Awesome Free | 5.13.1 | `site/assets/fonts/fontawesome/` | Site público (~18 MB, todo o pacote) |
+| Font Awesome Free | 5.13.1 | `site/assets/fonts/fontawesome/` | Site público: agora FA 6.7.2 do pacote partilhado `fontawesome`; esta cópia (~18 MB) só como recurso, sem uso se o submódulo tiver `functions_icons.php` |
| PHPMailer | 7.1.1 | `vendor/PHPMailer/` | Envio de email (`config/functions_mail.php`, partilhado) |
`assets/vendor/bootstrap/` (a cópia 4.3.1) ficou sem nenhuma referência depois da migração —
diff --git a/CLAUDE.md b/CLAUDE.md
index 128be62..ec75562 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -156,3 +156,9 @@ or adapted for production, and these accounts must never exist in a production d
## Bootstrap re-tematizado (2026-10-13)
- `assets/css/bs-brand.css` (carregado depois do Bootstrap em `includes/header.php` e `includes/auth_header.php`) sobrescreve as cores do Bootstrap só com variáveis `--bs-*` e as variáveis de componente (`.btn-*`, `.form-check-input`, `.page-link`…), claro e escuro. A cor de marca é `--fitme-accent` (fallback `#C2D500`); todos os tons derivam dela com `color-mix()`; `--brand-on` é o texto sobre a cor. Secondary/success/danger/warning/info têm valores próprios. Verificação: `platform.php?tool=branding` (Montra da marca) não deve mostrar nenhum azul por omissão. O site público ainda não carrega este ficheiro.
+
+## Pacotes de ícones partilhados (2026-10-13)
+- `config/db.php` regista `'icons' => ['packs' => ['bootstrap-icons','fontawesome'], 'default' => 'bootstrap-icons']` só se `shared/platform-tools/functions_icons.php` existe. Flaticon NÃO está registado: o site usa PNGs (`uploads/modalidades/icons`), não a fonte.
+- `fit_icon_assets($packs, $fallbackLocal)` (`config/functions_icons.php`) imprime `pt_icon_assets()` ou, sem submódulo novo, os `` locais. Backoffice (`includes/header.php`, `includes/auth_header.php`): `bootstrap-icons`; site público (`site/includes/include.php`): `fontawesome` (FA 6.7.2; as classes `fas/far/fab` e os nomes FA5 funcionam por aliases).
+- Sidebar > Sistema: «Pacotes de ícones» (sysadmin) -> `platform.php?tool=icons`.
+- Sem uso quando o submódulo é novo (não apagados): `assets/vendor/bootstrap-icons/`, `site/assets/fonts/fontawesome/`, `site/assets/icon-fonts/`, `site/assets/css/flaticon.css`. `config/error_handler.php` ainda usa bootstrap-icons por CDN (página de erro autónoma).
diff --git a/config/db.php b/config/db.php
index 2d0eb78..27dd54c 100644
--- a/config/db.php
+++ b/config/db.php
@@ -96,7 +96,17 @@ try {
// para deixar a porta aberta a usar o throttle partilhado no futuro. Ver
// views/auth/login.php para a nota completa.
require_once dirname(__DIR__) . '/shared/platform-tools/functions_connector.php';
-platform_connect($pdo, [
+// Pacotes de ícones partilhados (platform?tool=icons, pt_icon_assets()). Só se o
+// submódulo já os tem; sem ele os layouts caem nas cópias locais (fit_icon_assets()).
+// Flaticon NÃO está registado: o site usa PNGs (uploads/modalidades/icons), não a fonte.
+$iconsFile = dirname(__DIR__) . '/shared/platform-tools/functions_icons.php';
+if (is_file($iconsFile)) {
+ require_once $iconsFile;
+}
+$iconsOpt = is_file($iconsFile)
+ ? ['icons' => ['packs' => ['bootstrap-icons', 'fontawesome'], 'default' => 'bootstrap-icons']]
+ : [];
+platform_connect($pdo, $iconsOpt + [
'auth' => 'shared',
'roles' => [
// Preserva a hierarquia que config/auth.php já tinha (sysadmin >
diff --git a/config/functions.php b/config/functions.php
index 16d6b53..a2a803f 100644
--- a/config/functions.php
+++ b/config/functions.php
@@ -27,6 +27,7 @@ require_once __DIR__ . '/functions_migrations.php';// platform_update.php migrat
require_once __DIR__ . '/functions_queue.php'; // message_queue + enqueue_*/flush_message
require_once __DIR__ . '/functions_csrf.php';
require_once __DIR__ . '/functions_html.php'; // allowlist HTML sanitiser (clean_richtext/clean_map_embed)
+require_once __DIR__ . '/functions_icons.php'; // fit_icon_assets(): pacotes de ícones partilhados + recurso local
require_once __DIR__ . '/ci_compat.php'; // CI4 view-helper shim (script_tag/link_tag/view/esc/session)
require_once __DIR__ . '/functions_gyms.php'; // multi-gym: gyms, URL folders, admin gym switcher
require_once __DIR__ . '/functions_site.php'; // public-site data (site_info/offer/team/modalidades/horario)
diff --git a/config/functions_icons.php b/config/functions_icons.php
new file mode 100644
index 0000000..688eb33
--- /dev/null
+++ b/config/functions_icons.php
@@ -0,0 +1,18 @@
+ locais de recurso, caminhos para link_tag()/base_url()
+function fit_icon_assets(array $packs, array $localHrefs): string {
+ if (function_exists('pt_icon_assets')) {
+ $html = pt_icon_assets($packs);
+ if ($html !== '') return $html;
+ }
+ $out = '';
+ foreach ($localHrefs as $href) {
+ $out .= '' . "\n";
+ }
+ return $out;
+}
diff --git a/includes/auth_header.php b/includes/auth_header.php
index 2b6743e..2d65a91 100644
--- a/includes/auth_header.php
+++ b/includes/auth_header.php
@@ -30,7 +30,7 @@ $app_name = defined('APP_NAME') ? APP_NAME : 'FitMe 3070';
-
+ = fit_icon_assets(['bootstrap-icons'], ['assets/vendor/bootstrap-icons/bootstrap-icons.css']) ?>