diff --git a/AGENTS.md b/AGENTS.md
index 8bd0e39..3de87c0 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -3,3 +3,72 @@
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
+
+# Algoria Project Rules & Design System
+
+This document outlines the design system, architecture rules, and coding standards for the Algoria project. All AI agents working on this codebase must adhere strictly to these guidelines.
+
+## 1. Design System & Aesthetics
+
+### Typography
+- **Primary Font**: Geist Sans (sans-serif) for body text and general interface.
+- **Monospace Font**: Geist Mono / system monospace for code, metrics, and technical data.
+- **Digital LCD Font**: `Share Tech Mono` (imported from Google Fonts). Used for stopwatch numbers and digital display readouts (`.font-digital`).
+- **Sci-Fi Display Font**: `Orbitron` (imported from Google Fonts). Used for headers and technical badges (`.font-orbitron`).
+
+### Border Radius & Shapes
+- **Zero Rounding Rule**: **DO NOT use rounded corners on any UI elements.** All buttons, inputs, dialogs, cards, progress bars, and badges must have sharp, square corners.
+ - Use `rounded-none` or omit the `rounded` utility class entirely.
+ - Avoid `rounded-sm`, `rounded-md`, `rounded-lg`, etc.
+
+### Colors & Themes
+- **Dark Mode (Default)**:
+ - Background: `#020617` (Deep space slate/black)
+ - Foreground: `#f8fafc`
+ - Secondary/Cards: `#0f172a`
+ - Border: `#1e293b`
+- **Light Mode**:
+ - Background: `#ffffff`
+ - Foreground: `#020617`
+ - Secondary/Cards: `#f1f5f9`
+ - Border: `#e2e8f0`
+- **Brand Colors**:
+ - **Primary**: Indigo (`#4f46e5` for light, `#818cf8` for dark)
+ - **Gamification Accent**: Orange/Amber (`#f97316` / `#f59e0b`) for active rewards and challenges.
+ - **Success/Complete Accent**: Emerald/Green (`#10b981` / `#22c55e`) for completed items.
+
+### Animations & Motion
+- **No Idle Pulsing**: Avoid looping animations such as `animate-pulse` or `animate-ping` on active status badges or pills to prevent visual clutter.
+- **Transitions**: Keep page and state transitions subtle using Framer Motion (e.g. slight Y-axis slide or opacity transitions).
+
+---
+
+## 2. Architecture & Code Structure
+
+### Clean Separation of Concerns
+- **Logic vs View**: Do not bundle complex states, timers, event listeners, or storage reads/writes directly in UI view components.
+ - Move state, timing, and progress checks to **custom React hooks** (e.g., `useDailyChallenge`).
+ - Move storage keys, static constants, formatting helpers, and pure functions to **utility files** (e.g., `daily-challenge-utils.ts`).
+ - Keep `.tsx` UI files focused purely on layout, styling, and rendering.
+
+---
+
+## 3. Product Rules & Features
+
+### Authentication & Gating
+- **Full Gating**: The user must be logged in to view any primary problem solving content or dashboard data. Use `RequireAuth` to wrap protected views.
+- **Auth Dialog**: Trigger the global `AuthDialog` via `AuthDialogProvider` to prompt user login/registration when trying to view protected pages, and redirect the user to their target pathname upon successful authentication.
+- **Account Deletion**: When a user profile is deleted:
+ - Delete all records and progress associated with that user from the database.
+ - Perform `localStorage.clear()` on the client side to wipe all local progress caches.
+
+### Daily Challenge Mechanic
+- **Timer Details**:
+ - Requires **3 minutes (180 seconds)** of active page visibility to complete.
+ - Must pause automatically if the user switches browser tabs (`document.hidden`). Use sub-second (50ms) intervals to render a fluid stopwatch (`HH:MM:SS:CC`) in the UI.
+- **Checklist Requirements**:
+ - Daily challenges are completed only if:
+ 1. The problem is unlocked/accessible for the user.
+ 2. The statement page is visited.
+ 3. Both optimal and brute-force solutions (if both exist) have been visited.
+ 4. The 3-minute active timer has finished.
diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index 43c994c..0000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1 +0,0 @@
-@AGENTS.md
diff --git a/README.md b/README.md
index d6915c1..9304c24 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Algoria
-
+
Plataforma em português para estudar **algoritmos e decisões em código** através de leitura guiada: catálogo de problemas com várias soluções (brute-force, óptima, alternativa), **code player** linha-a-linha com três níveis de explicação, mini-guias em **Conceitos**, **curso modular** com avaliações locais, hub de **inglês técnico para entrevistas** (conteúdo em inglês) e guias de **engenharia aplicada** (front, back, DevOps, SoftSkills e IA).
diff --git a/RELEASE.md b/RELEASE.md
new file mode 100644
index 0000000..c210963
--- /dev/null
+++ b/RELEASE.md
@@ -0,0 +1,25 @@
+# Notas de Release (v1.6.0)
+
+### 🚀 Novas Funcionalidades
+- **Controle de Autenticação Estrito (Full Gating & Auth Dialog)**: Implementado o bloqueio completo de qualquer conteúdo de estudo (problemas, soluções comentadas, conceitos e guias de carreira) para utilizadores não autenticados. O acesso é interceptado reativamente através do componente `RequireAuth` que ativa o `AuthDialog` global e redireciona automaticamente o utilizador para a página pretendida após o sucesso do login.
+- **Exclusão de Conta com Limpeza Total (Wipe)**: Criada uma caixa de diálogo de confirmação para a exclusão de conta no perfil do utilizador. A confirmação remove definitivamente todos os registros e históricos de progresso do banco de dados (Postgres) e limpa completamente o cache local do cliente através de `localStorage.clear()`.
+- **Desafio Diário Aprimorado (Checklist e Validação)**: O sistema de Desafio Diário agora exige a validação estrita de três tarefas antes de considerar o desafio completo: 1) o problema deve ser acessível ao utilizador, 2) o enunciado deve ser visitado, 3) todas as soluções disponíveis do problema devem ser lidas, e 4) o utilizador deve passar pelo menos 3 minutos (180 segundos) de tempo ativo na página.
+
+### 🛠️ Melhorias Técnicas & UI
+- **Cronómetro Digital LCD/LED (Glowing Clock)**: Adicionado um widget de cronómetro baseado no modelo digital de sete segmentos (`HH:MM:SS:CC`) com renderização em tempo real atualizada a cada 50ms para exibição fluida de centésimos de segundo. O contador usa uma caixa preta de alto contraste com fontes personalizadas e sombras de texto luminescentes (*glow*) brancas e verdes.
+- **Estrutura Modular (Separação de Conceitos)**: O rastreador do desafio foi dividido em três partes organizadas: os utilitários de armazenamento e formatação (`daily-challenge-utils.ts`), o hook de controle de efeitos e tempo ativo (`use-daily-challenge.ts`) e o componente de interface pura (`daily-challenge-tracker.tsx`).
+- **Alinhamento com o Design System Estrito**: Removidas todas as bordas arredondadas da interface do banner (`rounded-none` absoluto) e limpos os efeitos de pulsação ociosa (`animate-pulse` / `animate-ping`) para garantir sobriedade visual e consistência técnica.
+- **Layout Inteligente Flutuante (Sticky)**: O banner agora acompanha o scroll da página de forma fixa (`sticky top-16`) mantendo exatamente a mesma largura útil do conteúdo principal (`max-w-7xl px-6`) com efeito translúcido no fundo e zero impacto na tela quando inativo.
+
+---
+
+# Changelog
+
+## 2026-05-29 — Strict Auth Gating, Account Wipe, and High-Fidelity Stopwatch Tracker
+Esta versão foca-se na segurança de dados, privacidade do utilizador e fidelidade visual da interface de desafios, trazendo alinhamentos estritos com o design system da plataforma (zero cantos arredondados) e melhorias na estrutura do código de gamificação.
+
+- **Controle de Acesso Total**: Gating estrito de todo o conteúdo educativo da plataforma, exigindo autenticação via modal global integrado antes do redirecionamento ao destino.
+- **Apagamento Completo de Dados**: Funcionalidade de exclusão de conta no perfil que limpa as tabelas relacionais em nuvem e esvazia o armazenamento local do navegador em um único passo.
+- **Cronómetro Centesimal com Glow**: Novo design de cronómetro digital com efeito neon de 8 dígitos, medindo o tempo de engajamento do utilizador com suporte a pausas de visibilidade da aba do browser.
+- **Status Dashboard Monospace**: Exibição simplificada de requisitos em formato de terminal técnico, oferecendo maior clareza visual sobre as tarefas cumpridas (acesso, leitura e soluções visitadas) sem poluição por animações.
+- **Arquitetura Modular em React**: Separação de utilitários de storage e custom hooks de timer, simplificando o componente de visualização.
diff --git a/app/auth/sign-in/page.tsx b/app/auth/sign-in/page.tsx
index f174921..44515ed 100644
--- a/app/auth/sign-in/page.tsx
+++ b/app/auth/sign-in/page.tsx
@@ -1,10 +1,6 @@
-import Link from 'next/link';
import type { Metadata } from 'next';
-import { ArrowLeft } from 'lucide-react';
-import { SignInForm } from '@/components/auth/sign-in-form';
-import { AlgoriaMark } from '@/components/branding/algoria-logo';
-import { Button } from '@/components/ui/button';
+import { SignInRedirector } from '@/components/auth/sign-in-redirector';
import { buildPublicMetadata } from '@/lib/seo/build-metadata';
export const metadata: Metadata = buildPublicMetadata({
@@ -15,68 +11,5 @@ export const metadata: Metadata = buildPublicMetadata({
});
export default function SignInPage() {
- return (
-
- {/* Decorative gradients */}
-
-
-
-
-
-
-
-
-
- {/* Left — branding + value props */}
-
-
-
Conta
-
- Iniciar sessão
-
-
- Sincroniza o teu progresso, acede a todo o conteúdo Pro e retoma onde paraste.
-
-
-
-
-
- {[
- { label: 'Progresso na nuvem', desc: 'Continua o estudo em qualquer dispositivo sem perder o histórico.' },
- { label: 'Catálogo completo', desc: 'Acesso a todos os problemas, soluções comentadas e code player.' },
- { label: 'Curso guiado', desc: 'Módulos com avaliações e certificado gravado no browser.' },
- ].map((item) => (
-
-
-
-
-
-
{item.label}
-
{item.desc}
-
-
- ))}
-
-
-
-
- {/* Right — form card */}
-
-
-
-
-
-
- Algoria
-
-
-
-
-
-
-
-
- );
+ return ;
}
diff --git a/app/auth/sign-up/page.tsx b/app/auth/sign-up/page.tsx
index ac9f48e..029783f 100644
--- a/app/auth/sign-up/page.tsx
+++ b/app/auth/sign-up/page.tsx
@@ -1,10 +1,6 @@
-import Link from 'next/link';
import type { Metadata } from 'next';
-import { ArrowLeft } from 'lucide-react';
-import { SignUpForm } from '@/components/auth/sign-up-form';
-import { AlgoriaMark } from '@/components/branding/algoria-logo';
-import { Button } from '@/components/ui/button';
+import { SignUpRedirector } from '@/components/auth/sign-up-redirector';
import { buildPublicMetadata } from '@/lib/seo/build-metadata';
export const metadata: Metadata = buildPublicMetadata({
@@ -15,68 +11,5 @@ export const metadata: Metadata = buildPublicMetadata({
});
export default function SignUpPage() {
- return (
-
- {/* Decorative gradients */}
-
-
-
-
-
-
-
-
-
- {/* Left — branding + value props */}
-
-
-
Nova conta
-
- Criar conta
-
-
- Cria a tua conta gratuita e começa a estudar algoritmos com leitura guiada de código.
-
-
-
-
-
- {[
- { label: 'Gratuito para começar', desc: 'Acesso a problemas free, conceitos, inglês técnico e guias de engenharia.' },
- { label: 'Progresso sincronizado', desc: 'O teu progresso local será fundido com a conta no primeiro login.' },
- { label: 'Upgrade quando quiseres', desc: 'Plano Pro desbloqueia o catálogo completo de soluções e o code player.' },
- ].map((item) => (
-
-
-
-
-
-
{item.label}
-
{item.desc}
-
-
- ))}
-
-
-
-
- {/* Right — form card */}
-
-
-
-
-
-
- Algoria
-
-
-
-
-
-
-
-
- );
+ return ;
}
diff --git a/app/concepts/[slug]/page.tsx b/app/concepts/[slug]/page.tsx
index 51efcf8..0483151 100644
--- a/app/concepts/[slug]/page.tsx
+++ b/app/concepts/[slug]/page.tsx
@@ -1,20 +1,21 @@
-import Link from 'next/link';
+import { ArrowLeft, Clock } from 'lucide-react';
import type { Metadata } from 'next';
-import { notFound } from 'next/navigation';
import { headers } from 'next/headers';
-import { ArrowLeft, Clock } from 'lucide-react';
+import Link from 'next/link';
+import { notFound } from 'next/navigation';
+import { RequireAuth } from '@/components/auth/require-auth';
import { UpgradePrompt } from '@/components/billing/upgrade-prompt';
-import { Badge } from '@/components/ui/badge';
-import { Button } from '@/components/ui/button';
import { DifficultyBadge } from '@/components/catalog/difficulty-badge';
import { ConceptVisitTracker } from '@/components/concepts/concept-visit-tracker';
import { ContentNavigation } from '@/components/layout/content-navigation';
import { JsonLdScript } from '@/components/seo/json-ld';
+import { Badge } from '@/components/ui/badge';
+import { Button } from '@/components/ui/button';
import { auth } from '@/lib/auth';
import { userHasPro } from '@/lib/billing/entitlements';
import { getConceptAccess, isContentUnlockedForUser } from '@/lib/billing/tiering';
-import { getAllConceptSlugs, getConcept, getAdjacentConcepts } from '@/lib/content/loader';
+import { getAdjacentConcepts, getAllConceptSlugs, getConcept } from '@/lib/content/loader';
import { buildPublicMetadata } from '@/lib/seo/build-metadata';
import { learningResourceJsonLd } from '@/lib/seo/structured-data';
@@ -71,8 +72,9 @@ export default async function ConceptPage({
const adjacent = await getAdjacentConcepts(slug);
return (
-
-
+
+
+
);
}
diff --git a/app/course/[slug]/module/[moduleId]/certificate/page.tsx b/app/course/[slug]/module/[moduleId]/certificate/page.tsx
index f6e7bcd..30d6895 100644
--- a/app/course/[slug]/module/[moduleId]/certificate/page.tsx
+++ b/app/course/[slug]/module/[moduleId]/certificate/page.tsx
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
+import { RequireAuth } from "@/components/auth/require-auth";
import { ModuleCertificatePageContent } from "@/components/course/module-certificate-page-content";
import {
buildCertificateMetadata,
@@ -25,5 +26,9 @@ export default async function ModuleCertificatePage({
params: Promise;
}) {
const { slug, moduleId } = await params;
- return ;
+ return (
+
+
+
+ );
}
diff --git a/app/course/[slug]/module/[moduleId]/page.tsx b/app/course/[slug]/module/[moduleId]/page.tsx
index d32df49..04e352d 100644
--- a/app/course/[slug]/module/[moduleId]/page.tsx
+++ b/app/course/[slug]/module/[moduleId]/page.tsx
@@ -6,6 +6,7 @@ import { ArrowLeft } from 'lucide-react';
import { CourseModuleRunner } from '@/components/course/course-module-runner';
import { Button } from '@/components/ui/button';
import { JsonLdScript } from '@/components/seo/json-ld';
+import { RequireAuth } from '@/components/auth/require-auth';
import { getCoursePackHydrated, listCourseSlugs } from '@/lib/courses/hydrate-course-pack';
import { buildPublicMetadata } from '@/lib/seo/build-metadata';
import { learningResourceJsonLd } from '@/lib/seo/structured-data';
@@ -63,8 +64,9 @@ export default async function CourseModulePage({ params }: { params: Promise
-
+
+ Índice do programa
-
-
+
+
+
);
}
diff --git a/app/engineering-work/[slug]/page.tsx b/app/engineering-work/[slug]/page.tsx
index 54f3145..7ad46ab 100644
--- a/app/engineering-work/[slug]/page.tsx
+++ b/app/engineering-work/[slug]/page.tsx
@@ -3,28 +3,29 @@ import type { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
+import { RequireAuth } from "@/components/auth/require-auth";
+import { UpgradePrompt } from "@/components/billing/upgrade-prompt";
import { AuthorInfo } from "@/components/engenharia-trabalho/author-info";
import { EngineeringGuideArticle } from "@/components/engenharia-trabalho/engineering-guide-article";
import { ContentNavigation } from "@/components/layout/content-navigation";
import { JsonLdScript } from "@/components/seo/json-ld";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
+import { auth } from "@/lib/auth";
+import { userHasPro } from "@/lib/billing/entitlements";
+import { isContentUnlockedForUser } from "@/lib/billing/tiering";
import {
getAdjacentEngineeringWork,
getAllEngineeringWorkSlugs,
getEngineeringWorkGuide,
} from "@/lib/content/loader";
-import { auth } from "@/lib/auth";
-import { userHasPro } from "@/lib/billing/entitlements";
-import { isContentUnlockedForUser } from "@/lib/billing/tiering";
-import { UpgradePrompt } from "@/components/billing/upgrade-prompt";
-import { headers } from "next/headers";
import type { EngineeringWorkPillar } from "@/lib/content/schemas";
import { db } from "@/lib/db";
import { user } from "@/lib/db/schema";
import { buildPublicMetadata } from "@/lib/seo/build-metadata";
import { articleJsonLd } from "@/lib/seo/structured-data";
import { eq } from "drizzle-orm";
+import { headers } from "next/headers";
interface Params {
slug: string;
@@ -83,7 +84,6 @@ export default async function EngineeringWorkGuidePage({
const adjacent = await getAdjacentEngineeringWork(slug);
- // Busca o ID do Jonatas para o link do perfil
let authorData = null;
try {
authorData = (await db.query.user.findFirst({
@@ -94,8 +94,9 @@ export default async function EngineeringWorkGuidePage({
}
return (
-