mirror of
https://github.com/lukaszraczylo/beat-delivery-methodology.git
synced 2026-06-05 22:44:18 +00:00
kimi-changes
This commit is contained in:
+43
-7
@@ -4,22 +4,58 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#3b82f6" />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>BEAT - Balanced. Empowered. Async. Teams.</title>
|
||||
<meta name="description" content="The BEAT Manifesto - A software delivery methodology built for how developers actually work. Deep work, async communication, individual autonomy, sustainable pace." />
|
||||
<meta name="keywords" content="BEAT, software development methodology, agile alternative, remote work, async communication, deep work, developer productivity" />
|
||||
<meta name="author" content="Lukasz Raczylo" />
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="BEAT - Balanced. Empowered. Async. Teams." />
|
||||
<meta property="og:description" content="A software delivery methodology built for how developers actually work." />
|
||||
<meta property="og:site_name" content="BEAT Manifesto" />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:title" content="BEAT - Balanced. Empowered. Async. Teams." />
|
||||
<meta property="twitter:description" content="A software delivery methodology built for how developers actually work." />
|
||||
|
||||
<!-- Preconnect for performance -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
<!-- Dark mode initialization (prevents flash) -->
|
||||
<script>
|
||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
(function() {
|
||||
const theme = localStorage.theme;
|
||||
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
if (theme === 'dark' || (!theme && systemDark)) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300">
|
||||
<body class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300 antialiased">
|
||||
<!-- Skip to main content link for accessibility -->
|
||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
|
||||
<!-- No-JS fallback -->
|
||||
<noscript>
|
||||
<div style="padding: 2rem; text-align: center; font-family: system-ui, sans-serif;">
|
||||
<h1 style="font-size: 1.5rem; margin-bottom: 1rem;">JavaScript Required</h1>
|
||||
<p>This website requires JavaScript to function properly. Please enable JavaScript in your browser settings.</p>
|
||||
</div>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+68
-7
@@ -1,14 +1,25 @@
|
||||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
import NavBar from '@/components/layout/NavBar.vue'
|
||||
import Footer from '@/components/layout/Footer.vue'
|
||||
import ReadingProgress from '@/components/layout/ReadingProgress.vue'
|
||||
|
||||
onMounted(() => {
|
||||
document.documentElement.style.scrollBehavior = 'smooth'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen flex flex-col">
|
||||
<div class="min-h-screen flex flex-col bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<ReadingProgress />
|
||||
<NavBar />
|
||||
<main class="flex-1">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="fade" mode="out-in">
|
||||
<transition
|
||||
name="page"
|
||||
mode="out-in"
|
||||
appear
|
||||
>
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
@@ -18,13 +29,63 @@ import Footer from '@/components/layout/Footer.vue'
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
/* Page transition animations */
|
||||
.page-enter-active,
|
||||
.page-leave-active {
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
.page-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px) scale(0.98);
|
||||
}
|
||||
|
||||
.page-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px) scale(0.98);
|
||||
}
|
||||
|
||||
.page-enter-to,
|
||||
.page-leave-from {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
|
||||
/* Ensure content is visible during transition */
|
||||
.page-enter-active > *,
|
||||
.page-leave-active > * {
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
|
||||
/* Improved focus visible styles for accessibility */
|
||||
:focus-visible {
|
||||
outline: 2px solid #3b82f6;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.dark :focus-visible {
|
||||
outline-color: #60a5fa;
|
||||
}
|
||||
|
||||
/* Remove focus outline for mouse users, keep for keyboard */
|
||||
:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Smooth scroll behavior */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Reduce motion for users who prefer it */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -13,73 +13,525 @@
|
||||
button, a {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
/* Selection colors */
|
||||
::selection {
|
||||
@apply bg-blue-500/30 text-blue-900 dark:text-blue-100;
|
||||
}
|
||||
|
||||
/* Improved focus visible for accessibility */
|
||||
:focus-visible {
|
||||
@apply outline-2 outline-offset-2 outline-blue-500;
|
||||
}
|
||||
|
||||
.dark :focus-visible {
|
||||
@apply outline-blue-400;
|
||||
}
|
||||
|
||||
/* Skip link for accessibility */
|
||||
.skip-link {
|
||||
@apply sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-blue-600 focus:text-white focus:rounded-lg;
|
||||
}
|
||||
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
@apply bg-gray-100 dark:bg-gray-800;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
@apply bg-gray-300 dark:bg-gray-600 rounded-full;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
@apply bg-gray-400 dark:bg-gray-500;
|
||||
}
|
||||
|
||||
/* Responsive base styles */
|
||||
body {
|
||||
@apply text-sm sm:text-base;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
/* Container that adapts to all screen sizes */
|
||||
.container-responsive {
|
||||
@apply w-full mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 2xl:max-w-7xl 3xl:max-w-8xl 4xl:max-w-9xl;
|
||||
}
|
||||
|
||||
/* Enhanced glass morphism */
|
||||
.glass {
|
||||
@apply bg-white/70 dark:bg-gray-800/70 backdrop-blur-lg border border-white/20 dark:border-gray-700/50;
|
||||
@apply bg-white/80 dark:bg-gray-800/80 backdrop-blur-xl border border-white/30 dark:border-gray-700/50;
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgba(0, 0, 0, 0.05),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.05),
|
||||
inset 0 1px 0 0 rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.dark .glass {
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgba(0, 0, 0, 0.3),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.2),
|
||||
inset 0 1px 0 0 rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
/* Gradient text with animation */
|
||||
.gradient-text {
|
||||
@apply bg-gradient-to-r from-blue-600 via-purple-600 to-cyan-600 dark:from-blue-400 dark:via-purple-400 dark:to-cyan-400 bg-clip-text text-transparent;
|
||||
@apply bg-clip-text text-transparent;
|
||||
background-image: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 50%, #06b6d4 100%);
|
||||
background-size: 200% 200%;
|
||||
animation: gradient-shift 8s ease infinite;
|
||||
}
|
||||
|
||||
.dark .gradient-text {
|
||||
background-image: linear-gradient(135deg, #60a5fa 0%, #a78bfa 50%, #22d3ee 100%);
|
||||
}
|
||||
|
||||
@keyframes gradient-shift {
|
||||
0%, 100% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
}
|
||||
|
||||
/* Modern shadow */
|
||||
.shadow-modern {
|
||||
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.1);
|
||||
box-shadow:
|
||||
0 20px 25px -5px rgba(0, 0, 0, 0.08),
|
||||
0 8px 10px -6px rgba(0, 0, 0, 0.05),
|
||||
0 0 0 1px rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.dark .shadow-modern {
|
||||
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.4);
|
||||
box-shadow:
|
||||
0 20px 25px -5px rgba(0, 0, 0, 0.4),
|
||||
0 8px 10px -6px rgba(0, 0, 0, 0.2),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
/* Primary button with enhanced effects */
|
||||
.btn-primary {
|
||||
@apply bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white px-5 sm:px-6 py-2.5 sm:py-3 rounded-lg font-medium transition-all duration-300 shadow-lg hover:shadow-xl hover:scale-105 text-sm sm:text-base min-h-[44px] flex items-center justify-center;
|
||||
@apply relative overflow-hidden bg-gradient-to-r from-blue-600 to-purple-600 text-white px-4 sm:px-6 py-2.5 sm:py-3 rounded-xl font-semibold transition-all duration-300;
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgba(59, 130, 246, 0.3),
|
||||
0 2px 4px -2px rgba(59, 130, 246, 0.2),
|
||||
inset 0 1px 0 0 rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary::before {
|
||||
content: '';
|
||||
@apply absolute inset-0 bg-gradient-to-r from-purple-600 to-blue-600 opacity-0 transition-opacity duration-300;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
@apply scale-105;
|
||||
box-shadow:
|
||||
0 10px 15px -3px rgba(59, 130, 246, 0.4),
|
||||
0 4px 6px -4px rgba(59, 130, 246, 0.3),
|
||||
inset 0 1px 0 0 rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary:hover::before {
|
||||
@apply opacity-100;
|
||||
}
|
||||
|
||||
.btn-primary:active {
|
||||
@apply scale-100;
|
||||
}
|
||||
|
||||
.btn-primary > * {
|
||||
@apply relative z-10;
|
||||
}
|
||||
|
||||
/* Secondary button */
|
||||
.btn-secondary {
|
||||
@apply glass hover:shadow-lg text-gray-900 dark:text-gray-100 px-5 sm:px-6 py-2.5 sm:py-3 rounded-lg font-medium transition-all duration-300 hover:scale-105 text-sm sm:text-base min-h-[44px] flex items-center justify-center;
|
||||
@apply glass text-gray-900 dark:text-gray-100 px-4 sm:px-6 py-2.5 sm:py-3 rounded-xl font-semibold transition-all duration-300;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
@apply scale-105;
|
||||
box-shadow:
|
||||
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.dark .btn-secondary:hover {
|
||||
box-shadow:
|
||||
0 10px 15px -3px rgba(0, 0, 0, 0.4),
|
||||
0 4px 6px -4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Section titles - responsive */
|
||||
.section-title {
|
||||
@apply text-2xl sm:text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4;
|
||||
@apply text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4 tracking-tight;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
@apply text-base sm:text-lg text-gray-600 dark:text-gray-300 px-2 sm:px-0;
|
||||
@apply text-base sm:text-lg md:text-xl text-gray-600 dark:text-gray-300 px-2 sm:px-0 leading-relaxed;
|
||||
}
|
||||
|
||||
/* Enhanced card with 3D hover */
|
||||
.card {
|
||||
@apply glass p-4 sm:p-6 rounded-xl transition-all duration-300 hover:shadow-lg;
|
||||
@apply glass p-4 sm:p-6 lg:p-8 rounded-2xl transition-all duration-500;
|
||||
transform-style: preserve-3d;
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
@apply -translate-y-1 sm:-translate-y-2;
|
||||
box-shadow:
|
||||
0 25px 50px -12px rgba(0, 0, 0, 0.15),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.1) inset;
|
||||
}
|
||||
|
||||
.dark .card:hover {
|
||||
box-shadow:
|
||||
0 25px 50px -12px rgba(0, 0, 0, 0.5),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
|
||||
}
|
||||
|
||||
/* Navigation link */
|
||||
.nav-link {
|
||||
@apply text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium transition-colors duration-200;
|
||||
@apply relative text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 font-medium transition-colors duration-200;
|
||||
}
|
||||
|
||||
.nav-link::after {
|
||||
content: '';
|
||||
@apply absolute -bottom-1 left-0 w-0 h-0.5 bg-gradient-to-r from-blue-500 to-purple-500 transition-all duration-300 rounded-full;
|
||||
}
|
||||
|
||||
.nav-link:hover::after {
|
||||
@apply w-full;
|
||||
}
|
||||
|
||||
/* Icon box */
|
||||
.icon-box {
|
||||
@apply w-10 h-10 sm:w-12 sm:h-12 rounded-xl flex items-center justify-center flex-shrink-0 transition-transform duration-300 group-hover:scale-110;
|
||||
@apply w-10 h-10 sm:w-12 sm:h-12 rounded-xl flex items-center justify-center flex-shrink-0;
|
||||
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
/* Section spacing responsive */
|
||||
.group:hover .icon-box {
|
||||
transform: scale(1.1) rotate(3deg);
|
||||
}
|
||||
|
||||
/* Section padding - responsive */
|
||||
.section-padding {
|
||||
@apply py-10 sm:py-12 md:py-16;
|
||||
@apply py-12 sm:py-16 md:py-20 lg:py-24;
|
||||
}
|
||||
|
||||
/* Gradient border effect */
|
||||
.gradient-border {
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(139, 92, 246, 0.1));
|
||||
}
|
||||
|
||||
.gradient-border::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
padding: 1px;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(135deg, #3b82f6, #8b5cf6, #06b6d4);
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
}
|
||||
|
||||
/* Shimmer loading effect */
|
||||
.shimmer {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.4) 50%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% { background-position: -200% 0; }
|
||||
100% { background-position: 200% 0; }
|
||||
}
|
||||
|
||||
/* Glow effects */
|
||||
.glow-blue {
|
||||
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3), 0 0 40px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.glow-purple {
|
||||
box-shadow: 0 0 20px rgba(139, 92, 246, 0.3), 0 0 40px rgba(139, 92, 246, 0.1);
|
||||
}
|
||||
|
||||
/* Number badge */
|
||||
.number-badge {
|
||||
@apply w-8 h-8 sm:w-10 sm:h-10 rounded-full bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center text-white font-bold text-sm sm:text-base;
|
||||
box-shadow: 0 4px 6px -1px rgba(59, 130, 246, 0.3);
|
||||
}
|
||||
|
||||
/* Status indicators */
|
||||
.status-dot {
|
||||
@apply w-2 h-2 rounded-full;
|
||||
animation: pulse-dot 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse-dot {
|
||||
0%, 100% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 0.5; transform: scale(1.2); }
|
||||
}
|
||||
|
||||
/* Code block styling */
|
||||
.code-block {
|
||||
@apply font-mono text-xs sm:text-sm bg-gray-900 text-gray-100 p-3 sm:p-4 rounded-xl;
|
||||
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Feature highlight */
|
||||
.feature-highlight {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.feature-highlight::before {
|
||||
content: '';
|
||||
@apply absolute -inset-2 bg-gradient-to-r from-blue-500/10 to-purple-500/10 rounded-xl -z-10;
|
||||
filter: blur(8px);
|
||||
}
|
||||
|
||||
/* Mobile-optimized touch targets */
|
||||
.touch-target {
|
||||
@apply min-h-[44px] min-w-[44px];
|
||||
}
|
||||
|
||||
/* Responsive table wrapper */
|
||||
.table-wrapper {
|
||||
@apply overflow-x-auto -mx-4 px-4 sm:mx-0 sm:px-0;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* Responsive grid gaps */
|
||||
.grid-responsive {
|
||||
@apply gap-4 sm:gap-5 lg:gap-6;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.animate-delay-100 {
|
||||
animation-delay: 0.1s;
|
||||
/* Animation delays */
|
||||
.animate-delay-100 { animation-delay: 0.1s; }
|
||||
.animate-delay-200 { animation-delay: 0.2s; }
|
||||
.animate-delay-300 { animation-delay: 0.3s; }
|
||||
.animate-delay-400 { animation-delay: 0.4s; }
|
||||
.animate-delay-500 { animation-delay: 0.5s; }
|
||||
.animate-delay-600 { animation-delay: 0.6s; }
|
||||
.animate-delay-700 { animation-delay: 0.7s; }
|
||||
.animate-delay-800 { animation-delay: 0.8s; }
|
||||
.animate-delay-1000 { animation-delay: 1s; }
|
||||
.animate-delay-2000 { animation-delay: 2s; }
|
||||
|
||||
/* Custom animations */
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.6s ease-out forwards;
|
||||
}
|
||||
.animate-delay-200 {
|
||||
animation-delay: 0.2s;
|
||||
|
||||
.animate-fade-in-up {
|
||||
animation: fadeInUp 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
.animate-delay-300 {
|
||||
animation-delay: 0.3s;
|
||||
|
||||
.animate-scale-in {
|
||||
animation: scaleIn 0.5s ease-out forwards;
|
||||
}
|
||||
.animate-delay-1000 {
|
||||
animation-delay: 1s;
|
||||
|
||||
.animate-slide-in-right {
|
||||
animation: slideInRight 0.5s ease-out forwards;
|
||||
}
|
||||
.animate-delay-2000 {
|
||||
animation-delay: 2s;
|
||||
|
||||
.animate-float {
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-pulse-slow {
|
||||
animation: pulse-slow 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-spin-slow {
|
||||
animation: spin 8s linear infinite;
|
||||
}
|
||||
|
||||
/* Hover lift effect */
|
||||
.hover-lift {
|
||||
@apply transition-all duration-300;
|
||||
}
|
||||
|
||||
.hover-lift:hover {
|
||||
@apply -translate-y-1;
|
||||
box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Text balance for better typography */
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
/* Backdrop blur utilities */
|
||||
.backdrop-blur-xs {
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
/* Safe area for notched phones */
|
||||
.safe-area-inset {
|
||||
padding-left: env(safe-area-inset-left);
|
||||
padding-right: env(safe-area-inset-right);
|
||||
}
|
||||
|
||||
.safe-area-bottom {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyframe animations */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
||||
33% { transform: translateY(-15px) rotate(1deg); }
|
||||
66% { transform: translateY(-8px) rotate(-1deg); }
|
||||
}
|
||||
|
||||
@keyframes pulse-slow {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.7; }
|
||||
}
|
||||
|
||||
/* Print styles */
|
||||
@media print {
|
||||
.glass {
|
||||
@apply bg-white border-gray-200;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.gradient-text {
|
||||
background: none !important;
|
||||
@apply text-gray-900;
|
||||
}
|
||||
|
||||
/* Hide non-essential elements when printing */
|
||||
nav, footer, .no-print {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Ensure good contrast for printed content */
|
||||
body {
|
||||
@apply text-black bg-white;
|
||||
}
|
||||
|
||||
/* Page breaks */
|
||||
.page-break {
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
/* Prevent orphans and widows */
|
||||
p, li {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile-specific optimizations */
|
||||
@media (max-width: 640px) {
|
||||
/* Larger touch targets on small screens */
|
||||
button,
|
||||
a {
|
||||
@apply min-h-[44px] min-w-[44px];
|
||||
}
|
||||
|
||||
/* Adjust card padding */
|
||||
.card {
|
||||
@apply p-4;
|
||||
}
|
||||
|
||||
/* Smaller hero text on mobile */
|
||||
.section-title {
|
||||
@apply text-2xl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet optimizations */
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.card {
|
||||
@apply p-6;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ultrawide screen optimizations */
|
||||
@media (min-width: 1920px) {
|
||||
/* Larger text for better readability at distance */
|
||||
body {
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
/* More spacious layouts */
|
||||
.section-padding {
|
||||
@apply py-28;
|
||||
}
|
||||
|
||||
/* Larger cards */
|
||||
.card {
|
||||
@apply p-10;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape mode on mobile */
|
||||
@media (max-height: 500px) and (orientation: landscape) {
|
||||
.section-padding {
|
||||
@apply py-8;
|
||||
}
|
||||
|
||||
.hero-min-height {
|
||||
min-height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +1,125 @@
|
||||
<script setup>
|
||||
const currentYear = new Date().getFullYear()
|
||||
|
||||
const quickLinks = [
|
||||
{ path: '/values', label: 'Core Values' },
|
||||
{ path: '/principles', label: '12 Principles' },
|
||||
{ path: '/framework', label: 'Framework' },
|
||||
{ path: '/reference', label: 'Quick Reference' },
|
||||
]
|
||||
|
||||
const resources = [
|
||||
{ path: '/assessment', label: 'Team Assessment' },
|
||||
{ path: '/anti-patterns', label: 'Anti-Patterns' },
|
||||
{ path: '/onboarding', label: 'Onboarding' },
|
||||
{ path: '/practices', label: 'Practices' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="bg-gray-50 dark:bg-gray-800/50 border-t border-gray-200 dark:border-gray-700 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-8 sm:py-12">
|
||||
<div class="grid sm:grid-cols-2 md:grid-cols-3 gap-8">
|
||||
<div class="sm:col-span-2 md:col-span-1">
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white font-bold text-lg">B</span>
|
||||
<footer class="relative bg-gray-50 dark:bg-gray-800/50 border-t border-gray-200 dark:border-gray-700 transition-colors duration-300">
|
||||
<!-- Top gradient line -->
|
||||
<div class="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-blue-500/50 to-transparent"></div>
|
||||
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 py-10 sm:py-12 lg:py-16">
|
||||
<!-- Main footer content - responsive grid -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-12">
|
||||
<!-- Brand -->
|
||||
<div class="sm:col-span-2 lg:col-span-1">
|
||||
<RouterLink to="/" class="flex items-center gap-3 group mb-4">
|
||||
<div
|
||||
class="w-10 h-10 sm:w-12 sm:h-12 rounded-xl bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center transition-all duration-300 group-hover:scale-110 group-hover:rotate-3 group-hover:shadow-glow-blue"
|
||||
>
|
||||
<span class="text-white font-bold text-lg sm:text-xl">B</span>
|
||||
</div>
|
||||
<span class="text-xl font-bold gradient-text">BEAT</span>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm leading-relaxed">
|
||||
<div>
|
||||
<span class="text-lg sm:text-xl font-bold gradient-text block">BEAT</span>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">v1.0</span>
|
||||
</div>
|
||||
</RouterLink>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm leading-relaxed mb-2">
|
||||
<strong>B</strong>alanced. <strong>E</strong>mpowered. <strong>A</strong>sync. <strong>T</strong>eams.
|
||||
</p>
|
||||
<p class="text-gray-500 dark:text-gray-500 text-sm mt-2">
|
||||
<p class="text-gray-500 dark:text-gray-500 text-sm">
|
||||
Built for how developers actually work.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Quick Links -->
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Quick Links</h3>
|
||||
<ul class="grid grid-cols-2 sm:grid-cols-1 gap-2 text-sm">
|
||||
<li>
|
||||
<RouterLink to="/values" class="text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors py-1 inline-block">
|
||||
Core Values
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink to="/principles" class="text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors py-1 inline-block">
|
||||
12 Principles
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink to="/framework" class="text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors py-1 inline-block">
|
||||
Framework
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink to="/reference" class="text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors py-1 inline-block">
|
||||
Quick Reference
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2 text-sm sm:text-base">
|
||||
<i class="fas fa-compass text-blue-500 text-sm"></i>
|
||||
Explore
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<li v-for="link in quickLinks" :key="link.path">
|
||||
<RouterLink
|
||||
:to="link.path"
|
||||
class="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 flex items-center gap-2 group"
|
||||
>
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 group-hover:bg-blue-500 transition-colors"></span>
|
||||
{{ link.label }}
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Resources -->
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Created By</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm mb-3">
|
||||
The BEAT Manifesto was created by <strong>Lukasz Raczylo</strong>.
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2 text-sm sm:text-base">
|
||||
<i class="fas fa-book text-purple-500 text-sm"></i>
|
||||
Resources
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<li v-for="link in resources" :key="link.path">
|
||||
<RouterLink
|
||||
:to="link.path"
|
||||
class="text-sm text-gray-600 dark:text-gray-400 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-200 flex items-center gap-2 group"
|
||||
>
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 group-hover:bg-purple-500 transition-colors"></span>
|
||||
{{ link.label }}
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Author -->
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2 text-sm sm:text-base">
|
||||
<i class="fas fa-user text-cyan-500 text-sm"></i>
|
||||
Created By
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm mb-4">
|
||||
The BEAT Manifesto was created by <strong class="text-gray-900 dark:text-gray-100">Lukasz Raczylo</strong>.
|
||||
</p>
|
||||
<div class="flex space-x-1">
|
||||
<div class="flex gap-2">
|
||||
<a
|
||||
href="https://github.com/lukaszraczylo"
|
||||
target="_blank"
|
||||
class="text-gray-500 hover:text-gray-900 dark:hover:text-gray-100 transition-colors p-2 min-w-[44px] min-h-[44px] flex items-center justify-center"
|
||||
class="w-10 h-10 rounded-lg bg-gray-100 dark:bg-gray-700 flex items-center justify-center text-gray-500 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-200 dark:hover:bg-gray-600 transition-all duration-300 hover:scale-110"
|
||||
aria-label="GitHub"
|
||||
>
|
||||
<i class="fab fa-github text-xl"></i>
|
||||
<i class="fab fa-github text-lg"></i>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.linkedin.com/in/raczylo/"
|
||||
target="_blank"
|
||||
class="text-gray-500 hover:text-blue-600 transition-colors p-2 min-w-[44px] min-h-[44px] flex items-center justify-center"
|
||||
class="w-10 h-10 rounded-lg bg-gray-100 dark:bg-gray-700 flex items-center justify-center text-gray-500 hover:text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/30 transition-all duration-300 hover:scale-110"
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<i class="fab fa-linkedin text-xl"></i>
|
||||
<i class="fab fa-linkedin text-lg"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 sm:mt-8 pt-6 sm:pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<!-- Bottom bar -->
|
||||
<div class="mt-8 sm:mt-10 lg:mt-12 pt-6 sm:pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="flex flex-col sm:flex-row justify-between items-center gap-3 sm:gap-4 text-center sm:text-left">
|
||||
<p class="text-gray-500 dark:text-gray-500 text-xs sm:text-sm">
|
||||
© {{ currentYear }} BEAT Manifesto by Lukasz Raczylo. Open for use and adaptation.
|
||||
© {{ currentYear }} BEAT Manifesto by Lukasz Raczylo
|
||||
</p>
|
||||
<p class="text-gray-400 dark:text-gray-600 text-xs">
|
||||
<p class="text-gray-400 dark:text-gray-600 text-xs italic">
|
||||
Attribution appreciated. Improvement welcomed. Dogma discouraged.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,99 +1,229 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import ThemeToggle from './ThemeToggle.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const mobileMenuOpen = ref(false)
|
||||
const scrolled = ref(false)
|
||||
|
||||
const navItems = [
|
||||
{ path: '/', label: 'Home' },
|
||||
{ path: '/values', label: 'Values' },
|
||||
{ path: '/principles', label: 'Principles' },
|
||||
{ path: '/framework', label: 'Framework' },
|
||||
{ path: '/practices', label: 'Practices' },
|
||||
{ path: '/onboarding', label: 'Onboarding' },
|
||||
{ path: '/anti-patterns', label: 'Anti-Patterns' },
|
||||
{ path: '/reference', label: 'Reference' },
|
||||
{ path: '/assessment', label: 'Assessment' }
|
||||
{ path: '/', label: 'Home', icon: 'fas fa-home' },
|
||||
{ path: '/values', label: 'Values', icon: 'fas fa-heart' },
|
||||
{ path: '/principles', label: 'Principles', icon: 'fas fa-compass' },
|
||||
{ path: '/framework', label: 'Framework', icon: 'fas fa-sitemap' },
|
||||
{ path: '/practices', label: 'Practices', icon: 'fas fa-cogs' },
|
||||
{ path: '/onboarding', label: 'Onboarding', icon: 'fas fa-user-plus' },
|
||||
{ path: '/anti-patterns', label: 'Anti-Patterns', icon: 'fas fa-exclamation-triangle' },
|
||||
{ path: '/reference', label: 'Reference', icon: 'fas fa-book' },
|
||||
{ path: '/assessment', label: 'Assessment', icon: 'fas fa-clipboard-check' }
|
||||
]
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
mobileMenuOpen.value = !mobileMenuOpen.value
|
||||
// Prevent body scroll when menu is open
|
||||
document.body.style.overflow = mobileMenuOpen.value ? 'hidden' : ''
|
||||
}
|
||||
|
||||
const closeMobileMenu = () => {
|
||||
mobileMenuOpen.value = false
|
||||
document.body.style.overflow = ''
|
||||
}
|
||||
|
||||
const handleScroll = () => {
|
||||
scrolled.value = window.scrollY > 20
|
||||
}
|
||||
|
||||
// Close mobile menu on route change
|
||||
watch(() => route.path, () => {
|
||||
closeMobileMenu()
|
||||
})
|
||||
|
||||
// Close mobile menu on escape key
|
||||
const handleEscape = (e) => {
|
||||
if (e.key === 'Escape' && mobileMenuOpen.value) {
|
||||
closeMobileMenu()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('scroll', handleScroll, { passive: true })
|
||||
window.addEventListener('keydown', handleEscape)
|
||||
handleScroll()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
window.removeEventListener('keydown', handleEscape)
|
||||
document.body.style.overflow = ''
|
||||
})
|
||||
|
||||
import { watch } from 'vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="fixed w-full glass shadow-modern z-50 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="flex justify-between h-16 items-center">
|
||||
<RouterLink to="/" class="flex items-center hover:opacity-80 transition-opacity duration-300 gap-2">
|
||||
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center">
|
||||
<span class="text-white font-bold text-lg">B</span>
|
||||
<nav
|
||||
class="fixed w-full z-50 transition-all duration-500"
|
||||
:class="[
|
||||
scrolled
|
||||
? 'bg-white/90 dark:bg-gray-900/90 backdrop-blur-xl shadow-modern'
|
||||
: 'bg-transparent'
|
||||
]"
|
||||
>
|
||||
<!-- Top gradient line -->
|
||||
<div
|
||||
class="h-1 bg-gradient-to-r from-blue-500 via-purple-500 to-cyan-500 transition-all duration-500"
|
||||
:class="scrolled ? 'opacity-100' : 'opacity-0'"
|
||||
></div>
|
||||
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
|
||||
<div class="flex justify-between h-14 sm:h-16 items-center">
|
||||
<!-- Logo -->
|
||||
<RouterLink
|
||||
to="/"
|
||||
class="flex items-center gap-2 sm:gap-3 group"
|
||||
>
|
||||
<div
|
||||
class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg sm:rounded-xl bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center transition-all duration-300 group-hover:scale-110 group-hover:rotate-3 group-hover:shadow-glow-blue"
|
||||
>
|
||||
<span class="text-white font-bold text-sm sm:text-lg">B</span>
|
||||
</div>
|
||||
<span class="text-xl font-bold gradient-text hidden sm:inline">BEAT</span>
|
||||
<span
|
||||
class="text-lg sm:text-xl font-bold gradient-text hidden sm:inline transition-all duration-300 group-hover:tracking-wide"
|
||||
>BEAT</span>
|
||||
</RouterLink>
|
||||
|
||||
<div class="hidden lg:flex space-x-4 xl:space-x-6">
|
||||
<!-- Desktop Navigation - hidden on mobile, shown on lg+ -->
|
||||
<div class="hidden lg:flex items-center space-x-1">
|
||||
<RouterLink
|
||||
v-for="item in navItems"
|
||||
v-for="(item, index) in navItems"
|
||||
:key="item.path"
|
||||
:to="item.path"
|
||||
class="nav-link text-sm"
|
||||
:class="{ 'text-blue-600 dark:text-blue-400': route.path === item.path }"
|
||||
class="relative px-2 xl:px-3 py-2 text-xs xl:text-sm font-medium rounded-lg transition-all duration-300"
|
||||
:class="[
|
||||
route.path === item.path
|
||||
? 'text-blue-600 dark:text-blue-400 bg-blue-50/50 dark:bg-blue-900/20'
|
||||
: 'text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100/50 dark:hover:bg-gray-800/50'
|
||||
]"
|
||||
:style="{ animationDelay: `${index * 50}ms` }"
|
||||
>
|
||||
{{ item.label }}
|
||||
<!-- Active indicator -->
|
||||
<span
|
||||
v-if="route.path === item.path"
|
||||
class="absolute -bottom-1 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-blue-500"
|
||||
></span>
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<!-- Right side actions -->
|
||||
<div class="flex items-center gap-1 sm:gap-2">
|
||||
<ThemeToggle />
|
||||
<a
|
||||
href="https://github.com/lukaszraczylo"
|
||||
target="_blank"
|
||||
class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 min-w-[44px] min-h-[44px] flex items-center justify-center transition-colors duration-200"
|
||||
class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 sm:p-2.5 rounded-lg min-w-[40px] min-h-[40px] flex items-center justify-center transition-all duration-300 hover:bg-gray-100/50 dark:hover:bg-gray-800/50 hover:scale-110"
|
||||
aria-label="View author on GitHub"
|
||||
>
|
||||
<i class="fab fa-github text-xl"></i>
|
||||
<i class="fab fa-github text-lg sm:text-xl"></i>
|
||||
</a>
|
||||
|
||||
<!-- Mobile menu button -->
|
||||
<button
|
||||
@click="toggleMobileMenu"
|
||||
class="lg:hidden text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 min-w-[44px] min-h-[44px] flex items-center justify-center"
|
||||
class="lg:hidden text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 p-2 sm:p-2.5 rounded-lg min-w-[44px] min-h-[44px] flex items-center justify-center transition-all duration-300 hover:bg-gray-100/50 dark:hover:bg-gray-800/50"
|
||||
aria-label="Toggle menu"
|
||||
aria-expanded="mobileMenuOpen"
|
||||
aria-controls="mobile-menu"
|
||||
>
|
||||
<i v-if="!mobileMenuOpen" class="fas fa-bars text-xl"></i>
|
||||
<i v-else class="fas fa-times text-xl"></i>
|
||||
<transition name="rotate" mode="out-in">
|
||||
<i v-if="!mobileMenuOpen" key="menu" class="fas fa-bars text-lg sm:text-xl"></i>
|
||||
<i v-else key="close" class="fas fa-times text-lg sm:text-xl"></i>
|
||||
</transition>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu Overlay -->
|
||||
<transition
|
||||
enter-active-class="transition duration-200 ease-out"
|
||||
enter-from-class="opacity-0 -translate-y-2"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
leave-active-class="transition duration-150 ease-in"
|
||||
leave-from-class="opacity-100 translate-y-0"
|
||||
leave-to-class="opacity-0 -translate-y-2"
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-from-class="opacity-0"
|
||||
enter-to-class="opacity-100"
|
||||
leave-active-class="transition duration-200 ease-in"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<div v-if="mobileMenuOpen" class="lg:hidden border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="px-4 py-3 space-y-1 bg-white dark:bg-gray-800">
|
||||
<div
|
||||
v-if="mobileMenuOpen"
|
||||
class="fixed inset-0 bg-black/50 backdrop-blur-sm lg:hidden z-40"
|
||||
@click="closeMobileMenu"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
</transition>
|
||||
|
||||
<!-- Mobile Menu Panel -->
|
||||
<transition
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-from-class="opacity-0 -translate-y-4"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
leave-active-class="transition duration-200 ease-in"
|
||||
leave-from-class="opacity-100 translate-y-0"
|
||||
leave-to-class="opacity-0 -translate-y-4"
|
||||
>
|
||||
<div
|
||||
v-if="mobileMenuOpen"
|
||||
id="mobile-menu"
|
||||
class="lg:hidden absolute top-full left-0 right-0 bg-white/95 dark:bg-gray-900/95 backdrop-blur-xl border-b border-gray-200 dark:border-gray-700 shadow-2xl max-h-[80vh] overflow-y-auto"
|
||||
>
|
||||
<div class="px-4 py-4 space-y-1 w-full max-w-7xl mx-auto">
|
||||
<RouterLink
|
||||
v-for="item in navItems"
|
||||
v-for="(item, index) in navItems"
|
||||
:key="item.path"
|
||||
:to="item.path"
|
||||
@click="closeMobileMenu"
|
||||
class="block px-3 py-3 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-700 rounded font-medium"
|
||||
:class="{ 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20': route.path === item.path }"
|
||||
class="flex items-center gap-3 px-4 py-3 rounded-xl font-medium transition-all duration-300"
|
||||
:class="[
|
||||
route.path === item.path
|
||||
? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20'
|
||||
: 'text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800'
|
||||
]"
|
||||
:style="{ animationDelay: `${index * 30}ms` }"
|
||||
>
|
||||
{{ item.label }}
|
||||
<div
|
||||
class="w-10 h-10 rounded-lg flex items-center justify-center"
|
||||
:class="route.path === item.path ? 'bg-blue-100 dark:bg-blue-800' : 'bg-gray-100 dark:bg-gray-800'"
|
||||
>
|
||||
<i :class="item.icon" class="text-sm"></i>
|
||||
</div>
|
||||
<span class="flex-1">{{ item.label }}</span>
|
||||
<i
|
||||
v-if="route.path === item.path"
|
||||
class="fas fa-chevron-right text-xs text-blue-500"
|
||||
></i>
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
<!-- Mobile menu footer -->
|
||||
<div class="px-4 py-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<p class="text-xs text-center text-gray-500 dark:text-gray-500">
|
||||
BEAT Manifesto v1.0
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.rotate-enter-active,
|
||||
.rotate-leave-active {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.rotate-enter-from,
|
||||
.rotate-leave-to {
|
||||
opacity: 0;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
const progress = ref(0)
|
||||
const showBackToTop = ref(false)
|
||||
|
||||
const calculateProgress = () => {
|
||||
const windowHeight = window.innerHeight
|
||||
const documentHeight = document.documentElement.scrollHeight - windowHeight
|
||||
const scrollTop = window.scrollY
|
||||
|
||||
if (documentHeight > 0) {
|
||||
progress.value = Math.min(100, Math.max(0, (scrollTop / documentHeight) * 100))
|
||||
}
|
||||
|
||||
showBackToTop.value = scrollTop > 500
|
||||
}
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('scroll', calculateProgress, { passive: true })
|
||||
calculateProgress()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', calculateProgress)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Reading Progress Bar -->
|
||||
<div class="fixed top-0 left-0 right-0 h-1 z-[60] bg-transparent">
|
||||
<div
|
||||
class="h-full bg-gradient-to-r from-blue-500 via-purple-500 to-cyan-500 transition-all duration-150 ease-out"
|
||||
:style="{ width: `${progress}%` }"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- Back to Top Button -->
|
||||
<transition
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-from-class="opacity-0 translate-y-4"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
leave-active-class="transition duration-200 ease-in"
|
||||
leave-from-class="opacity-100 translate-y-0"
|
||||
leave-to-class="opacity-0 translate-y-4"
|
||||
>
|
||||
<button
|
||||
v-if="showBackToTop"
|
||||
@click="scrollToTop"
|
||||
class="fixed bottom-8 right-8 w-12 h-12 rounded-full bg-gradient-to-br from-blue-600 to-purple-600 text-white shadow-lg hover:shadow-xl hover:scale-110 transition-all duration-300 z-50 flex items-center justify-center group"
|
||||
aria-label="Back to top"
|
||||
>
|
||||
<i class="fas fa-arrow-up group-hover:-translate-y-0.5 transition-transform"></i>
|
||||
</button>
|
||||
</transition>
|
||||
</template>
|
||||
@@ -7,23 +7,30 @@ defineProps({
|
||||
gradient: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
glow: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="glass p-6 rounded-xl transition-all duration-300"
|
||||
:class="{ 'hover:shadow-lg hover:-translate-y-1': hover }"
|
||||
class="card"
|
||||
:class="{
|
||||
'hover:-translate-y-2': hover,
|
||||
[`shadow-glow-${glow}`]: glow
|
||||
}"
|
||||
>
|
||||
<div v-if="gradient" class="flex items-start gap-4">
|
||||
<div v-if="gradient" class="flex items-start gap-5">
|
||||
<div
|
||||
class="icon-box"
|
||||
class="icon-box w-14 h-14 rounded-2xl"
|
||||
:class="gradient"
|
||||
>
|
||||
<slot name="icon"></slot>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex-1 min-w-0">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Copy'
|
||||
},
|
||||
copiedLabel: {
|
||||
type: String,
|
||||
default: 'Copied!'
|
||||
}
|
||||
})
|
||||
|
||||
const copied = ref(false)
|
||||
const error = ref(false)
|
||||
|
||||
const copyToClipboard = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(props.text)
|
||||
copied.value = true
|
||||
error.value = false
|
||||
|
||||
setTimeout(() => {
|
||||
copied.value = false
|
||||
}, 2000)
|
||||
} catch (err) {
|
||||
error.value = true
|
||||
setTimeout(() => {
|
||||
error.value = false
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
@click="copyToClipboard"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200"
|
||||
:class="[
|
||||
copied
|
||||
? 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300'
|
||||
: error
|
||||
? 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300'
|
||||
: 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700'
|
||||
]"
|
||||
:title="copied ? copiedLabel : label"
|
||||
>
|
||||
<transition name="scale" mode="out-in">
|
||||
<i v-if="copied" key="check" class="fas fa-check"></i>
|
||||
<i v-else-if="error" key="error" class="fas fa-exclamation-circle"></i>
|
||||
<i v-else key="copy" class="fas fa-copy"></i>
|
||||
</transition>
|
||||
<span v-if="copied">{{ copiedLabel }}</span>
|
||||
<span v-else-if="error">Failed</span>
|
||||
<span v-else>{{ label }}</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.scale-enter-active,
|
||||
.scale-leave-active {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.scale-enter-from,
|
||||
.scale-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
</style>
|
||||
@@ -15,24 +15,39 @@ defineProps({
|
||||
gradient: {
|
||||
type: String,
|
||||
default: 'from-blue-500 to-blue-600'
|
||||
},
|
||||
href: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300">
|
||||
<div class="flex items-start gap-4">
|
||||
<component
|
||||
:is="href ? 'a' : 'div'"
|
||||
:href="href"
|
||||
class="group card p-6 cursor-pointer"
|
||||
:class="{ 'hover:-translate-y-2': href }"
|
||||
>
|
||||
<div class="flex items-start gap-5">
|
||||
<div
|
||||
class="w-12 h-12 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300"
|
||||
class="w-14 h-14 rounded-2xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 transition-all duration-300 group-hover:scale-110 group-hover:rotate-3"
|
||||
:class="gradient"
|
||||
>
|
||||
<i :class="icon" class="text-white"></i>
|
||||
<i :class="icon" class="text-white text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">{{ title }}</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">{{ description }}</p>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="font-semibold text-lg text-gray-900 dark:text-gray-100 mb-2 flex items-center gap-2">
|
||||
{{ title }}
|
||||
<i
|
||||
v-if="href"
|
||||
class="fas fa-arrow-right text-sm opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-300 text-blue-500"
|
||||
></i>
|
||||
</h3>
|
||||
<p v-if="description" class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">{{ description }}</p>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
delay: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'up', // 'up', 'down', 'left', 'right'
|
||||
validator: (value) => ['up', 'down', 'left', 'right'].includes(value)
|
||||
},
|
||||
distance: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 600
|
||||
},
|
||||
once: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
threshold: {
|
||||
type: Number,
|
||||
default: 0.1
|
||||
}
|
||||
})
|
||||
|
||||
const elementRef = ref(null)
|
||||
const isVisible = ref(false)
|
||||
|
||||
const getInitialTransform = () => {
|
||||
switch (props.direction) {
|
||||
case 'up': return `translateY(${props.distance}px)`
|
||||
case 'down': return `translateY(-${props.distance}px)`
|
||||
case 'left': return `translateX(${props.distance}px)`
|
||||
case 'right': return `translateX(-${props.distance}px)`
|
||||
default: return `translateY(${props.distance}px)`
|
||||
}
|
||||
}
|
||||
|
||||
let observer = null
|
||||
|
||||
onMounted(() => {
|
||||
if (!elementRef.value) return
|
||||
|
||||
observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setTimeout(() => {
|
||||
isVisible.value = true
|
||||
}, props.delay)
|
||||
|
||||
if (props.once && observer) {
|
||||
observer.unobserve(entry.target)
|
||||
}
|
||||
} else if (!props.once) {
|
||||
isVisible.value = false
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
threshold: props.threshold,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
}
|
||||
)
|
||||
|
||||
observer.observe(elementRef.value)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (observer && elementRef.value) {
|
||||
observer.unobserve(elementRef.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="elementRef"
|
||||
class="scroll-reveal"
|
||||
:class="{ 'is-visible': isVisible }"
|
||||
:style="{
|
||||
opacity: isVisible ? 1 : 0,
|
||||
transform: isVisible ? 'translate(0)' : getInitialTransform(),
|
||||
transition: `opacity ${duration}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${duration}ms cubic-bezier(0.4, 0, 0.2, 1)`
|
||||
}"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.scroll-reveal {
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
</style>
|
||||
@@ -16,36 +16,38 @@ defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="glass rounded-xl overflow-hidden">
|
||||
<div v-if="title" class="px-4 sm:px-6 py-3 sm:py-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="glass rounded-2xl overflow-hidden">
|
||||
<div v-if="title" class="px-4 sm:px-6 py-3 sm:py-4 border-b border-gray-200 dark:border-gray-700 bg-gray-50/50 dark:bg-gray-800/50">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 text-sm sm:text-base">{{ title }}</h3>
|
||||
</div>
|
||||
<!-- Mobile card view -->
|
||||
|
||||
<!-- Mobile card view - shown on small screens -->
|
||||
<div class="block sm:hidden">
|
||||
<div
|
||||
v-for="(row, rowIndex) in rows"
|
||||
:key="rowIndex"
|
||||
class="p-4 border-b border-gray-200 dark:border-gray-700 last:border-b-0"
|
||||
class="p-4 border-b border-gray-200 dark:border-gray-700 last:border-b-0 hover:bg-gray-50/50 dark:hover:bg-gray-800/30 transition-colors"
|
||||
>
|
||||
<div
|
||||
v-for="(cell, cellIndex) in row"
|
||||
:key="cellIndex"
|
||||
class="py-1"
|
||||
class="py-1.5"
|
||||
>
|
||||
<span class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase">{{ headers[cellIndex] }}: </span>
|
||||
<span class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">{{ headers[cellIndex] }}: </span>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300" v-html="cell"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Desktop table view -->
|
||||
|
||||
<!-- Desktop table view - hidden on mobile, shown on sm+ -->
|
||||
<div class="hidden sm:block overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
<tr class="bg-gray-50 dark:bg-gray-800/50">
|
||||
<tr class="bg-gray-50/80 dark:bg-gray-800/80">
|
||||
<th
|
||||
v-for="header in headers"
|
||||
:key="header"
|
||||
class="px-4 md:px-6 py-3 text-left text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase tracking-wider"
|
||||
class="px-4 md:px-6 py-3 text-left text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase tracking-wider whitespace-nowrap"
|
||||
>
|
||||
{{ header }}
|
||||
</th>
|
||||
@@ -55,14 +57,14 @@ defineProps({
|
||||
<tr
|
||||
v-for="(row, index) in rows"
|
||||
:key="index"
|
||||
class="hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors"
|
||||
class="hover:bg-gray-50/50 dark:hover:bg-gray-800/30 transition-all duration-200 group"
|
||||
>
|
||||
<td
|
||||
v-for="(cell, cellIndex) in row"
|
||||
:key="cellIndex"
|
||||
class="px-4 md:px-6 py-3 md:py-4 text-sm text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
<span v-html="cell"></span>
|
||||
<span v-html="cell" class="group-hover:text-gray-900 dark:group-hover:text-gray-100 transition-colors"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
position: {
|
||||
type: String,
|
||||
default: 'top',
|
||||
validator: (value) => ['top', 'bottom', 'left', 'right'].includes(value)
|
||||
}
|
||||
})
|
||||
|
||||
const show = ref(false)
|
||||
|
||||
const positionClasses = {
|
||||
top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
|
||||
bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
|
||||
left: 'right-full top-1/2 -translate-y-1/2 mr-2',
|
||||
right: 'left-full top-1/2 -translate-y-1/2 ml-2'
|
||||
}
|
||||
|
||||
const arrowClasses = {
|
||||
top: 'top-full left-1/2 -translate-x-1/2 -mt-1 border-l-transparent border-r-transparent border-b-transparent',
|
||||
bottom: 'bottom-full left-1/2 -translate-x-1/2 -mb-1 border-l-transparent border-r-transparent border-t-transparent',
|
||||
left: 'left-full top-1/2 -translate-y-1/2 -ml-1 border-t-transparent border-b-transparent border-r-transparent',
|
||||
right: 'right-full top-1/2 -translate-y-1/2 -mr-1 border-t-transparent border-b-transparent border-l-transparent'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="relative inline-block"
|
||||
@mouseenter="show = true"
|
||||
@mouseleave="show = false"
|
||||
@focus="show = true"
|
||||
@blur="show = false"
|
||||
>
|
||||
<slot></slot>
|
||||
|
||||
<transition
|
||||
enter-active-class="transition duration-200 ease-out"
|
||||
enter-from-class="opacity-0 scale-95"
|
||||
enter-to-class="opacity-100 scale-100"
|
||||
leave-active-class="transition duration-150 ease-in"
|
||||
leave-from-class="opacity-100 scale-100"
|
||||
leave-to-class="opacity-0 scale-95"
|
||||
>
|
||||
<div
|
||||
v-if="show"
|
||||
:class="[
|
||||
'absolute z-50 px-3 py-2 text-sm font-medium text-white bg-gray-900 dark:bg-gray-700 rounded-lg shadow-lg whitespace-nowrap pointer-events-none',
|
||||
positionClasses[position]
|
||||
]"
|
||||
role="tooltip"
|
||||
>
|
||||
{{ text }}
|
||||
<div
|
||||
:class="[
|
||||
'absolute w-2 h-2 bg-gray-900 dark:bg-gray-700 rotate-45 border-4 border-gray-900 dark:border-gray-700',
|
||||
arrowClasses[position]
|
||||
]"
|
||||
></div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
@@ -35,92 +35,104 @@ const warningSigns = [
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-red-50 via-orange-50 to-amber-50 dark:from-gray-900 dark:via-red-900/10 dark:to-orange-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-red-300 dark:bg-red-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-orange-300 dark:bg-orange-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-32 sm:pt-40 pb-16 sm:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-red-50 via-orange-50 to-amber-50 dark:from-gray-900 dark:via-red-950/20 dark:to-orange-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-96 h-96 bg-red-400/20 dark:bg-red-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-80 h-80 bg-orange-400/20 dark:bg-orange-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-red-500 to-orange-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-exclamation-triangle text-white text-2xl"></i>
|
||||
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300 text-sm font-medium mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Watch Out
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Anti-Patterns</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-red-500 to-orange-500 flex items-center justify-center mx-auto mb-8 animate-fade-in-up animate-delay-100">
|
||||
<i class="fas fa-exclamation-triangle text-white text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">Anti-Patterns</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
Common ways teams fail at BEAT—and how to fix them.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Anti-Patterns -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-red-500 to-red-600 flex items-center justify-center">
|
||||
<i class="fas fa-cogs text-white"></i>
|
||||
<div class="flex items-center gap-4 mb-10">
|
||||
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-red-500 to-red-600 flex items-center justify-center shadow-lg">
|
||||
<i class="fas fa-cogs text-white text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">Process Anti-Patterns</h2>
|
||||
<p class="text-gray-500 dark:text-gray-400">Issues in how work flows</p>
|
||||
</div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">Process Anti-Patterns</h2>
|
||||
</div>
|
||||
<TableCard :headers="processHeaders" :rows="processRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- People Anti-Patterns -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center">
|
||||
<i class="fas fa-users text-white"></i>
|
||||
<div class="flex items-center gap-4 mb-10">
|
||||
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center shadow-lg">
|
||||
<i class="fas fa-users text-white text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">People Anti-Patterns</h2>
|
||||
<p class="text-gray-500 dark:text-gray-400">Issues in team dynamics</p>
|
||||
</div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">People Anti-Patterns</h2>
|
||||
</div>
|
||||
<TableCard :headers="peopleHeaders" :rows="peopleRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Organizational Anti-Patterns -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-purple-500 to-purple-600 flex items-center justify-center">
|
||||
<i class="fas fa-building text-white"></i>
|
||||
<div class="flex items-center gap-4 mb-10">
|
||||
<div class="w-14 h-14 rounded-2xl bg-gradient-to-br from-purple-500 to-purple-600 flex items-center justify-center shadow-lg">
|
||||
<i class="fas fa-building text-white text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">Organizational Anti-Patterns</h2>
|
||||
<p class="text-gray-500 dark:text-gray-400">Issues from outside the team</p>
|
||||
</div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">Organizational Anti-Patterns</h2>
|
||||
</div>
|
||||
<TableCard :headers="orgHeaders" :rows="orgRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Warning Signs -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">When BEAT Isn't Working</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">When BEAT Isn't Working</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Signs the methodology isn't serving the team:</p>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-8">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-5 mb-10">
|
||||
<div
|
||||
v-for="sign in warningSigns"
|
||||
v-for="(sign, index) in warningSigns"
|
||||
:key="sign"
|
||||
class="glass p-4 rounded-xl border-l-4 border-red-500"
|
||||
class="card p-5 border-l-4 border-red-500"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<i class="fas fa-exclamation-circle text-red-500"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300 text-sm">{{ sign }}</span>
|
||||
<i class="fas fa-exclamation-circle text-red-500 text-lg"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ sign }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-blue-500 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-lightbulb text-white"></i>
|
||||
<div class="card p-8 bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800">
|
||||
<div class="flex items-start gap-5">
|
||||
<div class="w-14 h-14 rounded-xl bg-blue-500 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-lightbulb text-white text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-semibold text-blue-800 dark:text-blue-200 mb-2">Response</h4>
|
||||
<p class="text-blue-700 dark:text-blue-300 text-sm">
|
||||
Discuss in Beat Close. Adapt the framework. BEAT is a tool, not a religion. If it's not working, change it or choose something else.
|
||||
</p>
|
||||
<h4 class="font-bold text-blue-800 dark:text-blue-200 mb-2 text-lg">Response</h4>
|
||||
<p class="text-blue-700 dark:text-blue-300">Discuss in Beat Close. Adapt the framework. BEAT is a tool, not a religion. If it's not working, change it or choose something else.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,60 +140,66 @@ const warningSigns = [
|
||||
</section>
|
||||
|
||||
<!-- Where BEAT Fits -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Where BEAT Fits</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Where BEAT Fits</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Know your context. Adapt accordingly.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-6">
|
||||
<div class="glass p-6 rounded-xl border-t-4 border-green-500">
|
||||
<h3 class="font-bold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
||||
<i class="fas fa-check-circle text-green-500"></i>
|
||||
<div class="card p-8 border-t-4 border-emerald-500">
|
||||
<h3 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-xl bg-emerald-100 dark:bg-emerald-900/30 flex items-center justify-center">
|
||||
<i class="fas fa-check-circle text-emerald-500 text-xl"></i>
|
||||
</div>
|
||||
Works Best For
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<ul class="space-y-3">
|
||||
<li
|
||||
v-for="item in whereItFits.worksFor"
|
||||
:key="item"
|
||||
class="text-sm text-gray-600 dark:text-gray-400 flex items-center gap-2"
|
||||
class="text-gray-600 dark:text-gray-400 flex items-center gap-3 p-3 rounded-xl bg-emerald-50 dark:bg-emerald-900/20"
|
||||
>
|
||||
<i class="fas fa-check text-green-500 text-xs"></i>
|
||||
<i class="fas fa-check text-emerald-500"></i>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl border-t-4 border-red-500">
|
||||
<h3 class="font-bold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
||||
<i class="fas fa-times-circle text-red-500"></i>
|
||||
<div class="card p-8 border-t-4 border-red-500">
|
||||
<h3 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-xl bg-red-100 dark:bg-red-900/30 flex items-center justify-center">
|
||||
<i class="fas fa-times-circle text-red-500 text-xl"></i>
|
||||
</div>
|
||||
Fits Poorly For
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<ul class="space-y-3">
|
||||
<li
|
||||
v-for="item in whereItFits.fitsPoorly"
|
||||
:key="item"
|
||||
class="text-sm text-gray-600 dark:text-gray-400 flex items-center gap-2"
|
||||
class="text-gray-600 dark:text-gray-400 flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20"
|
||||
>
|
||||
<i class="fas fa-times text-red-500 text-xs"></i>
|
||||
<i class="fas fa-times text-red-500"></i>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl border-t-4 border-amber-500">
|
||||
<h3 class="font-bold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
||||
<i class="fas fa-sliders-h text-amber-500"></i>
|
||||
<div class="card p-8 border-t-4 border-amber-500">
|
||||
<h3 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-xl bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center">
|
||||
<i class="fas fa-sliders-h text-amber-500 text-xl"></i>
|
||||
</div>
|
||||
Can Adapt For
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<ul class="space-y-3">
|
||||
<li
|
||||
v-for="item in whereItFits.canAdapt"
|
||||
:key="item"
|
||||
class="text-sm text-gray-600 dark:text-gray-400 flex items-center gap-2"
|
||||
class="text-gray-600 dark:text-gray-400 flex items-center gap-3 p-3 rounded-xl bg-amber-50 dark:bg-amber-900/20"
|
||||
>
|
||||
<i class="fas fa-adjust text-amber-500 text-xs"></i>
|
||||
<i class="fas fa-adjust text-amber-500"></i>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ref, computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { assessmentCategories, assessmentQuestions, beatRecommendations, overallAssessment } from '@/data/assessment'
|
||||
|
||||
const currentStep = ref(0) // 0 = intro, 1-12 = questions, 13 = results
|
||||
const currentStep = ref(0)
|
||||
const answers = ref({})
|
||||
const showResults = ref(false)
|
||||
|
||||
@@ -43,7 +43,6 @@ const restartAssessment = () => {
|
||||
showResults.value = false
|
||||
}
|
||||
|
||||
// Calculate scores
|
||||
const categoryScores = computed(() => {
|
||||
const scores = {}
|
||||
assessmentCategories.forEach(cat => {
|
||||
@@ -94,11 +93,11 @@ const colorClasses = {
|
||||
progress: 'bg-purple-500'
|
||||
},
|
||||
green: {
|
||||
bg: 'bg-green-50 dark:bg-green-900/20',
|
||||
border: 'border-green-200 dark:border-green-800',
|
||||
text: 'text-green-600 dark:text-green-400',
|
||||
gradient: 'from-green-500 to-green-600',
|
||||
progress: 'bg-green-500'
|
||||
bg: 'bg-emerald-50 dark:bg-emerald-900/20',
|
||||
border: 'border-emerald-200 dark:border-emerald-800',
|
||||
text: 'text-emerald-600 dark:text-emerald-400',
|
||||
gradient: 'from-emerald-500 to-emerald-600',
|
||||
progress: 'bg-emerald-500'
|
||||
},
|
||||
amber: {
|
||||
bg: 'bg-amber-50 dark:bg-amber-900/20',
|
||||
@@ -120,50 +119,65 @@ const colorClasses = {
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50 dark:from-gray-900 dark:via-indigo-900/10 dark:to-purple-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-indigo-300 dark:bg-indigo-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-purple-300 dark:bg-purple-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-28 sm:pt-32 lg:pt-40 pb-10 sm:pb-12 lg:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50 dark:from-gray-900 dark:via-indigo-950/20 dark:to-purple-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-72 h-72 sm:w-96 sm:h-96 bg-indigo-400/20 dark:bg-indigo-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-64 h-64 sm:w-80 sm:h-80 bg-purple-400/20 dark:bg-purple-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-clipboard-check text-white text-2xl"></i>
|
||||
<div class="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 text-center">
|
||||
<div class="inline-flex items-center gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-indigo-100 dark:bg-indigo-900/30 text-indigo-700 dark:text-indigo-300 text-xs sm:text-sm font-medium mb-4 sm:mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-clipboard-check"></i>
|
||||
Self-Assessment
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Team Assessment</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-16 h-16 sm:w-20 sm:h-20 rounded-xl sm:rounded-2xl bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center mx-auto mb-6 sm:mb-8 animate-fade-in-up animate-delay-100">
|
||||
<i class="fas fa-clipboard-check text-white text-2xl sm:text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">Team Assessment</h1>
|
||||
<p class="section-subtitle max-w-2xl lg:max-w-3xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
Discover how BEAT can help your team deliver better and faster.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Intro Screen -->
|
||||
<section v-if="currentStep === 0" class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<div class="glass p-6 sm:p-8 rounded-2xl text-center">
|
||||
<div class="w-20 h-20 rounded-full bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center mx-auto mb-6">
|
||||
<i class="fas fa-tasks text-white text-3xl"></i>
|
||||
<section v-if="currentStep === 0" class="py-8 sm:py-10 lg:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="w-full max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="card p-6 sm:p-8 lg:p-10 text-center">
|
||||
<div class="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center mx-auto mb-6 sm:mb-8 shadow-glow-purple">
|
||||
<i class="fas fa-tasks text-white text-2xl sm:text-4xl"></i>
|
||||
</div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<h2 class="text-xl sm:text-2xl lg:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">
|
||||
How BEAT-Ready is Your Team?
|
||||
</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6 leading-relaxed">
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6 sm:mb-8 leading-relaxed text-sm sm:text-base">
|
||||
Answer 12 quick questions about your current practices. We'll analyze your responses and show you specifically how BEAT principles can help your team.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-8">
|
||||
<div v-for="cat in assessmentCategories" :key="cat.id" class="p-3 rounded-lg" :class="colorClasses[cat.color].bg">
|
||||
<i :class="[cat.icon, colorClasses[cat.color].text]" class="text-xl mb-2"></i>
|
||||
<div class="text-xs text-gray-600 dark:text-gray-400">{{ cat.title }}</div>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4 mb-6 sm:mb-8">
|
||||
<div v-for="cat in assessmentCategories" :key="cat.id" class="p-3 sm:p-4 rounded-xl" :class="colorClasses[cat.color].bg">
|
||||
<div
|
||||
class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg sm:rounded-xl bg-gradient-to-br flex items-center justify-center mx-auto mb-2 sm:mb-3"
|
||||
:class="cat.gradient"
|
||||
>
|
||||
<i :class="cat.icon" class="text-white text-base sm:text-xl"></i>
|
||||
</div>
|
||||
<div class="text-xs sm:text-sm text-gray-700 dark:text-gray-300 font-medium">{{ cat.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center justify-center gap-3 sm:gap-4 text-xs sm:text-sm text-gray-500 dark:text-gray-500 mb-6">
|
||||
<span><i class="fas fa-clock mr-1"></i> 3-5 min</span>
|
||||
<span><i class="fas fa-shield-alt mr-1"></i> Anonymous</span>
|
||||
<span><i class="fas fa-chart-bar mr-1"></i> Instant results</span>
|
||||
<div class="flex flex-wrap items-center justify-center gap-2 sm:gap-4 text-xs sm:text-sm text-gray-500 dark:text-gray-500 mb-6 sm:mb-8">
|
||||
<span class="flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-gray-100 dark:bg-gray-800">
|
||||
<i class="fas fa-clock"></i> 3-5 min
|
||||
</span>
|
||||
<span class="flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-gray-100 dark:bg-gray-800">
|
||||
<i class="fas fa-shield-alt"></i> Anonymous
|
||||
</span>
|
||||
<span class="flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-gray-100 dark:bg-gray-800">
|
||||
<i class="fas fa-chart-bar"></i> Instant results
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button @click="startAssessment" class="btn-primary w-full sm:w-auto">
|
||||
<button @click="startAssessment" class="btn-primary text-sm sm:text-base px-8 sm:px-10 py-3 sm:py-4">
|
||||
<i class="fas fa-play mr-2"></i>
|
||||
Start Assessment
|
||||
</button>
|
||||
@@ -172,15 +186,15 @@ const colorClasses = {
|
||||
</section>
|
||||
|
||||
<!-- Question Screen -->
|
||||
<section v-else-if="!showResults" class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<section v-else-if="!showResults" class="py-6 sm:py-8 lg:py-10 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="w-full max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<!-- Progress Bar -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between text-sm text-gray-600 dark:text-gray-400 mb-2">
|
||||
<span>Question {{ currentStep }} of {{ totalQuestions }}</span>
|
||||
<div class="mb-5 sm:mb-6">
|
||||
<div class="flex items-center justify-between text-xs sm:text-sm text-gray-600 dark:text-gray-400 mb-2">
|
||||
<span class="font-medium">Question {{ currentStep }} of {{ totalQuestions }}</span>
|
||||
<span>{{ progress }}% complete</span>
|
||||
</div>
|
||||
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div class="h-2.5 sm:h-3 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full bg-gradient-to-r from-indigo-500 to-purple-500 transition-all duration-500 ease-out rounded-full"
|
||||
:style="{ width: `${progress}%` }"
|
||||
@@ -189,65 +203,65 @@ const colorClasses = {
|
||||
</div>
|
||||
|
||||
<!-- Category Badge -->
|
||||
<div class="mb-4">
|
||||
<div class="mb-4 sm:mb-6">
|
||||
<span
|
||||
class="inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs font-medium"
|
||||
class="inline-flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full text-xs sm:text-sm font-medium"
|
||||
:class="[colorClasses[assessmentCategories.find(c => c.id === currentQuestion.category)?.color || 'blue'].bg, colorClasses[assessmentCategories.find(c => c.id === currentQuestion.category)?.color || 'blue'].text]"
|
||||
>
|
||||
<i :class="assessmentCategories.find(c => c.id === currentQuestion.category)?.icon"></i>
|
||||
<i :class="assessmentCategories.find(c => c.id === currentQuestion.category)?.icon" class="text-xs"></i>
|
||||
{{ assessmentCategories.find(c => c.id === currentQuestion.category)?.title }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Question Card -->
|
||||
<div class="glass p-6 sm:p-8 rounded-2xl">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-6">
|
||||
<div class="card p-5 sm:p-6 lg:p-8">
|
||||
<h2 class="text-base sm:text-lg lg:text-xl font-bold text-gray-900 dark:text-gray-100 mb-5 sm:mb-6">
|
||||
{{ currentQuestion.question }}
|
||||
</h2>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div class="space-y-2.5 sm:space-y-3">
|
||||
<button
|
||||
v-for="option in currentQuestion.options"
|
||||
:key="option.value"
|
||||
@click="selectAnswer(currentQuestion.id, option.value)"
|
||||
class="w-full p-4 rounded-xl border-2 text-left transition-all duration-200 hover:shadow-md min-h-[60px]"
|
||||
class="w-full p-3 sm:p-4 lg:p-5 rounded-xl border-2 text-left transition-all duration-200 hover:shadow-md min-h-[64px] sm:min-h-[72px] group"
|
||||
:class="[
|
||||
answers[currentQuestion.id] === option.value
|
||||
? 'border-indigo-500 bg-indigo-50 dark:bg-indigo-900/20'
|
||||
: 'border-gray-200 dark:border-gray-700 hover:border-indigo-300 dark:hover:border-indigo-600'
|
||||
]"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex items-start gap-3 sm:gap-4">
|
||||
<div
|
||||
class="w-6 h-6 rounded-full border-2 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
class="w-5 h-5 sm:w-6 sm:h-6 rounded-full border-2 flex items-center justify-center flex-shrink-0 mt-0.5 transition-colors"
|
||||
:class="[
|
||||
answers[currentQuestion.id] === option.value
|
||||
? 'border-indigo-500 bg-indigo-500'
|
||||
: 'border-gray-300 dark:border-gray-600'
|
||||
: 'border-gray-300 dark:border-gray-600 group-hover:border-indigo-400'
|
||||
]"
|
||||
>
|
||||
<i v-if="answers[currentQuestion.id] === option.value" class="fas fa-check text-white text-xs"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-gray-900 dark:text-gray-100">{{ option.label }}</div>
|
||||
<div class="text-sm text-gray-500 dark:text-gray-500">{{ option.description }}</div>
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100 mb-0.5 sm:mb-1 text-sm sm:text-base">{{ option.label }}</div>
|
||||
<div class="text-xs sm:text-sm text-gray-500 dark:text-gray-500">{{ option.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between mt-6 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center justify-between mt-5 sm:mt-6 pt-4 sm:pt-5 border-t border-gray-200 dark:border-gray-700">
|
||||
<button
|
||||
v-if="currentStep > 1"
|
||||
@click="goBack"
|
||||
class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors min-w-[44px] min-h-[44px] px-3 sm:px-4 py-2 flex items-center justify-center"
|
||||
class="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors px-3 sm:px-4 py-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-sm sm:text-base"
|
||||
>
|
||||
<i class="fas fa-arrow-left mr-2"></i>
|
||||
<span class="hidden sm:inline">Back</span>
|
||||
Back
|
||||
</button>
|
||||
<div v-else></div>
|
||||
|
||||
<div class="hidden sm:flex items-center gap-1">
|
||||
<div class="hidden sm:flex items-center gap-1.5">
|
||||
<div
|
||||
v-for="i in totalQuestions"
|
||||
:key="i"
|
||||
@@ -259,7 +273,7 @@ const colorClasses = {
|
||||
]"
|
||||
></div>
|
||||
</div>
|
||||
<div class="sm:hidden text-sm text-gray-500 dark:text-gray-500">
|
||||
<div class="sm:hidden text-xs sm:text-sm text-gray-500 dark:text-gray-500">
|
||||
{{ currentStep }}/{{ totalQuestions }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -268,59 +282,62 @@ const colorClasses = {
|
||||
</section>
|
||||
|
||||
<!-- Results Screen -->
|
||||
<section v-else class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<section v-else class="py-6 sm:py-8 lg:py-10 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="w-full max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<!-- Overall Score -->
|
||||
<div class="glass p-6 sm:p-8 rounded-2xl mb-8 text-center">
|
||||
<div class="card p-6 sm:p-8 lg:p-10 mb-6 sm:mb-8 text-center">
|
||||
<div
|
||||
class="w-20 h-20 rounded-full flex items-center justify-center mx-auto mb-4"
|
||||
class="w-16 h-16 sm:w-20 sm:h-20 lg:w-24 lg:h-24 rounded-full flex items-center justify-center mx-auto mb-4 sm:mb-6"
|
||||
:class="colorClasses[overallLevel.color].bg"
|
||||
>
|
||||
<i :class="[overallLevel.icon, colorClasses[overallLevel.color].text]" class="text-3xl"></i>
|
||||
<i :class="[overallLevel.icon, colorClasses[overallLevel.color].text]" class="text-2xl sm:text-3xl lg:text-4xl"></i>
|
||||
</div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2">
|
||||
<h2 class="text-lg sm:text-xl lg:text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2">
|
||||
{{ overallLevel.title }}
|
||||
</h2>
|
||||
<div class="text-3xl sm:text-4xl font-bold gradient-text mb-4">
|
||||
<div class="text-2xl sm:text-3xl lg:text-4xl font-bold gradient-text mb-3 sm:mb-4">
|
||||
{{ totalScore }} / 48
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-400 max-w-xl mx-auto mb-4">
|
||||
<p class="text-gray-600 dark:text-gray-400 max-w-xl mx-auto mb-3 sm:mb-4 text-sm sm:text-base">
|
||||
{{ overallLevel.description }}
|
||||
</p>
|
||||
<div
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-lg"
|
||||
class="inline-flex items-center gap-2 px-4 sm:px-5 py-2 sm:py-2.5 rounded-xl"
|
||||
:class="[colorClasses[overallLevel.color].bg, colorClasses[overallLevel.color].border]"
|
||||
>
|
||||
<i class="fas fa-lightbulb" :class="colorClasses[overallLevel.color].text"></i>
|
||||
<span class="text-sm font-medium" :class="colorClasses[overallLevel.color].text">{{ overallLevel.callToAction }}</span>
|
||||
<span class="font-medium text-sm sm:text-base" :class="colorClasses[overallLevel.color].text">{{ overallLevel.callToAction }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Breakdown -->
|
||||
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Category Breakdown</h3>
|
||||
<div class="grid sm:grid-cols-2 gap-4 mb-8">
|
||||
<h3 class="text-base sm:text-lg lg:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4 sm:mb-5 flex items-center gap-2 sm:gap-3">
|
||||
<div class="w-0.5 sm:w-1 h-5 sm:h-6 rounded-full bg-gradient-to-b from-indigo-500 to-purple-500"></div>
|
||||
Category Breakdown
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4 mb-6 sm:mb-8">
|
||||
<div
|
||||
v-for="cat in assessmentCategories"
|
||||
:key="cat.id"
|
||||
class="glass p-5 rounded-xl"
|
||||
class="card p-4 sm:p-5"
|
||||
>
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="flex items-center gap-3 sm:gap-4 mb-3 sm:mb-4">
|
||||
<div
|
||||
class="w-10 h-10 rounded-lg bg-gradient-to-br flex items-center justify-center"
|
||||
class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg sm:rounded-xl bg-gradient-to-br flex items-center justify-center"
|
||||
:class="cat.gradient"
|
||||
>
|
||||
<i :class="cat.icon" class="text-white"></i>
|
||||
<i :class="cat.icon" class="text-white text-base sm:text-lg"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100">{{ cat.title }}</div>
|
||||
<div class="text-sm" :class="colorClasses[cat.color].text">
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100 text-sm sm:text-base truncate">{{ cat.title }}</div>
|
||||
<div class="text-xs sm:text-sm" :class="colorClasses[cat.color].text">
|
||||
{{ categoryScores[cat.id]?.percentage }}% ({{ categoryScores[cat.id]?.score }}/{{ categoryScores[cat.id]?.max }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div class="h-2 sm:h-2.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full rounded-full transition-all duration-500"
|
||||
class="h-full rounded-full transition-all duration-1000"
|
||||
:class="colorClasses[cat.color].progress"
|
||||
:style="{ width: `${categoryScores[cat.id]?.percentage}%` }"
|
||||
></div>
|
||||
@@ -329,57 +346,60 @@ const colorClasses = {
|
||||
</div>
|
||||
|
||||
<!-- Detailed Recommendations -->
|
||||
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">How BEAT Can Help</h3>
|
||||
<div class="space-y-6">
|
||||
<h3 class="text-base sm:text-lg lg:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4 sm:mb-5 flex items-center gap-2 sm:gap-3">
|
||||
<div class="w-0.5 sm:w-1 h-5 sm:h-6 rounded-full bg-gradient-to-b from-emerald-500 to-teal-500"></div>
|
||||
How BEAT Can Help
|
||||
</h3>
|
||||
<div class="space-y-4 sm:space-y-5 mb-6 sm:mb-8">
|
||||
<div
|
||||
v-for="cat in assessmentCategories"
|
||||
:key="cat.id"
|
||||
class="glass p-5 sm:p-6 rounded-xl"
|
||||
class="card p-4 sm:p-5 lg:p-6"
|
||||
>
|
||||
<div class="flex items-start gap-4 mb-4">
|
||||
<div class="flex items-start gap-3 sm:gap-4 mb-3 sm:mb-4">
|
||||
<div
|
||||
class="w-12 h-12 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg sm:rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
:class="cat.gradient"
|
||||
>
|
||||
<i :class="cat.icon" class="text-white text-lg"></i>
|
||||
<i :class="cat.icon" class="text-white text-base sm:text-lg"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-bold text-gray-900 dark:text-gray-100">{{ getRecommendation(cat.id).title }}</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">{{ getRecommendation(cat.id).description }}</p>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h4 class="font-bold text-gray-900 dark:text-gray-100 text-sm sm:text-base lg:text-lg">{{ getRecommendation(cat.id).title }}</h4>
|
||||
<p class="text-gray-600 dark:text-gray-400 mt-0.5 sm:mt-1 text-xs sm:text-sm">{{ getRecommendation(cat.id).description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 mb-4">
|
||||
<div class="space-y-1.5 sm:space-y-2 mb-3 sm:mb-4">
|
||||
<div
|
||||
v-for="rec in getRecommendation(cat.id).recommendations"
|
||||
:key="rec"
|
||||
class="flex items-start gap-3 p-3 rounded-lg"
|
||||
class="flex items-start gap-2 sm:gap-3 p-2.5 sm:p-3 rounded-lg"
|
||||
:class="colorClasses[cat.color].bg"
|
||||
>
|
||||
<i class="fas fa-check-circle mt-0.5" :class="colorClasses[cat.color].text"></i>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ rec }}</span>
|
||||
<i class="fas fa-check-circle mt-0.5 text-xs sm:text-sm" :class="colorClasses[cat.color].text"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300 text-xs sm:text-sm">{{ rec }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-3 p-3 rounded-lg bg-gray-50 dark:bg-gray-800 border-l-4" :class="colorClasses[cat.color].border">
|
||||
<i class="fas fa-quote-left text-gray-400 mt-1"></i>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 italic">{{ getRecommendation(cat.id).beatPrinciple }}</p>
|
||||
<div class="flex items-start gap-2 sm:gap-3 p-3 sm:p-4 rounded-lg bg-gray-50 dark:bg-gray-800 border-l-4" :class="colorClasses[cat.color].border">
|
||||
<i class="fas fa-quote-left text-gray-400 mt-0.5 text-xs sm:text-sm"></i>
|
||||
<p class="text-gray-600 dark:text-gray-400 italic text-xs sm:text-sm">{{ getRecommendation(cat.id).beatPrinciple }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CTA -->
|
||||
<div class="mt-8 p-6 sm:p-8 rounded-2xl bg-gradient-to-br from-indigo-600 via-purple-600 to-pink-600 text-center">
|
||||
<h3 class="text-xl sm:text-2xl font-bold text-white mb-3">Ready to Transform Your Team?</h3>
|
||||
<p class="text-white/80 mb-6 max-w-xl mx-auto">
|
||||
<div class="p-6 sm:p-8 lg:p-10 rounded-2xl sm:rounded-3xl bg-gradient-to-br from-indigo-600 via-purple-600 to-pink-600 text-center">
|
||||
<h3 class="text-lg sm:text-xl lg:text-2xl font-bold text-white mb-2 sm:mb-3">Ready to Transform Your Team?</h3>
|
||||
<p class="text-white/80 mb-4 sm:mb-6 max-w-xl mx-auto text-sm sm:text-base">
|
||||
Explore the full BEAT manifesto and start implementing these practices today.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<RouterLink to="/values" class="bg-white text-indigo-600 px-6 py-3 rounded-lg font-medium hover:bg-gray-100 transition-colors min-h-[44px] flex items-center justify-center">
|
||||
<div class="flex flex-col sm:flex-row gap-2 sm:gap-3 justify-center">
|
||||
<RouterLink to="/values" class="bg-white text-indigo-600 px-5 sm:px-6 py-2.5 sm:py-3 rounded-lg font-semibold hover:bg-gray-100 transition-colors min-h-[48px] flex items-center justify-center text-sm sm:text-base">
|
||||
<i class="fas fa-book-open mr-2"></i>
|
||||
Read the Manifesto
|
||||
</RouterLink>
|
||||
<button @click="restartAssessment" class="bg-white/20 text-white px-6 py-3 rounded-lg font-medium hover:bg-white/30 transition-colors min-h-[44px] flex items-center justify-center">
|
||||
<button @click="restartAssessment" class="bg-white/20 text-white px-5 sm:px-6 py-2.5 sm:py-3 rounded-lg font-semibold hover:bg-white/30 transition-colors min-h-[48px] flex items-center justify-center text-sm sm:text-base">
|
||||
<i class="fas fa-redo mr-2"></i>
|
||||
Retake Assessment
|
||||
</button>
|
||||
|
||||
+131
-106
@@ -2,104 +2,123 @@
|
||||
import { roles, priorityBuckets, ceremonies, constraints } from '@/data/manifesto'
|
||||
|
||||
const workItems = [
|
||||
{ name: 'Tasks', time: 'hours', description: 'A one-liner. No ceremony needed.' },
|
||||
{ name: 'Work Items', time: 'days', description: 'Title, context, done condition. Three lines.' },
|
||||
{ name: 'Projects', time: 'week+', description: 'Half-page doc with breakdown. No more.' }
|
||||
{ name: 'Tasks', time: 'hours', description: 'A one-liner. No ceremony needed.', icon: 'fas fa-check', color: 'blue' },
|
||||
{ name: 'Work Items', time: 'days', description: 'Title, context, done condition. Three lines.', icon: 'fas fa-tasks', color: 'purple' },
|
||||
{ name: 'Projects', time: 'week+', description: 'Half-page doc with breakdown. No more.', icon: 'fas fa-folder', color: 'emerald' }
|
||||
]
|
||||
|
||||
const bucketColors = {
|
||||
red: 'from-red-500 to-red-600 border-red-500',
|
||||
red: 'from-red-500 to-red-600 border-red-500 shadow-glow-red',
|
||||
amber: 'from-amber-500 to-amber-600 border-amber-500',
|
||||
blue: 'from-blue-500 to-blue-600 border-blue-500',
|
||||
blue: 'from-blue-500 to-blue-600 border-blue-500 shadow-glow-blue',
|
||||
gray: 'from-gray-500 to-gray-600 border-gray-500'
|
||||
}
|
||||
|
||||
const boardColumns = [
|
||||
{ name: 'ICE', color: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400', icon: 'fas fa-snowflake' },
|
||||
{ name: 'LATER', color: 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300', icon: 'fas fa-clock' },
|
||||
{ name: 'NEXT', color: 'bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300', icon: 'fas fa-arrow-up' },
|
||||
{ name: 'IN PROGRESS', color: 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300', icon: 'fas fa-spinner' },
|
||||
{ name: 'DONE', color: 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300', icon: 'fas fa-check-circle' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-50 via-indigo-50 to-blue-50 dark:from-gray-900 dark:via-purple-900/10 dark:to-indigo-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-purple-300 dark:bg-purple-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-indigo-300 dark:bg-indigo-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-32 sm:pt-40 pb-16 sm:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-50 via-indigo-50 to-blue-50 dark:from-gray-900 dark:via-purple-950/20 dark:to-indigo-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-96 h-96 bg-purple-400/20 dark:bg-purple-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-80 h-80 bg-indigo-400/20 dark:bg-indigo-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-purple-500 to-indigo-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-sitemap text-white text-2xl"></i>
|
||||
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300 text-sm font-medium mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-sitemap"></i>
|
||||
Implementation
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">The Framework</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-purple-500 to-indigo-500 flex items-center justify-center mx-auto mb-8 animate-fade-in-up animate-delay-100 shadow-glow-purple">
|
||||
<i class="fas fa-sitemap text-white text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">The Framework</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
The principles guide us. The framework implements them.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Roles -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Roles</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Roles</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">We recognize three roles, loosely held.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="role in roles"
|
||||
v-for="(role, index) in roles"
|
||||
:key="role.name"
|
||||
class="glass p-6 rounded-xl group hover:shadow-lg transition-all duration-300"
|
||||
class="card group p-8 text-center"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div
|
||||
class="w-14 h-14 rounded-xl bg-gradient-to-br flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300"
|
||||
class="w-20 h-20 rounded-2xl bg-gradient-to-br flex items-center justify-center mx-auto mb-6 group-hover:scale-110 group-hover:rotate-3 transition-all duration-300 shadow-lg"
|
||||
:class="role.gradient"
|
||||
>
|
||||
<i :class="role.icon" class="text-white text-xl"></i>
|
||||
<i :class="role.icon" class="text-white text-2xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-3">{{ role.name }}</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm leading-relaxed">{{ role.description }}</p>
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-4">{{ role.name }}</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">{{ role.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Beats -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Beats</h2>
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300 relative overflow-hidden">
|
||||
<div class="absolute top-0 right-0 w-96 h-96 bg-blue-500/5 dark:bg-blue-500/10 rounded-full filter blur-3xl"></div>
|
||||
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 relative">
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Beats</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
|
||||
We work in beats—flexible iterations of one to two weeks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="glass p-8 rounded-2xl">
|
||||
<div class="grid md:grid-cols-3 gap-8">
|
||||
<div class="text-center">
|
||||
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center mx-auto mb-4">
|
||||
<i class="fas fa-play text-white"></i>
|
||||
<div class="glass p-8 sm:p-10 rounded-3xl">
|
||||
<!-- Timeline -->
|
||||
<div class="grid md:grid-cols-3 gap-8 relative">
|
||||
<!-- Connecting line -->
|
||||
<div class="hidden md:block absolute top-12 left-0 right-0 h-0.5 bg-gradient-to-r from-blue-500 via-purple-500 to-emerald-500"></div>
|
||||
|
||||
<div class="text-center relative">
|
||||
<div class="w-24 h-24 rounded-full bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center mx-auto mb-6 relative z-10 shadow-glow-blue group-hover:scale-110 transition-transform">
|
||||
<i class="fas fa-play text-white text-2xl"></i>
|
||||
</div>
|
||||
<h4 class="font-semibold text-gray-900 dark:text-gray-100 mb-2">Beat Start</h4>
|
||||
<h4 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-2">Beat Start</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Review priorities and pull initial work</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center mx-auto mb-4">
|
||||
<i class="fas fa-cogs text-white"></i>
|
||||
<div class="text-center relative">
|
||||
<div class="w-24 h-24 rounded-full bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center mx-auto mb-6 relative z-10 shadow-glow-purple">
|
||||
<i class="fas fa-cogs text-white text-2xl"></i>
|
||||
</div>
|
||||
<h4 class="font-semibold text-gray-900 dark:text-gray-100 mb-2">During Beat</h4>
|
||||
<h4 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-2">During Beat</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Check in async daily, work autonomously</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-green-500 to-emerald-500 flex items-center justify-center mx-auto mb-4">
|
||||
<i class="fas fa-flag-checkered text-white"></i>
|
||||
<div class="text-center relative">
|
||||
<div class="w-24 h-24 rounded-full bg-gradient-to-br from-emerald-500 to-teal-500 flex items-center justify-center mx-auto mb-6 relative z-10">
|
||||
<i class="fas fa-flag-checkered text-white text-2xl"></i>
|
||||
</div>
|
||||
<h4 class="font-semibold text-gray-900 dark:text-gray-100 mb-2">Beat Close</h4>
|
||||
<h4 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-2">Beat Close</h4>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Reflect: what worked, what didn't, what to improve</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 p-4 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<p class="text-sm text-blue-800 dark:text-blue-200">
|
||||
<i class="fas fa-info-circle mr-2"></i>
|
||||
Beats have <strong>goals</strong>, not commitments. We aim; we do not promise. There is no sprint pressure, no velocity tracking, no burndown theater.
|
||||
<div class="mt-10 p-5 rounded-xl bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<p class="text-sm text-blue-800 dark:text-blue-200 flex items-start gap-3">
|
||||
<i class="fas fa-info-circle mt-0.5"></i>
|
||||
<span>Beats have <strong>goals</strong>, not commitments. We aim; we do not promise. There is no sprint pressure, no velocity tracking, no burndown theater.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,112 +126,115 @@ const bucketColors = {
|
||||
</section>
|
||||
|
||||
<!-- Work Items -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Work Items</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Work Items</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Documentation effort scales with task size.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="item in workItems"
|
||||
v-for="(item, index) in workItems"
|
||||
:key="item.name"
|
||||
class="glass p-6 rounded-xl hover:shadow-lg transition-all duration-300"
|
||||
class="card group p-8"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div
|
||||
class="w-14 h-14 rounded-xl bg-gradient-to-br flex items-center justify-center group-hover:scale-110 transition-all duration-300"
|
||||
:class="[
|
||||
item.color === 'blue' ? 'from-blue-500 to-blue-600' :
|
||||
item.color === 'purple' ? 'from-purple-500 to-purple-600' :
|
||||
'from-emerald-500 to-emerald-600'
|
||||
]"
|
||||
>
|
||||
<i :class="item.icon" class="text-white text-xl"></i>
|
||||
</div>
|
||||
<span class="text-2xl font-bold gradient-text">{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="inline-block px-3 py-1 rounded-full bg-gray-100 dark:bg-gray-700 text-sm text-gray-600 dark:text-gray-400 mb-3">
|
||||
<div class="inline-block px-4 py-1.5 rounded-full bg-gray-100 dark:bg-gray-700 text-sm text-gray-600 dark:text-gray-400 mb-4 font-medium">
|
||||
{{ item.time }}
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ item.description }}</p>
|
||||
<p class="text-gray-600 dark:text-gray-400">{{ item.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 text-center">
|
||||
<p class="text-gray-500 dark:text-gray-500 text-sm">
|
||||
We size with <strong>S/M/L</strong>, not story points. We do not groom. We do not point. We do not track velocity.
|
||||
<p class="text-gray-500 dark:text-gray-500">
|
||||
We size with <strong class="text-gray-700 dark:text-gray-300">S/M/L</strong>, not story points. We do not groom. We do not point. We do not track velocity.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Prioritization -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Prioritization Buckets</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Prioritization Buckets</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">We use four buckets to organize work.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-5">
|
||||
<div
|
||||
v-for="bucket in priorityBuckets"
|
||||
v-for="(bucket, index) in priorityBuckets"
|
||||
:key="bucket.name"
|
||||
class="glass p-5 rounded-xl border-l-4 hover:shadow-lg transition-all duration-300"
|
||||
class="card p-6 border-l-4"
|
||||
:class="bucketColors[bucket.color]"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-2">{{ bucket.name }}</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">{{ bucket.description }}</p>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-3">{{ bucket.name }}</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">{{ bucket.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- The Board -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">The Board</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">The Board</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">A simple kanban with priority built in.</p>
|
||||
</div>
|
||||
|
||||
<!-- Visual Board Flow -->
|
||||
<div class="glass p-4 sm:p-6 rounded-xl overflow-x-auto">
|
||||
<div class="flex items-center justify-start sm:justify-center gap-2 sm:gap-3 min-w-max sm:min-w-0">
|
||||
<div class="px-3 sm:px-4 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 text-xs sm:text-sm font-medium">
|
||||
ICE
|
||||
</div>
|
||||
<i class="fas fa-arrow-right text-gray-400 text-xs"></i>
|
||||
<div class="px-3 sm:px-4 py-2 rounded-lg bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 text-xs sm:text-sm font-medium">
|
||||
LATER
|
||||
</div>
|
||||
<i class="fas fa-arrow-right text-gray-400 text-xs"></i>
|
||||
<div class="px-3 sm:px-4 py-2 rounded-lg bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 text-xs sm:text-sm font-medium">
|
||||
NEXT
|
||||
</div>
|
||||
<i class="fas fa-arrow-right text-gray-400 text-xs"></i>
|
||||
<div class="px-3 sm:px-4 py-2 rounded-lg bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300 text-xs sm:text-sm font-medium">
|
||||
IN PROGRESS
|
||||
</div>
|
||||
<i class="fas fa-arrow-right text-gray-400 text-xs"></i>
|
||||
<div class="px-3 sm:px-4 py-2 rounded-lg bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 text-xs sm:text-sm font-medium">
|
||||
DONE
|
||||
</div>
|
||||
<div class="glass p-6 sm:p-8 rounded-3xl overflow-x-auto mb-8">
|
||||
<div class="flex items-center justify-start sm:justify-center gap-3 min-w-max sm:min-w-0">
|
||||
<template v-for="(col, index) in boardColumns" :key="col.name">
|
||||
<div
|
||||
class="flex items-center gap-2 px-4 py-3 rounded-xl font-medium"
|
||||
:class="col.color"
|
||||
>
|
||||
<i :class="col.icon" class="text-sm"></i>
|
||||
<span class="text-sm">{{ col.name }}</span>
|
||||
</div>
|
||||
<i v-if="index < boardColumns.length - 1" class="fas fa-arrow-right text-gray-400"></i>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 grid sm:grid-cols-3 gap-4">
|
||||
<div class="glass p-4 rounded-lg">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<i class="fas fa-user text-blue-500"></i>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100">WIP Limit</span>
|
||||
<div class="grid sm:grid-cols-3 gap-5">
|
||||
<div class="card p-6 text-center group">
|
||||
<div class="w-14 h-14 rounded-xl bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
|
||||
<i class="fas fa-user text-blue-500 text-xl"></i>
|
||||
</div>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100 block mb-1">WIP Limit</span>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">3 items per maker</p>
|
||||
</div>
|
||||
<div class="glass p-4 rounded-lg">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<i class="fas fa-sort-amount-up text-purple-500"></i>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100">NEXT is Ordered</span>
|
||||
<div class="card p-6 text-center group">
|
||||
<div class="w-14 h-14 rounded-xl bg-purple-100 dark:bg-purple-900/30 flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
|
||||
<i class="fas fa-sort-amount-up text-purple-500 text-xl"></i>
|
||||
</div>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100 block mb-1">NEXT is Ordered</span>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Pull from top</p>
|
||||
</div>
|
||||
<div class="glass p-4 rounded-lg">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<i class="fas fa-clock text-amber-500"></i>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100">Stale Items</span>
|
||||
<div class="card p-6 text-center group">
|
||||
<div class="w-14 h-14 rounded-xl bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center mx-auto mb-4 group-hover:scale-110 transition-transform">
|
||||
<i class="fas fa-clock text-amber-500 text-xl"></i>
|
||||
</div>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100 block mb-1">Stale Items</span>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">Return to backlog after 5 days</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -220,17 +242,20 @@ const bucketColors = {
|
||||
</section>
|
||||
|
||||
<!-- Constraints -->
|
||||
<section class="py-16 bg-gradient-to-br from-purple-600 via-indigo-600 to-blue-600">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-white text-center mb-8">The Numbers</h2>
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<section class="py-20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-600 via-indigo-600 to-blue-600"></div>
|
||||
|
||||
<div class="relative max-w-5xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-white text-center mb-12">The Numbers</h2>
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
|
||||
<div
|
||||
v-for="item in constraints"
|
||||
v-for="(item, index) in constraints"
|
||||
:key="item.constraint"
|
||||
class="bg-white/10 backdrop-blur-sm p-4 rounded-xl"
|
||||
class="bg-white/10 backdrop-blur-sm p-5 rounded-2xl border border-white/10 hover:bg-white/20 transition-all duration-300"
|
||||
:style="{ animationDelay: `${index * 50}ms` }"
|
||||
>
|
||||
<div class="text-white/70 text-sm mb-1">{{ item.constraint }}</div>
|
||||
<div class="text-white text-xl font-bold">{{ item.limit }}</div>
|
||||
<div class="text-white text-2xl font-bold">{{ item.limit }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+157
-106
@@ -1,111 +1,158 @@
|
||||
<script setup>
|
||||
import { RouterLink } from 'vue-router'
|
||||
import IconCard from '@/components/ui/IconCard.vue'
|
||||
import { researchStats } from '@/data/manifesto'
|
||||
|
||||
const navCards = [
|
||||
{ path: '/values', title: 'Values', description: 'Core & team values that guide everything', icon: 'fas fa-heart', gradient: 'from-red-500 to-pink-500' },
|
||||
{ path: '/principles', title: 'Principles', description: 'The 12 principles of BEAT', icon: 'fas fa-compass', gradient: 'from-blue-500 to-cyan-500' },
|
||||
{ path: '/framework', title: 'Framework', description: 'Roles, beats, and the board', icon: 'fas fa-sitemap', gradient: 'from-purple-500 to-indigo-500' },
|
||||
{ path: '/practices', title: 'Practices', description: 'Meetings, collaboration, incidents', icon: 'fas fa-cogs', gradient: 'from-green-500 to-emerald-500' },
|
||||
{ path: '/onboarding', title: 'Onboarding', description: 'Getting started with BEAT', icon: 'fas fa-user-plus', gradient: 'from-amber-500 to-orange-500' },
|
||||
{ path: '/reference', title: 'Reference', description: 'Quick lookup tables', icon: 'fas fa-book', gradient: 'from-cyan-500 to-blue-500' }
|
||||
{ path: '/values', title: 'Values', description: 'Core & team values that guide everything', icon: 'fas fa-heart', gradient: 'from-rose-500 to-pink-500', color: 'rose' },
|
||||
{ path: '/principles', title: 'Principles', description: 'The 12 principles of BEAT', icon: 'fas fa-compass', gradient: 'from-blue-500 to-cyan-500', color: 'blue' },
|
||||
{ path: '/framework', title: 'Framework', description: 'Roles, beats, and the board', icon: 'fas fa-sitemap', gradient: 'from-purple-500 to-indigo-500', color: 'purple' },
|
||||
{ path: '/practices', title: 'Practices', description: 'Meetings, collaboration, incidents', icon: 'fas fa-cogs', gradient: 'from-emerald-500 to-teal-500', color: 'emerald' },
|
||||
{ path: '/onboarding', title: 'Onboarding', description: 'Getting started with BEAT', icon: 'fas fa-user-plus', gradient: 'from-amber-500 to-orange-500', color: 'amber' },
|
||||
{ path: '/reference', title: 'Reference', description: 'Quick lookup tables', icon: 'fas fa-book', gradient: 'from-cyan-500 to-sky-500', color: 'cyan' }
|
||||
]
|
||||
|
||||
const keyNumbers = [
|
||||
{ value: '4hrs', label: 'Sacred Focus Block', icon: 'fas fa-brain' },
|
||||
{ value: '2hrs', label: 'Max Meetings/Week', icon: 'fas fa-calendar' },
|
||||
{ value: '80%', label: 'Planning Capacity', icon: 'fas fa-battery-three-quarters' },
|
||||
{ value: '20%', label: 'Exploration Time', icon: 'fas fa-flask' }
|
||||
{ value: '4hrs', label: 'Sacred Focus Block', icon: 'fas fa-brain', color: 'blue' },
|
||||
{ value: '2hrs', label: 'Max Meetings/Week', icon: 'fas fa-calendar', color: 'purple' },
|
||||
{ value: '80%', label: 'Planning Capacity', icon: 'fas fa-battery-three-quarters', color: 'emerald' },
|
||||
{ value: '20%', label: 'Exploration Time', icon: 'fas fa-flask', color: 'amber' }
|
||||
]
|
||||
|
||||
const commitments = [
|
||||
{ icon: 'fas fa-shield-alt', title: 'Protecting focus', description: 'We will not interrupt sacred time. We will wait.' },
|
||||
{ icon: 'fas fa-pen', title: 'Defaulting to async', description: 'We will write first, meet only when writing fails.' },
|
||||
{ icon: 'fas fa-handshake', title: 'Trusting makers', description: 'We will provide goals, not instructions. Constraints, not control.' },
|
||||
{ icon: 'fas fa-heart', title: 'Sustaining pace', description: 'We will cut scope before we cut rest. We will plan for humans.' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero Section -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-16 sm:pb-24 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 via-purple-50 to-cyan-50 dark:from-gray-900 dark:via-blue-900/20 dark:to-purple-900/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-blue-300 dark:bg-blue-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-purple-300 dark:bg-purple-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<div class="absolute -bottom-8 left-20 w-72 h-72 bg-cyan-300 dark:bg-cyan-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-2000"></div>
|
||||
<section class="relative min-h-[85vh] sm:min-h-[90vh] flex items-center justify-center overflow-hidden">
|
||||
<!-- Animated background blobs -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 via-purple-50 to-cyan-50 dark:from-gray-900 dark:via-blue-950/30 dark:to-purple-950/30 transition-colors duration-500"></div>
|
||||
|
||||
<!-- Floating orbs - responsive sizing -->
|
||||
<div class="absolute top-20 left-[5%] w-48 h-48 sm:w-72 sm:h-72 lg:w-96 lg:h-96 bg-blue-400/20 dark:bg-blue-500/20 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 right-[5%] w-56 h-56 sm:w-80 sm:h-80 lg:w-[28rem] lg:h-[28rem] bg-purple-400/20 dark:bg-purple-500/20 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
<div class="absolute -bottom-10 left-1/4 w-52 h-52 sm:w-72 sm:h-72 lg:w-80 lg:h-80 bg-cyan-400/20 dark:bg-cyan-500/20 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-3xl animate-float animate-delay-1000"></div>
|
||||
|
||||
<!-- Grid pattern overlay -->
|
||||
<div class="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiM5Y2EzYWYiIGZpbGwtb3BhY2l0eT0iMC4wNSI+PHBhdGggZD0iTTM2IDM0aDR2NGgtNHpNMjQgMjRoNHY0aC00eiIvPjwvZz48L2c+PC9zdmc+')] opacity-50"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 py-16 sm:py-20 lg:py-24">
|
||||
<div class="text-center">
|
||||
<!-- Logo with glow effect -->
|
||||
<div class="mb-6 sm:mb-8 flex justify-center animate-fade-in-up">
|
||||
<div class="w-24 h-24 sm:w-32 sm:h-32 rounded-2xl bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600 flex items-center justify-center shadow-xl animate-float">
|
||||
<span class="text-white text-4xl sm:text-5xl font-bold">B</span>
|
||||
<div
|
||||
class="relative w-20 h-20 sm:w-28 sm:h-28 lg:w-36 lg:h-36 rounded-2xl bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600 flex items-center justify-center shadow-2xl animate-float"
|
||||
>
|
||||
<!-- Glow effect -->
|
||||
<div class="absolute inset-0 rounded-2xl bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600 blur-xl opacity-50 animate-pulse-slow"></div>
|
||||
<span class="relative text-white text-3xl sm:text-5xl lg:text-6xl font-bold">B</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold text-gray-900 dark:text-gray-100 mb-4 sm:mb-6 leading-tight animate-fade-in-up animate-delay-100">
|
||||
<!-- Title - responsive sizing -->
|
||||
<h1 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold text-gray-900 dark:text-gray-100 mb-4 sm:mb-6 leading-tight animate-fade-in-up animate-delay-100">
|
||||
The <span class="gradient-text">BEAT</span> Manifesto
|
||||
</h1>
|
||||
|
||||
<p class="text-xl sm:text-2xl md:text-3xl text-gray-700 dark:text-gray-200 mb-4 animate-fade-in-up animate-delay-200 font-medium">
|
||||
<!-- Subtitle -->
|
||||
<p class="text-xl sm:text-2xl md:text-3xl lg:text-4xl text-gray-700 dark:text-gray-200 mb-4 sm:mb-6 animate-fade-in-up animate-delay-200 font-medium tracking-tight">
|
||||
<span class="text-blue-600 dark:text-blue-400">B</span>alanced.
|
||||
<span class="text-purple-600 dark:text-purple-400">E</span>mpowered.
|
||||
<span class="text-cyan-600 dark:text-cyan-400">A</span>sync.
|
||||
<span class="text-pink-600 dark:text-pink-400">T</span>eams.
|
||||
</p>
|
||||
|
||||
<p class="text-base sm:text-lg text-gray-600 dark:text-gray-400 mb-8 max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
<!-- Description -->
|
||||
<p class="text-base sm:text-lg lg:text-xl text-gray-600 dark:text-gray-400 mb-8 sm:mb-10 max-w-2xl lg:max-w-3xl mx-auto animate-fade-in-up animate-delay-300 leading-relaxed px-4 sm:px-0">
|
||||
A software delivery methodology built for how developers actually work.
|
||||
<br class="hidden sm:block" />
|
||||
Created by <strong>Lukasz Raczylo</strong>.
|
||||
<span class="block mt-2 text-gray-500 dark:text-gray-500">Created by <strong class="text-gray-700 dark:text-gray-300">Lukasz Raczylo</strong>.</span>
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center animate-fade-in-up animate-delay-300">
|
||||
<RouterLink to="/values" class="btn-primary">
|
||||
<!-- CTA Buttons - stack on mobile, side by side on larger screens -->
|
||||
<div class="flex flex-col sm:flex-row gap-3 sm:gap-4 justify-center animate-fade-in-up animate-delay-400 px-4 sm:px-0">
|
||||
<RouterLink to="/values" class="btn-primary text-sm sm:text-base px-6 sm:px-8 py-3 sm:py-4">
|
||||
<i class="fas fa-book-open mr-2"></i>
|
||||
Start Reading
|
||||
</RouterLink>
|
||||
<RouterLink to="/reference" class="btn-secondary">
|
||||
<i class="fas fa-list mr-2"></i>
|
||||
Quick Reference
|
||||
<RouterLink to="/assessment" class="btn-secondary text-sm sm:text-base px-6 sm:px-8 py-3 sm:py-4">
|
||||
<i class="fas fa-clipboard-check mr-2"></i>
|
||||
Take Assessment
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scroll indicator - hide on very small screens -->
|
||||
<div class="absolute bottom-4 sm:bottom-8 left-1/2 -translate-x-1/2 animate-bounce-subtle hidden sm:block">
|
||||
<div class="w-6 h-10 rounded-full border-2 border-gray-400 dark:border-gray-600 flex items-start justify-center p-2">
|
||||
<div class="w-1.5 h-3 rounded-full bg-gray-400 dark:bg-gray-600 animate-pulse"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Key Numbers -->
|
||||
<section class="py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6">
|
||||
<section class="py-12 sm:py-16 lg:py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 lg:gap-6">
|
||||
<div
|
||||
v-for="item in keyNumbers"
|
||||
v-for="(item, index) in keyNumbers"
|
||||
:key="item.label"
|
||||
class="glass p-6 rounded-xl text-center group hover:shadow-lg transition-all duration-300"
|
||||
class="group card text-center p-4 sm:p-6 lg:p-8"
|
||||
:class="`hover:border-${item.color}-300 dark:hover:border-${item.color}-700`"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center mx-auto mb-3 group-hover:scale-110 transition-transform duration-300">
|
||||
<i :class="item.icon" class="text-white"></i>
|
||||
<div
|
||||
class="w-10 h-10 sm:w-12 sm:h-12 lg:w-14 lg:h-14 rounded-xl sm:rounded-2xl bg-gradient-to-br flex items-center justify-center mx-auto mb-3 sm:mb-4 transition-all duration-300 group-hover:scale-110 group-hover:rotate-3"
|
||||
:class="[
|
||||
item.color === 'blue' ? 'from-blue-500 to-blue-600 shadow-glow-blue' :
|
||||
item.color === 'purple' ? 'from-purple-500 to-purple-600 shadow-glow-purple' :
|
||||
item.color === 'emerald' ? 'from-emerald-500 to-emerald-600' :
|
||||
'from-amber-500 to-amber-600'
|
||||
]"
|
||||
>
|
||||
<i :class="item.icon" class="text-white text-base sm:text-xl lg:text-2xl"></i>
|
||||
</div>
|
||||
<div class="text-3xl sm:text-4xl font-bold gradient-text mb-1">{{ item.value }}</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">{{ item.label }}</div>
|
||||
<div class="text-2xl sm:text-3xl lg:text-4xl xl:text-5xl font-bold gradient-text mb-1 sm:mb-2">{{ item.value }}</div>
|
||||
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 font-medium">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Introduction -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<div class="glass p-8 sm:p-12 rounded-2xl">
|
||||
<p class="text-lg sm:text-xl text-gray-700 dark:text-gray-300 leading-relaxed mb-6">
|
||||
<section class="py-12 sm:py-16 lg:py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300 relative overflow-hidden">
|
||||
<!-- Decorative elements -->
|
||||
<div class="absolute top-0 right-0 w-48 h-48 sm:w-64 sm:h-64 bg-blue-500/5 dark:bg-blue-500/10 rounded-full filter blur-3xl"></div>
|
||||
<div class="absolute bottom-0 left-0 w-48 h-48 sm:w-64 sm:h-64 bg-purple-500/5 dark:bg-purple-500/10 rounded-full filter blur-3xl"></div>
|
||||
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 relative">
|
||||
<div class="glass p-6 sm:p-8 lg:p-12 xl:p-16 rounded-2xl sm:rounded-3xl">
|
||||
<div class="flex items-center gap-3 mb-4 sm:mb-6">
|
||||
<div class="w-1 h-6 sm:h-8 rounded-full bg-gradient-to-b from-blue-500 to-purple-500"></div>
|
||||
<h2 class="text-xl sm:text-2xl font-bold text-gray-900 dark:text-gray-100">Our Philosophy</h2>
|
||||
</div>
|
||||
|
||||
<p class="text-lg sm:text-xl lg:text-2xl text-gray-700 dark:text-gray-300 leading-relaxed mb-4 sm:mb-6 font-light">
|
||||
We are uncovering better ways of building software by doing it and helping others do it.
|
||||
</p>
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed mb-8">
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed mb-6 sm:mb-8 text-sm sm:text-base">
|
||||
BEAT emerges from research on how developers actually work. We built it for these realities, not against them.
|
||||
</p>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4">
|
||||
<div
|
||||
v-for="stat in researchStats"
|
||||
v-for="(stat, index) in researchStats"
|
||||
:key="stat.stat"
|
||||
class="flex items-center gap-3 p-3 rounded-lg bg-white/50 dark:bg-gray-700/50"
|
||||
class="flex items-center gap-3 p-3 sm:p-4 rounded-xl bg-white/60 dark:bg-gray-700/50 hover:bg-white dark:hover:bg-gray-700 transition-all duration-300 group"
|
||||
:style="{ animationDelay: `${index * 50}ms` }"
|
||||
>
|
||||
<span class="text-xl font-bold text-blue-600 dark:text-blue-400">{{ stat.stat }}</span>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">{{ stat.description }}</span>
|
||||
<span class="text-xl sm:text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-br from-blue-500 to-purple-500">{{ stat.stat }}</span>
|
||||
<span class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">{{ stat.description }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -113,33 +160,34 @@ const keyNumbers = [
|
||||
</section>
|
||||
|
||||
<!-- Navigation Cards -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<section class="py-12 sm:py-16 lg:py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
|
||||
<div class="text-center mb-10 sm:mb-14">
|
||||
<h2 class="section-title">Explore the Manifesto</h2>
|
||||
<p class="section-subtitle">Deep dive into each aspect of BEAT</p>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-5 lg:gap-6">
|
||||
<RouterLink
|
||||
v-for="card in navCards"
|
||||
v-for="(card, index) in navCards"
|
||||
:key="card.path"
|
||||
:to="card.path"
|
||||
class="glass p-6 rounded-xl group hover:shadow-lg transition-all duration-300 hover:-translate-y-1"
|
||||
class="group card p-5 sm:p-6 lg:p-8"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="flex items-start gap-4 sm:gap-5">
|
||||
<div
|
||||
class="w-12 h-12 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform duration-300"
|
||||
class="w-12 h-12 sm:w-14 sm:h-14 rounded-xl sm:rounded-2xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 transition-all duration-300 group-hover:scale-110 group-hover:rotate-6"
|
||||
:class="card.gradient"
|
||||
>
|
||||
<i :class="card.icon" class="text-white"></i>
|
||||
<i :class="card.icon" class="text-white text-lg sm:text-xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="font-semibold text-base sm:text-lg text-gray-900 dark:text-gray-100 mb-1 sm:mb-2 flex items-center gap-2 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||
{{ card.title }}
|
||||
<i class="fas fa-arrow-right ml-2 text-sm opacity-0 group-hover:opacity-100 transition-opacity"></i>
|
||||
<i class="fas fa-arrow-right text-xs sm:text-sm opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-300"></i>
|
||||
</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">{{ card.description }}</p>
|
||||
<p class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 leading-relaxed">{{ card.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</RouterLink>
|
||||
@@ -148,59 +196,62 @@ const keyNumbers = [
|
||||
</section>
|
||||
|
||||
<!-- Commitment Section -->
|
||||
<section class="py-16 bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-8">The BEAT Commitment</h2>
|
||||
<div class="grid sm:grid-cols-2 gap-4 text-left">
|
||||
<div class="bg-white/10 backdrop-blur-sm p-6 rounded-xl">
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<i class="fas fa-shield-alt text-white"></i>
|
||||
<span class="text-white font-semibold">Protecting focus</span>
|
||||
<section class="py-12 sm:py-16 lg:py-20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600"></div>
|
||||
|
||||
<!-- Animated background pattern -->
|
||||
<div class="absolute inset-0 opacity-10">
|
||||
<div class="absolute top-0 left-0 w-full h-full bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgNDBoNDBWMEgwVjQwWiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0wIDQwaDQwVjBIMFY0MFoiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+')] animate-pulse-slow"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
|
||||
<div class="text-center mb-8 sm:mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl lg:text-4xl font-bold text-white mb-3 sm:mb-4">The BEAT Commitment</h2>
|
||||
<p class="text-white/70 text-base sm:text-lg">By adopting BEAT, we commit to:</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4 lg:gap-5">
|
||||
<div
|
||||
v-for="(item, index) in commitments"
|
||||
:key="item.title"
|
||||
class="group bg-white/10 backdrop-blur-sm p-5 sm:p-6 rounded-xl sm:rounded-2xl border border-white/10 hover:bg-white/20 transition-all duration-300 hover:-translate-y-1"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-center gap-3 sm:gap-4 mb-2 sm:mb-3">
|
||||
<div class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg sm:rounded-xl bg-white/20 flex items-center justify-center transition-all duration-300 group-hover:scale-110 group-hover:bg-white/30">
|
||||
<i :class="item.icon" class="text-white text-base sm:text-xl"></i>
|
||||
</div>
|
||||
<span class="text-white font-semibold text-base sm:text-lg">{{ item.title }}</span>
|
||||
</div>
|
||||
<p class="text-white/80 text-sm">We will not interrupt sacred time. We will wait.</p>
|
||||
</div>
|
||||
<div class="bg-white/10 backdrop-blur-sm p-6 rounded-xl">
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<i class="fas fa-pen text-white"></i>
|
||||
<span class="text-white font-semibold">Defaulting to async</span>
|
||||
</div>
|
||||
<p class="text-white/80 text-sm">We will write first, meet only when writing fails.</p>
|
||||
</div>
|
||||
<div class="bg-white/10 backdrop-blur-sm p-6 rounded-xl">
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<i class="fas fa-handshake text-white"></i>
|
||||
<span class="text-white font-semibold">Trusting makers</span>
|
||||
</div>
|
||||
<p class="text-white/80 text-sm">We will provide goals, not instructions. Constraints, not control.</p>
|
||||
</div>
|
||||
<div class="bg-white/10 backdrop-blur-sm p-6 rounded-xl">
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<i class="fas fa-heart text-white"></i>
|
||||
<span class="text-white font-semibold">Sustaining pace</span>
|
||||
</div>
|
||||
<p class="text-white/80 text-sm">We will cut scope before we cut rest. We will plan for humans.</p>
|
||||
<p class="text-white/70 text-xs sm:text-sm leading-relaxed pl-13 sm:pl-16">{{ item.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Summary -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="glass p-8 rounded-2xl">
|
||||
<div class="font-mono text-lg sm:text-xl text-gray-700 dark:text-gray-300 space-y-2">
|
||||
<p>We protect focus.</p>
|
||||
<p>We write things down.</p>
|
||||
<p>We trust each other.</p>
|
||||
<p>We work sustainably.</p>
|
||||
<p>We ship and learn.</p>
|
||||
<section class="py-12 sm:py-16 lg:py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 text-center">
|
||||
<div class="glass p-6 sm:p-8 lg:p-10 xl:p-14 rounded-2xl sm:rounded-3xl relative overflow-hidden">
|
||||
<!-- Decorative gradient -->
|
||||
<div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-blue-500 via-purple-500 to-cyan-500"></div>
|
||||
|
||||
<div class="font-mono text-base sm:text-lg lg:text-xl xl:text-2xl text-gray-700 dark:text-gray-300 space-y-2 sm:space-y-3">
|
||||
<p class="hover:text-blue-600 dark:hover:text-blue-400 transition-colors cursor-default">We protect focus.</p>
|
||||
<p class="hover:text-purple-600 dark:hover:text-purple-400 transition-colors cursor-default">We write things down.</p>
|
||||
<p class="hover:text-cyan-600 dark:hover:text-cyan-400 transition-colors cursor-default">We trust each other.</p>
|
||||
<p class="hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors cursor-default">We work sustainably.</p>
|
||||
<p class="hover:text-pink-600 dark:hover:text-pink-400 transition-colors cursor-default">We ship and learn.</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 sm:mt-8 pt-6 sm:pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<p class="text-gray-500 dark:text-gray-500 italic text-base sm:text-lg">
|
||||
BEAT: Built for how developers actually work.
|
||||
</p>
|
||||
<p class="mt-3 sm:mt-4 text-xs sm:text-sm text-gray-400 dark:text-gray-600">
|
||||
BEAT v1.0 by Lukasz Raczylo
|
||||
</p>
|
||||
</div>
|
||||
<p class="mt-6 text-gray-500 dark:text-gray-500 italic">
|
||||
BEAT: Built for how developers actually work.
|
||||
</p>
|
||||
<p class="mt-4 text-sm text-gray-400 dark:text-gray-600">
|
||||
BEAT v1.0 by Lukasz Raczylo
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import { onboarding } from '@/data/manifesto'
|
||||
|
||||
const weeks = [
|
||||
{ ...onboarding.weekOne, icon: 'fas fa-eye', gradient: 'from-blue-500 to-cyan-500' },
|
||||
{ ...onboarding.weekTwo, icon: 'fas fa-hand-pointer', gradient: 'from-purple-500 to-pink-500' },
|
||||
{ ...onboarding.weekThree, icon: 'fas fa-rocket', gradient: 'from-green-500 to-emerald-500' }
|
||||
{ ...onboarding.weekOne, icon: 'fas fa-eye', gradient: 'from-blue-500 to-cyan-500', color: 'blue' },
|
||||
{ ...onboarding.weekTwo, icon: 'fas fa-hand-pointer', gradient: 'from-purple-500 to-pink-500', color: 'purple' },
|
||||
{ ...onboarding.weekThree, icon: 'fas fa-rocket', gradient: 'from-emerald-500 to-teal-500', color: 'emerald' }
|
||||
]
|
||||
|
||||
const whatWeDont = [
|
||||
@@ -18,48 +18,53 @@ const whatWeDont = [
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-amber-50 via-orange-50 to-red-50 dark:from-gray-900 dark:via-amber-900/10 dark:to-orange-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-amber-300 dark:bg-amber-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-orange-300 dark:bg-orange-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-32 sm:pt-40 pb-16 sm:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-amber-50 via-orange-50 to-red-50 dark:from-gray-900 dark:via-amber-950/20 dark:to-orange-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-96 h-96 bg-amber-400/20 dark:bg-amber-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-80 h-80 bg-orange-400/20 dark:bg-orange-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-amber-500 to-orange-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-user-plus text-white text-2xl"></i>
|
||||
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 text-sm font-medium mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
Getting Started
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Onboarding to BEAT</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-amber-500 to-orange-500 flex items-center justify-center mx-auto mb-8 animate-fade-in-up animate-delay-100">
|
||||
<i class="fas fa-user-plus text-white text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">Onboarding to BEAT</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
When someone new joins a BEAT team, here's how to get them up to speed.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Weekly Timeline -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="space-y-8">
|
||||
<div class="space-y-6">
|
||||
<div
|
||||
v-for="(week, index) in weeks"
|
||||
:key="week.title"
|
||||
class="glass p-6 sm:p-8 rounded-2xl hover:shadow-lg transition-all duration-300"
|
||||
class="card p-8"
|
||||
:style="{ animationDelay: `${index * 150}ms` }"
|
||||
>
|
||||
<div class="flex items-start gap-6">
|
||||
<div class="flex flex-col sm:flex-row sm:items-start gap-6">
|
||||
<div
|
||||
class="w-16 h-16 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
class="w-20 h-20 rounded-2xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 shadow-lg"
|
||||
:class="week.gradient"
|
||||
>
|
||||
<i :class="week.icon" class="text-white text-xl"></i>
|
||||
<i :class="week.icon" class="text-white text-2xl"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">{{ week.title }}</h3>
|
||||
<ul class="space-y-3">
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-5">{{ week.title }}</h3>
|
||||
<ul class="grid sm:grid-cols-2 gap-3">
|
||||
<li
|
||||
v-for="item in week.items"
|
||||
:key="item"
|
||||
class="flex items-start gap-3 text-gray-600 dark:text-gray-400"
|
||||
class="flex items-start gap-3 p-3 rounded-xl bg-gray-50 dark:bg-gray-800/50"
|
||||
>
|
||||
<i class="fas fa-check-circle text-green-500 mt-1"></i>
|
||||
<span>{{ item }}</span>
|
||||
<i class="fas fa-check-circle text-emerald-500 mt-1"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -70,68 +75,69 @@ const whatWeDont = [
|
||||
</section>
|
||||
|
||||
<!-- First Month -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">{{ onboarding.firstMonth.title }}</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">{{ onboarding.firstMonth.title }}</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">By the end of the first month, new members should:</p>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
|
||||
<div
|
||||
v-for="(item, index) in onboarding.firstMonth.items"
|
||||
:key="item"
|
||||
class="glass p-5 rounded-xl hover:shadow-lg transition-all duration-300"
|
||||
class="card p-6 group"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-amber-500 to-orange-500 flex items-center justify-center flex-shrink-0">
|
||||
<span class="text-white text-sm font-bold">{{ index + 1 }}</span>
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-amber-500 to-orange-500 flex items-center justify-center flex-shrink-0 group-hover:scale-110 transition-transform">
|
||||
<span class="text-white text-lg font-bold">{{ index + 1 }}</span>
|
||||
</div>
|
||||
<p class="text-gray-700 dark:text-gray-300 text-sm">{{ item }}</p>
|
||||
<p class="text-gray-700 dark:text-gray-300 pt-2">{{ item }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Connector's Responsibility -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<!-- Connector's Responsibility & What We Don't -->
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<div class="glass p-6 rounded-xl">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-cyan-500 to-blue-500 flex items-center justify-center">
|
||||
<i class="fas fa-project-diagram text-white"></i>
|
||||
<div class="card p-8">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-cyan-500 to-blue-500 flex items-center justify-center">
|
||||
<i class="fas fa-project-diagram text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Connector's Responsibility</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-4 text-sm">
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6">
|
||||
The Connector (or Enabler if no Connector) ensures:
|
||||
</p>
|
||||
<ul class="space-y-3">
|
||||
<li class="flex items-start gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-start gap-3 p-3 rounded-xl bg-cyan-50 dark:bg-cyan-900/20">
|
||||
<i class="fas fa-check text-cyan-500 mt-1"></i>
|
||||
Documentation is current and findable
|
||||
<span class="text-gray-700 dark:text-gray-300">Documentation is current and findable</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-start gap-3 p-3 rounded-xl bg-cyan-50 dark:bg-cyan-900/20">
|
||||
<i class="fas fa-check text-cyan-500 mt-1"></i>
|
||||
New member has a "buddy" for questions (informal, not mandatory pairing)
|
||||
<span class="text-gray-700 dark:text-gray-300">New member has a "buddy" for questions (informal, not mandatory pairing)</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-start gap-3 p-3 rounded-xl bg-cyan-50 dark:bg-cyan-900/20">
|
||||
<i class="fas fa-check text-cyan-500 mt-1"></i>
|
||||
First tasks are well-scoped and achievable
|
||||
<span class="text-gray-700 dark:text-gray-300">First tasks are well-scoped and achievable</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-start gap-3 p-3 rounded-xl bg-cyan-50 dark:bg-cyan-900/20">
|
||||
<i class="fas fa-check text-cyan-500 mt-1"></i>
|
||||
Overwhelm is caught early
|
||||
<span class="text-gray-700 dark:text-gray-300">Overwhelm is caught early</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl border-l-4 border-red-500">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-red-500 to-pink-500 flex items-center justify-center">
|
||||
<i class="fas fa-times text-white"></i>
|
||||
<div class="card p-8 border-l-4 border-red-500">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-red-500 to-pink-500 flex items-center justify-center">
|
||||
<i class="fas fa-times text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">What We Don't Do</h3>
|
||||
</div>
|
||||
@@ -139,10 +145,10 @@ const whatWeDont = [
|
||||
<li
|
||||
v-for="item in whatWeDont"
|
||||
:key="item"
|
||||
class="flex items-start gap-3 text-sm text-gray-600 dark:text-gray-400"
|
||||
class="flex items-start gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20"
|
||||
>
|
||||
<i class="fas fa-times text-red-500 mt-1"></i>
|
||||
{{ item }}
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -151,10 +157,15 @@ const whatWeDont = [
|
||||
</section>
|
||||
|
||||
<!-- Summary -->
|
||||
<section class="py-16 bg-gradient-to-br from-amber-500 via-orange-500 to-red-500">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-white mb-4">The Goal</h2>
|
||||
<p class="text-white/90 text-lg">
|
||||
<section class="py-20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-amber-500 via-orange-500 to-red-500"></div>
|
||||
|
||||
<div class="relative max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-20 h-20 rounded-full bg-white/20 flex items-center justify-center mx-auto mb-8">
|
||||
<i class="fas fa-bullseye text-white text-3xl"></i>
|
||||
</div>
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-white mb-6">The Goal</h2>
|
||||
<p class="text-white/90 text-xl leading-relaxed">
|
||||
Onboarding should feel like a gradual ramp, not a firehose or an abandonment.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
+248
-175
@@ -1,117 +1,153 @@
|
||||
<script setup>
|
||||
import { ceremonies, incidentProtocol, technicalPractices, definitionOfDone } from '@/data/manifesto'
|
||||
|
||||
const meetingLimits = [
|
||||
{ value: '2 hours', label: 'per week total', icon: 'fas fa-clock', color: 'blue' },
|
||||
{ value: '1 hour', label: 'maximum per meeting', icon: 'fas fa-hourglass-half', color: 'purple' },
|
||||
{ value: 'Agenda', label: 'required or cancelled', icon: 'fas fa-list-check', color: 'emerald' }
|
||||
]
|
||||
|
||||
const collaborationSteps = [
|
||||
{ text: 'Post when stuck', icon: 'fas fa-comment-dots' },
|
||||
{ text: 'Someone responds when available', icon: 'fas fa-reply' },
|
||||
{ text: 'Sync briefly if needed', icon: 'fas fa-video' },
|
||||
{ text: 'Return to solo work', icon: 'fas fa-user' }
|
||||
]
|
||||
|
||||
const multiMakerPrinciples = [
|
||||
{ title: 'Break vertically.', desc: 'Each maker owns an end-to-end slice.', icon: 'fas fa-arrows-alt-v' },
|
||||
{ title: 'Define interfaces first.', desc: 'Work in parallel against contracts.', icon: 'fas fa-plug' },
|
||||
{ title: 'Coordinate via doc.', desc: 'One feature doc as source of truth.', icon: 'fas fa-file-alt' },
|
||||
{ title: 'Sync only when stuck.', desc: 'Document outcome. Return to async.', icon: 'fas fa-sync' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-green-50 via-emerald-50 to-cyan-50 dark:from-gray-900 dark:via-green-900/10 dark:to-emerald-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-green-300 dark:bg-green-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-emerald-300 dark:bg-emerald-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-32 sm:pt-40 pb-16 sm:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-emerald-50 via-teal-50 to-cyan-50 dark:from-gray-900 dark:via-emerald-950/20 dark:to-teal-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-96 h-96 bg-emerald-400/20 dark:bg-emerald-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-80 h-80 bg-teal-400/20 dark:bg-teal-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-green-500 to-emerald-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-cogs text-white text-2xl"></i>
|
||||
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 text-sm font-medium mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-cogs"></i>
|
||||
Day-to-Day
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Practices</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-emerald-500 to-teal-500 flex items-center justify-center mx-auto mb-8 animate-fade-in-up animate-delay-100">
|
||||
<i class="fas fa-cogs text-white text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">Practices</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
How we work day-to-day: meetings, collaboration, incidents, and technical practices.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Meetings -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Meetings</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Meetings</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Hard limits protect our time.</p>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-2xl mb-8">
|
||||
<div class="grid sm:grid-cols-3 gap-6 text-center">
|
||||
<div>
|
||||
<div class="text-3xl font-bold gradient-text mb-2">2 hours</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">per week total</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-3xl font-bold gradient-text mb-2">1 hour</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">maximum per meeting</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-3xl font-bold gradient-text mb-2">Agenda</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">required or cancelled</div>
|
||||
<div class="glass p-8 sm:p-10 rounded-3xl mb-10">
|
||||
<div class="grid sm:grid-cols-3 gap-8">
|
||||
<div
|
||||
v-for="(item, index) in meetingLimits"
|
||||
:key="item.label"
|
||||
class="text-center group"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div
|
||||
class="w-16 h-16 rounded-2xl flex items-center justify-center mx-auto mb-4 transition-all duration-300 group-hover:scale-110"
|
||||
:class="[
|
||||
item.color === 'blue' ? 'bg-blue-100 dark:bg-blue-900/30' :
|
||||
item.color === 'purple' ? 'bg-purple-100 dark:bg-purple-900/30' :
|
||||
'bg-emerald-100 dark:bg-emerald-900/30'
|
||||
]"
|
||||
>
|
||||
<i :class="[item.icon, 'text-2xl', item.color === 'blue' ? 'text-blue-500' : item.color === 'purple' ? 'text-purple-500' : 'text-emerald-500']"></i>
|
||||
</div>
|
||||
<div class="text-3xl sm:text-4xl font-bold gradient-text mb-2">{{ item.value }}</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-5">
|
||||
<div
|
||||
v-for="ceremony in ceremonies"
|
||||
v-for="(ceremony, index) in ceremonies"
|
||||
:key="ceremony.name"
|
||||
class="glass p-5 rounded-xl hover:shadow-lg transition-all duration-300"
|
||||
class="card p-6"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-2">{{ ceremony.name }}</h3>
|
||||
<div class="text-sm text-blue-600 dark:text-blue-400 mb-2">{{ ceremony.duration }}</div>
|
||||
<h3 class="font-semibold text-lg text-gray-900 dark:text-gray-100 mb-2">{{ ceremony.name }}</h3>
|
||||
<div class="inline-block px-3 py-1 rounded-full bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 text-sm font-medium mb-3">
|
||||
{{ ceremony.duration }}
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">{{ ceremony.purpose }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 p-4 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<p class="text-sm text-amber-800 dark:text-amber-200">
|
||||
<i class="fas fa-lightbulb mr-2"></i>
|
||||
If a topic needs more than one hour: write first, comment async, meet on the delta. Never extend.
|
||||
<div class="mt-8 p-5 rounded-xl bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<p class="text-sm text-amber-800 dark:text-amber-200 flex items-start gap-3">
|
||||
<i class="fas fa-lightbulb mt-0.5"></i>
|
||||
<span>If a topic needs more than one hour: write first, comment async, meet on the delta. <strong>Never extend.</strong></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Daily Check-in -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Daily Check-in</h2>
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300 relative overflow-hidden">
|
||||
<div class="absolute bottom-0 left-0 w-96 h-96 bg-blue-500/5 dark:bg-blue-500/10 rounded-full filter blur-3xl"></div>
|
||||
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 relative">
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Daily Check-in</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Replace standups with written updates.</p>
|
||||
</div>
|
||||
|
||||
<div class="max-w-xl mx-auto">
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<!-- Visual Check-in Template -->
|
||||
<div class="glass p-5 sm:p-6 rounded-xl mb-6">
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center gap-3 p-3 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<div class="glass p-8 rounded-3xl mb-8">
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center gap-4 p-4 rounded-xl bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-tasks text-white"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs text-blue-600 dark:text-blue-400 font-semibold uppercase tracking-wide">Working on</div>
|
||||
<div class="text-sm text-gray-700 dark:text-gray-300">[current task]</div>
|
||||
<div class="text-gray-700 dark:text-gray-300">[current task]</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 p-3 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center flex-shrink-0">
|
||||
<div class="flex items-center gap-4 p-4 rounded-xl bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-hand-paper text-white"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs text-amber-600 dark:text-amber-400 font-semibold uppercase tracking-wide">Blocked by</div>
|
||||
<div class="text-sm text-gray-700 dark:text-gray-300">[nothing / specific issue]</div>
|
||||
<div class="text-gray-700 dark:text-gray-300">[nothing / specific issue]</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-3 sm:gap-4">
|
||||
<div class="glass p-3 sm:p-4 rounded-lg text-center">
|
||||
<i class="fas fa-clock text-blue-500 text-lg sm:text-xl mb-2"></i>
|
||||
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">Post once daily</div>
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div class="card p-5 text-center group">
|
||||
<i class="fas fa-clock text-blue-500 text-2xl mb-3 group-hover:scale-110 transition-transform block"></i>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 font-medium">Post once daily</div>
|
||||
</div>
|
||||
<div class="glass p-3 sm:p-4 rounded-lg text-center">
|
||||
<i class="fas fa-stopwatch text-purple-500 text-lg sm:text-xl mb-2"></i>
|
||||
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">Two minutes</div>
|
||||
<div class="card p-5 text-center group">
|
||||
<i class="fas fa-stopwatch text-purple-500 text-2xl mb-3 group-hover:scale-110 transition-transform block"></i>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 font-medium">Two minutes</div>
|
||||
</div>
|
||||
<div class="glass p-3 sm:p-4 rounded-lg text-center">
|
||||
<i class="fas fa-users-slash text-green-500 text-lg sm:text-xl mb-2"></i>
|
||||
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">No gathering</div>
|
||||
<div class="card p-5 text-center group">
|
||||
<i class="fas fa-users-slash text-emerald-500 text-2xl mb-3 group-hover:scale-110 transition-transform block"></i>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 font-medium">No gathering</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,66 +155,68 @@ import { ceremonies, incidentProtocol, technicalPractices, definitionOfDone } fr
|
||||
</section>
|
||||
|
||||
<!-- Collaboration -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Collaboration</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Collaboration</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Default mode is solo deep work.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<div class="glass p-6 rounded-xl">
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<i class="fas fa-hand-holding-heart text-blue-500 mr-2"></i>
|
||||
Ad-hoc Help
|
||||
</h3>
|
||||
<ol class="space-y-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="w-6 h-6 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex items-center justify-center flex-shrink-0 text-xs font-bold">1</span>
|
||||
Post when stuck
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="w-6 h-6 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex items-center justify-center flex-shrink-0 text-xs font-bold">2</span>
|
||||
Someone responds when available
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="w-6 h-6 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex items-center justify-center flex-shrink-0 text-xs font-bold">3</span>
|
||||
Sync briefly if needed
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="w-6 h-6 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex items-center justify-center flex-shrink-0 text-xs font-bold">4</span>
|
||||
Return to solo work
|
||||
</li>
|
||||
</ol>
|
||||
<!-- Ad-hoc Help -->
|
||||
<div class="card p-8">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center">
|
||||
<i class="fas fa-hand-holding-heart text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Ad-hoc Help</h3>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div
|
||||
v-for="(step, index) in collaborationSteps"
|
||||
:key="step.text"
|
||||
class="flex items-center gap-4 p-4 rounded-xl bg-gray-50 dark:bg-gray-800/50 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-colors"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="w-10 h-10 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 flex items-center justify-center flex-shrink-0 font-bold">
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<i :class="step.icon" class="text-blue-500"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ step.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl">
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<i class="fas fa-users text-purple-500 mr-2"></i>
|
||||
Multi-Maker Work
|
||||
</h3>
|
||||
<ul class="space-y-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-start gap-3">
|
||||
<i class="fas fa-check-circle text-green-500 mt-0.5"></i>
|
||||
<span><strong>Break vertically.</strong> Each maker owns an end-to-end slice.</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i class="fas fa-check-circle text-green-500 mt-0.5"></i>
|
||||
<span><strong>Define interfaces first.</strong> Work in parallel against contracts.</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i class="fas fa-check-circle text-green-500 mt-0.5"></i>
|
||||
<span><strong>Coordinate via doc.</strong> One feature doc as source of truth.</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i class="fas fa-check-circle text-green-500 mt-0.5"></i>
|
||||
<span><strong>Sync only when stuck.</strong> Document outcome. Return to async.</span>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Multi-Maker Work -->
|
||||
<div class="card p-8">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<i class="fas fa-users text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Multi-Maker Work</h3>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div
|
||||
v-for="(principle, index) in multiMakerPrinciples"
|
||||
:key="principle.title"
|
||||
class="flex items-start gap-4 p-4 rounded-xl bg-gray-50 dark:bg-gray-800/50 hover:bg-purple-50 dark:hover:bg-purple-900/20 transition-colors"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="w-10 h-10 rounded-full bg-emerald-100 dark:bg-emerald-900/30 flex items-center justify-center flex-shrink-0">
|
||||
<i :class="principle.icon" class="text-emerald-500"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-semibold text-gray-900 dark:text-gray-100 block">{{ principle.title }}</span>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">{{ principle.desc }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 p-4 rounded-lg bg-gray-100 dark:bg-gray-800">
|
||||
<div class="mt-8 p-5 rounded-xl bg-gray-100 dark:bg-gray-800">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 text-center">
|
||||
We do not schedule pairing. We do not mandate walkthroughs. We do not assign buddies. Collaboration is initiated by those who need it.
|
||||
</p>
|
||||
@@ -187,134 +225,169 @@ import { ceremonies, incidentProtocol, technicalPractices, definitionOfDone } fr
|
||||
</section>
|
||||
|
||||
<!-- Definition of Done -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Definition of Done</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Definition of Done</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Work is not done until it meets these criteria.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<div class="glass p-6 rounded-xl">
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<i class="fas fa-code text-blue-500 mr-2"></i>
|
||||
For Code
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<div class="card p-8">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center">
|
||||
<i class="fas fa-code text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">For Code</h3>
|
||||
</div>
|
||||
<ul class="space-y-3">
|
||||
<li
|
||||
v-for="item in definitionOfDone.code"
|
||||
:key="item"
|
||||
class="flex items-center gap-3 text-sm text-gray-600 dark:text-gray-400"
|
||||
class="flex items-center gap-3 p-3 rounded-xl bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-200 dark:border-emerald-800"
|
||||
>
|
||||
<i class="fas fa-check text-green-500"></i>
|
||||
{{ item }}
|
||||
<div class="w-8 h-8 rounded-full bg-emerald-500 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-check text-white text-sm"></i>
|
||||
</div>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl">
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<i class="fas fa-file-alt text-purple-500 mr-2"></i>
|
||||
For Non-Code
|
||||
</h3>
|
||||
<ul class="space-y-2">
|
||||
<div class="card p-8">
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center">
|
||||
<i class="fas fa-file-alt text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">For Non-Code</h3>
|
||||
</div>
|
||||
<ul class="space-y-3">
|
||||
<li
|
||||
v-for="item in definitionOfDone.nonCode"
|
||||
:key="item"
|
||||
class="flex items-center gap-3 text-sm text-gray-600 dark:text-gray-400"
|
||||
class="flex items-center gap-3 p-3 rounded-xl bg-purple-50 dark:bg-purple-900/20 border border-purple-200 dark:border-purple-800"
|
||||
>
|
||||
<i class="fas fa-check text-green-500"></i>
|
||||
{{ item }}
|
||||
<div class="w-8 h-8 rounded-full bg-purple-500 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-check text-white text-sm"></i>
|
||||
</div>
|
||||
<span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 p-4 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<p class="text-sm text-blue-800 dark:text-blue-200">
|
||||
<i class="fas fa-info-circle mr-2"></i>
|
||||
The team owns this definition. Adjust it as needed. But once agreed, honor it. "Done" means done—not "done but..." or "done except..."
|
||||
<div class="mt-8 p-5 rounded-xl bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<p class="text-sm text-blue-800 dark:text-blue-200 flex items-start gap-3">
|
||||
<i class="fas fa-info-circle mt-0.5"></i>
|
||||
<span>The team owns this definition. Adjust it as needed. But once agreed, honor it. "Done" means done—not "done but..." or "done except..."</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Incidents -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Incidents & Emergencies</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Incidents & Emergencies</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">When production breaks, normal rules suspend temporarily.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-8 mb-8">
|
||||
<div class="glass p-6 rounded-xl border-l-4 border-red-500">
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">What Qualifies</h3>
|
||||
<ul class="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<li class="flex items-center gap-2">
|
||||
<i class="fas fa-exclamation-triangle text-red-500"></i>
|
||||
Users cannot complete critical actions
|
||||
<div class="card p-8 border-l-4 border-red-500">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
|
||||
<i class="fas fa-exclamation-triangle text-red-500"></i>
|
||||
What Qualifies
|
||||
</h3>
|
||||
<ul class="space-y-4">
|
||||
<li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
|
||||
<i class="fas fa-times-circle text-red-500"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">Users cannot complete critical actions</span>
|
||||
</li>
|
||||
<li class="flex items-center gap-2">
|
||||
<i class="fas fa-exclamation-triangle text-red-500"></i>
|
||||
Data integrity is at risk
|
||||
<li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
|
||||
<i class="fas fa-times-circle text-red-500"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">Data integrity is at risk</span>
|
||||
</li>
|
||||
<li class="flex items-center gap-2">
|
||||
<i class="fas fa-exclamation-triangle text-red-500"></i>
|
||||
Security vulnerability being exploited
|
||||
<li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
|
||||
<i class="fas fa-times-circle text-red-500"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">Security vulnerability being exploited</span>
|
||||
</li>
|
||||
<li class="flex items-center gap-2">
|
||||
<i class="fas fa-exclamation-triangle text-red-500"></i>
|
||||
Significant revenue or reputation impact
|
||||
<li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
|
||||
<i class="fas fa-times-circle text-red-500"></i>
|
||||
<span class="text-gray-700 dark:text-gray-300">Significant revenue or reputation impact</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="glass p-6 rounded-xl">
|
||||
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">Incident Protocol</h3>
|
||||
<ol class="space-y-3">
|
||||
<li
|
||||
v-for="step in incidentProtocol"
|
||||
:key="step.step"
|
||||
class="flex items-start gap-3"
|
||||
>
|
||||
<span class="font-bold text-blue-600 dark:text-blue-400 text-sm">{{ step.step }}</span>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">{{ step.description }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="card p-8">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
|
||||
<i class="fas fa-clipboard-list text-blue-500"></i>
|
||||
Incident Protocol
|
||||
</h3>
|
||||
<div class="relative">
|
||||
<!-- Flow line -->
|
||||
<div class="absolute left-5 top-8 bottom-8 w-0.5 bg-gradient-to-b from-red-500 via-orange-500 to-green-500 hidden sm:block"></div>
|
||||
<div class="space-y-4">
|
||||
<div
|
||||
v-for="(step, index) in incidentProtocol"
|
||||
:key="step.step"
|
||||
class="flex items-start gap-4"
|
||||
>
|
||||
<div
|
||||
class="w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 z-10 text-sm font-bold"
|
||||
:class="[
|
||||
index === 0 ? 'bg-red-500 text-white' :
|
||||
index === 1 ? 'bg-orange-500 text-white' :
|
||||
index === 2 ? 'bg-amber-500 text-white' :
|
||||
index === 3 ? 'bg-blue-500 text-white' :
|
||||
'bg-green-500 text-white'
|
||||
]"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
<div class="flex-1 pb-2">
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100">{{ step.step.replace(/^\d+\.\s*/, '') }}</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">{{ step.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<p class="text-sm text-amber-800 dark:text-amber-200">
|
||||
<i class="fas fa-lightbulb mr-2"></i>
|
||||
This is not normal work. Incidents should be rare. If they're frequent, that's a systemic problem to solve—not a reason to abandon sustainable pace.
|
||||
<div class="p-5 rounded-xl bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<p class="text-sm text-amber-800 dark:text-amber-200 flex items-start gap-3">
|
||||
<i class="fas fa-lightbulb mt-0.5"></i>
|
||||
<span>This is not normal work. Incidents should be rare. If they're frequent, that's a systemic problem to solve—not a reason to abandon sustainable pace.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Technical Practices -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Technical Practices</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Technical Practices</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400">Optional practices that align well with BEAT principles.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
|
||||
<div
|
||||
v-for="practice in technicalPractices"
|
||||
v-for="(practice, index) in technicalPractices"
|
||||
:key="practice.name"
|
||||
class="glass p-5 rounded-xl hover:shadow-lg transition-all duration-300"
|
||||
class="card p-6 group"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-2">{{ practice.name }}</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">{{ practice.description }}</p>
|
||||
<h3 class="font-semibold text-lg text-gray-900 dark:text-gray-100 mb-3 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||
{{ practice.name }}
|
||||
</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">{{ practice.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="mt-8 text-center text-sm text-gray-500 dark:text-gray-500">
|
||||
These are not mandated. They are offered as practices that support focus, speed, and quality. Adopt what serves you. Discard what doesn't.
|
||||
<p class="mt-10 text-center text-gray-500 dark:text-gray-500">
|
||||
These are not mandated. They are offered as practices that support focus, speed, and quality. <strong class="text-gray-700 dark:text-gray-300">Adopt what serves you. Discard what doesn't.</strong>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -2,27 +2,31 @@
|
||||
import { principles } from '@/data/manifesto'
|
||||
|
||||
const categories = [
|
||||
{ key: 'focus', title: 'On Focus', icon: 'fas fa-bullseye', gradient: 'from-blue-500 to-cyan-500', color: 'blue' },
|
||||
{ key: 'communication', title: 'On Communication', icon: 'fas fa-comments', gradient: 'from-purple-500 to-pink-500', color: 'purple' },
|
||||
{ key: 'autonomy', title: 'On Autonomy', icon: 'fas fa-user-shield', gradient: 'from-green-500 to-emerald-500', color: 'green' },
|
||||
{ key: 'sustainability', title: 'On Sustainability', icon: 'fas fa-leaf', gradient: 'from-amber-500 to-orange-500', color: 'amber' }
|
||||
{ key: 'focus', title: 'On Focus', icon: 'fas fa-bullseye', gradient: 'from-blue-500 to-cyan-500', color: 'blue', desc: 'Protecting the deep work state' },
|
||||
{ key: 'communication', title: 'On Communication', icon: 'fas fa-comments', gradient: 'from-purple-500 to-pink-500', color: 'purple', desc: 'Writing first, meeting wisely' },
|
||||
{ key: 'autonomy', title: 'On Autonomy', icon: 'fas fa-user-shield', gradient: 'from-emerald-500 to-teal-500', color: 'emerald', desc: 'Trusting makers to make' },
|
||||
{ key: 'sustainability', title: 'On Sustainability', icon: 'fas fa-leaf', gradient: 'from-amber-500 to-orange-500', color: 'amber', desc: 'Pace that lasts' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 via-purple-50 to-green-50 dark:from-gray-900 dark:via-blue-900/10 dark:to-purple-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-blue-300 dark:bg-blue-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-purple-300 dark:bg-purple-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-28 sm:pt-32 lg:pt-40 pb-12 sm:pb-16 lg:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-50 via-purple-50 to-green-50 dark:from-gray-900 dark:via-blue-950/20 dark:to-purple-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-72 h-72 sm:w-96 sm:h-96 bg-blue-400/20 dark:bg-blue-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-64 h-64 sm:w-80 sm:h-80 bg-purple-400/20 dark:bg-purple-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-compass text-white text-2xl"></i>
|
||||
<div class="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 text-center">
|
||||
<div class="inline-flex items-center gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 text-xs sm:text-sm font-medium mb-4 sm:mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-compass"></i>
|
||||
Guiding Principles
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">The Twelve Principles</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-16 h-16 sm:w-20 sm:h-20 rounded-xl sm:rounded-2xl bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center mx-auto mb-6 sm:mb-8 animate-fade-in-up animate-delay-100 shadow-glow-blue">
|
||||
<i class="fas fa-compass text-white text-2xl sm:text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">The Twelve Principles</h1>
|
||||
<p class="section-subtitle max-w-2xl lg:max-w-3xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
Guiding principles organized into four categories: Focus, Communication, Autonomy, and Sustainability.
|
||||
</p>
|
||||
</div>
|
||||
@@ -30,40 +34,44 @@ const categories = [
|
||||
|
||||
<!-- Principles by Category -->
|
||||
<section
|
||||
v-for="category in categories"
|
||||
v-for="(category, catIndex) in categories"
|
||||
:key="category.key"
|
||||
class="py-16 transition-colors duration-300"
|
||||
:class="categories.indexOf(category) % 2 === 0 ? 'bg-white dark:bg-gray-900' : 'bg-gray-50 dark:bg-gray-800/50'"
|
||||
class="py-12 sm:py-16 lg:py-20 transition-colors duration-300 relative"
|
||||
:class="catIndex % 2 === 0 ? 'bg-white dark:bg-gray-900' : 'bg-gray-50 dark:bg-gray-800/30'"
|
||||
>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="flex items-center gap-4 mb-8">
|
||||
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4 mb-6 sm:mb-10">
|
||||
<div
|
||||
class="w-12 h-12 rounded-xl bg-gradient-to-br flex items-center justify-center"
|
||||
class="w-12 h-12 sm:w-14 sm:h-14 lg:w-16 lg:h-16 rounded-xl sm:rounded-2xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 shadow-lg"
|
||||
:class="category.gradient"
|
||||
>
|
||||
<i :class="category.icon" class="text-white"></i>
|
||||
<i :class="category.icon" class="text-white text-xl sm:text-2xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl sm:text-2xl lg:text-3xl font-bold text-gray-900 dark:text-gray-100">{{ category.title }}</h2>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-sm sm:text-base">{{ category.desc }}</p>
|
||||
</div>
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">{{ category.title }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="space-y-4 sm:space-y-5">
|
||||
<div
|
||||
v-for="principle in principles[category.key]"
|
||||
v-for="(principle, index) in principles[category.key]"
|
||||
:key="principle.number"
|
||||
class="glass p-6 sm:p-8 rounded-xl hover:shadow-lg transition-all duration-300"
|
||||
class="card group p-5 sm:p-6 lg:p-8"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="flex items-start gap-3 sm:gap-5">
|
||||
<div
|
||||
class="w-10 h-10 rounded-full bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
class="w-9 h-9 sm:w-10 sm:h-10 lg:w-12 lg:h-12 rounded-lg sm:rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0 shadow-md group-hover:scale-110 transition-all duration-300"
|
||||
:class="category.gradient"
|
||||
>
|
||||
<span class="text-white font-bold">{{ principle.number }}</span>
|
||||
<span class="text-white font-bold text-sm sm:text-base lg:text-lg">{{ principle.number }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-3">
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="text-lg sm:text-xl lg:text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2 sm:mb-3 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||
{{ principle.title }}
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed text-sm sm:text-base">
|
||||
{{ principle.description }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -74,22 +82,33 @@ const categories = [
|
||||
</section>
|
||||
|
||||
<!-- Summary -->
|
||||
<section class="py-16 bg-gradient-to-br from-blue-600 via-purple-600 to-green-600">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-white mb-6">Principles in Summary</h2>
|
||||
<div class="grid sm:grid-cols-2 gap-4 text-left">
|
||||
<section class="py-12 sm:py-16 lg:py-20 relative overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-emerald-600"></div>
|
||||
|
||||
<!-- Animated pattern -->
|
||||
<div class="absolute inset-0 opacity-10">
|
||||
<div class="absolute top-0 left-0 w-full h-full bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9InAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgNDBoNDBWMEgwVjQwWiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0wIDQwaDQwVjBIMFY0MFoiIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI3ApIi8+PC9zdmc+')] animate-pulse-slow"></div>
|
||||
</div>
|
||||
|
||||
<div class="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
|
||||
<h2 class="text-2xl sm:text-3xl lg:text-4xl font-bold text-white text-center mb-8 sm:mb-10">Principles in Summary</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-5">
|
||||
<div
|
||||
v-for="category in categories"
|
||||
v-for="(category, index) in categories"
|
||||
:key="category.key"
|
||||
class="bg-white/10 backdrop-blur-sm p-4 rounded-xl"
|
||||
class="bg-white/10 backdrop-blur-sm p-5 sm:p-6 rounded-xl sm:rounded-2xl border border-white/10 hover:bg-white/20 transition-all duration-300"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<i :class="category.icon" class="text-white"></i>
|
||||
<span class="text-white font-semibold">{{ category.title }}</span>
|
||||
<div class="flex items-center gap-3 mb-3 sm:mb-4">
|
||||
<div class="w-9 h-9 sm:w-10 sm:h-10 rounded-lg sm:rounded-xl bg-white/20 flex items-center justify-center">
|
||||
<i :class="category.icon" class="text-white"></i>
|
||||
</div>
|
||||
<span class="text-white font-semibold text-base sm:text-lg">{{ category.title }}</span>
|
||||
</div>
|
||||
<ul class="text-white/80 text-sm space-y-1">
|
||||
<li v-for="p in principles[category.key]" :key="p.number">
|
||||
{{ p.number }}. {{ p.title.split('.')[0] }}
|
||||
<ul class="text-white/80 text-xs sm:text-sm space-y-1.5 sm:space-y-2">
|
||||
<li v-for="p in principles[category.key]" :key="p.number" class="flex items-center gap-2">
|
||||
<span class="w-5 h-5 rounded-full bg-white/20 flex items-center justify-center text-xs flex-shrink-0">{{ p.number }}</span>
|
||||
<span class="truncate">{{ p.title.split('.')[0] }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup>
|
||||
import TableCard from '@/components/ui/TableCard.vue'
|
||||
import CopyButton from '@/components/ui/CopyButton.vue'
|
||||
import { coreValues, teamValues, constraints, priorityBuckets, roles, ceremonies, definitionOfDone, incidentProtocol } from '@/data/manifesto'
|
||||
|
||||
const coreValuesHeaders = ['We Value More', 'Over']
|
||||
@@ -47,66 +48,99 @@ const spottedIssueFlow = [
|
||||
]
|
||||
|
||||
const colorMap = {
|
||||
red: 'from-red-500 to-red-600 bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800 text-red-700 dark:text-red-300',
|
||||
amber: 'from-amber-500 to-amber-600 bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800 text-amber-700 dark:text-amber-300',
|
||||
blue: 'from-blue-500 to-blue-600 bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800 text-blue-700 dark:text-blue-300',
|
||||
purple: 'from-purple-500 to-purple-600 bg-purple-50 dark:bg-purple-900/20 border-purple-200 dark:border-purple-800 text-purple-700 dark:text-purple-300'
|
||||
red: { bg: 'from-red-500 to-red-600', border: 'border-red-200 dark:border-red-800', text: 'text-red-700 dark:text-red-300', badge: 'bg-red-50 dark:bg-red-900/20' },
|
||||
amber: { bg: 'from-amber-500 to-amber-600', border: 'border-amber-200 dark:border-amber-800', text: 'text-amber-700 dark:text-amber-300', badge: 'bg-amber-50 dark:bg-amber-900/20' },
|
||||
blue: { bg: 'from-blue-500 to-blue-600', border: 'border-blue-200 dark:border-blue-800', text: 'text-blue-700 dark:text-blue-300', badge: 'bg-blue-50 dark:bg-blue-900/20' },
|
||||
purple: { bg: 'from-purple-500 to-purple-600', border: 'border-purple-200 dark:border-purple-800', text: 'text-purple-700 dark:text-purple-300', badge: 'bg-purple-50 dark:bg-purple-900/20' }
|
||||
}
|
||||
|
||||
const incidentColors = [
|
||||
'from-red-500 to-red-600',
|
||||
'from-orange-500 to-orange-600',
|
||||
'from-amber-500 to-amber-600',
|
||||
'from-blue-500 to-blue-600',
|
||||
'from-green-500 to-green-600'
|
||||
]
|
||||
|
||||
// Template text for copying
|
||||
const dailyCheckinTemplate = `Working on: [current task]
|
||||
Blocked by: [nothing / specific issue]`
|
||||
|
||||
const definitionOfDoneText = definitionOfDone.code.join('\n')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-cyan-50 via-blue-50 to-indigo-50 dark:from-gray-900 dark:via-cyan-900/10 dark:to-blue-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-cyan-300 dark:bg-cyan-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-blue-300 dark:bg-blue-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-32 sm:pt-40 pb-16 sm:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-cyan-50 via-blue-50 to-indigo-50 dark:from-gray-900 dark:via-cyan-950/20 dark:to-blue-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-96 h-96 bg-cyan-400/20 dark:bg-cyan-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-80 h-80 bg-blue-400/20 dark:bg-blue-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-cyan-500 to-blue-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-book text-white text-2xl"></i>
|
||||
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300 text-sm font-medium mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-book"></i>
|
||||
Quick Lookup
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Quick Reference</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
Everything you need at a glance.
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-cyan-500 to-blue-500 flex items-center justify-center mx-auto mb-8 animate-fade-in-up animate-delay-100">
|
||||
<i class="fas fa-book text-white text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">Quick Reference</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
Everything you need at a glance. Copy templates with one click.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Core Values -->
|
||||
<section class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Core Values</h2>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-rose-500 to-pink-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Core Values</h2>
|
||||
</div>
|
||||
<TableCard :headers="coreValuesHeaders" :rows="coreValuesRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Team Values -->
|
||||
<section class="py-8 sm:py-12 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Team Values</h2>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-blue-500 to-purple-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Team Values</h2>
|
||||
</div>
|
||||
<TableCard :headers="teamValuesHeaders" :rows="teamValuesRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- The Numbers -->
|
||||
<section class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">The Numbers</h2>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-purple-500 to-indigo-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">The Numbers</h2>
|
||||
</div>
|
||||
<TableCard :headers="constraintsHeaders" :rows="constraintsRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Buckets & Roles -->
|
||||
<section class="py-8 sm:py-12 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid md:grid-cols-2 gap-6 sm:gap-8">
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Priority Buckets</h2>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-amber-500 to-orange-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Priority Buckets</h2>
|
||||
</div>
|
||||
<TableCard :headers="bucketsHeaders" :rows="bucketsRows" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Roles</h2>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-emerald-500 to-teal-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Roles</h2>
|
||||
</div>
|
||||
<TableCard :headers="rolesHeaders" :rows="rolesRows" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,71 +148,85 @@ const colorMap = {
|
||||
</section>
|
||||
|
||||
<!-- Ceremonies -->
|
||||
<section class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Ceremonies</h2>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-cyan-500 to-blue-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Ceremonies</h2>
|
||||
</div>
|
||||
<TableCard :headers="ceremoniesHeaders" :rows="ceremoniesRows" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Templates -->
|
||||
<section class="py-8 sm:py-12 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<!-- Templates with Copy Buttons -->
|
||||
<section class="py-10 sm:py-14 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-6">Templates</h2>
|
||||
<div class="flex items-center gap-3 mb-8">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-pink-500 to-rose-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Templates</h2>
|
||||
<span class="px-2 py-1 rounded-full bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 text-xs font-medium">Click to copy</span>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-6">
|
||||
<!-- Daily Check-in Card -->
|
||||
<div class="glass p-5 sm:p-6 rounded-xl">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
||||
<i class="fas fa-calendar-check text-blue-500"></i>
|
||||
Daily Check-in
|
||||
</h3>
|
||||
<div class="card p-6">
|
||||
<div class="flex items-center justify-between mb-5">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-xl bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center">
|
||||
<i class="fas fa-calendar-check text-blue-500"></i>
|
||||
</div>
|
||||
Daily Check-in
|
||||
</h3>
|
||||
<CopyButton :text="dailyCheckinTemplate" label="Copy" />
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center gap-3 p-3 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-tasks text-white text-xs"></i>
|
||||
<div class="flex items-center gap-4 p-4 rounded-xl bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-tasks text-white"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs text-blue-600 dark:text-blue-400 font-medium">Working on</div>
|
||||
<div class="text-sm text-gray-700 dark:text-gray-300">[current task]</div>
|
||||
<div class="text-xs text-blue-600 dark:text-blue-400 font-semibold uppercase tracking-wide">Working on</div>
|
||||
<div class="text-gray-700 dark:text-gray-300">[current task]</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 p-3 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-hand-paper text-white text-xs"></i>
|
||||
<div class="flex items-center gap-4 p-4 rounded-xl bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-hand-paper text-white"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xs text-amber-600 dark:text-amber-400 font-medium">Blocked by</div>
|
||||
<div class="text-sm text-gray-700 dark:text-gray-300">[nothing / specific issue]</div>
|
||||
<div class="text-xs text-amber-600 dark:text-amber-400 font-semibold uppercase tracking-wide">Blocked by</div>
|
||||
<div class="text-gray-700 dark:text-gray-300">[nothing / specific issue]</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Spotted Issue Decision Flow -->
|
||||
<div class="glass p-5 sm:p-6 rounded-xl">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2">
|
||||
<i class="fas fa-code-branch text-purple-500"></i>
|
||||
<div class="card p-6">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-5 flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-xl bg-purple-100 dark:bg-purple-900/30 flex items-center justify-center">
|
||||
<i class="fas fa-code-branch text-purple-500"></i>
|
||||
</div>
|
||||
Spotted Issue Decision
|
||||
</h3>
|
||||
<div class="space-y-2">
|
||||
<div class="space-y-3">
|
||||
<div
|
||||
v-for="(item, index) in spottedIssueFlow"
|
||||
:key="index"
|
||||
class="flex items-center gap-2 sm:gap-3 p-2 sm:p-3 rounded-lg border"
|
||||
:class="colorMap[item.color].split(' ').slice(2).join(' ')"
|
||||
class="flex items-center gap-3 p-3 rounded-xl border"
|
||||
:class="[colorMap[item.color].badge, colorMap[item.color].border]"
|
||||
>
|
||||
<div
|
||||
class="w-7 h-7 sm:w-8 sm:h-8 rounded-full bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
:class="colorMap[item.color].split(' ').slice(0, 2).join(' ')"
|
||||
class="w-10 h-10 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0"
|
||||
:class="colorMap[item.color].bg"
|
||||
>
|
||||
<i :class="item.icon" class="text-white text-xs"></i>
|
||||
<i :class="item.icon" class="text-white"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<span class="text-xs sm:text-sm font-medium">{{ item.question }}</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ item.question }}</span>
|
||||
</div>
|
||||
<i class="fas fa-arrow-right text-xs opacity-50 hidden sm:block"></i>
|
||||
<span class="text-xs sm:text-sm font-bold whitespace-nowrap">{{ item.answer }}</span>
|
||||
<i class="fas fa-arrow-right text-xs opacity-50"></i>
|
||||
<span class="text-sm font-bold whitespace-nowrap" :class="colorMap[item.color].text">{{ item.answer }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -187,18 +235,24 @@ const colorMap = {
|
||||
</section>
|
||||
|
||||
<!-- Definition of Done -->
|
||||
<section class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Definition of Done (Code)</h2>
|
||||
<div class="glass p-5 sm:p-6 rounded-xl">
|
||||
<div class="grid sm:grid-cols-2 gap-2 sm:gap-3">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-emerald-500 to-green-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Definition of Done (Code)</h2>
|
||||
</div>
|
||||
<CopyButton :text="definitionOfDoneText" label="Copy All" />
|
||||
</div>
|
||||
<div class="card p-6">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<div
|
||||
v-for="item in definitionOfDone.code"
|
||||
:key="item"
|
||||
class="flex items-center gap-3 p-2 sm:p-3 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800"
|
||||
class="flex items-center gap-3 p-4 rounded-xl bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-200 dark:border-emerald-800"
|
||||
>
|
||||
<div class="w-6 h-6 rounded-full bg-gradient-to-br from-green-500 to-green-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-check text-white text-xs"></i>
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-emerald-500 to-emerald-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-check text-white text-sm"></i>
|
||||
</div>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ item }}</span>
|
||||
</div>
|
||||
@@ -208,34 +262,31 @@ const colorMap = {
|
||||
</section>
|
||||
|
||||
<!-- Incident Protocol -->
|
||||
<section class="py-8 sm:py-12 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Incident Protocol</h2>
|
||||
<div class="glass p-5 sm:p-6 rounded-xl">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-1 h-6 rounded-full bg-gradient-to-b from-red-500 to-orange-500"></div>
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-gray-100">Incident Protocol</h2>
|
||||
</div>
|
||||
<div class="card p-6">
|
||||
<div class="relative">
|
||||
<!-- Flow line for desktop -->
|
||||
<div class="hidden sm:block absolute left-5 top-8 bottom-8 w-0.5 bg-gradient-to-b from-red-500 via-amber-500 to-green-500"></div>
|
||||
<div class="hidden sm:block absolute left-6 top-12 bottom-12 w-0.5 bg-gradient-to-b from-red-500 via-orange-500 via-amber-500 via-blue-500 to-green-500"></div>
|
||||
<div class="space-y-4">
|
||||
<div
|
||||
v-for="(step, index) in incidentProtocol"
|
||||
:key="step.step"
|
||||
class="flex items-start gap-3 sm:gap-4"
|
||||
class="flex items-start gap-4"
|
||||
>
|
||||
<div
|
||||
class="w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 z-10"
|
||||
:class="[
|
||||
index === 0 ? 'bg-gradient-to-br from-red-500 to-red-600' :
|
||||
index === 1 ? 'bg-gradient-to-br from-orange-500 to-orange-600' :
|
||||
index === 2 ? 'bg-gradient-to-br from-amber-500 to-amber-600' :
|
||||
index === 3 ? 'bg-gradient-to-br from-blue-500 to-blue-600' :
|
||||
'bg-gradient-to-br from-green-500 to-green-600'
|
||||
]"
|
||||
class="w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0 z-10 shadow-lg"
|
||||
:class="incidentColors[index]"
|
||||
>
|
||||
<span class="text-white font-bold text-sm">{{ index + 1 }}</span>
|
||||
<span class="text-white font-bold">{{ index + 1 }}</span>
|
||||
</div>
|
||||
<div class="flex-1 pb-2">
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100 text-sm sm:text-base">{{ step.step.replace(/^\d+\.\s*/, '') }}</div>
|
||||
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">{{ step.description }}</div>
|
||||
<div class="flex-1 pb-2 pt-2">
|
||||
<div class="font-semibold text-gray-900 dark:text-gray-100">{{ step.step.replace(/^\d+\.\s*/, '') }}</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400">{{ step.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -245,13 +296,13 @@ const colorMap = {
|
||||
</section>
|
||||
|
||||
<!-- Footer Note -->
|
||||
<section class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-10 sm:py-14 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="glass p-5 sm:p-6 rounded-xl">
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm mb-2">
|
||||
BEAT v1.0 by <strong>Lukasz Raczylo</strong>
|
||||
<div class="card p-8">
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-2">
|
||||
BEAT v1.0 by <strong class="text-gray-900 dark:text-gray-100">Lukasz Raczylo</strong>
|
||||
</p>
|
||||
<p class="text-gray-500 dark:text-gray-500 text-xs">
|
||||
<p class="text-gray-500 dark:text-gray-500 text-sm italic">
|
||||
Attribution appreciated. Improvement welcomed. Dogma discouraged.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup>
|
||||
import IconCard from '@/components/ui/IconCard.vue'
|
||||
import TableCard from '@/components/ui/TableCard.vue'
|
||||
import { coreValues, teamValues } from '@/data/manifesto'
|
||||
|
||||
@@ -13,27 +12,31 @@ const coreValuesRows = coreValues.map(v => [
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero -->
|
||||
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-red-50 via-pink-50 to-purple-50 dark:from-gray-900 dark:via-red-900/10 dark:to-pink-900/10 transition-colors duration-300"></div>
|
||||
<div class="absolute top-0 -left-4 w-72 h-72 bg-red-300 dark:bg-red-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float"></div>
|
||||
<div class="absolute top-0 -right-4 w-72 h-72 bg-pink-300 dark:bg-pink-500 rounded-full mix-blend-multiply dark:mix-blend-soft-light filter blur-xl opacity-20 animate-float animate-delay-1000"></div>
|
||||
<section class="relative pt-32 sm:pt-40 pb-16 sm:pb-20 overflow-hidden">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-rose-50 via-pink-50 to-purple-50 dark:from-gray-900 dark:via-rose-950/20 dark:to-pink-950/20 transition-colors duration-300"></div>
|
||||
<div class="absolute top-20 -left-20 w-96 h-96 bg-rose-400/20 dark:bg-rose-500/20 rounded-full filter blur-3xl animate-float"></div>
|
||||
<div class="absolute top-40 -right-20 w-80 h-80 bg-pink-400/20 dark:bg-pink-500/20 rounded-full filter blur-3xl animate-float animate-delay-2000"></div>
|
||||
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="w-16 h-16 rounded-xl bg-gradient-to-br from-red-500 to-pink-500 flex items-center justify-center mx-auto mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-heart text-white text-2xl"></i>
|
||||
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-rose-100 dark:bg-rose-900/30 text-rose-700 dark:text-rose-300 text-sm font-medium mb-6 animate-fade-in-up">
|
||||
<i class="fas fa-heart"></i>
|
||||
Foundation
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-100">Values</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200">
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-rose-500 to-pink-500 flex items-center justify-center mx-auto mb-8 animate-fade-in-up animate-delay-100 shadow-glow-blue">
|
||||
<i class="fas fa-heart text-white text-3xl"></i>
|
||||
</div>
|
||||
<h1 class="section-title animate-fade-in-up animate-delay-200">Values</h1>
|
||||
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-300">
|
||||
The foundation of everything we do. What we value in our work and how we treat each other.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Core Values -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Core Values</h2>
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">Core Values</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
|
||||
While there is value in the items on the right, we value the items on the left more.
|
||||
</p>
|
||||
@@ -44,18 +47,19 @@ const coreValuesRows = coreValues.map(v => [
|
||||
<!-- Visual Cards -->
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-12">
|
||||
<div
|
||||
v-for="value in coreValues"
|
||||
v-for="(value, index) in coreValues"
|
||||
:key="value.valueMore"
|
||||
class="glass p-6 rounded-xl group hover:shadow-lg transition-all duration-300"
|
||||
class="card group"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-center gap-4 mb-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center group-hover:scale-110 transition-transform duration-300">
|
||||
<i :class="value.icon" class="text-white text-sm"></i>
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center group-hover:scale-110 transition-all duration-300">
|
||||
<i :class="value.icon" class="text-white"></i>
|
||||
</div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-gray-100">{{ value.valueMore }}</h3>
|
||||
<h3 class="font-semibold text-lg text-gray-900 dark:text-gray-100">{{ value.valueMore }}</h3>
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-500">
|
||||
over {{ value.over }}
|
||||
over <span class="text-gray-700 dark:text-gray-300">{{ value.over }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,10 +67,12 @@ const coreValuesRows = coreValues.map(v => [
|
||||
</section>
|
||||
|
||||
<!-- Team Values -->
|
||||
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">The Five Team Values</h2>
|
||||
<section class="py-20 bg-gray-50 dark:bg-gray-800/30 transition-colors duration-300 relative overflow-hidden">
|
||||
<div class="absolute bottom-0 right-0 w-96 h-96 bg-purple-500/5 dark:bg-purple-500/10 rounded-full filter blur-3xl"></div>
|
||||
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 relative">
|
||||
<div class="text-center mb-14">
|
||||
<h2 class="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-4">The Five Team Values</h2>
|
||||
<p class="text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
|
||||
Beyond what we value in our work, we hold these values in how we treat each other.
|
||||
</p>
|
||||
@@ -74,20 +80,21 @@ const coreValuesRows = coreValues.map(v => [
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div
|
||||
v-for="value in teamValues"
|
||||
v-for="(value, index) in teamValues"
|
||||
:key="value.name"
|
||||
class="glass p-6 rounded-xl group hover:shadow-lg transition-all duration-300"
|
||||
class="card group p-8"
|
||||
:style="{ animationDelay: `${index * 100}ms` }"
|
||||
>
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="flex items-center gap-5 mb-5">
|
||||
<div
|
||||
class="w-12 h-12 rounded-xl bg-gradient-to-br flex items-center justify-center group-hover:scale-110 transition-transform duration-300"
|
||||
class="w-16 h-16 rounded-2xl bg-gradient-to-br flex items-center justify-center group-hover:scale-110 group-hover:rotate-3 transition-all duration-300"
|
||||
:class="value.gradient"
|
||||
>
|
||||
<i :class="value.icon" class="text-white"></i>
|
||||
<i :class="value.icon" class="text-white text-xl"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">{{ value.name }}</h3>
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100">{{ value.name }}</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 dark:text-gray-400 text-sm leading-relaxed">
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">
|
||||
{{ value.description }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -96,11 +103,13 @@ const coreValuesRows = coreValues.map(v => [
|
||||
</section>
|
||||
|
||||
<!-- Summary -->
|
||||
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<section class="py-20 bg-white dark:bg-gray-900 transition-colors duration-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||
<div class="glass p-8 rounded-2xl">
|
||||
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Values in Action</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">
|
||||
<div class="glass p-10 sm:p-14 rounded-3xl relative overflow-hidden">
|
||||
<div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-rose-500 via-pink-500 to-purple-500"></div>
|
||||
|
||||
<h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-6">Values in Action</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 leading-relaxed text-lg">
|
||||
These values are not just words on a page. They guide our daily decisions, how we interact with each other, and how we approach every piece of work. When in doubt, return to these values.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -11,19 +11,100 @@ export default {
|
||||
sans: ['Inter', 'system-ui', 'sans-serif'],
|
||||
mono: ['JetBrains Mono', 'monospace'],
|
||||
},
|
||||
// Extended screens for better responsive control
|
||||
screens: {
|
||||
'xs': '475px',
|
||||
'3xl': '1920px',
|
||||
'4xl': '2560px',
|
||||
},
|
||||
// Extended max-width for ultrawide support
|
||||
maxWidth: {
|
||||
'8xl': '88rem',
|
||||
'9xl': '96rem',
|
||||
},
|
||||
// Responsive font sizes
|
||||
fontSize: {
|
||||
'display': ['clamp(2.5rem, 8vw, 6rem)', { lineHeight: '1.1', letterSpacing: '-0.02em' }],
|
||||
'display-sm': ['clamp(2rem, 5vw, 3.5rem)', { lineHeight: '1.15', letterSpacing: '-0.02em' }],
|
||||
'title': ['clamp(1.5rem, 4vw, 2.5rem)', { lineHeight: '1.2', letterSpacing: '-0.01em' }],
|
||||
'body-lg': ['clamp(1rem, 1.5vw, 1.25rem)', { lineHeight: '1.7' }],
|
||||
'body': ['clamp(0.875rem, 1.2vw, 1rem)', { lineHeight: '1.6' }],
|
||||
},
|
||||
animation: {
|
||||
'fade-in-up': 'fadeInUp 0.6s ease-out',
|
||||
'float': 'float 3s ease-in-out infinite',
|
||||
'fade-in': 'fadeIn 0.6s ease-out forwards',
|
||||
'fade-in-up': 'fadeInUp 0.6s ease-out forwards',
|
||||
'fade-in-down': 'fadeInDown 0.6s ease-out forwards',
|
||||
'scale-in': 'scaleIn 0.5s ease-out forwards',
|
||||
'slide-in-right': 'slideInRight 0.5s ease-out forwards',
|
||||
'slide-in-left': 'slideInLeft 0.5s ease-out forwards',
|
||||
'float': 'float 6s ease-in-out infinite',
|
||||
'float-delayed': 'float 6s ease-in-out infinite 3s',
|
||||
'pulse-slow': 'pulseSlow 4s ease-in-out infinite',
|
||||
'spin-slow': 'spin 8s linear infinite',
|
||||
'bounce-subtle': 'bounceSubtle 2s ease-in-out infinite',
|
||||
'gradient-shift': 'gradientShift 8s ease infinite',
|
||||
'shimmer': 'shimmer 2s infinite',
|
||||
},
|
||||
keyframes: {
|
||||
fadeIn: {
|
||||
'0%': { opacity: '0' },
|
||||
'100%': { opacity: '1' },
|
||||
},
|
||||
fadeInUp: {
|
||||
'0%': { opacity: '0', transform: 'translateY(20px)' },
|
||||
'0%': { opacity: '0', transform: 'translateY(30px)' },
|
||||
'100%': { opacity: '1', transform: 'translateY(0)' },
|
||||
},
|
||||
float: {
|
||||
'0%, 100%': { transform: 'translateY(0px)' },
|
||||
'50%': { transform: 'translateY(-10px)' },
|
||||
fadeInDown: {
|
||||
'0%': { opacity: '0', transform: 'translateY(-20px)' },
|
||||
'100%': { opacity: '1', transform: 'translateY(0)' },
|
||||
},
|
||||
scaleIn: {
|
||||
'0%': { opacity: '0', transform: 'scale(0.95)' },
|
||||
'100%': { opacity: '1', transform: 'scale(1)' },
|
||||
},
|
||||
slideInRight: {
|
||||
'0%': { opacity: '0', transform: 'translateX(30px)' },
|
||||
'100%': { opacity: '1', transform: 'translateX(0)' },
|
||||
},
|
||||
slideInLeft: {
|
||||
'0%': { opacity: '0', transform: 'translateX(-30px)' },
|
||||
'100%': { opacity: '1', transform: 'translateX(0)' },
|
||||
},
|
||||
float: {
|
||||
'0%, 100%': { transform: 'translateY(0px) rotate(0deg)' },
|
||||
'33%': { transform: 'translateY(-15px) rotate(1deg)' },
|
||||
'66%': { transform: 'translateY(-8px) rotate(-1deg)' },
|
||||
},
|
||||
pulseSlow: {
|
||||
'0%, 100%': { opacity: '1' },
|
||||
'50%': { opacity: '0.7' },
|
||||
},
|
||||
bounceSubtle: {
|
||||
'0%, 100%': { transform: 'translateY(0)' },
|
||||
'50%': { transform: 'translateY(-5px)' },
|
||||
},
|
||||
gradientShift: {
|
||||
'0%, 100%': { backgroundPosition: '0% 50%' },
|
||||
'50%': { backgroundPosition: '100% 50%' },
|
||||
},
|
||||
shimmer: {
|
||||
'0%': { backgroundPosition: '-200% 0' },
|
||||
'100%': { backgroundPosition: '200% 0' },
|
||||
},
|
||||
},
|
||||
boxShadow: {
|
||||
'glow-blue': '0 0 20px rgba(59, 130, 246, 0.3), 0 0 40px rgba(59, 130, 246, 0.1)',
|
||||
'glow-purple': '0 0 20px rgba(139, 92, 246, 0.3), 0 0 40px rgba(139, 92, 246, 0.1)',
|
||||
'glow-cyan': '0 0 20px rgba(6, 182, 212, 0.3), 0 0 40px rgba(6, 182, 212, 0.1)',
|
||||
'modern': '0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.05)',
|
||||
'modern-hover': '0 25px 50px -12px rgba(0, 0, 0, 0.15)',
|
||||
},
|
||||
transitionTimingFunction: {
|
||||
'bounce-out': 'cubic-bezier(0.34, 1.56, 0.64, 1)',
|
||||
},
|
||||
spacing: {
|
||||
'18': '4.5rem',
|
||||
'22': '5.5rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user