inital commit

This commit is contained in:
headpatsyou 2026-01-24 20:20:48 +00:00
commit b73240b865
13 changed files with 1818 additions and 0 deletions

78
documents/documents.html Normal file
View file

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="pt-PT">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Documentos de Acessibilidade - Comfy Solutions">
<meta name="og:title" content="Documentos | Comfy Solutions">
<meta name="og:url" content="https://comfy.solutions/acessability/documents">
<title>Documentos | Comfy Solutions</title>
<!-- Material Design Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Google Sans Font -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<a href="#main-content" class="skip-link">Saltar para o conteúdo principal</a>
<div class="container">
<header class="header">
<div class="header-content">
<div class="header-left">
<div class="brand">
<img src="icon.png" alt="comfy.solutions" class="brand-icon">
<a href="../index.html" class="brand-link">comfy.solutions</a>
</div>
</div>
<nav class="nav-menu" id="nav-menu">
<a href="../index.html" class="nav-link" id="nav-commitment">Compromisso</a>
<a href="documents.html" class="nav-link nav-active" id="nav-documents">Documentos</a>
</nav>
<button id="language-toggle" class="btn btn-text" aria-label="Switch language">
<span class="material-icons">language</span>
<span id="lang-label">English</span>
</button>
</div>
</header>
<main class="main-content" id="main-content">
<section class="hero">
<h1 id="page-heading" lang="pt-PT">Documentos de Acessibilidade</h1>
</section>
<div id="portuguese-content" class="language-content">
<section class="content-section">
<p class="leading-paragraph">
Aqui encontra todos os documentos relacionados com o nosso compromisso de acessibilidade. Os documentos estão organizados por categoria.
</p>
<div id="documents-container" class="documents-grid">
<!-- Documents will be loaded here -->
</div>
</section>
</div>
<div id="english-content" class="language-content hidden">
<section class="content-section">
<p class="leading-paragraph">
Here you can find all documents related to our accessibility commitment. Documents are organized by category.
</p>
<div id="documents-container-en" class="documents-grid">
<!-- Documents will be loaded here -->
</div>
</section>
</div>
</main>
<footer class="footer">
<p>&copy; 2026 comfy.solutions. Todos os direitos reservados. | All rights reserved.</p>
</footer>
</div>
<script src="documents.js"></script>
</body>
</html>

153
documents/documents.js Normal file
View file

@ -0,0 +1,153 @@
document.addEventListener('DOMContentLoaded', function() {
const languageToggle = document.getElementById('language-toggle');
const langLabel = document.getElementById('lang-label');
const pageHeading = document.getElementById('page-heading');
const portugueseContent = document.getElementById('portuguese-content');
const englishContent = document.getElementById('english-content');
const navCommitment = document.getElementById('nav-commitment');
const navDocuments = document.getElementById('nav-documents');
const htmlElement = document.documentElement;
let documentsData = [];
// Load documents from JSON
fetch('./documents.json')
.then(response => response.json())
.then(data => {
documentsData = data.documents;
renderDocuments('pt-PT');
setLanguage(localStorage.getItem('preferred-language') || 'pt-PT');
})
.catch(error => console.error('Error loading documents:', error));
languageToggle.addEventListener('click', function() {
const currentLang = htmlElement.lang;
const newLang = currentLang === 'pt-PT' ? 'en' : 'pt-PT';
setLanguage(newLang);
});
function renderDocuments(lang) {
const container = lang === 'pt-PT'
? document.getElementById('documents-container')
: document.getElementById('documents-container-en');
const filtered = documentsData;
// Group by category
const grouped = {};
filtered.forEach(doc => {
if (!grouped[doc.category]) {
grouped[doc.category] = [];
}
grouped[doc.category].push(doc);
});
container.innerHTML = '';
Object.keys(grouped).forEach(category => {
const categoryTitle = getCategoryTitle(category, lang);
const categoryDiv = document.createElement('div');
categoryDiv.className = 'document-category';
const categoryHeading = document.createElement('h2');
categoryHeading.textContent = categoryTitle;
categoryDiv.appendChild(categoryHeading);
grouped[category].forEach(doc => {
const docCard = document.createElement('div');
docCard.className = 'document-card';
const cardHeader = document.createElement('div');
cardHeader.className = 'card-header';
const docTitle = document.createElement('h3');
docTitle.textContent = doc.title;
cardHeader.appendChild(docTitle);
const langBadge = document.createElement('div');
langBadge.className = 'language-badge';
const langText = getLanguageName(doc.language);
langBadge.innerHTML = `
<span class="material-icons">language</span>
<span>${langText}</span>
`;
cardHeader.appendChild(langBadge);
docCard.appendChild(cardHeader);
const docDesc = document.createElement('p');
docDesc.textContent = doc.description;
docCard.appendChild(docDesc);
const downloadLink = document.createElement('a');
downloadLink.href = doc.filename;
downloadLink.className = 'btn btn-primary';
downloadLink.download = '';
downloadLink.innerHTML = `
<span class="material-icons">download</span>
${lang === 'pt-PT' ? 'Download' : 'Download'}
`;
const linkWrapper = document.createElement('p');
linkWrapper.style.marginTop = '16px';
linkWrapper.appendChild(downloadLink);
docCard.appendChild(linkWrapper);
categoryDiv.appendChild(docCard);
});
container.appendChild(categoryDiv);
});
}
function getLanguageName(langCode) {
const names = {
'pt-PT': 'Português',
'en': 'English'
};
return names[langCode] || langCode;
}
function getCategoryTitle(category, lang) {
const titles = {
legal: {
'pt-PT': 'Documentos Legais',
'en': 'Legal Documents'
},
report: {
'pt-PT': 'Relatórios',
'en': 'Reports'
},
policy: {
'pt-PT': 'Políticas',
'en': 'Policies'
}
};
return titles[category][lang] || category;
}
function setLanguage(lang) {
if (lang === 'en') {
htmlElement.lang = 'en';
portugueseContent.classList.add('hidden');
englishContent.classList.remove('hidden');
pageHeading.lang = 'en';
pageHeading.textContent = 'Accessibility Documents';
langLabel.textContent = 'Português';
if (navCommitment) navCommitment.textContent = 'Commitment';
if (navDocuments) navDocuments.textContent = 'Documents';
renderDocuments('en');
} else {
htmlElement.lang = 'pt-PT';
englishContent.classList.add('hidden');
portugueseContent.classList.remove('hidden');
pageHeading.lang = 'pt-PT';
pageHeading.textContent = 'Documentos de Acessibilidade';
langLabel.textContent = 'English';
if (navCommitment) navCommitment.textContent = 'Compromisso';
if (navDocuments) navDocuments.textContent = 'Documentos';
renderDocuments('pt-PT');
}
localStorage.setItem('preferred-language', lang);
}
});

20
documents/documents.json Normal file
View file

@ -0,0 +1,20 @@
{
"documents": [
{
"id": "declaration-powerliftingpt",
"title": "Declaração de Acessibilidade - powerlifting.pt",
"description": "Declaração formal de acessibilidade conforme Decreto-Lei n.º 83/2018 para o website powerlifting.pt",
"filename": "powerliftingpt/accessibility-statement_2026-01-24.html",
"language": "pt-PT",
"category": "legal"
},
{
"id": "report-pt",
"title": "Checklist 10 aspetos funcionais - powerlifting.pt",
"description": "Relatório detalhado de testes de acessibilidade do WGAC 2.1 e do governo português.",
"filename": "powerliftingpt/sintese-10aspetos_powerliftingpt.xlsx",
"language": "pt-PT",
"category": "report"
}
]
}

BIN
documents/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

610
documents/style.css Normal file
View file

@ -0,0 +1,610 @@
/* Material Design 2 - Comfy Solutions */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-color: #5B7394;
--accent-color: #FDC95D;
--dark-color: #040D15;
--surface-color: #ffffff;
--surface-variant: #f5f5f5;
--text-primary: #1a1a1a;
--text-secondary: #424242;
--divider-color: #e0e0e0;
--focus-color: #FDC95D;
/* Material Design 2 elevation */
--elevation-1: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12);
--elevation-2: 0px 3px 1px -2px rgba(0,0,0,0.2), 0px 2px 2px 0px rgba(0,0,0,0.14), 0px 1px 5px 0px rgba(0,0,0,0.12);
--elevation-4: 0px 2px 4px -1px rgba(0,0,0,0.2), 0px 4px 5px 0px rgba(0,0,0,0.14), 0px 1px 10px 0px rgba(0,0,0,0.12);
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
line-height: 1.5;
color: var(--text-primary);
background-color: var(--surface-color);
font-size: 14px;
font-weight: 400;
letter-spacing: 0.25px;
}
.container {
max-width: 960px;
margin: 0 auto;
padding: 0;
}
/* Skip Link */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--primary-color);
color: white;
padding: 8px 16px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
/* Header */
.header {
background-color: var(--primary-color);
color: white;
box-shadow: var(--elevation-4);
padding: 16px 24px;
position: sticky;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 960px;
margin: 0 auto;
}
.header-left {
display: flex;
align-items: center;
gap: 40px;
}
.brand {
font-size: 20px;
font-weight: 500;
letter-spacing: 0.15px;
margin: 0;
color: white;
display: flex;
align-items: center;
gap: 12px;
}
.brand-link {
color: white;
text-decoration: none;
transition: color 0.2s ease;
}
.brand-link:hover {
color: #f0f0f0;
}
.brand-link:focus-visible {
outline: 3px solid var(--accent-color);
outline-offset: 2px;
border-radius: 2px;
}
/* Navigation Menu */
.nav-menu {
display: flex;
gap: 24px;
align-items: center;
}
.nav-link {
color: rgba(255, 255, 255, 0.87);
text-decoration: none;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.4px;
transition: color 0.2s ease;
padding-bottom: 4px;
border-bottom: 2px solid transparent;
}
.nav-link:hover {
color: white;
}
.nav-link:focus-visible {
outline: 3px solid var(--accent-color);
outline-offset: 2px;
}
.nav-link.nav-active {
color: white;
border-bottom-color: var(--accent-color);
}
.brand-icon {
height: 28px;
width: 28px;
object-fit: contain;
}
/* Buttons */
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 0;
border: none;
border-radius: 4px;
font-family: 'Roboto', sans-serif;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.4px;
text-decoration: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
text-transform: uppercase;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
padding: 10px 24px;
box-shadow: var(--elevation-2);
}
.btn-primary:hover {
background-color: #3d4d63;
box-shadow: var(--elevation-4);
}
.btn-primary:active {
box-shadow: var(--elevation-1);
}
.btn-text {
color: var(--dark-color);
background-color: var(--accent-color);
padding: 8px 16px;
gap: 8px;
box-shadow: var(--elevation-1);
}
.btn-text:hover {
background-color: #fdd96f;
box-shadow: var(--elevation-2);
}
.btn-text:focus-visible {
outline: 3px solid var(--dark-color);
}
/* Material Icons */
.material-icons {
font-size: 24px;
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.btn .material-icons {
font-size: 18px;
width: 18px;
height: 18px;
}
/* Main Content */
.main-content {
padding: 40px 24px;
max-width: 960px;
margin: 0 auto;
}
.hero {
text-align: center;
margin-bottom: 40px;
}
.hero h1 {
font-size: 32px;
font-weight: 300;
letter-spacing: 0.25px;
line-height: 1.4;
color: var(--dark-color);
margin: 0;
}
.content-section {
display: flex;
flex-direction: column;
gap: 24px;
}
.content-section h3 + p {
margin-top: -12px;
}
h3 {
font-size: 20px;
font-weight: 500;
letter-spacing: 0.15px;
color: var(--dark-color);
margin: 0 0 8px 0;
display: flex;
align-items: center;
gap: 12px;
}
h4 {
font-size: 16px;
font-weight: 500;
letter-spacing: 0.15px;
color: var(--dark-color);
margin: 0 0 8px 0;
display: flex;
align-items: center;
gap: 12px;
}
p {
font-size: 14px;
font-weight: 400;
letter-spacing: 0.25px;
line-height: 1.6;
color: var(--text-secondary);
margin: 0;
}
.leading-paragraph {
font-size: 16px;
font-weight: 400;
line-height: 1.7;
color: var(--text-primary);
margin: 0;
}
/* Links */
a {
color: var(--primary-color);
text-decoration: none;
transition: all 0.2s ease;
position: relative;
}
a:hover {
color: #3d4d63;
text-decoration: underline;
}
a:focus-visible {
outline: 3px solid var(--focus-color);
outline-offset: 2px;
}
/* Cards */
.verification-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
margin: 20px 0;
}
.card {
background-color: var(--surface-variant);
border-radius: 4px;
padding: 24px;
box-shadow: var(--elevation-1);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.card:hover {
box-shadow: var(--elevation-2);
transform: translateY(-2px);
}
.card h4 {
color: var(--primary-color);
margin-bottom: 12px;
}
.card p {
margin: 0;
color: var(--text-secondary);
}
.card a {
color: var(--primary-color);
font-weight: 500;
}
/* Boxes */
.commitment-box,
.contact-box {
background-color: var(--surface-variant);
border-left: 4px solid var(--accent-color);
border-radius: 4px;
padding: 24px;
box-shadow: var(--elevation-1);
}
.contact-box {
background-color: var(--dark-color);
color: white;
border-left-color: var(--accent-color);
}
.contact-box h3 {
color: white;
margin-bottom: 16px;
}
.contact-box p {
color: rgba(255, 255, 255, 0.87);
}
.contact-box a {
color: var(--accent-color);
}
.contact-box a:hover {
color: #fdd96f;
}
.contact-box .btn-primary {
background-color: var(--accent-color);
color: var(--dark-color);
margin-top: 16px;
}
.contact-box .btn-primary:hover {
background-color: #fdd96f;
}
/* Language Content */
.language-content {
opacity: 1;
transition: opacity 0.3s ease;
}
.language-content.hidden {
display: none;
}
/* Footer */
.footer {
border-top: 1px solid var(--divider-color);
padding: 24px;
text-align: center;
color: var(--text-secondary);
font-size: 12px;
letter-spacing: 0.4px;
margin-top: 32px;
}
/* Accessibility */
*:focus-visible {
outline: 3px solid var(--focus-color);
outline-offset: 2px;
}
/* Print Styles */
@media print {
.header,
.footer {
display: none;
}
.btn {
display: none;
}
}
/* Documents Page */
.documents-grid {
display: flex;
flex-direction: column;
gap: 32px;
}
.document-category {
display: flex;
flex-direction: column;
gap: 16px;
}
.document-category h2 {
margin: 0 0 8px 0;
padding-bottom: 12px;
border-bottom: 2px solid var(--accent-color);
}
.document-card {
background-color: var(--surface-variant);
border-radius: 4px;
padding: 24px;
box-shadow: var(--elevation-1);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.document-card:hover {
box-shadow: var(--elevation-2);
transform: translateY(-2px);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 16px;
margin-bottom: 8px;
}
.document-card h3 {
font-size: 18px;
font-weight: 500;
letter-spacing: 0.15px;
color: var(--primary-color);
margin: 0;
flex: 1;
}
.language-badge {
display: flex;
align-items: center;
gap: 6px;
background-color: var(--primary-color);
color: white;
padding: 6px 12px;
border-radius: 16px;
font-size: 12px;
font-weight: 500;
letter-spacing: 0.4px;
white-space: nowrap;
}
.language-badge .material-icons {
font-size: 16px;
width: 16px;
height: 16px;
}
.document-card p {
font-size: 14px;
color: var(--text-secondary);
margin: 0;
}
/* Responsive Design */
@media (max-width: 768px) {
.header {
padding: 12px 16px;
}
.header-content {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.header-left {
gap: 16px;
}
.nav-menu {
gap: 16px;
font-size: 13px;
}
.nav-link {
padding-bottom: 2px;
}
.brand {
font-size: 18px;
}
.main-content {
padding: 28px 16px;
}
.hero h2 {
font-size: 24px;
}
.verification-cards {
grid-template-columns: 1fr;
gap: 16px;
}
.card,
.commitment-box,
.contact-box {
padding: 16px;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 14px;
}
}
@media (max-width: 480px) {
.main-content {
padding: 24px 12px;
}
.hero h2 {
font-size: 20px;
}
.content-section {
gap: 20px;
}
h3 {
font-size: 16px;
}
h4 {
font-size: 14px;
}
.card,
.commitment-box,
.contact-box {
padding: 16px;
}
.btn {
width: 100%;
justify-content: center;
}
}
/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* High Contrast Mode */
@media (prefers-contrast: more) {
a {
text-decoration: underline;
}
.btn {
border: 2px solid currentColor;
}
}

27
eval(2).csv Normal file
View file

@ -0,0 +1,27 @@
URI;Data;ID;Tipo de erro;Nivel de Conformidade;Critério;Descrição;Número de ocorrências;Valor;Pontuação
;;img_01a;Sucesso;A;1.1.1;Constatei que todas as imagens da página têm o necessário equivalente alternativo em texto.;1;;9,1
;;a_01a;Aviso;A;2.4.1;Constatei que o primeiro link da página nos permite saltar para o conteúdo principal.;1;;9,1
;;a_02b;Aviso;A;2.4.1;Encontrei 1 link para contornar blocos de conteúdo.;1;;9,1
;;hx_01b;Aviso;AAA;1.3.1 2.4.10;Encontrei 12 cabeçalhos na página.;12;;9,1
;;hx_03;Erro;AAA;1.3.1 2.4.10;Encontrei 1 caso em que se viola a sequência hierárquica dos níveis de cabeçalho.;1;;9,1
;;layout_01a;Sucesso;A;1.3.1;Constatei que não há elementos obsoletos usados para controlo visual da apresentação.;0;;9,1
;;lang_01;Aviso;A;3.1.1;Verifiquei que o idioma principal da página está marcado como "pt-BR".;1;pt-BR;9,1
;;title_06;Sucesso;A;2.4.2;Encontrei um título na página e ele parece-me correto.;1;Compromisso de Acessibilidade | Comfy Solutions;9,1
;;heading_01;Sucesso;A;1.3.1;Constatei que todos os cabeçalhos desta página têm nome acessível;12;;9,1
;;heading_03;Sucesso;A;1.3.1;Identifiquei exatamente um cabeçalho de nível 1.;1;;9,1
;;aria_03;Sucesso;A;1.3.1;Verifiquei que todos os estados e todas as propriedades ARIA têm um tipo de valor válido.;1;;9,1
;;aria_05;Sucesso;A;;Verifiquei que todos os estados e todas as propriedades ARIA são permitidos.;1;;9,1
;;aria_07;Sucesso;A;;Verifiquei que todos os atributos aria-* estão de acordo com a especificação ARIA.;1;;9,1
;;button_01;Sucesso;A;;Verifiquei que todos os elementos button têm nome acessível.;1;;9,1
;;element_06;Sucesso;AA;3.1.2;Verifiquei que todos os elementos com atributo lang têm uma etiqueta de linguagem válida;1;;9,1
;;element_08;Sucesso;A;4.1.2;Constatei que todos os elementos com um papel semântico que confere aos seus descendentes um papel decorativo, não têm descendentes focáveis;2;;9,1
;;id_01;Sucesso;A;4.1.1;Constatei que nesta página não há</marks> atributos id repetidos.;6;;9,1
;;a_10;Sucesso;A;4.1.2;Verifiquei que todas as ligações têm nome acessível.;7;;9,1
;;textC_01;Aviso;AAA;1.4.6;Verifiquei que todas as combinações de cor têm uma relação de contraste superior ao rácio de contraste otimizado sugerido pelas WCAG, ou seja 4,5 para 1 para texto com letra grande e 7 para 1 para texto com letra normal.;44;;9,1
;;label_03;Erro;A;2.5.3;Encontrei 1 elemento interativo cujo texto visível não faz parte do nome acessível computado para o elemento;1;;9,1
;;landmark_01;Sucesso;AA;1.3.1 2.4.1;Constatei que o elemento com a semântica de banner não está contido dentro de nenhum elemento com outra semântica;1;;9,1
;;landmark_05;Sucesso;AA;1.3.1;Constatei que o elemento com a semântica de contentinfo não está contido dentro de nenhum elemento com outra semântica;1;;9,1
;;landmark_07;Sucesso;AA;1.3.1;Constatei que o elemento com a semântica de main não está contido dentro de nenhum elemento com outra semântica;1;;9,1
;;landmark_09;Sucesso;AA;1.3.1 2.4.1;Encontrei um elemento com a semântica de banner.;1;;9,1
;;landmark_11;Sucesso;AA;1.3.1;Encontrei um elemento com a semântica de contentinfo.;1;;9,1
;;landmark_13;Sucesso;AA;1.3.1;Encontrei um elemento com a semântica de main.;1;;9,1
Can't render this file because it contains an unexpected character in line 8 and column 89.

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

176
index.html Normal file
View file

@ -0,0 +1,176 @@
<!DOCTYPE html>
<html lang="pt-PT">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Compromisso de Acessibilidade - Comfy Solutions">
<meta name="og:title" content="Compromisso de Acessibilidade | Comfy Solutions">
<meta name="og:url" content="https://comfy.solutions/acessability">
<title>Compromisso de Acessibilidade | comfy.solutions</title>
<!-- Material Design Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Google Sans Font -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<a href="#main-content" class="skip-link">Saltar para o conteúdo principal</a>
<div class="container">
<header class="header">
<div class="header-content">
<div class="header-left">
<div class="brand">
<img src="icon.png" alt="comfy.solutions" class="brand-icon">
<a href="index.html" class="brand-link">comfy.solutions</a>
</div>
</div>
<nav class="nav-menu" id="nav-menu">
<a href="index.html" class="nav-link nav-active" id="nav-commitment">Compromisso</a>
<a href="documents/documents.html" class="nav-link" id="nav-documents">Documentos</a>
</nav>
<button id="language-toggle" class="btn btn-text" aria-label="Switch language">
<span class="material-icons">language</span>
<span id="lang-label">English</span>
</button>
</div>
</header>
<main class="main-content" id="main-content">
<section class="hero">
<h1 id="hero-heading" lang="pt-PT">A internet deve ser acessível para todos. Este é o nosso compromisso.</h1>
</section>
<div id="portuguese-content" class="language-content">
<section class="content-section">
<p class="leading-paragraph">
A comfy.solutions compromete-se a desenvolver sites acessíveis a todos. Todos os nossos sites seguem o Decreto-Lei n.º 83/2018, de 19 de outubro, que transpõe a Diretiva (UE) 2016/2102 do Parlamento Europeu e do Conselho, relativa à acessibilidade dos sítios Web e das aplicações móveis.
</p>
<h2>Metodologia</h2>
<p>
Seguimos os proseguimentos A e B (verificação automática e verificação manual) em todos os nossos sites.
</p>
<div class="verification-cards">
<div class="card">
<h4>
<span class="material-icons">check_circle</span>
Verificação Automática
</h4>
<p>
Utilizamos o <a href="https://accessmonitor.acessibilidade.gov.pt" target="_blank" rel="noopener noreferrer">accessMonitor</a>, do ecossistema acessibilidade.gov.pt.
</p>
</div>
<div class="card">
<h4>
<span class="material-icons">done_all</span>
Verificação Manual
</h4>
<p>
Utilizamos o <a href="https://www.acessibilidade.gov.pt/gerador/" target="_blank" rel="noopener noreferrer">Gerador da Declaração de Acessibilidade e Usabilidade</a>, também do ecossistema acessibilidade.gov.pt.
</p>
</div>
</div>
<div class="commitment-box">
<h2>
<span class="material-icons">calendar_today</span>
Compromisso de Revisão
</h2>
<p>
Compromotemos-nos em rever o nosso conteúdo pelo menos uma vez a cada 3 meses.
</p>
</div>
<div class="contact-box">
<h2>
<span class="material-icons">email</span>
Precisa de ajuda?
</h2>
<p>
Temos o nosso email de acessibilidade sempre disponível. Estamos sempre prontos a ajudar, todos os dias.
</p>
<p>
<a href="mailto:acessibilidade@comfy.solutions" class="btn btn-primary">
<span class="material-icons">mail</span>
acessibilidade@comfy.solutions
</a>
</p>
</div>
</section>
</div>
<div id="english-content" class="language-content hidden">
<section class="content-section">
<p class="leading-paragraph">
Comfy.solutions is committed to developing accessible websites for everyone. All our websites comply with Decree-Law no. 83/2018, of October 19, which transposes Directive (EU) 2016/2102 of the European Parliament and Council, relating to the accessibility of websites and mobile applications.
</p>
<h2>Methodology</h2>
<p>
We follow procedures A and B (automated testing and manual testing) on all our websites.
</p>
<div class="verification-cards">
<div class="card">
<h4>
<span class="material-icons">check_circle</span>
Automated Testing
</h4>
<p>
We use <a href="https://accessmonitor.acessibilidade.gov.pt" target="_blank" rel="noopener noreferrer">accessMonitor</a>, from the acessibilidade.gov.pt ecosystem.
</p>
</div>
<div class="card">
<h4>
<span class="material-icons">done_all</span>
Manual Testing
</h4>
<p>
We use the <a href="https://www.acessibilidade.gov.pt/gerador/" target="_blank" rel="noopener noreferrer">Accessibility and Usability Declaration Generator</a>, also from the acessibilidade.gov.pt ecosystem.
</p>
</div>
</div>
<div class="commitment-box">
<h2>
<span class="material-icons">calendar_today</span>
Review Commitment
</h2>
<p>
We commit to reviewing our content at least once every 3 months.
</p>
</div>
<div class="contact-box">
<h2>
<span class="material-icons">email</span>
Need Help?
</h2>
<p>
Our accessibility email is always available. We are always ready to help, every day.
</p>
<p>
<a href="mailto:acessibilidade@comfy.solutions" class="btn btn-primary">
<span class="material-icons">mail</span>
acessibilidade@comfy.solutions
</a>
</p>
</div>
</section>
</div>
</main>
<footer class="footer">
<p>&copy; 2026 comfy.solutions. Todos os direitos reservados. | All rights reserved.</p>
</footer>
</div>
<script src="script.js"></script>
</body>
</html>

43
script.js Normal file
View file

@ -0,0 +1,43 @@
document.addEventListener('DOMContentLoaded', function() {
const languageToggle = document.getElementById('language-toggle');
const langLabel = document.getElementById('lang-label');
const portugueseContent = document.getElementById('portuguese-content');
const englishContent = document.getElementById('english-content');
const heroHeading = document.getElementById('hero-heading');
const navCommitment = document.getElementById('nav-commitment');
const navDocuments = document.getElementById('nav-documents');
const htmlElement = document.documentElement;
// Get saved language preference or default to Portuguese
const savedLanguage = localStorage.getItem('preferred-language') || 'pt-PT';
setLanguage(savedLanguage);
languageToggle.addEventListener('click', function() {
const currentLang = htmlElement.lang;
const newLang = currentLang === 'pt-PT' ? 'en' : 'pt-PT';
setLanguage(newLang);
});
function setLanguage(lang) {
if (lang === 'en') {
htmlElement.lang = 'en';
portugueseContent.classList.add('hidden');
englishContent.classList.remove('hidden');
heroHeading.lang = 'en';
heroHeading.textContent = 'The internet should be accessible to everyone. This is our commitment.';
langLabel.textContent = 'Português';
if (navCommitment) navCommitment.textContent = 'Commitment';
if (navDocuments) navDocuments.textContent = 'Documents';
} else {
htmlElement.lang = 'pt-PT';
englishContent.classList.add('hidden');
portugueseContent.classList.remove('hidden');
heroHeading.lang = 'pt-PT';
heroHeading.textContent = 'A internet deve ser acessível para todos. Este é o nosso compromisso.';
langLabel.textContent = 'English';
if (navCommitment) navCommitment.textContent = 'Compromisso';
if (navDocuments) navDocuments.textContent = 'Documentos';
}
localStorage.setItem('preferred-language', lang);
}
});

19
stru.md Normal file
View file

@ -0,0 +1,19 @@
### comfy.solutions
## A internet deve ser acessível para todos. Este é o nosso compromisso.
A comfy.solutions compromete-se a desenvolver sites acessíveis a todos. Todos os nossos sites seguem o Decreto-Lei n.º 83/2018, de 19 de outubro, que transpõe a Diretiva (UE) 2016/2102 do Parlamento Europeu e do Conselho, relativa à acessibilidade dos sítios Web e das aplicações móveis.
Seguimos os proseguimentos A e B (verificação automática e verificação manual) em todos os nossos sites.
Para a verificação automática, utilizamos o [accessMonitor](https://accessmonitor.acessibilidade.gov.pt), do ecossistema acessibilidade.gov.pt.
Para a verificação manual, utilizamos o [Gerador da Declaração de Acessibilidade e Usabilidade](https://www.acessibilidade.gov.pt/gerador/), também do ecossistema ecossistema acessibilidade.gov.pt.
Compromotemos-nos em rever o nosso conteúdo pelo menos uma vez a cada 3 meses.
Temos o nosso email de acessibilidade sempre disponível. Estamos sempre prontos a ajudar, todos os dias.

581
style.css Normal file
View file

@ -0,0 +1,581 @@
/* Material Design 2 - Comfy Solutions */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-color: #5B7394;
--accent-color: #FDC95D;
--dark-color: #040D15;
--surface-color: #ffffff;
--surface-variant: #f5f5f5;
--text-primary: #1a1a1a;
--text-secondary: #424242;
--divider-color: #e0e0e0;
--focus-color: #FDC95D;
/* Material Design 2 elevation */
--elevation-1: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12);
--elevation-2: 0px 3px 1px -2px rgba(0,0,0,0.2), 0px 2px 2px 0px rgba(0,0,0,0.14), 0px 1px 5px 0px rgba(0,0,0,0.12);
--elevation-4: 0px 2px 4px -1px rgba(0,0,0,0.2), 0px 4px 5px 0px rgba(0,0,0,0.14), 0px 1px 10px 0px rgba(0,0,0,0.12);
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
line-height: 1.5;
color: var(--text-primary);
background-color: var(--surface-color);
font-size: 14px;
font-weight: 400;
letter-spacing: 0.25px;
}
.container {
max-width: 960px;
margin: 0 auto;
padding: 0;
}
/* Skip Link */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--primary-color);
color: white;
padding: 8px 16px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
/* Header */
.header {
background-color: var(--primary-color);
color: white;
box-shadow: var(--elevation-4);
padding: 16px 24px;
position: sticky;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 960px;
margin: 0 auto;
}
.header-left {
display: flex;
align-items: center;
gap: 40px;
}
.brand {
font-size: 20px;
font-weight: 500;
letter-spacing: 0.15px;
margin: 0;
color: white;
display: flex;
align-items: center;
gap: 12px;
}
.brand-link {
color: white;
text-decoration: none;
transition: color 0.2s ease;
}
.brand-link:hover {
color: #f0f0f0;
}
.brand-link:focus-visible {
outline: 3px solid var(--accent-color);
outline-offset: 2px;
border-radius: 2px;
}
/* Navigation Menu */
.nav-menu {
display: flex;
gap: 24px;
align-items: center;
}
.nav-link {
color: rgba(255, 255, 255, 0.87);
text-decoration: none;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.4px;
transition: color 0.2s ease;
padding-bottom: 4px;
border-bottom: 2px solid transparent;
}
.nav-link:hover {
color: white;
}
.nav-link:focus-visible {
outline: 3px solid var(--accent-color);
outline-offset: 2px;
}
.nav-link.nav-active {
color: white;
border-bottom-color: var(--accent-color);
}
.brand-icon {
height: 28px;
width: 28px;
object-fit: contain;
}
/* Buttons */
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 0;
border: none;
border-radius: 4px;
font-family: 'Roboto', sans-serif;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.4px;
text-decoration: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
text-transform: uppercase;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
padding: 10px 24px;
box-shadow: var(--elevation-2);
}
.btn-primary:hover {
background-color: #3d4d63;
box-shadow: var(--elevation-4);
}
.btn-primary:active {
box-shadow: var(--elevation-1);
}
.btn-text {
color: var(--dark-color);
background-color: var(--accent-color);
padding: 8px 16px;
gap: 8px;
box-shadow: var(--elevation-1);
}
.btn-text:hover {
background-color: #fdd96f;
box-shadow: var(--elevation-2);
}
.btn-text:focus-visible {
outline: 3px solid var(--dark-color);
}
/* Material Icons */
.material-icons {
font-size: 24px;
width: 24px;
height: 24px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.btn .material-icons {
font-size: 18px;
width: 18px;
height: 18px;
}
/* Main Content */
.main-content {
padding: 40px 24px;
max-width: 960px;
margin: 0 auto;
}
.hero {
text-align: center;
margin-bottom: 40px;
}
.hero h1 {
font-size: 32px;
font-weight: 300;
letter-spacing: 0.25px;
line-height: 1.4;
color: var(--dark-color);
margin: 0;
}
.content-section {
display: flex;
flex-direction: column;
gap: 24px;
}
.content-section h3 + p {
margin-top: -12px;
}
h3 {
font-size: 20px;
font-weight: 500;
letter-spacing: 0.15px;
color: var(--dark-color);
margin: 0 0 8px 0;
display: flex;
align-items: center;
gap: 12px;
}
h4 {
font-size: 16px;
font-weight: 500;
letter-spacing: 0.15px;
color: var(--dark-color);
margin: 0 0 8px 0;
display: flex;
align-items: center;
gap: 12px;
}
p {
font-size: 14px;
font-weight: 400;
letter-spacing: 0.25px;
line-height: 1.6;
color: var(--text-secondary);
margin: 0;
}
.leading-paragraph {
font-size: 16px;
font-weight: 400;
line-height: 1.7;
color: var(--text-primary);
margin: 0;
}
/* Links */
a {
color: var(--primary-color);
text-decoration: none;
transition: all 0.2s ease;
position: relative;
}
a:hover {
color: #3d4d63;
text-decoration: underline;
}
a:focus-visible {
outline: 3px solid var(--focus-color);
outline-offset: 2px;
}
/* Cards */
.verification-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
margin: 20px 0;
}
.card {
background-color: var(--surface-variant);
border-radius: 4px;
padding: 24px;
box-shadow: var(--elevation-1);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.card:hover {
box-shadow: var(--elevation-2);
transform: translateY(-2px);
}
.card h4 {
color: var(--primary-color);
margin-bottom: 12px;
}
.card p {
margin: 0;
color: var(--text-secondary);
}
.card a {
color: var(--primary-color);
font-weight: 500;
}
/* Boxes */
.commitment-box,
.contact-box {
background-color: var(--surface-variant);
border-left: 4px solid var(--accent-color);
border-radius: 4px;
padding: 24px;
box-shadow: var(--elevation-1);
}
.contact-box {
background-color: var(--dark-color);
color: white;
border-left-color: var(--accent-color);
}
.contact-box h3 {
color: white;
margin-bottom: 16px;
}
.contact-box p {
color: rgba(255, 255, 255, 0.87);
}
.contact-box a {
color: var(--accent-color);
}
.contact-box a:hover {
color: #fdd96f;
}
.contact-box .btn-primary {
background-color: var(--accent-color);
color: var(--dark-color);
margin-top: 16px;
}
.contact-box .btn-primary:hover {
background-color: #fdd96f;
}
/* Language Content */
.language-content {
opacity: 1;
transition: opacity 0.3s ease;
}
.language-content.hidden {
display: none;
}
/* Footer */
.footer {
border-top: 1px solid var(--divider-color);
padding: 24px;
text-align: center;
color: var(--text-secondary);
font-size: 12px;
letter-spacing: 0.4px;
margin-top: 32px;
}
/* Accessibility */
*:focus-visible {
outline: 3px solid var(--focus-color);
outline-offset: 2px;
}
/* Print Styles */
@media print {
.header,
.footer {
display: none;
}
.btn {
display: none;
}
}
/* Documents Page */
.documents-grid {
display: flex;
flex-direction: column;
gap: 32px;
}
.document-category {
display: flex;
flex-direction: column;
gap: 16px;
}
.document-category h2 {
margin: 0 0 8px 0;
padding-bottom: 12px;
border-bottom: 2px solid var(--accent-color);
}
.document-card {
background-color: var(--surface-variant);
border-radius: 4px;
padding: 24px;
box-shadow: var(--elevation-1);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.document-card:hover {
box-shadow: var(--elevation-2);
transform: translateY(-2px);
}
.document-card h3 {
font-size: 18px;
font-weight: 500;
letter-spacing: 0.15px;
color: var(--primary-color);
margin: 0 0 8px 0;
}
.document-card p {
font-size: 14px;
color: var(--text-secondary);
margin: 0;
}
/* Responsive Design */
@media (max-width: 768px) {
.header {
padding: 12px 16px;
}
.header-content {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.header-left {
gap: 16px;
}
.nav-menu {
gap: 16px;
font-size: 13px;
}
.nav-link {
padding-bottom: 2px;
}
.brand {
font-size: 18px;
}
.main-content {
padding: 28px 16px;
}
.hero h2 {
font-size: 24px;
}
.verification-cards {
grid-template-columns: 1fr;
gap: 16px;
}
.card,
.commitment-box,
.contact-box {
padding: 16px;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 14px;
}
}
@media (max-width: 480px) {
.main-content {
padding: 24px 12px;
}
.hero h2 {
font-size: 20px;
}
.content-section {
gap: 20px;
}
h3 {
font-size: 16px;
}
h4 {
font-size: 14px;
}
.card,
.commitment-box,
.contact-box {
padding: 16px;
}
.btn {
width: 100%;
justify-content: center;
}
}
/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* High Contrast Mode */
@media (prefers-contrast: more) {
a {
text-decoration: underline;
}
.btn {
border: 2px solid currentColor;
}
}