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