feat: dark mode completo via widget de acessibilidade

- main.css: @variant dark com seletor .app-dark (alinhado com PrimeVue darkModeSelector)
- AccessibilityWidget: novo toggle "Modo escuro" no painel; preferências persistidas no localStorage (fonte, contraste, escuro)
- PublicLayout/PortalLayout: dark:bg-slate-950/900, dark:border, dark:text em todos os elementos
- AppHeader/AppFooter: dark variants em bg, border, textos e links
- ServiceCard: usa cores primary em vez de blue hardcoded; dark variants completos
- HomeView: dark nos avisos do carrossel (bg coloridos suavizados), card de login, seção de serviços autenticados e CTA
- LoginView: dark no card, campo documento, label senha, links e botão voltar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gabriel Bezerra 2026-05-18 00:42:35 -03:00
parent 4658d60ad0
commit caf25236b5
10 changed files with 109 additions and 71 deletions

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

View File

@ -6,6 +6,9 @@
--font-sans: 'DM Sans', system-ui, sans-serif; --font-sans: 'DM Sans', system-ui, sans-serif;
} }
/* Dark mode via classe .app-dark — alinhado com darkModeSelector do PrimeVue */
@variant dark (&:where(.app-dark, .app-dark *));
/* Remove setas de number input */ /* Remove setas de number input */
input[type='number']::-webkit-outer-spin-button, input[type='number']::-webkit-outer-spin-button,
input[type='number']::-webkit-inner-spin-button { input[type='number']::-webkit-inner-spin-button {

View File

@ -1,9 +1,10 @@
<script setup> <script setup>
import { ref, watch } from 'vue' import { ref, watch, onMounted } from 'vue'
const aberto = ref(false) const aberto = ref(false)
const nivelFonte = ref(0) // 0 = normal, 1 = grande, 2 = extra-grande const nivelFonte = ref(Number(localStorage.getItem('a11y-fonte') || 0))
const altoContraste = ref(false) const altoContraste = ref(localStorage.getItem('a11y-contraste') === '1')
const modoEscuro = ref(localStorage.getItem('a11y-escuro') === '1')
const opcoesFonte = [ const opcoesFonte = [
{ nivel: 0, label: 'A', title: 'Texto normal' }, { nivel: 0, label: 'A', title: 'Texto normal' },
@ -11,14 +12,31 @@ const opcoesFonte = [
{ nivel: 2, label: 'A++', title: 'Texto extra-grande' }, { nivel: 2, label: 'A++', title: 'Texto extra-grande' },
] ]
watch(nivelFonte, (val) => { function applyFonte(nivel) {
document.documentElement.classList.remove('a11y-font-lg', 'a11y-font-xl') document.documentElement.classList.remove('a11y-font-lg', 'a11y-font-xl')
if (val === 1) document.documentElement.classList.add('a11y-font-lg') if (nivel === 1) document.documentElement.classList.add('a11y-font-lg')
if (val === 2) document.documentElement.classList.add('a11y-font-xl') if (nivel === 2) document.documentElement.classList.add('a11y-font-xl')
}, { immediate: true }) }
onMounted(() => {
applyFonte(nivelFonte.value)
document.documentElement.classList.toggle('a11y-contrast', altoContraste.value)
document.documentElement.classList.toggle('app-dark', modoEscuro.value)
})
watch(nivelFonte, (val) => {
applyFonte(val)
localStorage.setItem('a11y-fonte', val)
})
watch(altoContraste, (val) => { watch(altoContraste, (val) => {
document.documentElement.classList.toggle('a11y-contrast', val) document.documentElement.classList.toggle('a11y-contrast', val)
localStorage.setItem('a11y-contraste', val ? '1' : '0')
})
watch(modoEscuro, (val) => {
document.documentElement.classList.toggle('app-dark', val)
localStorage.setItem('a11y-escuro', val ? '1' : '0')
}) })
</script> </script>
@ -39,16 +57,16 @@ watch(altoContraste, (val) => {
id="a11y-panel" id="a11y-panel"
role="dialog" role="dialog"
aria-label="Opções de acessibilidade" aria-label="Opções de acessibilidade"
class="bg-white rounded-2xl shadow-2xl border border-slate-200 p-5 w-64 origin-bottom-right" class="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl border border-slate-200 dark:border-slate-700 p-5 w-64 origin-bottom-right"
> >
<div class="flex items-center gap-2 mb-4"> <div class="flex items-center gap-2 mb-4">
<i class="pi pi-eye text-primary text-sm" aria-hidden="true" /> <i class="pi pi-eye text-primary text-sm" aria-hidden="true" />
<p class="text-xs font-bold text-slate-600 uppercase tracking-wide">Acessibilidade</p> <p class="text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-wide">Acessibilidade</p>
</div> </div>
<!-- Tamanho do texto --> <!-- Tamanho do texto -->
<div class="mb-5"> <div class="mb-4">
<p class="text-sm font-semibold text-slate-700 mb-2">Tamanho do texto</p> <p class="text-sm font-semibold text-slate-700 dark:text-slate-200 mb-2">Tamanho do texto</p>
<div class="flex gap-2" role="group" aria-label="Escolha o tamanho do texto"> <div class="flex gap-2" role="group" aria-label="Escolha o tamanho do texto">
<button <button
v-for="op in opcoesFonte" v-for="op in opcoesFonte"
@ -59,7 +77,7 @@ watch(altoContraste, (val) => {
'flex-1 py-2 rounded-lg border text-sm font-bold transition-colors', 'flex-1 py-2 rounded-lg border text-sm font-bold transition-colors',
nivelFonte === op.nivel nivelFonte === op.nivel
? 'bg-primary text-white border-primary' ? 'bg-primary text-white border-primary'
: 'bg-white text-slate-600 border-slate-200 hover:border-primary/40 hover:text-primary' : 'bg-white dark:bg-slate-700 text-slate-600 dark:text-slate-300 border-slate-200 dark:border-slate-600 hover:border-primary/40 hover:text-primary'
]" ]"
@click="nivelFonte = op.nivel" @click="nivelFonte = op.nivel"
> >
@ -68,11 +86,24 @@ watch(altoContraste, (val) => {
</div> </div>
</div> </div>
<!-- Alto contraste --> <div class="space-y-3 pt-4 border-t border-slate-100 dark:border-slate-700">
<div class="flex items-center justify-between pt-4 border-t border-slate-100"> <!-- Modo escuro -->
<div class="flex items-center justify-between">
<div> <div>
<p class="text-sm font-semibold text-slate-700">Alto contraste</p> <p class="text-sm font-semibold text-slate-700 dark:text-slate-200">Modo escuro</p>
<p class="text-xs text-slate-400 mt-0.5">Melhora a legibilidade</p> <p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Tema de baixa luminosidade</p>
</div>
<ToggleSwitch
v-model="modoEscuro"
:aria-label="modoEscuro ? 'Desativar modo escuro' : 'Ativar modo escuro'"
/>
</div>
<!-- Alto contraste -->
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-semibold text-slate-700 dark:text-slate-200">Alto contraste</p>
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Melhora a legibilidade</p>
</div> </div>
<ToggleSwitch <ToggleSwitch
v-model="altoContraste" v-model="altoContraste"
@ -80,6 +111,7 @@ watch(altoContraste, (val) => {
/> />
</div> </div>
</div> </div>
</div>
</Transition> </Transition>
<!-- Botão flutuante --> <!-- Botão flutuante -->
@ -88,7 +120,7 @@ watch(altoContraste, (val) => {
'w-12 h-12 rounded-full shadow-lg border flex items-center justify-center transition-all hover:scale-105', 'w-12 h-12 rounded-full shadow-lg border flex items-center justify-center transition-all hover:scale-105',
aberto aberto
? 'bg-primary text-white border-primary shadow-primary/30' ? 'bg-primary text-white border-primary shadow-primary/30'
: 'bg-white text-slate-600 border-slate-200 hover:border-slate-300 hover:shadow-xl' : 'bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 border-slate-200 dark:border-slate-700 hover:border-slate-300 hover:shadow-xl'
]" ]"
:aria-label="aberto ? 'Fechar painel de acessibilidade' : 'Abrir painel de acessibilidade'" :aria-label="aberto ? 'Fechar painel de acessibilidade' : 'Abrir painel de acessibilidade'"
:aria-expanded="aberto" :aria-expanded="aberto"

View File

@ -2,17 +2,17 @@
</script> </script>
<template> <template>
<footer class="bg-white border-t border-slate-200 mt-auto" role="contentinfo"> <footer class="bg-white dark:bg-slate-900 border-t border-slate-200 dark:border-slate-700 mt-auto" role="contentinfo">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div class="flex flex-col sm:flex-row items-center justify-between gap-4"> <div class="flex flex-col sm:flex-row items-center justify-between gap-4">
<div class="flex items-center gap-2 text-sm text-slate-600"> <div class="flex items-center gap-2 text-sm text-slate-600 dark:text-slate-300">
<i class="pi pi-building text-primary" aria-hidden="true" /> <i class="pi pi-building text-primary" aria-hidden="true" />
<span>Portal do Contribuinte ModumFiscal</span> <span>Portal do Contribuinte ModumFiscal</span>
</div> </div>
<nav aria-label="Links institucionais" class="flex items-center gap-4 text-xs text-slate-500"> <nav aria-label="Links institucionais" class="flex items-center gap-4 text-xs text-slate-500 dark:text-slate-400">
<a href="#" class="hover:text-slate-700 transition-colors">Política de Privacidade</a> <a href="#" class="hover:text-slate-700 dark:hover:text-slate-200 transition-colors">Política de Privacidade</a>
<a href="#" class="hover:text-slate-700 transition-colors">Termos de Uso</a> <a href="#" class="hover:text-slate-700 dark:hover:text-slate-200 transition-colors">Termos de Uso</a>
<a href="#" class="hover:text-slate-700 transition-colors">Acessibilidade</a> <a href="#" class="hover:text-slate-700 dark:hover:text-slate-200 transition-colors">Acessibilidade</a>
</nav> </nav>
</div> </div>
</div> </div>

View File

@ -11,7 +11,7 @@ const logoSrc = computed(() => prefeitura.pathLogo || logoFallback)
</script> </script>
<template> <template>
<header class="bg-white border-b border-slate-200"> <header class="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-700">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<RouterLink <RouterLink
@ -26,8 +26,8 @@ const logoSrc = computed(() => prefeitura.pathLogo || logoFallback)
/> />
<div class="leading-tight min-w-0" aria-hidden="true"> <div class="leading-tight min-w-0" aria-hidden="true">
<p class="text-xs text-slate-500 font-normal truncate">Portal do Contribuinte</p> <p class="text-xs text-slate-500 dark:text-slate-400 font-normal truncate">Portal do Contribuinte</p>
<p class="text-sm font-semibold text-slate-800 truncate"> <p class="text-sm font-semibold text-slate-800 dark:text-slate-100 truncate">
{{ prefeitura.nomePrefeitura || 'ModumFiscal' }} {{ prefeitura.nomePrefeitura || 'ModumFiscal' }}
</p> </p>
</div> </div>
@ -36,7 +36,7 @@ const logoSrc = computed(() => prefeitura.pathLogo || logoFallback)
<nav aria-label="Navegação principal" class="hidden md:flex items-center gap-4"> <nav aria-label="Navegação principal" class="hidden md:flex items-center gap-4">
<RouterLink <RouterLink
:to="{ name: 'servicos' }" :to="{ name: 'servicos' }"
class="text-sm text-slate-600 hover:text-primary transition-colors" class="text-sm text-slate-600 dark:text-slate-300 hover:text-primary transition-colors"
:aria-current="$route.name === 'servicos' ? 'page' : undefined" :aria-current="$route.name === 'servicos' ? 'page' : undefined"
> >
Serviços Serviços

View File

@ -12,19 +12,19 @@ defineProps({
<component <component
:is="to ? 'RouterLink' : 'div'" :is="to ? 'RouterLink' : 'div'"
:to="to ?? undefined" :to="to ?? undefined"
class="group flex flex-col gap-3 bg-white rounded-xl border border-slate-200 p-5 hover:border-blue-300 hover:shadow-md transition-all duration-200 cursor-pointer" class="group flex flex-col gap-3 bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-5 hover:border-primary/40 dark:hover:border-primary/50 hover:shadow-md transition-all duration-200 cursor-pointer"
> >
<div class="flex items-start justify-between"> <div class="flex items-start justify-between">
<div class="w-10 h-10 bg-blue-50 rounded-lg flex items-center justify-center group-hover:bg-blue-100 transition-colors"> <div class="w-10 h-10 bg-primary/8 dark:bg-primary/15 rounded-lg flex items-center justify-center group-hover:bg-primary/15 dark:group-hover:bg-primary/25 transition-colors">
<i :class="['pi', icon, 'text-blue-700 text-lg']" /> <i :class="['pi', icon, 'text-primary text-lg']" />
</div> </div>
<i v-if="requiresAuth" class="pi pi-lock text-slate-300 text-xs" title="Requer login" /> <i v-if="requiresAuth" class="pi pi-lock text-slate-300 dark:text-slate-600 text-xs" title="Requer login" />
</div> </div>
<div> <div>
<p class="font-semibold text-slate-800 text-sm group-hover:text-blue-700 transition-colors">{{ titulo }}</p> <p class="font-semibold text-slate-800 dark:text-slate-100 text-sm group-hover:text-primary transition-colors">{{ titulo }}</p>
<p v-if="descricao" class="text-xs text-slate-500 mt-1 leading-relaxed">{{ descricao }}</p> <p v-if="descricao" class="text-xs text-slate-500 dark:text-slate-400 mt-1 leading-relaxed">{{ descricao }}</p>
</div> </div>
<div class="flex items-center gap-1 text-xs text-blue-600 font-medium opacity-0 group-hover:opacity-100 transition-opacity"> <div class="flex items-center gap-1 text-xs text-primary font-medium opacity-0 group-hover:opacity-100 transition-opacity">
<span>Acessar</span> <span>Acessar</span>
<i class="pi pi-arrow-right text-xs" /> <i class="pi pi-arrow-right text-xs" />
</div> </div>

View File

@ -20,8 +20,8 @@ function sair() {
</script> </script>
<template> <template>
<div class="min-h-screen flex flex-col bg-slate-50"> <div class="min-h-screen flex flex-col bg-slate-50 dark:bg-slate-950">
<header class="bg-white border-b border-slate-200 sticky top-0 z-40" role="banner"> <header class="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-700 sticky top-0 z-40" role="banner">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<RouterLink <RouterLink
:to="{ name: 'painel' }" :to="{ name: 'painel' }"
@ -31,7 +31,7 @@ function sair() {
<div class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center"> <div class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center">
<i class="pi pi-building text-white text-sm" aria-hidden="true" /> <i class="pi pi-building text-white text-sm" aria-hidden="true" />
</div> </div>
<span class="font-semibold text-slate-800">Portal do Contribuinte</span> <span class="font-semibold text-slate-800 dark:text-slate-100">Portal do Contribuinte</span>
</RouterLink> </RouterLink>
<nav aria-label="Menu do contribuinte" class="hidden md:flex items-center gap-1"> <nav aria-label="Menu do contribuinte" class="hidden md:flex items-center gap-1">
@ -39,7 +39,7 @@ function sair() {
v-for="item in navItems" v-for="item in navItems"
:key="item.name" :key="item.name"
:to="{ name: item.name }" :to="{ name: item.name }"
class="px-4 py-2 rounded-lg text-sm text-slate-600 hover:bg-slate-100 hover:text-slate-900 transition-colors" class="px-4 py-2 rounded-lg text-sm text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-100 transition-colors"
active-class="bg-primary/10 text-primary font-semibold" active-class="bg-primary/10 text-primary font-semibold"
:aria-current="$route.name === item.name ? 'page' : undefined" :aria-current="$route.name === item.name ? 'page' : undefined"
> >
@ -48,7 +48,7 @@ function sair() {
</nav> </nav>
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<span class="hidden sm:block text-sm text-slate-600" aria-live="polite"> <span class="hidden sm:block text-sm text-slate-600 dark:text-slate-300" aria-live="polite">
{{ auth.nomeUsuario }} {{ auth.nomeUsuario }}
</span> </span>
<Button <Button

View File

@ -2,7 +2,7 @@
</script> </script>
<template> <template>
<div class="min-h-screen flex flex-col bg-slate-50"> <div class="min-h-screen flex flex-col bg-slate-50 dark:bg-slate-950">
<AppHeader /> <AppHeader />
<!-- tabindex="-1" permite que o skip link mova o foco para --> <!-- tabindex="-1" permite que o skip link mova o foco para -->

View File

@ -70,9 +70,9 @@ const avisos = ref([
]) ])
const corAviso = { const corAviso = {
amber: { bg: 'bg-amber-50', borda: 'border-amber-200', icone: 'text-amber-600', tag: 'bg-amber-100 text-amber-700' }, amber: { bg: 'bg-amber-50 dark:bg-amber-900/20', borda: 'border-amber-200 dark:border-amber-700/40', icone: 'text-amber-600 dark:text-amber-400', tag: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300' },
green: { bg: 'bg-emerald-50', borda: 'border-emerald-200', icone: 'text-emerald-600', tag: 'bg-emerald-100 text-emerald-700' }, green: { bg: 'bg-emerald-50 dark:bg-emerald-900/20', borda: 'border-emerald-200 dark:border-emerald-700/40', icone: 'text-emerald-600 dark:text-emerald-400', tag: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300' },
blue: { bg: 'bg-blue-50', borda: 'border-blue-200', icone: 'text-blue-600', tag: 'bg-blue-100 text-blue-700' }, blue: { bg: 'bg-blue-50 dark:bg-blue-900/20', borda: 'border-blue-200 dark:border-blue-700/40', icone: 'text-blue-600 dark:text-blue-400', tag: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300' },
} }
// Serviços // Serviços
@ -190,7 +190,7 @@ function continuar() {
<!-- Direita Card de acesso --> <!-- Direita Card de acesso -->
<div class="flex justify-center lg:justify-end"> <div class="flex justify-center lg:justify-end">
<div class="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-sm backdrop-blur-sm"> <div class="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl p-8 w-full max-w-sm backdrop-blur-sm">
<!-- Cabeçalho do card --> <!-- Cabeçalho do card -->
<div class="flex items-center gap-3 mb-7"> <div class="flex items-center gap-3 mb-7">
@ -198,15 +198,15 @@ function continuar() {
<i class="pi pi-lock-open text-white text-lg" /> <i class="pi pi-lock-open text-white text-lg" />
</div> </div>
<div> <div>
<p class="font-bold text-slate-800 text-base">Área do Contribuinte</p> <p class="font-bold text-slate-800 dark:text-slate-100 text-base">Área do Contribuinte</p>
<p class="text-xs text-slate-500">Acesso seguro ao portal</p> <p class="text-xs text-slate-500 dark:text-slate-400">Acesso seguro ao portal</p>
</div> </div>
</div> </div>
<!-- Formulário --> <!-- Formulário -->
<div class="space-y-4"> <div class="space-y-4">
<div> <div>
<label class="block text-sm font-medium text-slate-700 mb-1.5"> <label class="block text-sm font-medium text-slate-700 dark:text-slate-200 mb-1.5">
CPF ou CNPJ CPF ou CNPJ
</label> </label>
<DocumentoInput <DocumentoInput
@ -236,14 +236,14 @@ function continuar() {
<div class="space-y-2.5 text-center"> <div class="space-y-2.5 text-center">
<RouterLink <RouterLink
:to="{ name: 'primeiro-acesso' }" :to="{ name: 'primeiro-acesso' }"
class="flex items-center justify-center gap-2 w-full px-4 py-2.5 rounded-lg border border-slate-200 text-sm text-slate-700 hover:bg-slate-50 hover:border-slate-300 transition-colors font-medium" class="flex items-center justify-center gap-2 w-full px-4 py-2.5 rounded-lg border border-slate-200 dark:border-slate-600 text-sm text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-700 hover:border-slate-300 dark:hover:border-slate-500 transition-colors font-medium"
> >
<i class="pi pi-key text-slate-500 text-sm" /> <i class="pi pi-key text-slate-500 dark:text-slate-400 text-sm" />
Criar minha senha Criar minha senha
</RouterLink> </RouterLink>
<RouterLink <RouterLink
:to="{ name: 'credenciamento' }" :to="{ name: 'credenciamento' }"
class="block text-xs text-slate-400 hover:text-slate-600 transition-colors" class="block text-xs text-slate-400 dark:text-slate-500 hover:text-slate-600 dark:hover:text-slate-300 transition-colors"
> >
Ainda não cadastrado? <span class="text-primary font-semibold">Credenciar-se</span> Ainda não cadastrado? <span class="text-primary font-semibold">Credenciar-se</span>
</RouterLink> </RouterLink>
@ -257,7 +257,7 @@ function continuar() {
</section> </section>
<!-- CAROUSEL DE AVISOS --> <!-- CAROUSEL DE AVISOS -->
<section class="bg-white border-b border-slate-100" aria-label="Avisos e comunicados"> <section class="bg-white dark:bg-slate-900 border-b border-slate-100 dark:border-slate-800" aria-label="Avisos e comunicados">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<!-- autoplay desativado quando prefers-reduced-motion está ativo --> <!-- autoplay desativado quando prefers-reduced-motion está ativo -->
<Carousel <Carousel
@ -285,8 +285,8 @@ function continuar() {
<i :class="['pi', aviso.icone, 'text-lg', corAviso[aviso.cor].icone]" /> <i :class="['pi', aviso.icone, 'text-lg', corAviso[aviso.cor].icone]" />
</div> </div>
<div class="flex-1 min-w-0"> <div class="flex-1 min-w-0">
<p class="font-semibold text-slate-800 text-sm">{{ aviso.titulo }}</p> <p class="font-semibold text-slate-800 dark:text-slate-100 text-sm">{{ aviso.titulo }}</p>
<p class="text-xs text-slate-600 mt-0.5 leading-relaxed">{{ aviso.descricao }}</p> <p class="text-xs text-slate-600 dark:text-slate-300 mt-0.5 leading-relaxed">{{ aviso.descricao }}</p>
<RouterLink <RouterLink
v-if="aviso.acao" v-if="aviso.acao"
:to="aviso.acao.to" :to="aviso.acao.to"
@ -310,8 +310,8 @@ function continuar() {
<section class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12" aria-labelledby="servicos-logados-titulo"> <section class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12" aria-labelledby="servicos-logados-titulo">
<div class="flex items-center justify-between mb-6"> <div class="flex items-center justify-between mb-6">
<div> <div>
<h2 id="servicos-logados-titulo" class="text-xl font-bold text-slate-800">Área logada</h2> <h2 id="servicos-logados-titulo" class="text-xl font-bold text-slate-800 dark:text-slate-100">Área logada</h2>
<p class="text-sm text-slate-600 mt-0.5">Serviços disponíveis após login</p> <p class="text-sm text-slate-600 dark:text-slate-400 mt-0.5">Serviços disponíveis após login</p>
</div> </div>
<span class="hidden sm:flex items-center gap-1.5 bg-primary/8 text-primary text-xs font-semibold px-3 py-1.5 rounded-full border border-primary/15"> <span class="hidden sm:flex items-center gap-1.5 bg-primary/8 text-primary text-xs font-semibold px-3 py-1.5 rounded-full border border-primary/15">
<i class="pi pi-lock text-xs" /> <i class="pi pi-lock text-xs" />
@ -329,10 +329,10 @@ function continuar() {
</div> </div>
<!-- CTA credenciamento --> <!-- CTA credenciamento -->
<div class="mt-10 bg-gradient-to-r from-primary/5 to-primary/10 border border-primary/15 rounded-2xl p-6 flex flex-col sm:flex-row items-center justify-between gap-5"> <div class="mt-10 bg-gradient-to-r from-primary/5 to-primary/10 dark:from-primary/10 dark:to-primary/15 border border-primary/15 dark:border-primary/20 rounded-2xl p-6 flex flex-col sm:flex-row items-center justify-between gap-5">
<div> <div>
<p class="font-bold text-slate-800 text-base">Ainda não tem acesso ao portal?</p> <p class="font-bold text-slate-800 dark:text-slate-100 text-base">Ainda não tem acesso ao portal?</p>
<p class="text-sm text-slate-500 mt-1 max-w-md"> <p class="text-sm text-slate-500 dark:text-slate-400 mt-1 max-w-md">
Solicite seu credenciamento e passe a gerenciar todos os seus tributos municipais de forma online. Solicite seu credenciamento e passe a gerenciar todos os seus tributos municipais de forma online.
</p> </p>
</div> </div>

View File

@ -53,7 +53,7 @@ async function entrar() {
<div class="min-h-[calc(100vh-8rem)] flex items-center justify-center px-4 py-12"> <div class="min-h-[calc(100vh-8rem)] flex items-center justify-center px-4 py-12">
<div class="w-full max-w-md"> <div class="w-full max-w-md">
<div class="bg-white rounded-2xl shadow-lg border border-slate-200 overflow-hidden"> <div class="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<!-- Cabeçalho h1 para hierarquia de heading correta --> <!-- Cabeçalho h1 para hierarquia de heading correta -->
<div class="bg-gradient-to-r from-primary-700 to-primary-800 px-8 py-6 bg-primary"> <div class="bg-gradient-to-r from-primary-700 to-primary-800 px-8 py-6 bg-primary">
@ -72,17 +72,17 @@ async function entrar() {
<!-- Documento identificado --> <!-- Documento identificado -->
<div> <div>
<p class="text-xs font-semibold text-slate-600 uppercase tracking-wide mb-2"> <p class="text-xs font-semibold text-slate-600 dark:text-slate-400 uppercase tracking-wide mb-2">
Entrando como Entrando como
</p> </p>
<div class="flex items-center justify-between bg-slate-50 border border-slate-200 rounded-xl px-4 py-3"> <div class="flex items-center justify-between bg-slate-50 dark:bg-slate-700 border border-slate-200 dark:border-slate-600 rounded-xl px-4 py-3">
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<div class="w-8 h-8 bg-primary/10 rounded-lg flex items-center justify-center" aria-hidden="true"> <div class="w-8 h-8 bg-primary/10 rounded-lg flex items-center justify-center" aria-hidden="true">
<i class="pi pi-id-card text-primary text-sm" /> <i class="pi pi-id-card text-primary text-sm" />
</div> </div>
<div> <div>
<p class="font-mono font-semibold text-slate-800 text-sm">{{ docFormatado }}</p> <p class="font-mono font-semibold text-slate-800 dark:text-slate-100 text-sm">{{ docFormatado }}</p>
<p class="text-xs text-slate-600">{{ tipoDoc }}</p> <p class="text-xs text-slate-600 dark:text-slate-300">{{ tipoDoc }}</p>
</div> </div>
</div> </div>
<!-- Alvo de 44px via py-3 px-3 --> <!-- Alvo de 44px via py-3 px-3 -->
@ -99,7 +99,7 @@ async function entrar() {
<!-- Senha --> <!-- Senha -->
<div> <div>
<label :for="senhaId" class="block text-sm font-semibold text-slate-700 mb-1.5"> <label :for="senhaId" class="block text-sm font-semibold text-slate-700 dark:text-slate-200 mb-1.5">
Senha Senha
</label> </label>
<Password <Password
@ -147,7 +147,7 @@ async function entrar() {
</RouterLink> </RouterLink>
<RouterLink <RouterLink
:to="{ name: 'credenciamento' }" :to="{ name: 'credenciamento' }"
class="block text-sm text-slate-600 py-2 hover:text-slate-800 transition-colors" class="block text-sm text-slate-600 dark:text-slate-400 py-2 hover:text-slate-800 dark:hover:text-slate-200 transition-colors"
> >
Ainda não tem acesso? <span class="text-primary font-semibold">Credenciar-se</span> Ainda não tem acesso? <span class="text-primary font-semibold">Credenciar-se</span>
</RouterLink> </RouterLink>
@ -159,7 +159,7 @@ async function entrar() {
<!-- Voltar alvo de 44px via py-3 --> <!-- Voltar alvo de 44px via py-3 -->
<div class="text-center mt-4"> <div class="text-center mt-4">
<button <button
class="inline-flex items-center gap-2 text-sm text-slate-600 hover:text-slate-800 transition-colors py-3 px-4 rounded-lg hover:bg-slate-100" class="inline-flex items-center gap-2 text-sm text-slate-600 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200 transition-colors py-3 px-4 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800"
@click="router.push({ name: 'home' })" @click="router.push({ name: 'home' })"
> >
<i class="pi pi-arrow-left text-xs" aria-hidden="true" /> <i class="pi pi-arrow-left text-xs" aria-hidden="true" />