~isu', $html, $paragraphs);
+ foreach ([...($paragraphs[1] ?? []), $html] as $paragraph) {
+ $text = trim(preg_replace('/\s+/u', ' ', html_entity_decode(strip_tags($paragraph), ENT_QUOTES | ENT_HTML5, 'UTF-8')));
+ if (mb_strlen($text) >= 60) return \Illuminate\Support\Str::limit($text, 320);
+ }
+ return trim(html_entity_decode(strip_tags($html), ENT_QUOTES | ENT_HTML5, 'UTF-8'));
+ }
+
/** Resolve a library identity, preserving the already stored source URLs and versions. */
/** @return array */
public function articleForResource(int $resourceId): array
diff --git a/app/Services/SectorInvestment.php b/app/Services/SectorInvestment.php
index ba12c18e..796d33ca 100644
--- a/app/Services/SectorInvestment.php
+++ b/app/Services/SectorInvestment.php
@@ -37,19 +37,7 @@ final class SectorInvestment
public function publicView(Sector $sector): array
{
$query = SectorOrganization::opportunities($sector);
- $articles = [];
- if (app(LegacyContent::class)->available()) {
- foreach (self::CONTENT[$sector->slug] ?? [] as $slug) {
- try {
- $a = app(LegacyContent::class)->article($slug);
- $articles[] = ['title' => $a['title'], 'href' => $a['href'], 'image' => $a['image'], 'sha256' => $a['sha256'], 'scope' => $slug === 'tech-fintech' && $sector->slug !== 'fintech' ? 'Especialização Fintech; não representa todo o setor.' : 'Conteúdo educativo relacionado; não é uma oportunidade concreta.'];
- } catch (HttpException $e) {
- if ($e->getStatusCode() !== 404) {
- throw $e;
- }
- }
- }
- }
+ $articles = $this->guides($sector);
$relations = [];
foreach (['projects' => 'project_id', 'clusters' => 'cluster_id', 'corridors' => 'corridor_id'] as $table => $foreign) {
$ids = DB::table('opportunity_'.$table)->whereIn('opportunity_id', (clone $query)->select('id'))->pluck($foreign);
@@ -74,6 +62,26 @@ final class SectorInvestment
'content_notice' => $sector->slug === 'mercado-financeiro' ? 'O artigo geral de Mercado Financeiro permanece vazio e não foi publicado. A preparação de negócios neste setor está disponível.' : null];
}
+ /** Published guides for an explicit sector; never inferred from proximity. */
+ public function guides(?Sector $sector): array
+ {
+ if (! $sector) return [];
+ $articles = [];
+ if (app(LegacyContent::class)->available()) {
+ foreach (self::CONTENT[$sector->slug] ?? [] as $slug) {
+ try {
+ $a = app(LegacyContent::class)->article($slug, false);
+ $articles[] = \Illuminate\Support\Arr::only($a, ['title', 'href', 'image', 'sha256', 'summary', 'author', 'opportunities_href', 'opportunities_label', 'has_opportunities']);
+ } catch (HttpException $e) {
+ if ($e->getStatusCode() !== 404) {
+ throw $e;
+ }
+ }
+ }
+ }
+ return $articles;
+ }
+
public function attach(User $actor, string $id, array $input): void
{
$data = Validator::make($input, ['version' => 'required|integer|min:1', 'sector_slug' => 'required|string|max:150'])->validate();
diff --git a/docs/investmoz/unification/educational-guides-qa-manifest.json b/docs/investmoz/unification/educational-guides-qa-manifest.json
new file mode 100644
index 00000000..9db3d966
--- /dev/null
+++ b/docs/investmoz/unification/educational-guides-qa-manifest.json
@@ -0,0 +1,84 @@
+{
+ "branch": "codex/educational-content-cards",
+ "base": "0e7d51f18fb424857fdaad48498a2fc43c044749",
+ "scope": "New QA delta; separate Tempo review before main",
+ "files": [
+ {
+ "path": "app/Http/Controllers/InvestmentDiscoveryController.php",
+ "sha256": "693d1217ead894747c266a7295774b26a8b987f8faf06003ed60a6d3e15aca6c"
+ },
+ {
+ "path": "app/Services/LegacyContent.php",
+ "sha256": "e856ba2a042e971933a401fd9544a50f6bc5c1541c28062719d840a8277da7b8"
+ },
+ {
+ "path": "app/Services/SectorInvestment.php",
+ "sha256": "a0ee1c9bf864ef765ed70fc1bcdc839781d0bed7d705d991c801bfaa9bf7e4a0"
+ },
+ {
+ "path": "docs/investmoz/unification/traceability-and-manual.md",
+ "sha256": "224a07ba0443a0a4a172fd5637ac311bfde64e21a0425aa12e0e729c89a456d6"
+ },
+ {
+ "path": "docs/investmoz/v2/auditoria-portal/backlog-priorizado.csv",
+ "sha256": "78a9642b3b0985d447a790a32f1373b7c19c4e240b21490019e907cc9c6428d3"
+ },
+ {
+ "path": "docs/investmoz/v2/auditoria-portal/backlog.md",
+ "sha256": "cbbcf81bf2f51de50e6f006dcf048bf0e1f47b51ab236f2b07895a627c1301d4"
+ },
+ {
+ "path": "docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv",
+ "sha256": "2652fc4558de01e307adf39b31ffe0897f32c475e3c77061627b03a6ab628227"
+ },
+ {
+ "path": "resources/js/components/educational-article-card.tsx",
+ "sha256": "03a298406702cd3211c44fad1fdf79d455ad029d997d417a416f450d6d420b6e"
+ },
+ {
+ "path": "resources/js/components/educational-guides.tsx",
+ "sha256": "2a2a52e50694e336f05544d51fc776a3bbc2b06d2ab61a1b3cdf1d261afca474"
+ },
+ {
+ "path": "resources/js/components/sector-entry.tsx",
+ "sha256": "39004abf04f096b987d852d834ce9b27fdf557d2283db3b5868678d3ff0bff1a"
+ },
+ {
+ "path": "resources/js/pages/investment/catalogue.tsx",
+ "sha256": "ced5e8d4b2910aeeaeb709d6ff0eb2d492f96d9b671d6ff832eea66d022a1f70"
+ },
+ {
+ "path": "resources/js/pages/investment/detail.tsx",
+ "sha256": "719b3c008887676dd0b69ffe48bd5a64426de92362d92da8ad39412a578c51bc"
+ },
+ {
+ "path": "resources/js/pages/portal/legacy.tsx",
+ "sha256": "dcd8462e940614f5935efa19d9c9444fe3432fbc704e9c05144508d5c944c90d"
+ },
+ {
+ "path": "tests/Feature/EducationalGuidesTest.php",
+ "sha256": "aa9e3f62890f1d75f639ad4e7e05713c18112ec96a7fd49c864e5e007807d3cf"
+ }
+ ],
+ "build_manifest_sha256": "89c3ce0c67d9faf8cb3c5f7e9d74b3ad5d0ad70dff81ca2e37ca5cac7a471620",
+ "migrations": [],
+ "imports": [],
+ "publication": false,
+ "remote_operations": [],
+ "ai": false,
+ "evidence": {
+ "backend": "1 test, 8 assertions; exact isolated QA guard and transactions",
+ "types": "passed",
+ "build": "passed",
+ "desktop_width": 2048,
+ "mobile_width": 390,
+ "mobile_document_width": 375,
+ "keyboard": "visible focus and Enter opened guide",
+ "visual_data": "Read-only copy of existing public Tourism article/image; not synthetic"
+ },
+ "limitations": [
+ "Real Tourism article absent from current QA database; authenticated dossier recovery for that actual source not demonstrated",
+ "Visual preview router and public snapshot stay private outside Git; no scan/publication records fabricated"
+ ],
+ "rollback": "Restore previous sources/build through existing deployment chain, preserving database/uploads/permissions and later data"
+}
diff --git a/docs/investmoz/unification/traceability-and-manual.md b/docs/investmoz/unification/traceability-and-manual.md
index b344144a..d1b6722d 100644
--- a/docs/investmoz/unification/traceability-and-manual.md
+++ b/docs/investmoz/unification/traceability-and-manual.md
@@ -1521,3 +1521,20 @@ Rever a branch e o manifesto nominal; reconciliar novos commits dos programadore
Não há migrations, importação ou publicação neste pacote. A reversão repõe as fontes/build da revisão anterior através da cadeia existente, preservando a base, uploads, referências, permissões e dados posteriores. Os helpers de contexto só transportam query local; não aceitam URL externa como destino de retorno. O manifesto lista fontes e hash do build QA; não inclui `.env`, credenciais, dumps, vendor/node_modules ou fixtures persistentes.
Conferência final dos consumidores: negócios também conferido no navegador com pesquisa vazia; retirado o resumo local repetido, conservando o resumo partilhado. Fintech é identificado como especialização do Mercado Financeiro também nesse selector. Os cartões de zonas traduzem categoria, desenvolvimento, disponibilidade e estado de actividade, preservando os códigos e significados persistidos. A vista combinada não repete na lista de não localizados a ficha que já aparece na lista principal.
+
+
+## Guias educativos relacionados — 20/10/2026
+
+Delta independente de `0e7d51f18fb4`, que já foi integrado e confirmado na homologação. Este incremento permanece na branch `codex/educational-content-cards`, em QA, sujeito a revisão própria. Origem: pedido expresso da Tempo; nenhuma nova regra organizacional.
+
+O componente `EducationalArticleCard` usa imagem pública autorizada, título original, resumo da edição apresentada, autoria e «Ler o guia». Turismo descreve hotelaria, ecoturismo, infraestruturas e referências regionais presentes no artigo, sem repetir metas financeiras como promessa. Outros artigos usam um excerto do texto efectivo. A apresentação não altera originais, fontes, autoria, direitos, versões, publicação ou scan. A imagem continua sujeita aos filtros públicos existentes. A acção secundária só surge quando a consulta de oportunidades públicas do sector tem resultados; não se infere disponibilidade por menção no artigo.
+
+Consumidores: sector (`SectorEntry`), exploração editorial e leituras relacionadas (`portal/legacy`), catálogo de oportunidades com sector explícito (incluindo vista territorial/mapa) e ficha de oportunidade com sector. Um filtro de localização sem sector não determina um artigo; não se inventaram associações territoriais. Nos restantes catálogos territoriais não foi encontrado um cartão editorial equivalente a substituir. Não se alteraram cartões de anúncios, documentos ou entidades que não sejam recomendações de artigos.
+
+Após a leitura, mantém-se «Iniciar ou continuar uma ideia», com `/investimentos/a-partir-de/{slug}` e o contexto autorizado do dossier quando existente. Não há novo percurso, conta ou privilégio. As provas anteriores de gravação documental mantêm-se; não foram repetidas.
+
+Provas novas: `EducationalGuidesTest`, isolado por guarda QA, transacções e armazenamento fictício do teste, 1 teste / 8 asserções (excerto, autoria, destino, percurso, ausência de resultados, fonte não publicada e scan pendente). TypeScript, sintaxe PHP e build passaram. Capturas a 2048 px e 390 px; a 390 px, conteúdo com 375 px, sem transbordo horizontal, foco visível e Enter no botão «Ler o guia». Imagem real carregada com 900 px de largura natural. A prévia HTTP `http://127.0.0.1:18570/qa/guias/turismo` usa uma cópia por leitura do artigo/imagem já públicos no destino; não usa texto ou imagem sintéticos nem escreve registos. O router privado e a cópia ficam fora do Git. O destino não foi alterado.
+
+Limitação: o artigo real não existe na base QA actual. A prévia permite conferir cartão e leitura; não comprova recuperação desse artigo num dossier autenticado nessa base. O URL original do percurso foi preservado e conferido pelo teste. Não se importaram dados ou fabricaram resultados para preencher essa lacuna. Capturas em `outputs/educational-guides-20261020/desktop.jpg` e `mobile.jpg` (ficheiros locais de prova).
+
+Gestão: editar e publicar pelos ecrãs existentes da biblioteca/editorial; o resumo acompanha a edição apresentada. A acção de oportunidades é calculada pelos registos publicados, não pelo editor. Disponibilização futura: revisão própria e integração em `main` pelo processo automático, após decisão. Sem migrations, importação ou publicação neste delta. Reversão pelas fontes/build anteriores, conservando base, ficheiros, permissões e dados posteriores. IA, oito lacunas contratuais e P7 separados.
diff --git a/docs/investmoz/v2/auditoria-portal/backlog-priorizado.csv b/docs/investmoz/v2/auditoria-portal/backlog-priorizado.csv
index ba423088..568a0b43 100644
--- a/docs/investmoz/v2/auditoria-portal/backlog-priorizado.csv
+++ b/docs/investmoz/v2/auditoria-portal/backlog-priorizado.csv
@@ -7381,3 +7381,4 @@ P1,AUD-SEARCH-T08,QA — revisão Tempo pendente,Nenhuma alteração de relaçõ
P1,AUD-SEARCH-T09,QA — revisão Tempo pendente,Gestão de procura/capacidade permanece separada e protegida; sem alteração de permissões.,Reutiliza integralmente a pesquisa corrigida com âmbito educação mantido.,,HTTP/Inertia: results.total=0 com texto inexistente; filtros e componente comuns.,,,,,,navegação/pesquisa,"Conversa Tempo 20/10/2026; manual, secção Pesquisa transversal QA",Consulta coerente e compreensível; nenhuma alteração de dados para coincidir contagens.,investment/catalogue,Gestão de procura/capacidade permanece separada e protegida; sem alteração de permissões.,,Rever a branch antes de integrar em main; sem disponibilização remota nesta execução.,,,Pesquisa transversal QA 20/10/2026,HTTP/Inertia: results.total=0 com texto inexistente; filtros e componente comuns.,,,,Apenas delta identificado; não certifica funcionalidades não alteradas.,
P1,AUD-SEARCH-T10,QA — revisão Tempo pendente,Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,"Resumo único nomeado Documentos, chips removíveis, controlos vazios ocultos sem apagar valores seleccionados, rodapé comum.",,HTTP/Inertia e navegador: vazio e termos preservados; retorno documental existente conservado.,,,,,,navegação/pesquisa,"Conversa Tempo 20/10/2026; manual, secção Pesquisa transversal QA",Consulta coerente e compreensível; nenhuma alteração de dados para coincidir contagens.,portal/services; portal/document,Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,,Rever a branch antes de integrar em main; sem disponibilização remota nesta execução.,,,Pesquisa transversal QA 20/10/2026,HTTP/Inertia e navegador: vazio e termos preservados; retorno documental existente conservado.,,,,Apenas delta identificado; não certifica funcionalidades não alteradas.,
P1,AUD-SEARCH-T11,QA — revisão Tempo pendente,"Situação jurídica, consulta e cálculo continuam independentes.",Reutiliza a correcção da biblioteca e preserva filtros jurídicos/documentais pertinentes.,,HTTP/Inertia: resources.total=0; consumidor e query pública partilhados.,,,,,,navegação/pesquisa,"Conversa Tempo 20/10/2026; manual, secção Pesquisa transversal QA",Consulta coerente e compreensível; nenhuma alteração de dados para coincidir contagens.,portal/services; portal/document,"Situação jurídica, consulta e cálculo continuam independentes.",,Rever a branch antes de integrar em main; sem disponibilização remota nesta execução.,,,Pesquisa transversal QA 20/10/2026,HTTP/Inertia: resources.total=0; consumidor e query pública partilhados.,,,,Apenas delta identificado; não certifica funcionalidades não alteradas.,
+P1,AUD-GUIDE-CARD-20261020,QA review pending,New delta; not approved for main,Common educational card and existing source/context adapter,,Desktop/mobile/keyboard; public-state and source checks,,,,,,educational presentation,Tempo 20/10/2026; same manual,,,Review; real-source dossier recovery absent from QA dataset,,Integration approval for new delta,,,,1 test / 8 assertions; TypeScript/build; real public-source visual preview,,,,No import; no remote changes; no claim of new dossier proof,
diff --git a/docs/investmoz/v2/auditoria-portal/backlog.md b/docs/investmoz/v2/auditoria-portal/backlog.md
index 06d3c259..02740424 100644
--- a/docs/investmoz/v2/auditoria-portal/backlog.md
+++ b/docs/investmoz/v2/auditoria-portal/backlog.md
@@ -2990,3 +2990,8 @@ Provas: outputs/investmoz-git-delivery-20261020/RECIBO-DISPONIBILIZACAO-GIT-MAIN
## Pesquisa transversal QA — 20/10/2026
Inventário finito AUD-SEARCH-T01–T11 na mesma matriz/CSV e comparação no manual. Correcções manuais na branch `codex/opportunity-search`, sem integração/remoto/publicação. Assistência NLP ainda não implementada: interpretador e prévia/confirmar da mesma query manual, 6–10 h para recorte local delimitado; modelo externo sujeito a decisão. As oito lacunas contratuais e P7 mantêm-se separados. Revisão Tempo pendente; as provas comuns não encerram requisitos de gestão ou publicação não alterados.
+
+
+## Guias educativos relacionados — delta QA após 0e7d51f18fb4
+
+AUD-GUIDE-CARD-20261020: componente comum com imagem autorizada, título, resumo do artigo publicado, autoria e «Ler o guia». Reutilizado em sectores, exploração editorial e leituras relacionadas; recomendado no catálogo por sector explícito e nas fichas de oportunidades. Sem associação territorial inferida. Botão secundário apenas com oportunidades públicas. QA: teste isolado 1/8, TypeScript/build e exemplos computador/móvel. Falta decisão sobre integração deste novo delta; a prévia visual de Turismo usa uma cópia por leitura do conteúdo público, sem importação. Recuperação documental num dossier com este acervo não demonstrada, pois o artigo não existe na base QA actual. Percurso e regras anteriores preservados; IA fora do lote.
diff --git a/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv b/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
index 3ad6e7dc..f89fce73 100644
--- a/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
+++ b/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
@@ -10650,3 +10650,4 @@ AUD-SEARCH-T08,Consistência transversal da pesquisa e navegação — Corredore
AUD-SEARCH-T09,Consistência transversal da pesquisa e navegação — Educação,Instruções expressas da Tempo na conversa de 20/10/2026; AGENTS.md; RF-MN-010 e AUD-GEO-01 preservados.,navegação/pesquisa,/educacao,investment/catalogue — Reutiliza integralmente a pesquisa corrigida com âmbito educação mantido.,Sem alteração remota nesta execução; revisão apenas na branch codex/opportunity-search.,HTTP/Inertia: results.total=0 com texto inexistente; filtros e componente comuns.,QA — delta delimitado; revisão Tempo pendente,Gestão de procura/capacidade permanece separada e protegida; sem alteração de permissões.,,"Filtros, contagem, resultados e URL coerentes; universos identificados; erro distinto de vazio; permissões e contexto conservados.",P1,,RF-MN-010; AUD-GEO-01,,,,,,,,,,,Herda formulário e contagens concorrentes das oportunidades.,Gestão de procura/capacidade permanece separada e protegida; sem alteração de permissões.,investment/catalogue; SearchState; SearchFeedback; TerritoryFields; portalNavigation,,"Integração em main apenas após revisão; assistência NLP, contratos e P7 separados.",Correcção/simplificação em QA,,HTTP/Inertia: results.total=0 com texto inexistente; filtros e componente comuns.,Pesquisa transversal QA 20/10/2026,20/10/2026,,,,,,,,,,Provas comuns cobrem o componente reutilizado; HTTP vazio não demonstra operações de gestão ou publicação. Gestão de procura/capacidade permanece separada e protegida; sem alteração de permissões.,,falha funcional; navegação; apresentação visual,,Disponível para revisão na aplicação QA local.
AUD-SEARCH-T10,Consistência transversal da pesquisa e navegação — Biblioteca,Instruções expressas da Tempo na conversa de 20/10/2026; AGENTS.md; RF-MN-010 e AUD-GEO-01 preservados.,navegação/pesquisa,/documentos,"portal/services; portal/document — Resumo único nomeado Documentos, chips removíveis, controlos vazios ocultos sem apagar valores seleccionados, rodapé comum.",Sem alteração remota nesta execução; revisão apenas na branch codex/opportunity-search.,HTTP/Inertia e navegador: vazio e termos preservados; retorno documental existente conservado.,QA — delta delimitado; revisão Tempo pendente,Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,,"Filtros, contagem, resultados e URL coerentes; universos identificados; erro distinto de vazio; permissões e contexto conservados.",P1,,RF-MN-010; AUD-GEO-01,,,,,,,,,,,"Dois resumos de contagem, filtros activos sem remoção individual, controlos sem opções e rodapé local repetido.",Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,portal/services; portal/document; SearchState; SearchFeedback; TerritoryFields; portalNavigation,,"Integração em main apenas após revisão; assistência NLP, contratos e P7 separados.",Correcção/simplificação em QA,,HTTP/Inertia e navegador: vazio e termos preservados; retorno documental existente conservado.,Pesquisa transversal QA 20/10/2026,20/10/2026,,,,,,,,,,Provas comuns cobrem o componente reutilizado; HTTP vazio não demonstra operações de gestão ou publicação. Não houve importação/publicação; a cópia QA usada não contém recursos públicos reais para nova prova positiva.,,falha funcional; navegação; apresentação visual,,Disponível para revisão na aplicação QA local.
AUD-SEARCH-T11,Consistência transversal da pesquisa e navegação — Legislação,Instruções expressas da Tempo na conversa de 20/10/2026; AGENTS.md; RF-MN-010 e AUD-GEO-01 preservados.,navegação/pesquisa,/legislacao,portal/services; portal/document — Reutiliza a correcção da biblioteca e preserva filtros jurídicos/documentais pertinentes.,Sem alteração remota nesta execução; revisão apenas na branch codex/opportunity-search.,HTTP/Inertia: resources.total=0; consumidor e query pública partilhados.,QA — delta delimitado; revisão Tempo pendente,"Situação jurídica, consulta e cálculo continuam independentes.",,"Filtros, contagem, resultados e URL coerentes; universos identificados; erro distinto de vazio; permissões e contexto conservados.",P1,,RF-MN-010; AUD-GEO-01,,,,,,,,,,,Mesmo padrão da biblioteca; não deve expor um universo concorrente.,"Situação jurídica, consulta e cálculo continuam independentes.",portal/services; portal/document; SearchState; SearchFeedback; TerritoryFields; portalNavigation,,"Integração em main apenas após revisão; assistência NLP, contratos e P7 separados.",Correcção/simplificação em QA,,HTTP/Inertia: resources.total=0; consumidor e query pública partilhados.,Pesquisa transversal QA 20/10/2026,20/10/2026,,,,,,,,,,"Provas comuns cobrem o componente reutilizado; HTTP vazio não demonstra operações de gestão ou publicação. Situação jurídica, consulta e cálculo continuam independentes.",,falha funcional; navegação; apresentação visual,,Disponível para revisão na aplicação QA local.
+AUD-GUIDE-CARD-20261020,"Related educational cards: image, source summary, clear actions",Tempo 20/10/2026; independent delta after 0e7d51f18fb4,educational presentation,/sectores/{slug}; /explorar/{group}; articles; /oportunidades and detail,EducationalArticleCard; EducationalGuides; LegacyContent; SectorInvestment,QA only,1 test / 8 assertions; PHP syntax; TypeScript/build; desktop2048/mobile390; keyboard,QA review pending,Visual public-source snapshot; real article absent from QA DB; authenticated dossier recovery not demonstrated,,Source-derived summary; public images; conditional opportunity action; context preserved,P1,,,,,,,,,,,,,,,,,,presentation,,,,20/10/2026,,,,,,,,,,,,content; navigation; visual presentation,,Ready for QA review
diff --git a/resources/js/components/educational-article-card.tsx b/resources/js/components/educational-article-card.tsx
new file mode 100644
index 00000000..f4215425
--- /dev/null
+++ b/resources/js/components/educational-article-card.tsx
@@ -0,0 +1,73 @@
+import { Link } from '@inertiajs/react';
+
+export type EducationalArticle = {
+ title: string;
+ href: string;
+ summary: string;
+ author?: string;
+ image: { href: string; alt: string } | null;
+ opportunities_href?: string | null;
+ opportunities_label?: string | null;
+ has_opportunities?: boolean;
+};
+
+export default function EducationalArticleCard({
+ article,
+}: {
+ article: EducationalArticle;
+}) {
+ const focus =
+ 'focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-emerald-800';
+ return (
+
+ {article.image && (
+
+ )}
+