kimi-changes

This commit is contained in:
2026-02-19 23:33:32 +00:00
parent 08a6e0dd5c
commit 9536a9b501
22 changed files with 2319 additions and 909 deletions
+43 -7
View File
@@ -4,22 +4,58 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <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> <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="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.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <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 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> <script>
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { (function() {
document.documentElement.classList.add('dark') const theme = localStorage.theme;
} else { const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.classList.remove('dark') if (theme === 'dark' || (!theme && systemDark)) {
} document.documentElement.classList.add('dark');
}
})();
</script> </script>
</head> </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> <div id="app"></div>
<script type="module" src="/src/main.js"></script> <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> </body>
</html> </html>
+68 -7
View File
@@ -1,14 +1,25 @@
<script setup> <script setup>
import { onMounted } from 'vue'
import NavBar from '@/components/layout/NavBar.vue' import NavBar from '@/components/layout/NavBar.vue'
import Footer from '@/components/layout/Footer.vue' import Footer from '@/components/layout/Footer.vue'
import ReadingProgress from '@/components/layout/ReadingProgress.vue'
onMounted(() => {
document.documentElement.style.scrollBehavior = 'smooth'
})
</script> </script>
<template> <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 /> <NavBar />
<main class="flex-1"> <main class="flex-1">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<transition name="fade" mode="out-in"> <transition
name="page"
mode="out-in"
appear
>
<component :is="Component" /> <component :is="Component" />
</transition> </transition>
</router-view> </router-view>
@@ -18,13 +29,63 @@ import Footer from '@/components/layout/Footer.vue'
</template> </template>
<style> <style>
.fade-enter-active, /* Page transition animations */
.fade-leave-active { .page-enter-active,
transition: opacity 0.2s ease; .page-leave-active {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
} }
.fade-enter-from, .page-enter-from {
.fade-leave-to {
opacity: 0; 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> </style>
+475 -23
View File
@@ -13,73 +13,525 @@
button, a { button, a {
touch-action: manipulation; 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 { @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 { .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 { .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 { .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 { .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 { .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 { .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 { .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 { .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 { .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 { .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 { .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 { .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 { @layer utilities {
.animate-delay-100 { /* Animation delays */
animation-delay: 0.1s; .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;
} }
} }
+83 -42
View File
@@ -1,84 +1,125 @@
<script setup> <script setup>
const currentYear = new Date().getFullYear() 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> </script>
<template> <template>
<footer class="bg-gray-50 dark:bg-gray-800/50 border-t border-gray-200 dark:border-gray-700 transition-colors duration-300"> <footer class="relative 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"> <!-- Top gradient line -->
<div class="grid sm:grid-cols-2 md:grid-cols-3 gap-8"> <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="sm:col-span-2 md:col-span-1">
<div class="flex items-center gap-2 mb-4"> <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">
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center"> <!-- Main footer content - responsive grid -->
<span class="text-white font-bold text-lg">B</span> <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> </div>
<span class="text-xl font-bold gradient-text">BEAT</span> <div>
</div> <span class="text-lg sm:text-xl font-bold gradient-text block">BEAT</span>
<p class="text-gray-600 dark:text-gray-400 text-sm leading-relaxed"> <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. <strong>B</strong>alanced. <strong>E</strong>mpowered. <strong>A</strong>sync. <strong>T</strong>eams.
</p> </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. Built for how developers actually work.
</p> </p>
</div> </div>
<!-- Quick Links -->
<div> <div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Quick Links</h3> <h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2 text-sm sm:text-base">
<ul class="grid grid-cols-2 sm:grid-cols-1 gap-2 text-sm"> <i class="fas fa-compass text-blue-500 text-sm"></i>
<li> Explore
<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"> </h3>
Core Values <ul class="space-y-2">
</RouterLink> <li v-for="link in quickLinks" :key="link.path">
</li> <RouterLink
<li> :to="link.path"
<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"> 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"
12 Principles >
</RouterLink> <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>
</li> {{ link.label }}
<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
</RouterLink> </RouterLink>
</li> </li>
</ul> </ul>
</div> </div>
<!-- Resources -->
<div> <div>
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-3 sm:mb-4">Created By</h3> <h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2 text-sm sm:text-base">
<p class="text-gray-600 dark:text-gray-400 text-sm mb-3"> <i class="fas fa-book text-purple-500 text-sm"></i>
The BEAT Manifesto was created by <strong>Lukasz Raczylo</strong>. 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> </p>
<div class="flex space-x-1"> <div class="flex gap-2">
<a <a
href="https://github.com/lukaszraczylo" href="https://github.com/lukaszraczylo"
target="_blank" 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" aria-label="GitHub"
> >
<i class="fab fa-github text-xl"></i> <i class="fab fa-github text-lg"></i>
</a> </a>
<a <a
href="https://www.linkedin.com/in/raczylo/" href="https://www.linkedin.com/in/raczylo/"
target="_blank" 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" aria-label="LinkedIn"
> >
<i class="fab fa-linkedin text-xl"></i> <i class="fab fa-linkedin text-lg"></i>
</a> </a>
</div> </div>
</div> </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"> <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"> <p class="text-gray-500 dark:text-gray-500 text-xs sm:text-sm">
&copy; {{ currentYear }} BEAT Manifesto by Lukasz Raczylo. Open for use and adaptation. &copy; {{ currentYear }} BEAT Manifesto by Lukasz Raczylo
</p> </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. Attribution appreciated. Improvement welcomed. Dogma discouraged.
</p> </p>
</div> </div>
+169 -39
View File
@@ -1,99 +1,229 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref, onMounted, onUnmounted } from 'vue'
import { RouterLink, useRoute } from 'vue-router' import { RouterLink, useRoute } from 'vue-router'
import ThemeToggle from './ThemeToggle.vue' import ThemeToggle from './ThemeToggle.vue'
const route = useRoute() const route = useRoute()
const mobileMenuOpen = ref(false) const mobileMenuOpen = ref(false)
const scrolled = ref(false)
const navItems = [ const navItems = [
{ path: '/', label: 'Home' }, { path: '/', label: 'Home', icon: 'fas fa-home' },
{ path: '/values', label: 'Values' }, { path: '/values', label: 'Values', icon: 'fas fa-heart' },
{ path: '/principles', label: 'Principles' }, { path: '/principles', label: 'Principles', icon: 'fas fa-compass' },
{ path: '/framework', label: 'Framework' }, { path: '/framework', label: 'Framework', icon: 'fas fa-sitemap' },
{ path: '/practices', label: 'Practices' }, { path: '/practices', label: 'Practices', icon: 'fas fa-cogs' },
{ path: '/onboarding', label: 'Onboarding' }, { path: '/onboarding', label: 'Onboarding', icon: 'fas fa-user-plus' },
{ path: '/anti-patterns', label: 'Anti-Patterns' }, { path: '/anti-patterns', label: 'Anti-Patterns', icon: 'fas fa-exclamation-triangle' },
{ path: '/reference', label: 'Reference' }, { path: '/reference', label: 'Reference', icon: 'fas fa-book' },
{ path: '/assessment', label: 'Assessment' } { path: '/assessment', label: 'Assessment', icon: 'fas fa-clipboard-check' }
] ]
const toggleMobileMenu = () => { const toggleMobileMenu = () => {
mobileMenuOpen.value = !mobileMenuOpen.value mobileMenuOpen.value = !mobileMenuOpen.value
// Prevent body scroll when menu is open
document.body.style.overflow = mobileMenuOpen.value ? 'hidden' : ''
} }
const closeMobileMenu = () => { const closeMobileMenu = () => {
mobileMenuOpen.value = false 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> </script>
<template> <template>
<nav class="fixed w-full glass shadow-modern z-50 transition-colors duration-300"> <nav
<div class="max-w-6xl mx-auto px-4 sm:px-6"> class="fixed w-full z-50 transition-all duration-500"
<div class="flex justify-between h-16 items-center"> :class="[
<RouterLink to="/" class="flex items-center hover:opacity-80 transition-opacity duration-300 gap-2"> scrolled
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center"> ? 'bg-white/90 dark:bg-gray-900/90 backdrop-blur-xl shadow-modern'
<span class="text-white font-bold text-lg">B</span> : '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> </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> </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 <RouterLink
v-for="item in navItems" v-for="(item, index) in navItems"
:key="item.path" :key="item.path"
:to="item.path" :to="item.path"
class="nav-link text-sm" class="relative px-2 xl:px-3 py-2 text-xs xl:text-sm font-medium rounded-lg transition-all duration-300"
:class="{ 'text-blue-600 dark:text-blue-400': route.path === item.path }" :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 }} {{ 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> </RouterLink>
</div> </div>
<div class="flex items-center space-x-2"> <!-- Right side actions -->
<div class="flex items-center gap-1 sm:gap-2">
<ThemeToggle /> <ThemeToggle />
<a <a
href="https://github.com/lukaszraczylo" href="https://github.com/lukaszraczylo"
target="_blank" 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" 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> </a>
<!-- Mobile menu button -->
<button <button
@click="toggleMobileMenu" @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-label="Toggle menu"
aria-expanded="mobileMenuOpen"
aria-controls="mobile-menu"
> >
<i v-if="!mobileMenuOpen" class="fas fa-bars text-xl"></i> <transition name="rotate" mode="out-in">
<i v-else class="fas fa-times text-xl"></i> <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> </button>
</div> </div>
</div> </div>
</div> </div>
<!-- Mobile Menu Overlay -->
<transition <transition
enter-active-class="transition duration-200 ease-out" enter-active-class="transition duration-300 ease-out"
enter-from-class="opacity-0 -translate-y-2" enter-from-class="opacity-0"
enter-to-class="opacity-100 translate-y-0" enter-to-class="opacity-100"
leave-active-class="transition duration-150 ease-in" leave-active-class="transition duration-200 ease-in"
leave-from-class="opacity-100 translate-y-0" leave-from-class="opacity-100"
leave-to-class="opacity-0 -translate-y-2" leave-to-class="opacity-0"
> >
<div v-if="mobileMenuOpen" class="lg:hidden border-t border-gray-200 dark:border-gray-700"> <div
<div class="px-4 py-3 space-y-1 bg-white dark:bg-gray-800"> 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 <RouterLink
v-for="item in navItems" v-for="(item, index) in navItems"
:key="item.path" :key="item.path"
:to="item.path" :to="item.path"
@click="closeMobileMenu" @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="flex items-center gap-3 px-4 py-3 rounded-xl font-medium transition-all duration-300"
:class="{ 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20': route.path === item.path }" :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> </RouterLink>
</div> </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> </div>
</transition> </transition>
</nav> </nav>
</template> </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>
+12 -5
View File
@@ -7,23 +7,30 @@ defineProps({
gradient: { gradient: {
type: String, type: String,
default: null default: null
},
glow: {
type: String,
default: null
} }
}) })
</script> </script>
<template> <template>
<div <div
class="glass p-6 rounded-xl transition-all duration-300" class="card"
:class="{ 'hover:shadow-lg hover:-translate-y-1': hover }" :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 <div
class="icon-box" class="icon-box w-14 h-14 rounded-2xl"
:class="gradient" :class="gradient"
> >
<slot name="icon"></slot> <slot name="icon"></slot>
</div> </div>
<div class="flex-1"> <div class="flex-1 min-w-0">
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
+75
View File
@@ -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>
+23 -8
View File
@@ -15,24 +15,39 @@ defineProps({
gradient: { gradient: {
type: String, type: String,
default: 'from-blue-500 to-blue-600' default: 'from-blue-500 to-blue-600'
},
href: {
type: String,
default: null
} }
}) })
</script> </script>
<template> <template>
<div class="glass p-5 rounded-xl group hover:shadow-lg transition-all duration-300"> <component
<div class="flex items-start gap-4"> :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 <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" :class="gradient"
> >
<i :class="icon" class="text-white"></i> <i :class="icon" class="text-white text-xl"></i>
</div> </div>
<div> <div class="flex-1 min-w-0">
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-1">{{ title }}</h3> <h3 class="font-semibold text-lg text-gray-900 dark:text-gray-100 mb-2 flex items-center gap-2">
<p class="text-sm text-gray-600 dark:text-gray-400">{{ description }}</p> {{ 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> <slot></slot>
</div> </div>
</div> </div>
</div> </component>
</template> </template>
+101
View File
@@ -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>
+13 -11
View File
@@ -16,36 +16,38 @@ defineProps({
</script> </script>
<template> <template>
<div class="glass rounded-xl overflow-hidden"> <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"> <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> <h3 class="font-semibold text-gray-900 dark:text-gray-100 text-sm sm:text-base">{{ title }}</h3>
</div> </div>
<!-- Mobile card view -->
<!-- Mobile card view - shown on small screens -->
<div class="block sm:hidden"> <div class="block sm:hidden">
<div <div
v-for="(row, rowIndex) in rows" v-for="(row, rowIndex) in rows"
:key="rowIndex" :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 <div
v-for="(cell, cellIndex) in row" v-for="(cell, cellIndex) in row"
:key="cellIndex" :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> <span class="text-sm text-gray-700 dark:text-gray-300" v-html="cell"></span>
</div> </div>
</div> </div>
</div> </div>
<!-- Desktop table view -->
<!-- Desktop table view - hidden on mobile, shown on sm+ -->
<div class="hidden sm:block overflow-x-auto"> <div class="hidden sm:block overflow-x-auto">
<table class="w-full"> <table class="w-full">
<thead> <thead>
<tr class="bg-gray-50 dark:bg-gray-800/50"> <tr class="bg-gray-50/80 dark:bg-gray-800/80">
<th <th
v-for="header in headers" v-for="header in headers"
:key="header" :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 }} {{ header }}
</th> </th>
@@ -55,14 +57,14 @@ defineProps({
<tr <tr
v-for="(row, index) in rows" v-for="(row, index) in rows"
:key="index" :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 <td
v-for="(cell, cellIndex) in row" v-for="(cell, cellIndex) in row"
:key="cellIndex" :key="cellIndex"
class="px-4 md:px-6 py-3 md:py-4 text-sm text-gray-700 dark:text-gray-300" 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> </td>
</tr> </tr>
</tbody> </tbody>
+69
View File
@@ -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>
+78 -60
View File
@@ -35,92 +35,104 @@ const warningSigns = [
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-900/10 dark:to-orange-900/10 transition-colors duration-300"></div> <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-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-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-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> <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="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"> <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 text-white text-2xl"></i> <i class="fas fa-exclamation-triangle"></i>
Watch Out
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">Anti-Patterns</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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 BEATand how to fix them. Common ways teams fail at BEATand how to fix them.
</p> </p>
</div> </div>
</section> </section>
<!-- Process Anti-Patterns --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="flex items-center gap-4 mb-8"> <div class="flex items-center gap-4 mb-10">
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-red-500 to-red-600 flex items-center justify-center"> <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"></i> <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> </div>
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">Process Anti-Patterns</h2>
</div> </div>
<TableCard :headers="processHeaders" :rows="processRows" /> <TableCard :headers="processHeaders" :rows="processRows" />
</div> </div>
</section> </section>
<!-- People Anti-Patterns --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="flex items-center gap-4 mb-8"> <div class="flex items-center gap-4 mb-10">
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center"> <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"></i> <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> </div>
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">People Anti-Patterns</h2>
</div> </div>
<TableCard :headers="peopleHeaders" :rows="peopleRows" /> <TableCard :headers="peopleHeaders" :rows="peopleRows" />
</div> </div>
</section> </section>
<!-- Organizational Anti-Patterns --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="flex items-center gap-4 mb-8"> <div class="flex items-center gap-4 mb-10">
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-purple-500 to-purple-600 flex items-center justify-center"> <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"></i> <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> </div>
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">Organizational Anti-Patterns</h2>
</div> </div>
<TableCard :headers="orgHeaders" :rows="orgRows" /> <TableCard :headers="orgHeaders" :rows="orgRows" />
</div> </div>
</section> </section>
<!-- Warning Signs --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">When BEAT Isn't Working</h2> <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> <p class="text-gray-600 dark:text-gray-400">Signs the methodology isn't serving the team:</p>
</div> </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 <div
v-for="sign in warningSigns" v-for="(sign, index) in warningSigns"
:key="sign" :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"> <div class="flex items-center gap-3">
<i class="fas fa-exclamation-circle text-red-500"></i> <i class="fas fa-exclamation-circle text-red-500 text-lg"></i>
<span class="text-gray-700 dark:text-gray-300 text-sm">{{ sign }}</span> <span class="text-gray-700 dark:text-gray-300">{{ sign }}</span>
</div> </div>
</div> </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="card p-8 bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800">
<div class="flex items-start gap-4"> <div class="flex items-start gap-5">
<div class="w-10 h-10 rounded-lg bg-blue-500 flex items-center justify-center flex-shrink-0"> <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"></i> <i class="fas fa-lightbulb text-white text-xl"></i>
</div> </div>
<div> <div>
<h4 class="font-semibold text-blue-800 dark:text-blue-200 mb-2">Response</h4> <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 text-sm"> <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>
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> </div>
</div> </div>
@@ -128,60 +140,66 @@ const warningSigns = [
</section> </section>
<!-- Where BEAT Fits --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Where BEAT Fits</h2> <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> <p class="text-gray-600 dark:text-gray-400">Know your context. Adapt accordingly.</p>
</div> </div>
<div class="grid md:grid-cols-3 gap-6"> <div class="grid md:grid-cols-3 gap-6">
<div class="glass p-6 rounded-xl border-t-4 border-green-500"> <div class="card p-8 border-t-4 border-emerald-500">
<h3 class="font-bold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2"> <h3 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
<i class="fas fa-check-circle text-green-500"></i> <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 Works Best For
</h3> </h3>
<ul class="space-y-2"> <ul class="space-y-3">
<li <li
v-for="item in whereItFits.worksFor" v-for="item in whereItFits.worksFor"
:key="item" :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 }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="glass p-6 rounded-xl border-t-4 border-red-500"> <div class="card p-8 border-t-4 border-red-500">
<h3 class="font-bold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2"> <h3 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
<i class="fas fa-times-circle text-red-500"></i> <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 Fits Poorly For
</h3> </h3>
<ul class="space-y-2"> <ul class="space-y-3">
<li <li
v-for="item in whereItFits.fitsPoorly" v-for="item in whereItFits.fitsPoorly"
:key="item" :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 }} {{ item }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="glass p-6 rounded-xl border-t-4 border-amber-500"> <div class="card p-8 border-t-4 border-amber-500">
<h3 class="font-bold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2"> <h3 class="font-bold text-xl text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
<i class="fas fa-sliders-h text-amber-500"></i> <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 Can Adapt For
</h3> </h3>
<ul class="space-y-2"> <ul class="space-y-3">
<li <li
v-for="item in whereItFits.canAdapt" v-for="item in whereItFits.canAdapt"
:key="item" :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 }} {{ item }}
</li> </li>
</ul> </ul>
+118 -98
View File
@@ -3,7 +3,7 @@ import { ref, computed } from 'vue'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { assessmentCategories, assessmentQuestions, beatRecommendations, overallAssessment } from '@/data/assessment' 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 answers = ref({})
const showResults = ref(false) const showResults = ref(false)
@@ -43,7 +43,6 @@ const restartAssessment = () => {
showResults.value = false showResults.value = false
} }
// Calculate scores
const categoryScores = computed(() => { const categoryScores = computed(() => {
const scores = {} const scores = {}
assessmentCategories.forEach(cat => { assessmentCategories.forEach(cat => {
@@ -94,11 +93,11 @@ const colorClasses = {
progress: 'bg-purple-500' progress: 'bg-purple-500'
}, },
green: { green: {
bg: 'bg-green-50 dark:bg-green-900/20', bg: 'bg-emerald-50 dark:bg-emerald-900/20',
border: 'border-green-200 dark:border-green-800', border: 'border-emerald-200 dark:border-emerald-800',
text: 'text-green-600 dark:text-green-400', text: 'text-emerald-600 dark:text-emerald-400',
gradient: 'from-green-500 to-green-600', gradient: 'from-emerald-500 to-emerald-600',
progress: 'bg-green-500' progress: 'bg-emerald-500'
}, },
amber: { amber: {
bg: 'bg-amber-50 dark:bg-amber-900/20', bg: 'bg-amber-50 dark:bg-amber-900/20',
@@ -120,50 +119,65 @@ const colorClasses = {
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-900/10 dark:to-purple-900/10 transition-colors duration-300"></div> <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-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-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-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 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="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 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"> <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 text-white text-2xl"></i> <i class="fas fa-clipboard-check"></i>
Self-Assessment
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">Team Assessment</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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. Discover how BEAT can help your team deliver better and faster.
</p> </p>
</div> </div>
</section> </section>
<!-- Intro Screen --> <!-- Intro Screen -->
<section v-if="currentStep === 0" class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300"> <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="max-w-3xl mx-auto px-4 sm:px-6"> <div class="w-full max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="glass p-6 sm:p-8 rounded-2xl text-center"> <div class="card p-6 sm:p-8 lg:p-10 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"> <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-3xl"></i> <i class="fas fa-tasks text-white text-2xl sm:text-4xl"></i>
</div> </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? How BEAT-Ready is Your Team?
</h2> </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. 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> </p>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-8"> <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 rounded-lg" :class="colorClasses[cat.color].bg"> <div v-for="cat in assessmentCategories" :key="cat.id" class="p-3 sm:p-4 rounded-xl" :class="colorClasses[cat.color].bg">
<i :class="[cat.icon, colorClasses[cat.color].text]" class="text-xl mb-2"></i> <div
<div class="text-xs text-gray-600 dark:text-gray-400">{{ cat.title }}</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> </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"> <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><i class="fas fa-clock mr-1"></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">
<span><i class="fas fa-shield-alt mr-1"></i> Anonymous</span> <i class="fas fa-clock"></i> 3-5 min
<span><i class="fas fa-chart-bar mr-1"></i> Instant results</span> </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> </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> <i class="fas fa-play mr-2"></i>
Start Assessment Start Assessment
</button> </button>
@@ -172,15 +186,15 @@ const colorClasses = {
</section> </section>
<!-- Question Screen --> <!-- Question Screen -->
<section v-else-if="!showResults" class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300"> <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="max-w-3xl mx-auto px-4 sm:px-6"> <div class="w-full max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Progress Bar --> <!-- Progress Bar -->
<div class="mb-6"> <div class="mb-5 sm:mb-6">
<div class="flex items-center justify-between text-sm text-gray-600 dark:text-gray-400 mb-2"> <div class="flex items-center justify-between text-xs sm:text-sm text-gray-600 dark:text-gray-400 mb-2">
<span>Question {{ currentStep }} of {{ totalQuestions }}</span> <span class="font-medium">Question {{ currentStep }} of {{ totalQuestions }}</span>
<span>{{ progress }}% complete</span> <span>{{ progress }}% complete</span>
</div> </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 <div
class="h-full bg-gradient-to-r from-indigo-500 to-purple-500 transition-all duration-500 ease-out rounded-full" class="h-full bg-gradient-to-r from-indigo-500 to-purple-500 transition-all duration-500 ease-out rounded-full"
:style="{ width: `${progress}%` }" :style="{ width: `${progress}%` }"
@@ -189,65 +203,65 @@ const colorClasses = {
</div> </div>
<!-- Category Badge --> <!-- Category Badge -->
<div class="mb-4"> <div class="mb-4 sm:mb-6">
<span <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]" :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 }} {{ assessmentCategories.find(c => c.id === currentQuestion.category)?.title }}
</span> </span>
</div> </div>
<!-- Question Card --> <!-- Question Card -->
<div class="glass p-6 sm:p-8 rounded-2xl"> <div class="card p-5 sm:p-6 lg:p-8">
<h2 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-6"> <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 }} {{ currentQuestion.question }}
</h2> </h2>
<div class="space-y-3"> <div class="space-y-2.5 sm:space-y-3">
<button <button
v-for="option in currentQuestion.options" v-for="option in currentQuestion.options"
:key="option.value" :key="option.value"
@click="selectAnswer(currentQuestion.id, 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="[ :class="[
answers[currentQuestion.id] === option.value answers[currentQuestion.id] === option.value
? 'border-indigo-500 bg-indigo-50 dark:bg-indigo-900/20' ? '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' : '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 <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="[ :class="[
answers[currentQuestion.id] === option.value answers[currentQuestion.id] === option.value
? 'border-indigo-500 bg-indigo-500' ? '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> <i v-if="answers[currentQuestion.id] === option.value" class="fas fa-check text-white text-xs"></i>
</div> </div>
<div> <div>
<div class="font-medium text-gray-900 dark:text-gray-100">{{ option.label }}</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-sm text-gray-500 dark:text-gray-500">{{ option.description }}</div> <div class="text-xs sm:text-sm text-gray-500 dark:text-gray-500">{{ option.description }}</div>
</div> </div>
</div> </div>
</button> </button>
</div> </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 <button
v-if="currentStep > 1" v-if="currentStep > 1"
@click="goBack" @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> <i class="fas fa-arrow-left mr-2"></i>
<span class="hidden sm:inline">Back</span> Back
</button> </button>
<div v-else></div> <div v-else></div>
<div class="hidden sm:flex items-center gap-1"> <div class="hidden sm:flex items-center gap-1.5">
<div <div
v-for="i in totalQuestions" v-for="i in totalQuestions"
:key="i" :key="i"
@@ -259,7 +273,7 @@ const colorClasses = {
]" ]"
></div> ></div>
</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 }} {{ currentStep }}/{{ totalQuestions }}
</div> </div>
</div> </div>
@@ -268,59 +282,62 @@ const colorClasses = {
</section> </section>
<!-- Results Screen --> <!-- Results Screen -->
<section v-else class="py-8 sm:py-12 bg-white dark:bg-gray-900 transition-colors duration-300"> <section v-else class="py-6 sm:py-8 lg:py-10 bg-white dark:bg-gray-900 transition-colors duration-300">
<div class="max-w-4xl mx-auto px-4 sm:px-6"> <div class="w-full max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Overall Score --> <!-- 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 <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" :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> </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 }} {{ overallLevel.title }}
</h2> </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 {{ totalScore }} / 48
</div> </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 }} {{ overallLevel.description }}
</p> </p>
<div <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]" :class="[colorClasses[overallLevel.color].bg, colorClasses[overallLevel.color].border]"
> >
<i class="fas fa-lightbulb" :class="colorClasses[overallLevel.color].text"></i> <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>
</div> </div>
<!-- Category Breakdown --> <!-- Category Breakdown -->
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Category Breakdown</h3> <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="grid sm:grid-cols-2 gap-4 mb-8"> <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 <div
v-for="cat in assessmentCategories" v-for="cat in assessmentCategories"
:key="cat.id" :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 <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" :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>
<div class="flex-1"> <div class="flex-1 min-w-0">
<div class="font-semibold text-gray-900 dark:text-gray-100">{{ cat.title }}</div> <div class="font-semibold text-gray-900 dark:text-gray-100 text-sm sm:text-base truncate">{{ cat.title }}</div>
<div class="text-sm" :class="colorClasses[cat.color].text"> <div class="text-xs sm:text-sm" :class="colorClasses[cat.color].text">
{{ categoryScores[cat.id]?.percentage }}% ({{ categoryScores[cat.id]?.score }}/{{ categoryScores[cat.id]?.max }}) {{ categoryScores[cat.id]?.percentage }}% ({{ categoryScores[cat.id]?.score }}/{{ categoryScores[cat.id]?.max }})
</div> </div>
</div> </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 <div
class="h-full rounded-full transition-all duration-500" class="h-full rounded-full transition-all duration-1000"
:class="colorClasses[cat.color].progress" :class="colorClasses[cat.color].progress"
:style="{ width: `${categoryScores[cat.id]?.percentage}%` }" :style="{ width: `${categoryScores[cat.id]?.percentage}%` }"
></div> ></div>
@@ -329,57 +346,60 @@ const colorClasses = {
</div> </div>
<!-- Detailed Recommendations --> <!-- 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> <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="space-y-6"> <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 <div
v-for="cat in assessmentCategories" v-for="cat in assessmentCategories"
:key="cat.id" :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 <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" :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>
<div> <div class="flex-1 min-w-0">
<h4 class="font-bold text-gray-900 dark:text-gray-100">{{ getRecommendation(cat.id).title }}</h4> <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-sm text-gray-600 dark:text-gray-400 mt-1">{{ getRecommendation(cat.id).description }}</p> <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> </div>
<div class="space-y-2 mb-4"> <div class="space-y-1.5 sm:space-y-2 mb-3 sm:mb-4">
<div <div
v-for="rec in getRecommendation(cat.id).recommendations" v-for="rec in getRecommendation(cat.id).recommendations"
:key="rec" :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" :class="colorClasses[cat.color].bg"
> >
<i class="fas fa-check-circle mt-0.5" :class="colorClasses[cat.color].text"></i> <i class="fas fa-check-circle mt-0.5 text-xs sm:text-sm" :class="colorClasses[cat.color].text"></i>
<span class="text-sm text-gray-700 dark:text-gray-300">{{ rec }}</span> <span class="text-gray-700 dark:text-gray-300 text-xs sm:text-sm">{{ rec }}</span>
</div> </div>
</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"> <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-1"></i> <i class="fas fa-quote-left text-gray-400 mt-0.5 text-xs sm:text-sm"></i>
<p class="text-sm text-gray-600 dark:text-gray-400 italic">{{ getRecommendation(cat.id).beatPrinciple }}</p> <p class="text-gray-600 dark:text-gray-400 italic text-xs sm:text-sm">{{ getRecommendation(cat.id).beatPrinciple }}</p>
</div> </div>
</div> </div>
</div> </div>
<!-- CTA --> <!-- 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"> <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-xl sm:text-2xl font-bold text-white mb-3">Ready to Transform Your Team?</h3> <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-6 max-w-xl mx-auto"> <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. Explore the full BEAT manifesto and start implementing these practices today.
</p> </p>
<div class="flex flex-col sm:flex-row gap-3 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-6 py-3 rounded-lg font-medium hover:bg-gray-100 transition-colors min-h-[44px] flex items-center 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> <i class="fas fa-book-open mr-2"></i>
Read the Manifesto Read the Manifesto
</RouterLink> </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> <i class="fas fa-redo mr-2"></i>
Retake Assessment Retake Assessment
</button> </button>
+131 -106
View File
@@ -2,104 +2,123 @@
import { roles, priorityBuckets, ceremonies, constraints } from '@/data/manifesto' import { roles, priorityBuckets, ceremonies, constraints } from '@/data/manifesto'
const workItems = [ const workItems = [
{ name: 'Tasks', time: 'hours', description: 'A one-liner. No ceremony needed.' }, { 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.' }, { 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.' } { name: 'Projects', time: 'week+', description: 'Half-page doc with breakdown. No more.', icon: 'fas fa-folder', color: 'emerald' }
] ]
const bucketColors = { 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', 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' 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> </script>
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-900/10 dark:to-indigo-900/10 transition-colors duration-300"></div> <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-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-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-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> <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="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"> <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 text-white text-2xl"></i> <i class="fas fa-sitemap"></i>
Implementation
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">The Framework</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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. The principles guide us. The framework implements them.
</p> </p>
</div> </div>
</section> </section>
<!-- Roles --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Roles</h2> <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> <p class="text-gray-600 dark:text-gray-400">We recognize three roles, loosely held.</p>
</div> </div>
<div class="grid md:grid-cols-3 gap-6"> <div class="grid md:grid-cols-3 gap-6">
<div <div
v-for="role in roles" v-for="(role, index) in roles"
:key="role.name" :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 <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" :class="role.gradient"
> >
<i :class="role.icon" class="text-white text-xl"></i> <i :class="role.icon" class="text-white text-2xl"></i>
</div> </div>
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-3">{{ role.name }}</h3> <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 text-sm leading-relaxed">{{ role.description }}</p> <p class="text-gray-600 dark:text-gray-400 leading-relaxed">{{ role.description }}</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Beats --> <!-- Beats -->
<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 relative overflow-hidden">
<div class="max-w-6xl mx-auto px-4 sm:px-6"> <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="text-center mb-12">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Beats</h2> <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"> <p class="text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
We work in beatsflexible iterations of one to two weeks. We work in beatsflexible iterations of one to two weeks.
</p> </p>
</div> </div>
<div class="glass p-8 rounded-2xl"> <div class="glass p-8 sm:p-10 rounded-3xl">
<div class="grid md:grid-cols-3 gap-8"> <!-- Timeline -->
<div class="text-center"> <div class="grid md:grid-cols-3 gap-8 relative">
<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"> <!-- Connecting line -->
<i class="fas fa-play text-white"></i> <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> </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> <p class="text-sm text-gray-600 dark:text-gray-400">Review priorities and pull initial work</p>
</div> </div>
<div class="text-center"> <div class="text-center relative">
<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"> <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"></i> <i class="fas fa-cogs text-white text-2xl"></i>
</div> </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> <p class="text-sm text-gray-600 dark:text-gray-400">Check in async daily, work autonomously</p>
</div> </div>
<div class="text-center"> <div class="text-center relative">
<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"> <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"></i> <i class="fas fa-flag-checkered text-white text-2xl"></i>
</div> </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> <p class="text-sm text-gray-600 dark:text-gray-400">Reflect: what worked, what didn't, what to improve</p>
</div> </div>
</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"> <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"> <p class="text-sm text-blue-800 dark:text-blue-200 flex items-start gap-3">
<i class="fas fa-info-circle mr-2"></i> <i class="fas fa-info-circle mt-0.5"></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. <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> </p>
</div> </div>
</div> </div>
@@ -107,112 +126,115 @@ const bucketColors = {
</section> </section>
<!-- Work Items --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Work Items</h2> <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> <p class="text-gray-600 dark:text-gray-400">Documentation effort scales with task size.</p>
</div> </div>
<div class="grid md:grid-cols-3 gap-6"> <div class="grid md:grid-cols-3 gap-6">
<div <div
v-for="item in workItems" v-for="(item, index) in workItems"
:key="item.name" :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> <span class="text-2xl font-bold gradient-text">{{ item.name }}</span>
</div> </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 }} {{ item.time }}
</div> </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> </div>
<div class="mt-8 text-center"> <div class="mt-8 text-center">
<p class="text-gray-500 dark:text-gray-500 text-sm"> <p class="text-gray-500 dark:text-gray-500">
We size with <strong>S/M/L</strong>, not story points. We do not groom. We do not point. We do not track velocity. 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> </p>
</div> </div>
</div> </div>
</section> </section>
<!-- Prioritization --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Prioritization Buckets</h2> <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> <p class="text-gray-600 dark:text-gray-400">We use four buckets to organize work.</p>
</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 <div
v-for="bucket in priorityBuckets" v-for="(bucket, index) in priorityBuckets"
:key="bucket.name" :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]" :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> <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">{{ bucket.description }}</p> <p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">{{ bucket.description }}</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- The Board --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">The Board</h2> <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> <p class="text-gray-600 dark:text-gray-400">A simple kanban with priority built in.</p>
</div> </div>
<!-- Visual Board Flow --> <!-- Visual Board Flow -->
<div class="glass p-4 sm:p-6 rounded-xl overflow-x-auto"> <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-2 sm:gap-3 min-w-max sm:min-w-0"> <div class="flex items-center justify-start sm:justify-center 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"> <template v-for="(col, index) in boardColumns" :key="col.name">
ICE <div
</div> class="flex items-center gap-2 px-4 py-3 rounded-xl font-medium"
<i class="fas fa-arrow-right text-gray-400 text-xs"></i> :class="col.color"
<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 <i :class="col.icon" class="text-sm"></i>
</div> <span class="text-sm">{{ col.name }}</span>
<i class="fas fa-arrow-right text-gray-400 text-xs"></i> </div>
<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"> <i v-if="index < boardColumns.length - 1" class="fas fa-arrow-right text-gray-400"></i>
NEXT </template>
</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> </div>
</div> </div>
<div class="mt-8 grid sm:grid-cols-3 gap-4"> <div class="grid sm:grid-cols-3 gap-5">
<div class="glass p-4 rounded-lg"> <div class="card p-6 text-center group">
<div class="flex items-center gap-2 mb-2"> <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"></i> <i class="fas fa-user text-blue-500 text-xl"></i>
<span class="font-semibold text-gray-900 dark:text-gray-100">WIP Limit</span>
</div> </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> <p class="text-sm text-gray-600 dark:text-gray-400">3 items per maker</p>
</div> </div>
<div class="glass p-4 rounded-lg"> <div class="card p-6 text-center group">
<div class="flex items-center gap-2 mb-2"> <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"></i> <i class="fas fa-sort-amount-up text-purple-500 text-xl"></i>
<span class="font-semibold text-gray-900 dark:text-gray-100">NEXT is Ordered</span>
</div> </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> <p class="text-sm text-gray-600 dark:text-gray-400">Pull from top</p>
</div> </div>
<div class="glass p-4 rounded-lg"> <div class="card p-6 text-center group">
<div class="flex items-center gap-2 mb-2"> <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"></i> <i class="fas fa-clock text-amber-500 text-xl"></i>
<span class="font-semibold text-gray-900 dark:text-gray-100">Stale Items</span>
</div> </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> <p class="text-sm text-gray-600 dark:text-gray-400">Return to backlog after 5 days</p>
</div> </div>
</div> </div>
@@ -220,17 +242,20 @@ const bucketColors = {
</section> </section>
<!-- Constraints --> <!-- Constraints -->
<section class="py-16 bg-gradient-to-br from-purple-600 via-indigo-600 to-blue-600"> <section class="py-20 relative overflow-hidden">
<div class="max-w-4xl mx-auto px-4 sm:px-6"> <div class="absolute inset-0 bg-gradient-to-br from-purple-600 via-indigo-600 to-blue-600"></div>
<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"> <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 <div
v-for="item in constraints" v-for="(item, index) in constraints"
:key="item.constraint" :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/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> </div>
</div> </div>
+157 -106
View File
@@ -1,111 +1,158 @@
<script setup> <script setup>
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import IconCard from '@/components/ui/IconCard.vue'
import { researchStats } from '@/data/manifesto' import { researchStats } from '@/data/manifesto'
const navCards = [ 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: '/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' }, { 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' }, { 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-green-500 to-emerald-500' }, { 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' }, { 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-blue-500' } { path: '/reference', title: 'Reference', description: 'Quick lookup tables', icon: 'fas fa-book', gradient: 'from-cyan-500 to-sky-500', color: 'cyan' }
] ]
const keyNumbers = [ const keyNumbers = [
{ value: '4hrs', label: 'Sacred Focus Block', icon: 'fas fa-brain' }, { value: '4hrs', label: 'Sacred Focus Block', icon: 'fas fa-brain', color: 'blue' },
{ value: '2hrs', label: 'Max Meetings/Week', icon: 'fas fa-calendar' }, { value: '2hrs', label: 'Max Meetings/Week', icon: 'fas fa-calendar', color: 'purple' },
{ value: '80%', label: 'Planning Capacity', icon: 'fas fa-battery-three-quarters' }, { value: '80%', label: 'Planning Capacity', icon: 'fas fa-battery-three-quarters', color: 'emerald' },
{ value: '20%', label: 'Exploration Time', icon: 'fas fa-flask' } { 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> </script>
<template> <template>
<div> <div>
<!-- Hero Section --> <!-- Hero Section -->
<section class="relative pt-24 sm:pt-32 pb-16 sm:pb-24 overflow-hidden"> <section class="relative min-h-[85vh] sm:min-h-[90vh] flex items-center justify-center 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> <!-- Animated background blobs -->
<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 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>
<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> <!-- 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"> <div class="text-center">
<!-- Logo with glow effect -->
<div class="mb-6 sm:mb-8 flex justify-center animate-fade-in-up"> <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"> <div
<span class="text-white text-4xl sm:text-5xl font-bold">B</span> 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>
</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 The <span class="gradient-text">BEAT</span> Manifesto
</h1> </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-blue-600 dark:text-blue-400">B</span>alanced.
<span class="text-purple-600 dark:text-purple-400">E</span>mpowered. <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-cyan-600 dark:text-cyan-400">A</span>sync.
<span class="text-pink-600 dark:text-pink-400">T</span>eams. <span class="text-pink-600 dark:text-pink-400">T</span>eams.
</p> </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. A software delivery methodology built for how developers actually work.
<br class="hidden sm:block" /> <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>
Created by <strong>Lukasz Raczylo</strong>.
</p> </p>
<div class="flex flex-col sm:flex-row gap-4 justify-center animate-fade-in-up animate-delay-300"> <!-- CTA Buttons - stack on mobile, side by side on larger screens -->
<RouterLink to="/values" class="btn-primary"> <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> <i class="fas fa-book-open mr-2"></i>
Start Reading Start Reading
</RouterLink> </RouterLink>
<RouterLink to="/reference" class="btn-secondary"> <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-list mr-2"></i> <i class="fas fa-clipboard-check mr-2"></i>
Quick Reference Take Assessment
</RouterLink> </RouterLink>
</div> </div>
</div> </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> </section>
<!-- Key Numbers --> <!-- Key Numbers -->
<section class="py-12 bg-white dark:bg-gray-900 transition-colors duration-300"> <section class="py-12 sm:py-16 lg: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="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-4 sm:gap-6"> <div class="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 lg:gap-6">
<div <div
v-for="item in keyNumbers" v-for="(item, index) in keyNumbers"
:key="item.label" :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"> <div
<i :class="item.icon" class="text-white"></i> 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>
<div class="text-3xl sm:text-4xl font-bold gradient-text mb-1">{{ item.value }}</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-sm text-gray-600 dark:text-gray-400">{{ item.label }}</div> <div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400 font-medium">{{ item.label }}</div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Introduction --> <!-- Introduction -->
<section class="py-16 bg-gray-50 dark:bg-gray-800/50 transition-colors duration-300"> <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">
<div class="max-w-4xl mx-auto px-4 sm:px-6"> <!-- Decorative elements -->
<div class="glass p-8 sm:p-12 rounded-2xl"> <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>
<p class="text-lg sm:text-xl text-gray-700 dark:text-gray-300 leading-relaxed mb-6"> <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. We are uncovering better ways of building software by doing it and helping others do it.
</p> </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. BEAT emerges from research on how developers actually work. We built it for these realities, not against them.
</p> </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 <div
v-for="stat in researchStats" v-for="(stat, index) in researchStats"
:key="stat.stat" :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-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-sm text-gray-600 dark:text-gray-400">{{ stat.description }}</span> <span class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">{{ stat.description }}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -113,33 +160,34 @@ const keyNumbers = [
</section> </section>
<!-- Navigation Cards --> <!-- Navigation Cards -->
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300"> <section class="py-12 sm:py-16 lg: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="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
<div class="text-center mb-12"> <div class="text-center mb-10 sm:mb-14">
<h2 class="section-title">Explore the Manifesto</h2> <h2 class="section-title">Explore the Manifesto</h2>
<p class="section-subtitle">Deep dive into each aspect of BEAT</p> <p class="section-subtitle">Deep dive into each aspect of BEAT</p>
</div> </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 <RouterLink
v-for="card in navCards" v-for="(card, index) in navCards"
:key="card.path" :key="card.path"
:to="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 <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" :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>
<div> <div class="flex-1 min-w-0">
<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"> <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 }} {{ 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> </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>
</div> </div>
</RouterLink> </RouterLink>
@@ -148,59 +196,62 @@ const keyNumbers = [
</section> </section>
<!-- Commitment Section --> <!-- Commitment Section -->
<section class="py-16 bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600"> <section class="py-12 sm:py-16 lg:py-20 relative overflow-hidden">
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center"> <div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-cyan-600"></div>
<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"> <!-- Animated background pattern -->
<div class="bg-white/10 backdrop-blur-sm p-6 rounded-xl"> <div class="absolute inset-0 opacity-10">
<div class="flex items-center gap-3 mb-2"> <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>
<i class="fas fa-shield-alt text-white"></i> </div>
<span class="text-white font-semibold">Protecting focus</span>
<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> </div>
<p class="text-white/80 text-sm">We will not interrupt sacred time. We will wait.</p> <p class="text-white/70 text-xs sm:text-sm leading-relaxed pl-13 sm:pl-16">{{ item.description }}</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>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Summary --> <!-- Summary -->
<section class="py-16 bg-white dark:bg-gray-900 transition-colors duration-300"> <section class="py-12 sm:py-16 lg: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="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 text-center">
<div class="glass p-8 rounded-2xl"> <div class="glass p-6 sm:p-8 lg:p-10 xl:p-14 rounded-2xl sm:rounded-3xl relative overflow-hidden">
<div class="font-mono text-lg sm:text-xl text-gray-700 dark:text-gray-300 space-y-2"> <!-- Decorative gradient -->
<p>We protect focus.</p> <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>
<p>We write things down.</p>
<p>We trust each other.</p> <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>We work sustainably.</p> <p class="hover:text-blue-600 dark:hover:text-blue-400 transition-colors cursor-default">We protect focus.</p>
<p>We ship and learn.</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> </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>
</div> </div>
</section> </section>
+67 -56
View File
@@ -2,9 +2,9 @@
import { onboarding } from '@/data/manifesto' import { onboarding } from '@/data/manifesto'
const weeks = [ const weeks = [
{ ...onboarding.weekOne, icon: 'fas fa-eye', gradient: 'from-blue-500 to-cyan-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' }, { ...onboarding.weekTwo, icon: 'fas fa-hand-pointer', gradient: 'from-purple-500 to-pink-500', color: 'purple' },
{ ...onboarding.weekThree, icon: 'fas fa-rocket', gradient: 'from-green-500 to-emerald-500' } { ...onboarding.weekThree, icon: 'fas fa-rocket', gradient: 'from-emerald-500 to-teal-500', color: 'emerald' }
] ]
const whatWeDont = [ const whatWeDont = [
@@ -18,48 +18,53 @@ const whatWeDont = [
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-900/10 dark:to-orange-900/10 transition-colors duration-300"></div> <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-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-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-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> <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="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"> <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 text-white text-2xl"></i> <i class="fas fa-user-plus"></i>
Getting Started
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">Onboarding to BEAT</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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. When someone new joins a BEAT team, here's how to get them up to speed.
</p> </p>
</div> </div>
</section> </section>
<!-- Weekly Timeline --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="space-y-8"> <div class="space-y-6">
<div <div
v-for="(week, index) in weeks" v-for="(week, index) in weeks"
:key="week.title" :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 <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" :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>
<div class="flex-1"> <div class="flex-1">
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">{{ week.title }}</h3> <h3 class="text-2xl font-bold text-gray-900 dark:text-gray-100 mb-5">{{ week.title }}</h3>
<ul class="space-y-3"> <ul class="grid sm:grid-cols-2 gap-3">
<li <li
v-for="item in week.items" v-for="item in week.items"
:key="item" :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> <i class="fas fa-check-circle text-emerald-500 mt-1"></i>
<span>{{ item }}</span> <span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
</li> </li>
</ul> </ul>
</div> </div>
@@ -70,68 +75,69 @@ const whatWeDont = [
</section> </section>
<!-- First Month --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">{{ onboarding.firstMonth.title }}</h2> <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> <p class="text-gray-600 dark:text-gray-400">By the end of the first month, new members should:</p>
</div> </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 <div
v-for="(item, index) in onboarding.firstMonth.items" v-for="(item, index) in onboarding.firstMonth.items"
:key="item" :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="flex items-start gap-4">
<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"> <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-sm font-bold">{{ index + 1 }}</span> <span class="text-white text-lg font-bold">{{ index + 1 }}</span>
</div> </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>
</div> </div>
</div> </div>
</section> </section>
<!-- Connector's Responsibility --> <!-- Connector's Responsibility & What We Don't -->
<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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="grid md:grid-cols-2 gap-8"> <div class="grid md:grid-cols-2 gap-8">
<div class="glass p-6 rounded-xl"> <div class="card p-8">
<div class="flex items-center gap-3 mb-6"> <div class="flex items-center gap-4 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"> <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"></i> <i class="fas fa-project-diagram text-white text-xl"></i>
</div> </div>
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Connector's Responsibility</h3> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Connector's Responsibility</h3>
</div> </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: The Connector (or Enabler if no Connector) ensures:
</p> </p>
<ul class="space-y-3"> <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> <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>
<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> <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>
<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> <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>
<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> <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> </li>
</ul> </ul>
</div> </div>
<div class="glass p-6 rounded-xl border-l-4 border-red-500"> <div class="card p-8 border-l-4 border-red-500">
<div class="flex items-center gap-3 mb-6"> <div class="flex items-center gap-4 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"> <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"></i> <i class="fas fa-times text-white text-xl"></i>
</div> </div>
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">What We Don't Do</h3> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">What We Don't Do</h3>
</div> </div>
@@ -139,10 +145,10 @@ const whatWeDont = [
<li <li
v-for="item in whatWeDont" v-for="item in whatWeDont"
:key="item" :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> <i class="fas fa-times text-red-500 mt-1"></i>
{{ item }} <span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
</li> </li>
</ul> </ul>
</div> </div>
@@ -151,10 +157,15 @@ const whatWeDont = [
</section> </section>
<!-- Summary --> <!-- Summary -->
<section class="py-16 bg-gradient-to-br from-amber-500 via-orange-500 to-red-500"> <section class="py-20 relative overflow-hidden">
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center"> <div class="absolute inset-0 bg-gradient-to-br from-amber-500 via-orange-500 to-red-500"></div>
<h2 class="text-2xl sm:text-3xl font-bold text-white mb-4">The Goal</h2>
<p class="text-white/90 text-lg"> <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. Onboarding should feel like a gradual ramp, not a firehose or an abandonment.
</p> </p>
</div> </div>
+248 -175
View File
@@ -1,117 +1,153 @@
<script setup> <script setup>
import { ceremonies, incidentProtocol, technicalPractices, definitionOfDone } from '@/data/manifesto' 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> </script>
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-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 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-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-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-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> <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="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"> <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 text-white text-2xl"></i> <i class="fas fa-cogs"></i>
Day-to-Day
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">Practices</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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. How we work day-to-day: meetings, collaboration, incidents, and technical practices.
</p> </p>
</div> </div>
</section> </section>
<!-- Meetings --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Meetings</h2> <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> <p class="text-gray-600 dark:text-gray-400">Hard limits protect our time.</p>
</div> </div>
<div class="glass p-6 rounded-2xl mb-8"> <div class="glass p-8 sm:p-10 rounded-3xl mb-10">
<div class="grid sm:grid-cols-3 gap-6 text-center"> <div class="grid sm:grid-cols-3 gap-8">
<div> <div
<div class="text-3xl font-bold gradient-text mb-2">2 hours</div> v-for="(item, index) in meetingLimits"
<div class="text-gray-600 dark:text-gray-400 text-sm">per week total</div> :key="item.label"
</div> class="text-center group"
<div> :style="{ animationDelay: `${index * 100}ms` }"
<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> class="w-16 h-16 rounded-2xl flex items-center justify-center mx-auto mb-4 transition-all duration-300 group-hover:scale-110"
<div> :class="[
<div class="text-3xl font-bold gradient-text mb-2">Agenda</div> item.color === 'blue' ? 'bg-blue-100 dark:bg-blue-900/30' :
<div class="text-gray-600 dark:text-gray-400 text-sm">required or cancelled</div> 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>
</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 <div
v-for="ceremony in ceremonies" v-for="(ceremony, index) in ceremonies"
:key="ceremony.name" :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> <h3 class="font-semibold text-lg 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> <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> <p class="text-sm text-gray-600 dark:text-gray-400">{{ ceremony.purpose }}</p>
</div> </div>
</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"> <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"> <p class="text-sm text-amber-800 dark:text-amber-200 flex items-start gap-3">
<i class="fas fa-lightbulb mr-2"></i> <i class="fas fa-lightbulb mt-0.5"></i>
If a topic needs more than one hour: write first, comment async, meet on the delta. Never extend. <span>If a topic needs more than one hour: write first, comment async, meet on the delta. <strong>Never extend.</strong></span>
</p> </p>
</div> </div>
</div> </div>
</section> </section>
<!-- Daily Check-in --> <!-- Daily Check-in -->
<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 relative overflow-hidden">
<div class="max-w-6xl mx-auto px-4 sm:px-6"> <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="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> <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> <p class="text-gray-600 dark:text-gray-400">Replace standups with written updates.</p>
</div> </div>
<div class="max-w-xl mx-auto"> <div class="max-w-2xl mx-auto">
<!-- Visual Check-in Template --> <!-- Visual Check-in Template -->
<div class="glass p-5 sm:p-6 rounded-xl mb-6"> <div class="glass p-8 rounded-3xl mb-8">
<div class="space-y-3"> <div class="space-y-4">
<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="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-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="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> <i class="fas fa-tasks text-white"></i>
</div> </div>
<div> <div>
<div class="text-xs text-blue-600 dark:text-blue-400 font-semibold uppercase tracking-wide">Working on</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> </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="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-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="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> <i class="fas fa-hand-paper text-white"></i>
</div> </div>
<div> <div>
<div class="text-xs text-amber-600 dark:text-amber-400 font-semibold uppercase tracking-wide">Blocked by</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> </div>
</div> </div>
<div class="grid grid-cols-3 gap-3 sm:gap-4"> <div class="grid grid-cols-3 gap-4">
<div class="glass p-3 sm:p-4 rounded-lg text-center"> <div class="card p-5 text-center group">
<i class="fas fa-clock text-blue-500 text-lg sm:text-xl mb-2"></i> <i class="fas fa-clock text-blue-500 text-2xl mb-3 group-hover:scale-110 transition-transform block"></i>
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">Post once daily</div> <div class="text-sm text-gray-600 dark:text-gray-400 font-medium">Post once daily</div>
</div> </div>
<div class="glass p-3 sm:p-4 rounded-lg text-center"> <div class="card p-5 text-center group">
<i class="fas fa-stopwatch text-purple-500 text-lg sm:text-xl mb-2"></i> <i class="fas fa-stopwatch text-purple-500 text-2xl mb-3 group-hover:scale-110 transition-transform block"></i>
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">Two minutes</div> <div class="text-sm text-gray-600 dark:text-gray-400 font-medium">Two minutes</div>
</div> </div>
<div class="glass p-3 sm:p-4 rounded-lg text-center"> <div class="card p-5 text-center group">
<i class="fas fa-users-slash text-green-500 text-lg sm:text-xl mb-2"></i> <i class="fas fa-users-slash text-emerald-500 text-2xl mb-3 group-hover:scale-110 transition-transform block"></i>
<div class="text-xs sm:text-sm text-gray-600 dark:text-gray-400">No gathering</div> <div class="text-sm text-gray-600 dark:text-gray-400 font-medium">No gathering</div>
</div> </div>
</div> </div>
</div> </div>
@@ -119,66 +155,68 @@ import { ceremonies, incidentProtocol, technicalPractices, definitionOfDone } fr
</section> </section>
<!-- Collaboration --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Collaboration</h2> <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> <p class="text-gray-600 dark:text-gray-400">Default mode is solo deep work.</p>
</div> </div>
<div class="grid md:grid-cols-2 gap-8"> <div class="grid md:grid-cols-2 gap-8">
<div class="glass p-6 rounded-xl"> <!-- Ad-hoc Help -->
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4"> <div class="card p-8">
<i class="fas fa-hand-holding-heart text-blue-500 mr-2"></i> <div class="flex items-center gap-4 mb-6">
Ad-hoc Help <div class="w-14 h-14 rounded-xl bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center">
</h3> <i class="fas fa-hand-holding-heart text-white text-xl"></i>
<ol class="space-y-3 text-sm text-gray-600 dark:text-gray-400"> </div>
<li class="flex items-start gap-3"> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Ad-hoc Help</h3>
<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> </div>
Post when stuck <div class="space-y-4">
</li> <div
<li class="flex items-start gap-3"> v-for="(step, index) in collaborationSteps"
<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> :key="step.text"
Someone responds when available 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"
</li> :style="{ animationDelay: `${index * 100}ms` }"
<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> <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">
Sync briefly if needed {{ index + 1 }}
</li> </div>
<li class="flex items-start gap-3"> <div class="flex items-center 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> <i :class="step.icon" class="text-blue-500"></i>
Return to solo work <span class="text-gray-700 dark:text-gray-300">{{ step.text }}</span>
</li> </div>
</ol> </div>
</div>
</div> </div>
<div class="glass p-6 rounded-xl"> <!-- Multi-Maker Work -->
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4"> <div class="card p-8">
<i class="fas fa-users text-purple-500 mr-2"></i> <div class="flex items-center gap-4 mb-6">
Multi-Maker Work <div class="w-14 h-14 rounded-xl bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center">
</h3> <i class="fas fa-users text-white text-xl"></i>
<ul class="space-y-3 text-sm text-gray-600 dark:text-gray-400"> </div>
<li class="flex items-start gap-3"> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">Multi-Maker Work</h3>
<i class="fas fa-check-circle text-green-500 mt-0.5"></i> </div>
<span><strong>Break vertically.</strong> Each maker owns an end-to-end slice.</span> <div class="space-y-4">
</li> <div
<li class="flex items-start gap-3"> v-for="(principle, index) in multiMakerPrinciples"
<i class="fas fa-check-circle text-green-500 mt-0.5"></i> :key="principle.title"
<span><strong>Define interfaces first.</strong> Work in parallel against contracts.</span> 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"
</li> :style="{ animationDelay: `${index * 100}ms` }"
<li class="flex items-start gap-3"> >
<i class="fas fa-check-circle text-green-500 mt-0.5"></i> <div class="w-10 h-10 rounded-full bg-emerald-100 dark:bg-emerald-900/30 flex items-center justify-center flex-shrink-0">
<span><strong>Coordinate via doc.</strong> One feature doc as source of truth.</span> <i :class="principle.icon" class="text-emerald-500"></i>
</li> </div>
<li class="flex items-start gap-3"> <div>
<i class="fas fa-check-circle text-green-500 mt-0.5"></i> <span class="font-semibold text-gray-900 dark:text-gray-100 block">{{ principle.title }}</span>
<span><strong>Sync only when stuck.</strong> Document outcome. Return to async.</span> <span class="text-sm text-gray-600 dark:text-gray-400">{{ principle.desc }}</span>
</li> </div>
</ul> </div>
</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"> <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. We do not schedule pairing. We do not mandate walkthroughs. We do not assign buddies. Collaboration is initiated by those who need it.
</p> </p>
@@ -187,134 +225,169 @@ import { ceremonies, incidentProtocol, technicalPractices, definitionOfDone } fr
</section> </section>
<!-- Definition of Done --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Definition of Done</h2> <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> <p class="text-gray-600 dark:text-gray-400">Work is not done until it meets these criteria.</p>
</div> </div>
<div class="grid md:grid-cols-2 gap-8"> <div class="grid md:grid-cols-2 gap-8">
<div class="glass p-6 rounded-xl"> <div class="card p-8">
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4"> <div class="flex items-center gap-4 mb-6">
<i class="fas fa-code text-blue-500 mr-2"></i> <div class="w-14 h-14 rounded-xl bg-gradient-to-br from-blue-500 to-cyan-500 flex items-center justify-center">
For Code <i class="fas fa-code text-white text-xl"></i>
</h3> </div>
<ul class="space-y-2"> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">For Code</h3>
</div>
<ul class="space-y-3">
<li <li
v-for="item in definitionOfDone.code" v-for="item in definitionOfDone.code"
:key="item" :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> <div class="w-8 h-8 rounded-full bg-emerald-500 flex items-center justify-center flex-shrink-0">
{{ item }} <i class="fas fa-check text-white text-sm"></i>
</div>
<span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class="glass p-6 rounded-xl"> <div class="card p-8">
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4"> <div class="flex items-center gap-4 mb-6">
<i class="fas fa-file-alt text-purple-500 mr-2"></i> <div class="w-14 h-14 rounded-xl bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center">
For Non-Code <i class="fas fa-file-alt text-white text-xl"></i>
</h3> </div>
<ul class="space-y-2"> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100">For Non-Code</h3>
</div>
<ul class="space-y-3">
<li <li
v-for="item in definitionOfDone.nonCode" v-for="item in definitionOfDone.nonCode"
:key="item" :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> <div class="w-8 h-8 rounded-full bg-purple-500 flex items-center justify-center flex-shrink-0">
{{ item }} <i class="fas fa-check text-white text-sm"></i>
</div>
<span class="text-gray-700 dark:text-gray-300">{{ item }}</span>
</li> </li>
</ul> </ul>
</div> </div>
</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"> <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"> <p class="text-sm text-blue-800 dark:text-blue-200 flex items-start gap-3">
<i class="fas fa-info-circle mr-2"></i> <i class="fas fa-info-circle mt-0.5"></i>
The team owns this definition. Adjust it as needed. But once agreed, honor it. "Done" means donenot "done but..." or "done except..." <span>The team owns this definition. Adjust it as needed. But once agreed, honor it. "Done" means donenot "done but..." or "done except..."</span>
</p> </p>
</div> </div>
</div> </div>
</section> </section>
<!-- Incidents --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Incidents & Emergencies</h2> <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> <p class="text-gray-600 dark:text-gray-400">When production breaks, normal rules suspend temporarily.</p>
</div> </div>
<div class="grid md:grid-cols-2 gap-8 mb-8"> <div class="grid md:grid-cols-2 gap-8 mb-8">
<div class="glass p-6 rounded-xl border-l-4 border-red-500"> <div class="card p-8 border-l-4 border-red-500">
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">What Qualifies</h3> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
<ul class="space-y-2 text-sm text-gray-600 dark:text-gray-400"> <i class="fas fa-exclamation-triangle text-red-500"></i>
<li class="flex items-center gap-2"> What Qualifies
<i class="fas fa-exclamation-triangle text-red-500"></i> </h3>
Users cannot complete critical actions <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>
<li class="flex items-center gap-2"> <li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
<i class="fas fa-exclamation-triangle text-red-500"></i> <i class="fas fa-times-circle text-red-500"></i>
Data integrity is at risk <span class="text-gray-700 dark:text-gray-300">Data integrity is at risk</span>
</li> </li>
<li class="flex items-center gap-2"> <li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
<i class="fas fa-exclamation-triangle text-red-500"></i> <i class="fas fa-times-circle text-red-500"></i>
Security vulnerability being exploited <span class="text-gray-700 dark:text-gray-300">Security vulnerability being exploited</span>
</li> </li>
<li class="flex items-center gap-2"> <li class="flex items-center gap-3 p-3 rounded-xl bg-red-50 dark:bg-red-900/20">
<i class="fas fa-exclamation-triangle text-red-500"></i> <i class="fas fa-times-circle text-red-500"></i>
Significant revenue or reputation impact <span class="text-gray-700 dark:text-gray-300">Significant revenue or reputation impact</span>
</li> </li>
</ul> </ul>
</div> </div>
<div class="glass p-6 rounded-xl"> <div class="card p-8">
<h3 class="text-lg font-bold text-gray-900 dark:text-gray-100 mb-4">Incident Protocol</h3> <h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-6 flex items-center gap-3">
<ol class="space-y-3"> <i class="fas fa-clipboard-list text-blue-500"></i>
<li Incident Protocol
v-for="step in incidentProtocol" </h3>
:key="step.step" <div class="relative">
class="flex items-start gap-3" <!-- 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>
<span class="font-bold text-blue-600 dark:text-blue-400 text-sm">{{ step.step }}</span> <div class="space-y-4">
<span class="text-sm text-gray-600 dark:text-gray-400">{{ step.description }}</span> <div
</li> v-for="(step, index) in incidentProtocol"
</ol> :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> </div>
<div class="p-4 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800"> <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"> <p class="text-sm text-amber-800 dark:text-amber-200 flex items-start gap-3">
<i class="fas fa-lightbulb mr-2"></i> <i class="fas fa-lightbulb mt-0.5"></i>
This is not normal work. Incidents should be rare. If they're frequent, that's a systemic problem to solvenot a reason to abandon sustainable pace. <span>This is not normal work. Incidents should be rare. If they're frequent, that's a systemic problem to solvenot a reason to abandon sustainable pace.</span>
</p> </p>
</div> </div>
</div> </div>
</section> </section>
<!-- Technical Practices --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Technical Practices</h2> <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> <p class="text-gray-600 dark:text-gray-400">Optional practices that align well with BEAT principles.</p>
</div> </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 <div
v-for="practice in technicalPractices" v-for="(practice, index) in technicalPractices"
:key="practice.name" :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> <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">
<p class="text-sm text-gray-600 dark:text-gray-400">{{ practice.description }}</p> {{ practice.name }}
</h3>
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">{{ practice.description }}</p>
</div> </div>
</div> </div>
<p class="mt-8 text-center text-sm text-gray-500 dark:text-gray-500"> <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. Adopt what serves you. Discard what doesn't. 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> </p>
</div> </div>
</section> </section>
+61 -42
View File
@@ -2,27 +2,31 @@
import { principles } from '@/data/manifesto' import { principles } from '@/data/manifesto'
const categories = [ const categories = [
{ key: 'focus', title: 'On Focus', icon: 'fas fa-bullseye', gradient: 'from-blue-500 to-cyan-500', color: 'blue' }, { 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' }, { 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-green-500 to-emerald-500', color: 'green' }, { 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' } { key: 'sustainability', title: 'On Sustainability', icon: 'fas fa-leaf', gradient: 'from-amber-500 to-orange-500', color: 'amber', desc: 'Pace that lasts' }
] ]
</script> </script>
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-900/10 dark:to-purple-900/10 transition-colors duration-300"></div> <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-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-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-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 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="relative w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12 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"> <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 text-white text-2xl"></i> <i class="fas fa-compass"></i>
Guiding Principles
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">The Twelve Principles</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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. Guiding principles organized into four categories: Focus, Communication, Autonomy, and Sustainability.
</p> </p>
</div> </div>
@@ -30,40 +34,44 @@ const categories = [
<!-- Principles by Category --> <!-- Principles by Category -->
<section <section
v-for="category in categories" v-for="(category, catIndex) in categories"
:key="category.key" :key="category.key"
class="py-16 transition-colors duration-300" class="py-12 sm:py-16 lg:py-20 transition-colors duration-300 relative"
:class="categories.indexOf(category) % 2 === 0 ? 'bg-white dark:bg-gray-900' : 'bg-gray-50 dark:bg-gray-800/50'" :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="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:px-12">
<div class="flex items-center gap-4 mb-8"> <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4 mb-6 sm:mb-10">
<div <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" :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> </div>
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">{{ category.title }}</h2>
</div> </div>
<div class="space-y-6"> <div class="space-y-4 sm:space-y-5">
<div <div
v-for="principle in principles[category.key]" v-for="(principle, index) in principles[category.key]"
:key="principle.number" :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 <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" :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>
<div> <div class="flex-1 min-w-0">
<h3 class="text-lg sm:text-xl font-bold text-gray-900 dark:text-gray-100 mb-3"> <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 }} {{ principle.title }}
</h3> </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 }} {{ principle.description }}
</p> </p>
</div> </div>
@@ -74,22 +82,33 @@ const categories = [
</section> </section>
<!-- Summary --> <!-- Summary -->
<section class="py-16 bg-gradient-to-br from-blue-600 via-purple-600 to-green-600"> <section class="py-12 sm:py-16 lg:py-20 relative overflow-hidden">
<div class="max-w-4xl mx-auto px-4 sm:px-6 text-center"> <div class="absolute inset-0 bg-gradient-to-br from-blue-600 via-purple-600 to-emerald-600"></div>
<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"> <!-- 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 <div
v-for="category in categories" v-for="(category, index) in categories"
:key="category.key" :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"> <div class="flex items-center gap-3 mb-3 sm:mb-4">
<i :class="category.icon" class="text-white"></i> <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">
<span class="text-white font-semibold">{{ category.title }}</span> <i :class="category.icon" class="text-white"></i>
</div>
<span class="text-white font-semibold text-base sm:text-lg">{{ category.title }}</span>
</div> </div>
<ul class="text-white/80 text-sm space-y-1"> <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"> <li v-for="p in principles[category.key]" :key="p.number" class="flex items-center gap-2">
{{ p.number }}. {{ p.title.split('.')[0] }} <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> </li>
</ul> </ul>
</div> </div>
+135 -84
View File
@@ -1,5 +1,6 @@
<script setup> <script setup>
import TableCard from '@/components/ui/TableCard.vue' 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' import { coreValues, teamValues, constraints, priorityBuckets, roles, ceremonies, definitionOfDone, incidentProtocol } from '@/data/manifesto'
const coreValuesHeaders = ['We Value More', 'Over'] const coreValuesHeaders = ['We Value More', 'Over']
@@ -47,66 +48,99 @@ const spottedIssueFlow = [
] ]
const colorMap = { 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', 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: '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', 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: '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', 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: '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' 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> </script>
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-900/10 dark:to-blue-900/10 transition-colors duration-300"></div> <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-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-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-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> <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="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"> <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 text-white text-2xl"></i> <i class="fas fa-book"></i>
Quick Lookup
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">Quick Reference</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <i class="fas fa-book text-white text-3xl"></i>
Everything you need at a glance. </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> </p>
</div> </div>
</section> </section>
<!-- Core Values --> <!-- 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"> <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" /> <TableCard :headers="coreValuesHeaders" :rows="coreValuesRows" />
</div> </div>
</section> </section>
<!-- Team Values --> <!-- 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"> <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" /> <TableCard :headers="teamValuesHeaders" :rows="teamValuesRows" />
</div> </div>
</section> </section>
<!-- The Numbers --> <!-- 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"> <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" /> <TableCard :headers="constraintsHeaders" :rows="constraintsRows" />
</div> </div>
</section> </section>
<!-- Buckets & Roles --> <!-- 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="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> <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" /> <TableCard :headers="bucketsHeaders" :rows="bucketsRows" />
</div> </div>
<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" /> <TableCard :headers="rolesHeaders" :rows="rolesRows" />
</div> </div>
</div> </div>
@@ -114,71 +148,85 @@ const colorMap = {
</section> </section>
<!-- Ceremonies --> <!-- 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"> <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" /> <TableCard :headers="ceremoniesHeaders" :rows="ceremoniesRows" />
</div> </div>
</section> </section>
<!-- Templates --> <!-- Templates with Copy Buttons -->
<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="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"> <div class="grid md:grid-cols-2 gap-6">
<!-- Daily Check-in Card --> <!-- Daily Check-in Card -->
<div class="glass p-5 sm:p-6 rounded-xl"> <div class="card p-6">
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2"> <div class="flex items-center justify-between mb-5">
<i class="fas fa-calendar-check text-blue-500"></i> <h3 class="font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-3">
Daily Check-in <div class="w-10 h-10 rounded-xl bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center">
</h3> <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="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="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-8 h-8 rounded-full bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center flex-shrink-0"> <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 text-xs"></i> <i class="fas fa-tasks text-white"></i>
</div> </div>
<div> <div>
<div class="text-xs text-blue-600 dark:text-blue-400 font-medium">Working on</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> </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="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-8 h-8 rounded-full bg-gradient-to-br from-amber-500 to-amber-600 flex items-center justify-center flex-shrink-0"> <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 text-xs"></i> <i class="fas fa-hand-paper text-white"></i>
</div> </div>
<div> <div>
<div class="text-xs text-amber-600 dark:text-amber-400 font-medium">Blocked by</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> </div>
</div> </div>
<!-- Spotted Issue Decision Flow --> <!-- Spotted Issue Decision Flow -->
<div class="glass p-5 sm:p-6 rounded-xl"> <div class="card p-6">
<h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-4 flex items-center gap-2"> <h3 class="font-semibold text-gray-900 dark:text-gray-100 mb-5 flex items-center gap-3">
<i class="fas fa-code-branch text-purple-500"></i> <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 Spotted Issue Decision
</h3> </h3>
<div class="space-y-2"> <div class="space-y-3">
<div <div
v-for="(item, index) in spottedIssueFlow" v-for="(item, index) in spottedIssueFlow"
:key="index" :key="index"
class="flex items-center gap-2 sm:gap-3 p-2 sm:p-3 rounded-lg border" class="flex items-center gap-3 p-3 rounded-xl border"
:class="colorMap[item.color].split(' ').slice(2).join(' ')" :class="[colorMap[item.color].badge, colorMap[item.color].border]"
> >
<div <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="w-10 h-10 rounded-xl bg-gradient-to-br flex items-center justify-center flex-shrink-0"
:class="colorMap[item.color].split(' ').slice(0, 2).join(' ')" :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>
<div class="flex-1 min-w-0"> <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> </div>
<i class="fas fa-arrow-right text-xs opacity-50 hidden sm:block"></i> <i class="fas fa-arrow-right text-xs opacity-50"></i>
<span class="text-xs sm:text-sm font-bold whitespace-nowrap">{{ item.answer }}</span> <span class="text-sm font-bold whitespace-nowrap" :class="colorMap[item.color].text">{{ item.answer }}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -187,18 +235,24 @@ const colorMap = {
</section> </section>
<!-- Definition of Done --> <!-- 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"> <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="flex items-center justify-between mb-6">
<div class="glass p-5 sm:p-6 rounded-xl"> <div class="flex items-center gap-3">
<div class="grid sm:grid-cols-2 gap-2 sm: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 <div
v-for="item in definitionOfDone.code" v-for="item in definitionOfDone.code"
:key="item" :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"> <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-xs"></i> <i class="fas fa-check text-white text-sm"></i>
</div> </div>
<span class="text-sm text-gray-700 dark:text-gray-300">{{ item }}</span> <span class="text-sm text-gray-700 dark:text-gray-300">{{ item }}</span>
</div> </div>
@@ -208,34 +262,31 @@ const colorMap = {
</section> </section>
<!-- Incident Protocol --> <!-- 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"> <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="flex items-center gap-3 mb-6">
<div class="glass p-5 sm:p-6 rounded-xl"> <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"> <div class="relative">
<!-- Flow line for desktop --> <!-- 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 class="space-y-4">
<div <div
v-for="(step, index) in incidentProtocol" v-for="(step, index) in incidentProtocol"
:key="step.step" :key="step.step"
class="flex items-start gap-3 sm:gap-4" class="flex items-start gap-4"
> >
<div <div
class="w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 z-10" class="w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0 z-10 shadow-lg"
:class="[ :class="incidentColors[index]"
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'
]"
> >
<span class="text-white font-bold text-sm">{{ index + 1 }}</span> <span class="text-white font-bold">{{ index + 1 }}</span>
</div> </div>
<div class="flex-1 pb-2"> <div class="flex-1 pb-2 pt-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="font-semibold text-gray-900 dark:text-gray-100">{{ 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="text-sm text-gray-600 dark:text-gray-400">{{ step.description }}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -245,13 +296,13 @@ const colorMap = {
</section> </section>
<!-- Footer Note --> <!-- 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="max-w-4xl mx-auto px-4 sm:px-6 text-center">
<div class="glass p-5 sm:p-6 rounded-xl"> <div class="card p-8">
<p class="text-gray-600 dark:text-gray-400 text-sm mb-2"> <p class="text-gray-600 dark:text-gray-400 mb-2">
BEAT v1.0 by <strong>Lukasz Raczylo</strong> BEAT v1.0 by <strong class="text-gray-900 dark:text-gray-100">Lukasz Raczylo</strong>
</p> </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. Attribution appreciated. Improvement welcomed. Dogma discouraged.
</p> </p>
</div> </div>
+43 -34
View File
@@ -1,5 +1,4 @@
<script setup> <script setup>
import IconCard from '@/components/ui/IconCard.vue'
import TableCard from '@/components/ui/TableCard.vue' import TableCard from '@/components/ui/TableCard.vue'
import { coreValues, teamValues } from '@/data/manifesto' import { coreValues, teamValues } from '@/data/manifesto'
@@ -13,27 +12,31 @@ const coreValuesRows = coreValues.map(v => [
<template> <template>
<div> <div>
<!-- Hero --> <!-- Hero -->
<section class="relative pt-24 sm:pt-32 pb-12 sm:pb-16 overflow-hidden"> <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-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 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-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-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-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> <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="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"> <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 text-white text-2xl"></i> <i class="fas fa-heart"></i>
Foundation
</div> </div>
<h1 class="section-title animate-fade-in-up animate-delay-100">Values</h1> <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">
<p class="section-subtitle max-w-2xl mx-auto animate-fade-in-up animate-delay-200"> <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. The foundation of everything we do. What we value in our work and how we treat each other.
</p> </p>
</div> </div>
</section> </section>
<!-- Core Values --> <!-- 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="max-w-6xl mx-auto px-4 sm:px-6">
<div class="text-center mb-12"> <div class="text-center mb-14">
<h2 class="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">Core Values</h2> <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"> <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. While there is value in the items on the right, we value the items on the left more.
</p> </p>
@@ -44,18 +47,19 @@ const coreValuesRows = coreValues.map(v => [
<!-- Visual Cards --> <!-- Visual Cards -->
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-12"> <div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-12">
<div <div
v-for="value in coreValues" v-for="(value, index) in coreValues"
:key="value.valueMore" :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="flex items-center gap-4 mb-4">
<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"> <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 text-sm"></i> <i :class="value.icon" class="text-white"></i>
</div> </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> </div>
<p class="text-sm text-gray-500 dark:text-gray-500"> <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> </p>
</div> </div>
</div> </div>
@@ -63,10 +67,12 @@ const coreValuesRows = coreValues.map(v => [
</section> </section>
<!-- Team Values --> <!-- Team Values -->
<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 relative overflow-hidden">
<div class="max-w-6xl mx-auto px-4 sm:px-6"> <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="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> <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"> <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. Beyond what we value in our work, we hold these values in how we treat each other.
</p> </p>
@@ -74,20 +80,21 @@ const coreValuesRows = coreValues.map(v => [
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6"> <div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
<div <div
v-for="value in teamValues" v-for="(value, index) in teamValues"
:key="value.name" :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 <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" :class="value.gradient"
> >
<i :class="value.icon" class="text-white"></i> <i :class="value.icon" class="text-white text-xl"></i>
</div> </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> </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 }} {{ value.description }}
</p> </p>
</div> </div>
@@ -96,11 +103,13 @@ const coreValuesRows = coreValues.map(v => [
</section> </section>
<!-- Summary --> <!-- 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="max-w-4xl mx-auto px-4 sm:px-6 text-center">
<div class="glass p-8 rounded-2xl"> <div class="glass p-10 sm:p-14 rounded-3xl relative overflow-hidden">
<h3 class="text-xl font-bold text-gray-900 dark:text-gray-100 mb-4">Values in Action</h3> <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>
<p class="text-gray-600 dark:text-gray-400 leading-relaxed">
<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. 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> </p>
</div> </div>
+87 -6
View File
@@ -11,19 +11,100 @@ export default {
sans: ['Inter', 'system-ui', 'sans-serif'], sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'], 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: { animation: {
'fade-in-up': 'fadeInUp 0.6s ease-out', 'fade-in': 'fadeIn 0.6s ease-out forwards',
'float': 'float 3s ease-in-out infinite', '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: { keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
fadeInUp: { fadeInUp: {
'0%': { opacity: '0', transform: 'translateY(20px)' }, '0%': { opacity: '0', transform: 'translateY(30px)' },
'100%': { opacity: '1', transform: 'translateY(0)' }, '100%': { opacity: '1', transform: 'translateY(0)' },
}, },
float: { fadeInDown: {
'0%, 100%': { transform: 'translateY(0px)' }, '0%': { opacity: '0', transform: 'translateY(-20px)' },
'50%': { transform: 'translateY(-10px)' }, '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',
}, },
}, },
}, },