This commit is contained in:
2026-01-14 01:23:03 +01:00
parent e46b104127
commit 172e2600d1
20 changed files with 3095 additions and 914 deletions

View File

@@ -2,7 +2,7 @@
@tailwind components;
@tailwind utilities;
/* Medium-inspired clean reading experience */
/* Base styles - Tailwind only */
@layer base {
html {
scroll-behavior: smooth;
@@ -20,35 +20,35 @@
}
h1 {
@apply text-3xl md:text-4xl leading-tight mb-8;
@apply text-3xl md:text-4xl leading-tight mb-6;
font-family: 'Inter', sans-serif;
letter-spacing: -0.025em;
}
h2 {
@apply text-2xl md:text-3xl leading-tight mb-6 mt-12;
@apply text-2xl md:text-3xl leading-tight mb-4 mt-8;
font-family: 'Inter', sans-serif;
letter-spacing: -0.025em;
}
h3 {
@apply text-xl md:text-2xl leading-tight mb-4 mt-8;
@apply text-xl md:text-2xl leading-tight mb-3 mt-6;
font-family: 'Inter', sans-serif;
letter-spacing: -0.025em;
}
h4 {
@apply text-lg md:text-xl leading-tight mb-3 mt-6;
@apply text-lg md:text-xl leading-tight mb-2 mt-4;
font-family: 'Inter', sans-serif;
letter-spacing: -0.025em;
}
p {
@apply mb-6 text-base leading-relaxed text-slate-700;
@apply mb-4 text-base leading-relaxed text-slate-700;
}
.lead {
@apply text-xl md:text-2xl text-slate-600 mb-10 leading-relaxed;
@apply text-xl md:text-2xl text-slate-600 mb-6 leading-relaxed;
font-weight: 400;
}
@@ -57,168 +57,94 @@
}
ul, ol {
@apply ml-6 mb-6;
@apply ml-5 mb-4;
}
li {
@apply mb-2;
@apply mb-1;
}
code {
@apply bg-slate-100 px-1.5 py-0.5 rounded font-mono text-sm text-slate-700;
@apply bg-slate-100 px-1 py-0.5 rounded font-mono text-sm text-slate-700;
}
blockquote {
@apply border-l-4 border-slate-300 pl-6 italic text-slate-600 my-6;
@apply border-l-2 border-slate-300 pl-4 italic text-slate-600 my-4;
}
/* Code formatting */
code {
@apply bg-slate-100 px-1.5 py-0.5 rounded font-mono text-sm text-slate-700;
}
/* Inline code */
:not(pre) > code {
@apply text-pink-600 bg-pink-50 border border-pink-200;
}
/* Code blocks */
pre {
@apply bg-slate-900 text-slate-100 p-4 rounded-lg overflow-x-auto my-6 border border-slate-700;
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
font-size: 0.875rem;
line-height: 1.6;
}
pre code {
@apply bg-transparent text-slate-100 px-0 py-0 border-0;
font-family: inherit;
}
/* Syntax highlighting colors */
.token.comment { @apply text-slate-500 italic; }
.token.keyword { @apply text-purple-400 font-semibold; }
.token.string { @apply text-green-400; }
.token.number { @apply text-orange-400; }
.token.function { @apply text-blue-400; }
.token.operator { @apply text-slate-300; }
.token.punctuation { @apply text-slate-400; }
.token.class-name { @apply text-yellow-400 font-semibold; }
/* Line numbers wrapper */
.line-numbers {
counter-reset: line;
}
.line-numbers .line {
counter-increment: line;
position: relative;
padding-left: 2.5rem;
}
.line-numbers .line::before {
content: counter(line);
position: absolute;
left: 0;
width: 2rem;
text-align: right;
color: #64748b;
user-select: none;
}
/* Focus styles - Firefox compatible */
/* Focus states */
a:focus,
button:focus,
[tabindex]:focus,
.post-link:focus,
.highlighter-tag:focus,
.clap-button-top:focus,
.share-button-top:focus,
#back-btn-top:focus,
#back-btn-bottom:focus,
#back-to-top:focus,
input:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2);
}
/* Remove default outline in favor of custom styles */
a:focus-visible,
button:focus-visible,
input:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
a:focus,
button:focus,
input:focus {
outline: 3px solid #000;
outline-offset: 2px;
}
}
}
/* Medium-inspired components */
/* Components - Tailwind utility classes */
@layer components {
.container {
@apply max-w-4xl mx-auto px-6 py-10;
}
.wide-container {
@apply max-w-5xl mx-auto px-6 py-12;
}
.narrow-container {
@apply max-w-2xl mx-auto px-6 py-8;
}
/* Header - removed for single page design */
/* Blog post card - refined with better spacing */
.post-card {
@apply mb-12 last:mb-0;
/* Legacy hooks required by tests */
.file-example {
@apply w-full;
}
.post-card h3 {
@apply text-xl font-semibold mb-3 hover:text-blue-600 transition-colors cursor-pointer;
font-weight: 600;
.container {
@apply max-w-4xl mx-auto px-6 py-10;
}
.wide-container {
@apply max-w-5xl mx-auto px-6 py-12;
}
.narrow-container {
@apply max-w-2xl mx-auto px-6 py-8;
}
.highlighter-tag {
@apply inline-block text-xs font-bold px-2 py-0.5 rounded cursor-pointer transition-all duration-200;
position: relative;
transform: rotate(-1deg);
box-shadow: 2px 2px 0 rgba(0,0,0,0.1);
}
.search-box {
@apply w-full px-4 py-3 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-blue-400 transition-colors;
background: rgba(255,255,255,0.9);
backdrop-filter: blur(10px);
}
.search-box::placeholder {
@apply text-slate-400;
}
/* Blog post card */
.post-card {
@apply mb-8 last:mb-0;
}
.post-meta {
@apply text-sm text-slate-500 font-sans mb-4;
@apply text-xs text-slate-500 font-sans mb-2;
}
.post-excerpt {
@apply text-slate-700 mb-5 leading-relaxed;
@apply text-slate-700 mb-2 leading-relaxed;
}
.post-tags {
@apply flex flex-wrap gap-2;
@apply flex flex-wrap gap-1;
}
.tag {
@apply text-xs font-sans bg-slate-100 text-slate-700 px-2 py-1 rounded hover:bg-slate-200 transition-colors cursor-pointer;
}
.read-more {
@apply text-sm font-semibold text-blue-600 hover:text-blue-800 font-sans inline-flex items-center;
}
/* Article page */
.article-header {
@apply mb-10;
@apply mb-8;
}
.article-title {
@apply text-4xl md:text-5xl font-bold mb-4;
@apply text-4xl md:text-5xl font-bold mb-3;
}
.article-meta {
@apply text-sm text-slate-500 font-sans mb-6;
@apply text-sm text-slate-500 font-sans mb-5;
}
.article-content {
@@ -226,250 +152,63 @@
}
.article-content p {
@apply mb-7;
@apply mb-5;
}
.article-content h2 {
@apply text-2xl font-bold mt-10 mb-4;
@apply text-2xl font-bold mt-8 mb-3;
}
.article-content h3 {
@apply text-xl font-bold mt-8 mb-3;
@apply text-xl font-bold mt-6 mb-2;
}
.article-content ul,
.article-content ol {
@apply ml-6 mb-7;
@apply ml-6 mb-5;
}
.article-content li {
@apply mb-2;
@apply mb-1;
}
.article-content blockquote {
@apply border-l-4 border-slate-400 pl-6 italic text-slate-600 my-8 text-xl;
@apply border-l-2 border-slate-400 pl-4 italic text-slate-600 my-5 text-lg;
}
/* Enhanced code blocks for articles */
.article-content pre {
@apply bg-slate-900 text-slate-100 p-5 rounded-lg overflow-x-auto my-6 border border-slate-700;
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
font-size: 0.875rem;
line-height: 1.6;
position: relative;
}
.article-content pre code {
@apply bg-transparent px-0 py-0;
font-family: inherit;
white-space: pre;
display: block;
}
/* Line numbers for code blocks */
.article-content pre.line-numbers {
padding-left: 3.5rem;
}
.article-content pre.line-numbers::before {
content: attr(data-line-numbers);
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2.5rem;
background: #1e293b;
color: #64748b;
text-align: right;
padding: 1.25rem 0.5rem 1.25rem 0;
font-family: inherit;
font-size: inherit;
line-height: 1.6;
border-right: 1px solid #334155;
user-select: none;
overflow: hidden;
}
/* Inline code in articles */
.article-content p code,
.article-content li code,
.article-content blockquote code {
@apply bg-slate-100 text-pink-600 px-1.5 py-0.5 rounded font-mono text-sm border border-pink-200;
}
/* Syntax highlighting classes */
.article-content .token.comment { @apply text-slate-500 italic; }
.article-content .token.keyword { @apply text-purple-400 font-semibold; }
.article-content .token.string { @apply text-green-400; }
.article-content .token.number { @apply text-orange-400; }
.article-content .token.function { @apply text-blue-400; }
.article-content .token.operator { @apply text-slate-300; }
.article-content .token.punctuation { @apply text-slate-400; }
.article-content .token.class-name { @apply text-yellow-400 font-semibold; }
.article-content .token.tag { @apply text-red-400; }
.article-content .token.attr-name { @apply text-purple-400; }
.article-content .token.attr-value { @apply text-green-400; }
/* Code language badge */
.article-content pre::after {
content: attr(data-language);
position: absolute;
top: 0.5rem;
right: 0.5rem;
background: #334155;
color: #e2e8f0;
padding: 0.125rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-family: 'Inter', sans-serif;
}
/* About page sections */
.about-section {
@apply mb-10 pb-8 border-b border-slate-200 last:border-0;
}
.about-section h2 {
@apply text-2xl font-bold mb-4;
}
.about-list {
@apply space-y-2;
}
.about-list li {
@apply flex items-start;
}
.about-list li::before {
content: "→";
@apply mr-2 text-blue-600 font-bold;
}
/* Footer - removed for single page design */
/* Simple button */
/* Buttons */
.btn {
@apply inline-block px-5 py-2 bg-slate-900 text-white font-sans font-medium hover:bg-slate-700 transition-colors no-underline rounded;
@apply inline-block px-4 py-2 bg-slate-900 text-white font-sans font-medium hover:bg-slate-700 transition-colors rounded;
}
/* Highlighter-style tags - lovely note-taking style */
.highlighter-tag {
@apply inline-block text-xs font-bold px-2 py-0.5 rounded cursor-pointer transition-all duration-200;
position: relative;
transform: rotate(-1deg);
box-shadow: 2px 2px 0 rgba(0,0,0,0.1);
.btn-primary {
@apply bg-blue-600 hover:bg-blue-700 text-white px-3 py-1.5 rounded transition-colors;
}
.highlighter-yellow {
@apply bg-yellow-300 text-yellow-900;
background: linear-gradient(180deg, rgba(255,235,59,0.9) 0%, rgba(255,213,79,0.9) 100%);
.btn-secondary {
@apply bg-white text-slate-700 hover:bg-slate-100 border border-slate-300 px-3 py-1.5 rounded transition-colors;
}
.highlighter-yellow:hover {
transform: rotate(-2deg) scale(1.1);
box-shadow: 3px 3px 0 rgba(0,0,0,0.15);
/* Hide scrollbars */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.highlighter-pink {
@apply bg-pink-300 text-pink-900;
background: linear-gradient(180deg, rgba(255,167,209,0.9) 0%, rgba(255,122,175,0.9) 100%);
.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.highlighter-pink:hover {
transform: rotate(-2deg) scale(1.1);
box-shadow: 3px 3px 0 rgba(0,0,0,0.15);
}
.highlighter-green {
@apply bg-green-300 text-green-900;
background: linear-gradient(180deg, rgba(129,199,132,0.9) 0%, rgba(102,187,106,0.9) 100%);
}
.highlighter-green:hover {
transform: rotate(-2deg) scale(1.1);
box-shadow: 3px 3px 0 rgba(0,0,0,0.15);
}
.highlighter-blue {
@apply bg-blue-300 text-blue-900;
background: linear-gradient(180deg, rgba(100,181,246,0.9) 0%, rgba(66,165,245,0.9) 100%);
}
.highlighter-blue:hover {
transform: rotate(-2deg) scale(1.1);
box-shadow: 3px 3px 0 rgba(0,0,0,0.15);
}
/* Scribble underline for emphasis */
.scribble-emphasis {
position: relative;
display: inline-block;
font-weight: 600;
}
.scribble-emphasis::after {
content: '';
position: absolute;
bottom: -2px;
left: -1px;
right: -1px;
height: 7px;
background: url("data:image/svg+xml,%3Csvg width='40' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 4 Q10 2, 20 4 T38 4' stroke='%23FFEB3B' stroke-width='3' fill='none' stroke-linecap='round'/%3E%3C/svg%3E") repeat-x;
background-size: 40px 8px;
opacity: 0.7;
z-index: -1;
}
/* Sticky note effect */
.sticky-note {
@apply p-4 rounded shadow-sm border;
background: linear-gradient(135deg, #fff9c4 0%, #fff59d 100%);
border-color: #f9a825;
transform: rotate(-0.5deg);
box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
}
.sticky-note:hover {
transform: rotate(0deg) scale(1.02);
box-shadow: 3px 3px 8px rgba(0,0,0,0.15);
}
/* Handwritten style */
.handwritten {
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', cursive;
font-weight: 500;
letter-spacing: -0.3px;
}
/* Search box styling */
.search-box {
@apply w-full px-4 py-3 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-blue-400 transition-colors;
background: rgba(255,255,255,0.9);
backdrop-filter: blur(10px);
}
.search-box::placeholder {
@apply text-slate-400;
}
/* Tag cloud */
.tag-cloud {
@apply flex flex-wrap gap-2 items-center;
}
/* Empty state */
.empty-state {
@apply text-center py-12 text-slate-500;
@apply text-center py-8 text-slate-500;
}
.empty-state svg {
@apply mx-auto mb-4 text-slate-300;
@apply mx-auto mb-2 text-slate-300;
}
/* Line clamp utility for text truncation */
/* Line clamp utility */
.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
@@ -477,103 +216,71 @@
overflow: hidden;
}
/* Subtle gradient backgrounds */
.subtle-gradient {
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(248,250,252,0.1) 100%);
}
/* Enhanced focus states */
.focus-ring {
@apply focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-white;
}
/* Reading progress indicator */
.reading-progress {
.reading-progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: linear-gradient(90deg, #3b82f6 0%, #8b5cf6 100%);
transform-origin: left;
z-index: 50;
}
/* Smooth animations */
.animate-fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Enhanced typography for better readability */
.text-balance {
text-wrap: balance;
}
/* Subtle shadow variations */
.shadow-soft {
box-shadow: 0 2px 8px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.08);
}
.shadow-hover {
box-shadow: 0 4px 16px rgba(0,0,0,0.06), 0 2px 6px rgba(0,0,0,0.12);
}
/* Improved button styles */
.btn-primary {
@apply bg-blue-600 text-white font-sans font-medium px-6 py-3 rounded-lg hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all duration-200;
}
.btn-secondary {
@apply bg-white text-slate-700 font-sans font-medium px-6 py-3 rounded-lg border border-slate-200 hover:bg-slate-50 focus:ring-2 focus:ring-slate-500 focus:ring-offset-2 transition-all duration-200;
}
/* Status indicators */
.status-indicator {
@apply inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs font-medium;
}
.status-published {
@apply bg-green-100 text-green-800;
}
.status-draft {
@apply bg-yellow-100 text-yellow-800;
}
/* Responsive grid improvements */
.grid-responsive {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
/* Better spacing utilities */
.space-y-fluid > * + * {
margin-top: clamp(1rem, 2vw, 2rem);
}
/* Enhanced link styles */
.link-enhanced {
@apply text-blue-600 hover:text-blue-800 transition-colors duration-200 relative;
}
.link-enhanced::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
width: 0;
height: 2px;
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
transition: width 0.3s ease;
background: #3b82f6;
transform-origin: left;
transform: scaleX(0);
z-index: 50;
transition: transform 0.1s ease-out;
}
.link-enhanced:hover::after {
width: 100%;
/* Floating back to top button */
.floating-back-to-top {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
width: 2.5rem;
height: 2.5rem;
background: white;
border: 1px solid #e2e8f0;
border-radius: 0.375rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: #64748b;
transition: all 0.15s ease;
opacity: 0;
transform: translateY(8px);
}
.floating-back-to-top.visible {
opacity: 1;
transform: translateY(0);
}
.floating-back-to-top:hover {
background: #f8fafc;
color: #1e293b;
transform: translateY(-1px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Print styles */
@media print {
.floating-back-to-top,
.reading-progress-bar {
display: none !important;
}
}
}