diff --git a/docs/WEB-DESIGN-SYSTEM.md b/docs/WEB-DESIGN-SYSTEM.md
new file mode 100644
index 000000000..481c49c96
--- /dev/null
+++ b/docs/WEB-DESIGN-SYSTEM.md
@@ -0,0 +1,926 @@
+# Hammer Editor Web Design System
+
+This document describes the design system used for Hammer Editor's server-side web interface. The design follows a "
+Writer's Desk" aesthetic with a unified component library using BEM naming conventions.
+
+## Table of Contents
+
+- [Design Philosophy](#design-philosophy)
+- [CSS Architecture](#css-architecture)
+- [Design Tokens](#design-tokens)
+- [Typography](#typography)
+- [Shared Animations](#shared-animations)
+- [Layout Components](#layout-components)
+- [UI Components](#ui-components)
+- [Form Components](#form-components)
+- [Utility Classes](#utility-classes)
+- [Responsive Design](#responsive-design)
+- [Accessibility](#accessibility)
+
+---
+
+## Design Philosophy
+
+The Hammer web interface uses a **"Writer's Desk"** aesthetic that evokes:
+
+- **Notebook paper** with lined backgrounds and red margin lines
+- **Typewriter typography** for headings and labels
+- **Warm, paper-like colors** with amber/gold accents
+- **Sticky note aesthetics** for feature cards
+- **Subtle shadows and textures** that feel tactile
+
+The goal is to create an interface that feels familiar and comfortable to writers, while remaining modern and
+functional.
+
+---
+
+## CSS Architecture
+
+### File Structure
+
+```
+server/src/main/resources/assets/css/
+├── base.css # Design tokens, typography, shared components
+├── home.css # Landing/marketing page
+├── dashboard.css # User dashboard
+├── admin.css # Admin pages
+├── login.css # Login page
+├── author.css # Public author pages
+├── story.css # Story viewing/editing pages
+└── error.css # Error pages (404, 500, etc.)
+```
+
+### Naming Convention
+
+We use **BEM (Block Element Modifier)** naming:
+
+```css
+.block {
+}
+
+/* Component block */
+.block__element {
+}
+
+/* Child element */
+.block--modifier {
+}
+
+/* Variant/state */
+```
+
+Examples:
+
+- `.card` - Block (the component)
+- `.card__title` - Element (part of the card)
+- `.card--interactive` - Modifier (makes it clickable)
+
+---
+
+## Design Tokens
+
+### Color Palette
+
+```css
+/* Primary Colors */
+--primary: #2563eb
+
+; /* Blue - links, primary actions */
+--primary-dark: #1e40af
+
+;
+--primary-light: #3b82f6
+
+;
+
+/* Accent Colors (Amber/Gold) */
+--accent: #d97706
+
+; /* Main accent - borders, highlights */
+--accent-light: #f59e0b
+
+;
+--accent-dark: #b45309
+
+;
+
+/* Neutral Scale (Stone) */
+--neutral-50: #fafaf9
+
+;
+--neutral-100: #f5f5f4
+
+;
+--neutral-200: #e7e5e4
+
+;
+--neutral-300: #d6d3d1
+
+;
+--neutral-400: #a8a29e
+
+;
+--neutral-500: #78716c
+
+;
+--neutral-600: #57534e
+
+;
+--neutral-700: #44403c
+
+;
+--neutral-800: #292524
+
+;
+--neutral-900: #1c1917
+
+;
+
+/* Writer's Desk Colors */
+--sticky-yellow: #fef08a
+
+; /* Yellow sticky notes */
+--sticky-blue: #bfdbfe
+
+; /* Blue sticky notes */
+--sticky-green: #bbf7d0
+
+; /* Green sticky notes */
+--sticky-pink: #fbcfe8
+
+; /* Pink sticky notes */
+--paper-white: #fffef9
+
+; /* Warm paper color */
+--ink: #1c1917
+
+; /* Dark ink color */
+
+/* Semantic Colors */
+--success: #10b981
+
+; /* Green - success states */
+--warning: #f59e0b
+
+; /* Amber - warnings */
+--error: #ef4444
+
+; /* Red - errors */
+```
+
+### Shadows
+
+```css
+--shadow-sm:
+
+0
+1
+px
+
+2
+px
+
+0
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.05
+)
+;
+--shadow-md:
+
+0
+4
+px
+
+6
+px
+
+-
+1
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.1
+)
+,
+0
+2
+px
+
+4
+px
+
+-
+1
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.06
+)
+;
+--shadow-lg:
+
+0
+10
+px
+
+15
+px
+
+-
+3
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.1
+)
+,
+0
+4
+px
+
+6
+px
+
+-
+2
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.05
+)
+;
+--shadow-xl:
+
+0
+20
+px
+
+25
+px
+
+-
+5
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.1
+)
+,
+0
+10
+px
+
+10
+px
+
+-
+5
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.04
+)
+;
+--shadow-sticky:
+
+0
+1
+px
+
+3
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.12
+)
+,
+0
+1
+px
+
+2
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.24
+)
+;
+--shadow-sticky-hover:
+
+0
+10
+px
+
+20
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.15
+)
+,
+0
+3
+px
+
+6
+px
+
+rgba
+(
+0
+,
+0
+,
+0
+,
+0.10
+)
+;
+```
+
+### Animation Timing
+
+```css
+--transition-fast:
+
+150
+ms
+
+cubic-bezier
+(
+0.4
+,
+0
+,
+0.2
+,
+1
+)
+;
+--transition-base:
+
+250
+ms
+
+cubic-bezier
+(
+0.4
+,
+0
+,
+0.2
+,
+1
+)
+;
+--transition-slow:
+
+350
+ms
+
+cubic-bezier
+(
+0.4
+,
+0
+,
+0.2
+,
+1
+)
+;
+```
+
+---
+
+## Typography
+
+### Font Families
+
+1. **Kingthings Typewriter** - Headings, labels, buttons
+ - Evokes vintage typewriter aesthetic
+ - Used for all `h1-h6`, form labels, button text
+
+2. **Lora** - Body text, paragraphs
+ - Elegant serif font for readability
+ - Used for body copy, descriptions, input values
+
+### Usage
+
+```css
+/* Headings and UI elements */
+font-family:
+
+'Kingthings Typewriter'
+,
+monospace
+
+;
+
+/* Body text */
+font-family:
+
+'Lora'
+,
+Georgia, serif
+
+;
+```
+
+### Responsive Font Sizes
+
+```css
+h1 {
+ font-size: clamp(2.5rem, 5vw, 4.5rem);
+}
+
+h2 {
+ font-size: clamp(2rem, 4vw, 3.5rem);
+}
+
+h3 {
+ font-size: clamp(1.5rem, 3vw, 2.25rem);
+}
+```
+
+---
+
+## Shared Animations
+
+These animations are defined in `base.css` and can be used across all pages:
+
+```css
+/* Fade effects */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+
+/* Slide effects */
+@keyframes slideInUp {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes slideInDown {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+```
+
+Usage:
+
+```css
+.my-element {
+ animation: slideInUp 0.5s ease-out;
+}
+```
+
+---
+
+## Layout Components
+
+### Page Container
+
+The base wrapper for page content.
+
+```html
+
+
+
+
+
+
+```
+
+**Modifiers:**
+
+- `.page--centered` - Centers content vertically and horizontally
+- `.page__container--narrow` - Max-width 480px (forms, login)
+- `.page__container--wide` - Max-width 1200px (admin, dashboards)
+
+**Page-specific modifiers:**
+
+- `.page__container--author` - Max-width 900px
+- `.page__container--error` - Max-width 600px
+
+### Page Header
+
+Dark header bar with title, subtitle, and optional actions.
+
+```html
+
+
+```
+
+### Paper Section
+
+Notebook-style content sections with lined background and red margin.
+
+```html
+
+
+
+
Manage your writing projects.
+
+
+```
+
+**Modifiers:**
+
+- `.paper-section--compact` - Reduced padding
+- `.paper-section--centered` - Center-aligned text
+
+---
+
+## UI Components
+
+### Cards
+
+Interactive card components for lists of items.
+
+```html
+
+
+```
+
+**Modifiers:**
+
+- `.card--interactive` - Adds hover effects (translateX, border change)
+- `.card--gradient` - Gradient background
+
+### Dialog/Modal
+
+Modal dialogs with header, body, and actions.
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+**Modifiers:**
+
+- `.dialog--warning` - Warning variant with amber tint
+
+**JavaScript:**
+Add `.closing` class to `.dialog-overlay` to trigger fade-out animation.
+
+### Buttons
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Pagination
+
+```html
+
+
+```
+
+### Empty State
+
+For displaying when lists have no content.
+
+```html
+
+
+
📝
+
No projects yet. Start writing!
+
+```
+
+### Toast Notifications
+
+```html
+
+
+
+ ✓
+ Changes saved successfully
+
+
+
+```
+
+**Variants:** `.toast-success`, `.toast-warning`, `.toast-error`, `.toast-info`
+
+---
+
+## Form Components
+
+### Form Field
+
+```html
+
+
+
+
+
+```
+
+### Input Types
+
+```html
+
+
+
+
+
+
+
+
+```
+
+### Form Field Label Variants
+
+```html
+
+
+```
+
+---
+
+## Utility Classes
+
+```css
+.hidden {
+ display: none !important;
+}
+```
+
+---
+
+## Responsive Design
+
+The design system includes responsive breakpoints:
+
+| Breakpoint | Width | Usage |
+|------------|----------------|-----------------------|
+| Large | > 1024px | Full desktop layout |
+| Medium | 769px - 1024px | Tablet/narrow desktop |
+| Small | 601px - 768px | Large mobile |
+| X-Small | ≤ 600px | Mobile phones |
+| XX-Small | ≤ 480px | Small phones |
+
+### Behavior Changes
+
+**768px and below:**
+
+- Page headers stack vertically
+- Paper sections reduce padding
+- Cards don't transform on hover
+- Dialogs use 95% width
+
+**480px and below:**
+
+- Smaller font sizes for titles
+- Reduced spacing throughout
+
+---
+
+## Accessibility
+
+### Reduced Motion
+
+All animations respect `prefers-reduced-motion`:
+
+```css
+@media (prefers-reduced-motion: reduce) {
+ *, *::before, *::after {
+ animation-duration: 0.01ms !important;
+ transition-duration: 0.01ms !important;
+ }
+}
+```
+
+### Focus States
+
+All interactive elements have visible focus states:
+
+```css
+*:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 3px;
+}
+```
+
+### Color Contrast
+
+- Text colors meet WCAG AA contrast requirements
+- Interactive elements have clear hover/focus states
+- Error states use both color and icons for accessibility
+
+---
+
+## Page-Specific Extensions
+
+While the shared components cover most use cases, some pages have additional specific styles:
+
+- **home.css** - Marketing page sticky notes, feature grid, download cards
+- **dashboard.css** - Pen name section, danger zone, account info
+- **admin.css** - Sidebar navigation, whitelist management
+- **login.css** - Login header styling, error shake animation, whitelist notices
+- **author.css** - Author header with avatar, story count
+- **story.css** - Story content formatting, publish toggle, access list
+- **error.css** - Colored sticky-note error cards with animations
+
+---
+
+## Example: Complete Page Structure
+
+```html
+{{> header}}
+
+
+
+
+
+{{> footer}}
+```
diff --git a/server/src/main/resources/assets/css/admin.css b/server/src/main/resources/assets/css/admin.css
index 5ba7da0a2..1a038e12d 100644
--- a/server/src/main/resources/assets/css/admin.css
+++ b/server/src/main/resources/assets/css/admin.css
@@ -1,519 +1,4 @@
-/* Admin Page Styles */
-
-.admin-page {
- min-height: calc(100vh - 200px);
- padding: 2rem;
- background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-50) 100%);
-}
-
-.admin-container {
- max-width: 1000px;
- margin: 0 auto;
- animation: fadeIn 0.5s ease-out;
-}
-
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-/* Admin Header */
-.admin-header {
- background: var(--neutral-900);
- color: white;
- padding: 2.5rem 3rem;
- border-radius: 0.75rem;
- margin-bottom: 2rem;
- display: flex;
- justify-content: space-between;
- align-items: center;
- box-shadow: var(--shadow-lg);
- border-bottom: 3px solid var(--accent);
- animation: slideInDown 0.5s ease-out;
-}
-
-@keyframes slideInDown {
- from {
- opacity: 0;
- transform: translateY(-20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-.admin-header-content h1 {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 2.5rem;
- color: white;
- margin-bottom: 0.5rem;
-}
-
-.admin-subtitle {
- color: var(--neutral-700);
- font-size: 1.0625rem;
- font-style: italic;
- margin: 0;
-}
-
-.logout-form {
- margin: 0;
-}
-
-
-/* Section Cards */
-.admin-section {
- background: var(--surface);
- background-image: repeating-linear-gradient(
- transparent,
- transparent 31px,
- rgba(0, 0, 0, 0.03) 31px,
- rgba(0, 0, 0, 0.03) 32px
- );
- padding: 2.5rem 3rem 2.5rem 4rem;
- margin-bottom: 2rem;
- border-radius: 0.75rem;
- box-shadow: var(--shadow-lg),
- inset 0 0 0 1px rgba(0, 0, 0, 0.05);
- border-left: 4px solid var(--accent);
- position: relative;
- animation: slideInUp 0.5s ease-out;
- animation-fill-mode: both;
-}
-
-.admin-section:nth-child(2) {
- animation-delay: 0.1s;
-}
-
-.admin-section:nth-child(3) {
- animation-delay: 0.2s;
-}
-
-@keyframes slideInUp {
- from {
- opacity: 0;
- transform: translateY(20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Red margin line like notebook paper */
-.admin-section::before {
- content: '';
- position: absolute;
- left: 2.5rem;
- top: 0;
- bottom: 0;
- width: 2px;
- background: rgba(239, 68, 68, 0.2);
- pointer-events: none;
-}
-
-/* Section Headers */
-.section-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- gap: 1rem;
- margin-bottom: 1rem;
-}
-
-.section-title-group {
- display: flex;
- flex-direction: column;
- gap: 0.25rem;
-}
-
-.section-header h2 {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 2rem;
- color: var(--text-primary);
- margin: 0;
-}
-
-.section-header-actions {
- display: flex;
- align-items: center;
- gap: 1rem;
-}
-
-.toggle-button {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1rem;
- padding: 0.75rem 1.5rem;
- background: var(--accent);
- color: white;
- border: none;
- border-radius: 0.5rem;
- cursor: pointer;
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
- white-space: nowrap;
-}
-
-.toggle-button:hover {
- background: var(--accent-dark);
- transform: translateY(-2px);
- box-shadow: var(--shadow-md);
-}
-
-.toggle-button.active {
- background: rgba(239, 68, 68, 0.9);
-}
-
-.toggle-button.active:hover {
- background: #dc2626;
-}
-
-.section-badge {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.875rem;
- padding: 0.375rem 0.875rem;
- background: var(--neutral-200);
- color: var(--neutral-700);
- border-radius: 0.375rem;
- font-weight: normal;
-}
-
-.section-badge.accent {
- background: var(--accent-light);
- color: var(--accent-dark);
-}
-
-.section-description {
- color: var(--text-secondary);
- font-size: 1rem;
- margin-bottom: 1.5rem;
- line-height: 1.6;
-}
-
-/* Message Display */
-.message-display {
- background: var(--neutral-100);
- border: 2px solid var(--neutral-300);
- border-radius: 0.5rem;
- padding: 1.5rem;
- margin-top: 1rem;
-}
-
-.message-display pre {
- font-family: 'Courier New', monospace;
- font-size: 0.9375rem;
- color: var(--text-primary);
- white-space: pre-wrap;
- line-height: 1.6;
- margin: 0;
-}
-
-/* Whitelist Form */
-.whitelist-form {
- margin: 1.5rem 0;
- padding: 1.5rem;
- background: rgba(217, 119, 6, 0.05);
- border: 2px solid rgba(217, 119, 6, 0.2);
- border-radius: 0.5rem;
-}
-
-.form-group {
- display: flex;
- flex-direction: column;
- gap: 0.75rem;
-}
-
-.form-group label {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1.125rem;
- color: var(--text-primary);
-}
-
-.form-input-group {
- display: flex;
- gap: 0.75rem;
-}
-
-.form-input-group input {
- flex: 1;
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- padding: 0.875rem 1rem;
- border: 2px solid var(--neutral-300);
- border-radius: 0.5rem;
- background: white;
- color: var(--text-primary);
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
-}
-
-.form-input-group input::placeholder {
- color: var(--neutral-400);
- font-style: italic;
-}
-
-.form-input-group input:hover {
- border-color: var(--neutral-400);
-}
-
-.form-input-group input:focus {
- outline: none;
- border-color: var(--accent);
- box-shadow: var(--shadow-md),
- 0 0 0 3px rgba(217, 119, 6, 0.1);
-}
-
-.add-button,
-.save-button {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1rem;
- padding: 0.875rem 2rem;
- background: var(--accent);
- color: white;
- border: none;
- border-radius: 0.5rem;
- cursor: pointer;
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
- white-space: nowrap;
-}
-
-.add-button:hover,
-.save-button:hover {
- background: var(--accent-dark);
- transform: translateY(-2px);
- box-shadow: var(--shadow-md);
-}
-
-.add-button:active,
-.save-button:active {
- transform: translateY(0);
-}
-
-.settings-form {
- display: flex;
- flex-direction: column;
- gap: 1.5rem;
-}
-
-.settings-select {
- width: 100%;
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- padding: 0.875rem 1rem;
- border: 2px solid var(--neutral-300);
- border-radius: 0.5rem;
- background: white;
- color: var(--text-primary);
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
- cursor: pointer;
-}
-
-.settings-select:focus {
- outline: none;
- border-color: var(--accent);
- box-shadow: var(--shadow-md),
- 0 0 0 3px rgba(217, 119, 6, 0.1);
-}
-
-.settings-textarea {
- width: 100%;
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- padding: 0.875rem 1rem;
- border: 2px solid var(--neutral-300);
- border-radius: 0.5rem;
- background: white;
- color: var(--text-primary);
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
- resize: vertical;
- min-height: 100px;
-}
-
-.settings-textarea:focus {
- outline: none;
- border-color: var(--accent);
- box-shadow: var(--shadow-md),
- 0 0 0 3px rgba(217, 119, 6, 0.1);
-}
-
-.form-actions {
- display: flex;
- justify-content: flex-end;
-}
-
-/* Whitelist Container */
-.whitelist-container {
- margin-top: 2rem;
-}
-
-/* Whitelist User Items (for HTMX loaded content) */
-#whitelist {
- display: flex;
- flex-direction: column;
- gap: 0.75rem;
-}
-
-.whitelist-user {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 1rem 1.25rem;
- background: white;
- border: 2px solid var(--neutral-200);
- border-radius: 0.5rem;
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
-}
-
-.whitelist-user:hover {
- border-color: var(--neutral-300);
- box-shadow: var(--shadow-md);
- transform: translateX(4px);
-}
-
-.whitelist-user-email {
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- color: var(--text-primary);
- font-weight: 500;
-}
-
-.whitelist-user-actions {
- display: flex;
- gap: 0.5rem;
-}
-
-.remove-button {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.875rem;
- padding: 0.5rem 1rem;
- background: transparent;
- color: #dc2626;
- border: 2px solid #dc2626;
- border-radius: 0.375rem;
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.remove-button:hover {
- background: #dc2626;
- color: white;
- transform: translateY(-1px);
- box-shadow: var(--shadow-sm);
-}
-
-.remove-button:active {
- transform: translateY(0);
-}
-
-/* Empty State */
-.whitelist-empty {
- text-align: center;
- padding: 3rem 2rem;
- color: var(--text-secondary);
- font-style: italic;
-}
-
-.whitelist-empty::before {
- content: '📝';
- display: block;
- font-size: 3rem;
- margin-bottom: 1rem;
- opacity: 0.5;
-}
-
-/* Responsive Design */
-@media only screen and (max-width: 768px) {
- .admin-page {
- padding: 1.5rem;
- }
-
- .admin-header {
- flex-direction: column;
- gap: 1.5rem;
- padding: 2rem 1.75rem;
- text-align: center;
- }
-
- .admin-header-content h1 {
- font-size: 2rem;
- }
-
- .admin-section {
- padding: 2rem 1.75rem 2rem 3rem;
- }
-
- .admin-section::before {
- left: 1.5rem;
- }
-
- .section-header {
- flex-direction: column;
- align-items: flex-start;
- gap: 0.5rem;
- }
-
- .section-header h2 {
- font-size: 1.75rem;
- }
-
- .form-input-group {
- flex-direction: column;
- }
-
- .add-button {
- width: 100%;
- }
-
- .whitelist-user {
- flex-direction: column;
- align-items: flex-start;
- gap: 1rem;
- }
-
- .whitelist-user-actions {
- width: 100%;
- }
-
- .remove-button {
- flex: 1;
- }
-}
-
-@media only screen and (max-width: 480px) {
- .admin-header-content h1 {
- font-size: 1.75rem;
- }
-
- .admin-subtitle {
- font-size: 0.9375rem;
- }
-
- .section-header h2 {
- font-size: 1.5rem;
- }
-}
-
-/* Accessibility */
-@media (prefers-reduced-motion: reduce) {
- .admin-container,
- .admin-header,
- .admin-section {
- animation: none;
- }
-
- .whitelist-user:hover {
- transform: none;
- }
-}
+/* Admin Page Styles - Page-specific overrides */
/* ========================================
Admin Layout with Sidebar
@@ -588,32 +73,187 @@
min-width: 0;
}
-/* Header actions for whitelist page */
-.admin-header-actions {
+/* ========================================
+ Admin-specific Buttons
+ ======================================== */
+
+.toggle-button {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 1rem;
+ padding: 0.75rem 1.5rem;
+ background: var(--accent);
+ color: white;
+ border: none;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
+ white-space: nowrap;
+}
+
+.toggle-button:hover {
+ background: var(--accent-dark);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-md);
+}
+
+.toggle-button.active {
+ background: rgba(239, 68, 68, 0.9);
+}
+
+.toggle-button.active:hover {
+ background: #dc2626;
+}
+
+.section-badge {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 0.875rem;
+ padding: 0.375rem 0.875rem;
+ background: var(--neutral-200);
+ color: var(--neutral-700);
+ border-radius: 0.375rem;
+ font-weight: normal;
+}
+
+.section-badge.accent {
+ background: var(--accent-light);
+ color: var(--accent-dark);
+}
+
+/* ========================================
+ Form Styling
+ ======================================== */
+
+.logout-form {
+ margin: 0;
+}
+
+.whitelist-form {
+ margin: 1.5rem 0;
+ padding: 1.5rem;
+ background: rgba(217, 119, 6, 0.05);
+ border: 2px solid rgba(217, 119, 6, 0.2);
+ border-radius: 0.5rem;
+}
+
+.form-group {
display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.form-input-group {
+ display: flex;
+ gap: 0.75rem;
+}
+
+.form-input-group .form-input {
+ flex: 1;
+}
+
+.add-button,
+.save-button {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 1rem;
+ padding: 0.875rem 2rem;
+ background: var(--accent);
+ color: white;
+ border: none;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
+ white-space: nowrap;
+}
+
+.add-button:hover,
+.save-button:hover {
+ background: var(--accent-dark);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-md);
+}
+
+.add-button:active,
+.save-button:active {
+ transform: translateY(0);
+}
+
+.settings-form {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.form-actions {
+ display: flex;
+ justify-content: flex-end;
+}
+
+/* ========================================
+ Whitelist Items
+ ======================================== */
+
+.whitelist-container {
+ margin-top: 2rem;
+}
+
+#whitelist {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.whitelist-user {
+ display: flex;
+ justify-content: space-between;
align-items: center;
- gap: 1rem;
+ padding: 1rem 1.25rem;
+ background: white;
+ border: 2px solid var(--neutral-200);
+ border-radius: 0.5rem;
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
}
-/* Placeholder styling for User Management */
-.placeholder-content {
- text-align: center;
- padding: 4rem 2rem;
- color: var(--text-tertiary);
+.whitelist-user:hover {
+ border-color: var(--neutral-300);
+ box-shadow: var(--shadow-md);
+ transform: translateX(4px);
}
-.placeholder-icon {
- font-size: 4rem;
- margin-bottom: 1.5rem;
- opacity: 0.3;
-}
-
-.placeholder-content p {
+.whitelist-user-email {
font-family: 'Lora', Georgia, serif;
- font-size: 1.125rem;
- font-style: italic;
- max-width: 400px;
- margin: 0 auto;
+ font-size: 1rem;
+ color: var(--text-primary);
+ font-weight: 500;
+}
+
+.whitelist-user-actions {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.remove-button {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 0.875rem;
+ padding: 0.5rem 1rem;
+ background: transparent;
+ color: #dc2626;
+ border: 2px solid #dc2626;
+ border-radius: 0.375rem;
+ cursor: pointer;
+ transition: all var(--transition-base);
+}
+
+.remove-button:hover {
+ background: #dc2626;
+ color: white;
+ transform: translateY(-1px);
+ box-shadow: var(--shadow-sm);
+}
+
+.remove-button:active {
+ transform: translateY(0);
}
/* ========================================
@@ -702,61 +342,10 @@
font-size: 0.75rem;
}
-.users-empty {
- text-align: center;
- padding: 3rem 2rem;
- color: var(--text-secondary);
- font-style: italic;
-}
+/* ========================================
+ Responsive Design
+ ======================================== */
-.users-empty::before {
- content: '\f0c0';
- font-family: 'Font Awesome 6 Free';
- font-weight: 900;
- display: block;
- font-size: 3rem;
- margin-bottom: 1rem;
- opacity: 0.3;
-}
-
-/* Pagination Styles */
-.pagination {
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 1rem;
- margin-top: 2rem;
- padding-top: 1.5rem;
- border-top: 2px solid var(--neutral-200);
-}
-
-.pagination-button {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.875rem;
- padding: 0.5rem 1rem;
- background: var(--neutral-100);
- color: var(--text-primary);
- border: 2px solid var(--neutral-300);
- border-radius: 0.375rem;
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.pagination-button:hover {
- background: var(--accent);
- color: white;
- border-color: var(--accent);
- transform: translateY(-1px);
- box-shadow: var(--shadow-sm);
-}
-
-.pagination-info {
- font-family: 'Lora', Georgia, serif;
- font-size: 0.875rem;
- color: var(--text-secondary);
-}
-
-/* Responsive: Stack on mobile */
@media only screen and (max-width: 900px) {
.admin-layout {
flex-direction: column;
@@ -801,10 +390,29 @@
.admin-nav-link span {
font-size: 0.875rem;
}
+}
- .admin-header-actions {
+@media only screen and (max-width: 768px) {
+ .form-input-group {
flex-direction: column;
- gap: 0.75rem;
+ }
+
+ .add-button {
+ width: 100%;
+ }
+
+ .whitelist-user {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
+
+ .whitelist-user-actions {
+ width: 100%;
+ }
+
+ .remove-button {
+ flex: 1;
}
.user-item {
@@ -821,10 +429,12 @@
flex-direction: column;
gap: 0.5rem;
}
-
- .pagination {
- flex-direction: column;
- gap: 0.75rem;
- }
}
+/* Accessibility */
+@media (prefers-reduced-motion: reduce) {
+ .whitelist-user:hover,
+ .user-item:hover {
+ transform: none;
+ }
+}
diff --git a/server/src/main/resources/assets/css/author.css b/server/src/main/resources/assets/css/author.css
index 505aa5555..f6cf8499d 100644
--- a/server/src/main/resources/assets/css/author.css
+++ b/server/src/main/resources/assets/css/author.css
@@ -1,17 +1,9 @@
/* Author Page Styles */
/* A clean, simple literary portfolio */
-.author-page {
- min-height: calc(100vh - 200px);
- padding: 2rem 1rem;
- background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-50) 100%);
- display: flex;
- justify-content: center;
-}
-
-.author-container {
+/* Author-specific container width */
+.page__container--author {
max-width: 900px;
- width: 100%;
}
/* ========================================
@@ -26,11 +18,6 @@
animation: fadeIn 0.5s ease-out;
}
-@keyframes fadeIn {
- from { opacity: 0; }
- to { opacity: 1; }
-}
-
/* ========================================
Author Header (inside the card)
======================================== */
@@ -85,75 +72,6 @@
font-style: italic;
}
-/* ========================================
- Stories List
- ======================================== */
-
-.stories-list {
- display: flex;
- flex-direction: column;
- gap: 0.75rem;
-}
-
-/* ========================================
- Story Card
- ======================================== */
-
-.story-card {
- display: flex;
- align-items: center;
- text-decoration: none;
- background: linear-gradient(135deg, #fdfcfb 0%, #f5f4f0 100%);
- border: 1px solid var(--neutral-200);
- border-radius: 0.5rem;
- box-shadow: var(--shadow-sm);
- transition: all 0.2s ease;
- padding: 1rem 1.25rem;
-}
-
-.story-card:hover {
- background: white;
- border-color: var(--accent);
- box-shadow: var(--shadow-md);
-}
-
-.story-info {
- flex: 1;
- min-width: 0;
-}
-
-.story-name {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1.125rem;
- color: var(--text-primary);
- margin: 0 0 0.25rem;
- line-height: 1.3;
- transition: color 0.2s ease;
-}
-
-.story-card:hover .story-name {
- color: var(--accent-dark);
-}
-
-.story-date {
- font-family: 'Lora', Georgia, serif;
- font-size: 0.8125rem;
- color: var(--text-secondary);
- font-style: italic;
-}
-
-.story-arrow {
- color: var(--neutral-400);
- font-size: 0.875rem;
- transition: all 0.2s ease;
- margin-left: 1rem;
-}
-
-.story-card:hover .story-arrow {
- color: var(--accent);
- transform: translateX(3px);
-}
-
/* ========================================
Story Count
======================================== */
@@ -239,10 +157,6 @@
======================================== */
@media only screen and (max-width: 768px) {
- .author-page {
- padding: 1.5rem 1rem;
- }
-
.stories-section {
padding: 1.5rem;
border-radius: 0.5rem;
@@ -273,14 +187,6 @@
.author-name {
font-size: 1.5rem;
}
-
- .story-card {
- padding: 0.875rem 1rem;
- }
-
- .story-name {
- font-size: 1rem;
- }
}
/* ========================================
@@ -288,16 +194,7 @@
======================================== */
@media (prefers-reduced-motion: reduce) {
- .stories-section,
- .story-card,
- .read-link i {
+ .stories-section {
animation: none;
- transition: none;
}
}
-
-/* Focus styles for keyboard navigation */
-.story-card:focus-visible {
- outline: 3px solid var(--accent);
- outline-offset: 2px;
-}
diff --git a/server/src/main/resources/assets/css/base.css b/server/src/main/resources/assets/css/base.css
index f96cf7c7f..f61ae774d 100644
--- a/server/src/main/resources/assets/css/base.css
+++ b/server/src/main/resources/assets/css/base.css
@@ -549,3 +549,672 @@ a:focus-visible {
color: var(--text-secondary);
font-weight: 500;
}
+
+
+/* ========================================
+ Shared Component System
+ BEM naming: .block__element--modifier
+ ======================================== */
+
+/* ----------------------------------------
+ Shared Animations
+ ---------------------------------------- */
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes slideInUp {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes slideInDown {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+/* ----------------------------------------
+ Page Layout System
+ ---------------------------------------- */
+
+.page {
+ min-height: calc(100vh - 200px);
+ padding: 2rem;
+ background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-50) 100%);
+}
+
+.page--centered {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.page__container {
+ max-width: 1000px;
+ margin: 0 auto;
+ width: 100%;
+ animation: fadeIn 0.5s ease-out;
+}
+
+.page__container--narrow {
+ max-width: 480px;
+}
+
+.page__container--wide {
+ max-width: 1200px;
+}
+
+/* ----------------------------------------
+ Page Header (dark header bar)
+ ---------------------------------------- */
+
+.page-header {
+ background: var(--neutral-900);
+ color: white;
+ padding: 2.5rem 3rem;
+ border-radius: 0.75rem;
+ margin-bottom: 2rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ box-shadow: var(--shadow-lg);
+ border-bottom: 3px solid var(--accent);
+ animation: slideInDown 0.5s ease-out;
+}
+
+.page-header__content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.page-header__title {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 2.5rem;
+ color: white;
+ margin: 0;
+}
+
+.page-header__subtitle {
+ color: var(--neutral-400);
+ font-size: 1.0625rem;
+ font-style: italic;
+ margin: 0;
+}
+
+.page-header__actions {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+/* ----------------------------------------
+ Paper Section (notebook aesthetic)
+ ---------------------------------------- */
+
+.paper-section {
+ background: var(--surface);
+ background-image: repeating-linear-gradient(
+ transparent,
+ transparent 31px,
+ rgba(0, 0, 0, 0.03) 31px,
+ rgba(0, 0, 0, 0.03) 32px
+ );
+ padding: 2.5rem 3rem 2.5rem 4rem;
+ margin-bottom: 2rem;
+ border-radius: 0.75rem;
+ box-shadow: var(--shadow-lg),
+ inset 0 0 0 1px rgba(0, 0, 0, 0.05);
+ border-left: 4px solid var(--accent);
+ position: relative;
+ animation: slideInUp 0.5s ease-out;
+ animation-fill-mode: both;
+}
+
+/* Red margin line like notebook paper */
+.paper-section::before {
+ content: '';
+ position: absolute;
+ left: 2.5rem;
+ top: 0;
+ bottom: 0;
+ width: 2px;
+ background: rgba(239, 68, 68, 0.2);
+ pointer-events: none;
+}
+
+.paper-section--compact {
+ padding: 3rem 2.5rem 3rem 4rem;
+ box-shadow: var(--shadow-xl),
+ inset 0 0 0 1px rgba(0, 0, 0, 0.05);
+}
+
+.paper-section--centered {
+ text-align: center;
+}
+
+/* Section Header */
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 1rem;
+ margin-bottom: 1rem;
+}
+
+.section-header__title {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 2rem;
+ color: var(--text-primary);
+ margin: 0;
+}
+
+.section-header__actions {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+.section-description {
+ color: var(--text-secondary);
+ font-size: 1rem;
+ margin-bottom: 1.5rem;
+ line-height: 1.6;
+}
+
+/* ----------------------------------------
+ Card System
+ ---------------------------------------- */
+
+.card {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1.25rem 1.5rem;
+ background: white;
+ border: 2px solid var(--neutral-200);
+ border-radius: 0.5rem;
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
+ text-decoration: none;
+ color: inherit;
+}
+
+.card--interactive {
+ cursor: pointer;
+}
+
+.card--interactive:hover {
+ border-color: var(--accent);
+ box-shadow: var(--shadow-md);
+ transform: translateX(4px);
+}
+
+.card--gradient {
+ background: linear-gradient(135deg, #fdfcfb 0%, #f5f4f0 100%);
+ border: 1px solid var(--neutral-200);
+}
+
+.card--gradient:hover {
+ background: white;
+ border-color: var(--accent);
+}
+
+.card-list {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.card__info {
+ display: flex;
+ flex-direction: column;
+ gap: 0.375rem;
+ flex: 1;
+ min-width: 0;
+}
+
+.card__title {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 1.25rem;
+ color: var(--text-primary);
+ font-weight: normal;
+ margin: 0;
+ transition: color 0.2s ease;
+}
+
+.card--interactive:hover .card__title {
+ color: var(--accent-dark);
+}
+
+.card__subtitle {
+ font-family: 'Lora', Georgia, serif;
+ font-size: 0.875rem;
+ color: var(--text-secondary);
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.card__arrow {
+ color: var(--neutral-400);
+ font-size: 0.875rem;
+ transition: all 0.2s ease;
+ margin-left: 1rem;
+}
+
+.card--interactive:hover .card__arrow {
+ color: var(--accent);
+ transform: translateX(3px);
+}
+
+/* ----------------------------------------
+ Dialog/Modal System
+ ---------------------------------------- */
+
+.dialog-overlay {
+ position: fixed;
+ inset: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+ animation: fadeIn 0.2s ease-out;
+ backdrop-filter: blur(2px);
+}
+
+.dialog-overlay.closing {
+ animation: fadeOut 0.2s ease-out forwards;
+}
+
+.dialog {
+ background: linear-gradient(135deg, rgba(255, 253, 250, 0.98) 0%, rgba(255, 250, 245, 1) 100%);
+ border: 2px solid var(--neutral-200);
+ border-radius: 0.75rem;
+ box-shadow: var(--shadow-xl),
+ 0 0 0 1px rgba(0, 0, 0, 0.05);
+ max-width: 420px;
+ width: 90%;
+ animation: slideInUp 0.3s ease-out;
+}
+
+.dialog--warning {
+ background: linear-gradient(135deg, rgba(255, 253, 250, 0.99) 0%, rgba(255, 251, 235, 1) 100%);
+ border-color: var(--neutral-300);
+ max-width: 480px;
+}
+
+.dialog__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 1.25rem 1.5rem;
+ border-bottom: 1px dashed var(--neutral-200);
+}
+
+.dialog__header h3 {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 1.25rem;
+ color: var(--text-primary);
+ margin: 0;
+}
+
+.dialog__close {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 2rem;
+ height: 2rem;
+ background: transparent;
+ border: none;
+ border-radius: 50%;
+ color: var(--text-secondary);
+ cursor: pointer;
+ transition: all var(--transition-base);
+}
+
+.dialog__close:hover {
+ background: var(--neutral-100);
+ color: var(--text-primary);
+}
+
+.dialog__body {
+ padding: 1.5rem;
+}
+
+.dialog__actions {
+ display: flex;
+ gap: 0.75rem;
+ justify-content: flex-end;
+ padding: 1rem 1.5rem;
+ background: rgba(255, 255, 255, 0.5);
+ border-top: 1px dashed var(--neutral-200);
+}
+
+/* ----------------------------------------
+ Button Variants
+ ---------------------------------------- */
+
+.btn--primary {
+ background: var(--neutral-900);
+ color: white;
+ border-color: var(--neutral-900);
+}
+
+.btn--primary:hover {
+ background: var(--accent);
+ border-color: var(--accent);
+ color: white;
+}
+
+.btn--accent {
+ background: var(--accent);
+ color: white;
+ border-color: var(--accent);
+}
+
+.btn--accent:hover {
+ background: var(--accent-dark);
+ border-color: var(--accent-dark);
+ color: white;
+}
+
+.btn--danger {
+ background: transparent;
+ color: #dc2626;
+ border-color: #dc2626;
+}
+
+.btn--danger:hover {
+ background: #dc2626;
+ color: white;
+}
+
+.btn--ghost {
+ background: transparent;
+ color: var(--text-secondary);
+ border-color: var(--neutral-300);
+}
+
+.btn--ghost:hover {
+ background: var(--neutral-100);
+ border-color: var(--neutral-400);
+ color: var(--text-primary);
+}
+
+.btn--block {
+ width: 100%;
+ justify-content: center;
+}
+
+/* ----------------------------------------
+ Form System
+ ---------------------------------------- */
+
+.form-field {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ margin-bottom: 1.25rem;
+}
+
+.form-field:last-child {
+ margin-bottom: 0;
+}
+
+.form-field__label {
+ font-family: 'Kingthings Typewriter', monospace;
+ font-size: 1.125rem;
+ color: var(--text-primary);
+ letter-spacing: 0.01em;
+}
+
+.form-field__label--small {
+ font-size: 0.875rem;
+ color: var(--text-secondary);
+}
+
+.form-input {
+ font-family: 'Lora', Georgia, serif;
+ font-size: 1rem;
+ padding: 0.875rem 1rem;
+ border: 2px solid var(--neutral-300);
+ border-radius: 0.5rem;
+ background: white;
+ color: var(--text-primary);
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
+}
+
+.form-input::placeholder {
+ color: var(--neutral-400);
+ font-style: italic;
+}
+
+.form-input:hover {
+ border-color: var(--neutral-400);
+}
+
+.form-input:focus {
+ outline: none;
+ border-color: var(--accent);
+ box-shadow: var(--shadow-md),
+ 0 0 0 3px rgba(217, 119, 6, 0.1);
+}
+
+.form-select {
+ font-family: 'Lora', Georgia, serif;
+ font-size: 1rem;
+ padding: 0.875rem 1rem;
+ border: 2px solid var(--neutral-300);
+ border-radius: 0.5rem;
+ background: white;
+ color: var(--text-primary);
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
+ cursor: pointer;
+}
+
+.form-select:hover {
+ border-color: var(--neutral-400);
+}
+
+.form-select:focus {
+ outline: none;
+ border-color: var(--accent);
+ box-shadow: var(--shadow-md),
+ 0 0 0 3px rgba(217, 119, 6, 0.1);
+}
+
+.form-textarea {
+ font-family: 'Lora', Georgia, serif;
+ font-size: 1rem;
+ padding: 0.875rem 1rem;
+ border: 2px solid var(--neutral-300);
+ border-radius: 0.5rem;
+ background: white;
+ color: var(--text-primary);
+ transition: all var(--transition-base);
+ box-shadow: var(--shadow-sm);
+ resize: vertical;
+ min-height: 100px;
+}
+
+.form-textarea:hover {
+ border-color: var(--neutral-400);
+}
+
+.form-textarea:focus {
+ outline: none;
+ border-color: var(--accent);
+ box-shadow: var(--shadow-md),
+ 0 0 0 3px rgba(217, 119, 6, 0.1);
+}
+
+/* ----------------------------------------
+ Utility Components
+ ---------------------------------------- */
+
+.empty-state {
+ text-align: center;
+ padding: 3rem 2rem;
+ color: var(--text-secondary);
+ font-style: italic;
+}
+
+.empty-state__icon {
+ font-size: 3rem;
+ margin-bottom: 1rem;
+ opacity: 0.5;
+}
+
+.info-panel {
+ background: linear-gradient(135deg, rgba(255, 253, 250, 0.95) 0%, rgba(255, 250, 245, 0.98) 100%);
+ border: 2px solid var(--neutral-200);
+ border-radius: 0.5rem;
+ overflow: hidden;
+ box-shadow: var(--shadow-sm);
+ margin-bottom: 1rem;
+}
+
+.info-panel__header {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 0.875rem 1.25rem;
+ background: rgba(255, 255, 255, 0.6);
+ border-bottom: 1px dashed var(--neutral-200);
+}
+
+.info-panel__content {
+ padding: 1rem 1.25rem;
+}
+
+.info-panel--collapsible .info-panel__header {
+ cursor: pointer;
+ transition: all var(--transition-base);
+}
+
+.info-panel--collapsible .info-panel__header:hover {
+ background: rgba(217, 119, 6, 0.05);
+}
+
+/* Hidden utility class */
+.hidden {
+ display: none !important;
+}
+
+/* ----------------------------------------
+ Responsive Design for Shared Components
+ ---------------------------------------- */
+
+@media only screen and (max-width: 768px) {
+ .page {
+ padding: 1.5rem;
+ }
+
+ .page-header {
+ flex-direction: column;
+ gap: 1.5rem;
+ padding: 2rem 1.75rem;
+ text-align: center;
+ }
+
+ .page-header__title {
+ font-size: 2rem;
+ }
+
+ .page-header__actions {
+ flex-direction: column;
+ gap: 0.75rem;
+ width: 100%;
+ }
+
+ .paper-section {
+ padding: 2rem 1.75rem 2rem 3rem;
+ }
+
+ .paper-section::before {
+ left: 1.5rem;
+ }
+
+ .paper-section--compact {
+ padding: 2rem 1.75rem 2rem 3rem;
+ }
+
+ .paper-section--compact::before {
+ left: 1.5rem;
+ }
+
+ .section-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.5rem;
+ }
+
+ .section-header__title {
+ font-size: 1.75rem;
+ }
+
+ .card--interactive:hover {
+ transform: none;
+ }
+
+ .dialog {
+ width: 95%;
+ margin: 1rem;
+ }
+}
+
+@media only screen and (max-width: 600px) {
+ .page--centered {
+ padding: 1.5rem;
+ min-height: calc(100vh - 150px);
+ }
+
+ .paper-section--compact {
+ padding: 2rem 1.75rem 2rem 3rem;
+ }
+}
+
+@media only screen and (max-width: 480px) {
+ .page-header__title {
+ font-size: 1.75rem;
+ }
+
+ .page-header__subtitle {
+ font-size: 0.9375rem;
+ }
+
+ .section-header__title {
+ font-size: 1.5rem;
+ }
+}
diff --git a/server/src/main/resources/assets/css/dashboard.css b/server/src/main/resources/assets/css/dashboard.css
index 88fb280c8..b650729cc 100644
--- a/server/src/main/resources/assets/css/dashboard.css
+++ b/server/src/main/resources/assets/css/dashboard.css
@@ -1,66 +1,6 @@
-/* Dashboard Page Styles */
-
-.dashboard-page {
- min-height: calc(100vh - 200px);
- padding: 2rem;
- background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-50) 100%);
-}
-
-.dashboard-container {
- max-width: 1000px;
- margin: 0 auto;
- animation: fadeIn 0.5s ease-out;
-}
-
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-/* Dashboard Header */
-.dashboard-header {
- background: var(--neutral-900);
- color: white;
- padding: 2.5rem 3rem;
- border-radius: 0.75rem;
- margin-bottom: 2rem;
- display: flex;
- justify-content: space-between;
- align-items: center;
- box-shadow: var(--shadow-lg);
- border-bottom: 3px solid var(--accent);
- animation: slideInDown 0.5s ease-out;
-}
-
-@keyframes slideInDown {
- from {
- opacity: 0;
- transform: translateY(-20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-.dashboard-header-content h1 {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 2.5rem;
- color: white;
- margin-bottom: 0.5rem;
-}
-
-.dashboard-subtitle {
- color: var(--neutral-700);
- font-size: 1.0625rem;
- font-style: italic;
- margin: 0;
-}
+/* Dashboard Page Styles - Page-specific overrides */
+/* Dashboard-specific header buttons */
.logout-form {
margin: 0;
}
@@ -89,85 +29,6 @@
transform: translateY(0);
}
-/* Section Cards */
-.dashboard-section {
- background: var(--surface);
- background-image: repeating-linear-gradient(
- transparent,
- transparent 31px,
- rgba(0, 0, 0, 0.03) 31px,
- rgba(0, 0, 0, 0.03) 32px
- );
- padding: 2.5rem 3rem 2.5rem 4rem;
- margin-bottom: 2rem;
- border-radius: 0.75rem;
- box-shadow: var(--shadow-lg),
- inset 0 0 0 1px rgba(0, 0, 0, 0.05);
- border-left: 4px solid var(--accent);
- position: relative;
- animation: slideInUp 0.5s ease-out;
- animation-fill-mode: both;
-}
-
-@keyframes slideInUp {
- from {
- opacity: 0;
- transform: translateY(20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Red margin line like notebook paper */
-.dashboard-section::before {
- content: '';
- position: absolute;
- left: 2.5rem;
- top: 0;
- bottom: 0;
- width: 2px;
- background: rgba(239, 68, 68, 0.2);
- pointer-events: none;
-}
-
-/* Section Headers */
-.section-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- gap: 1rem;
- margin-bottom: 1rem;
-}
-
-.section-title-group {
- display: flex;
- flex-direction: column;
- gap: 0.25rem;
-}
-
-.section-header h2 {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 2rem;
- color: var(--text-primary);
- margin: 0;
-}
-
-.section-description {
- color: var(--text-secondary);
- font-size: 1rem;
- margin-bottom: 1.5rem;
- line-height: 1.6;
-}
-
-/* Dashboard Header Actions */
-.dashboard-header-actions {
- display: flex;
- align-items: center;
- gap: 1rem;
-}
-
.manage-server-button {
font-family: 'Kingthings Typewriter', monospace;
font-size: 1rem;
@@ -189,14 +50,6 @@
box-shadow: var(--shadow-md);
}
-.account-info p {
- margin-bottom: 0.5rem;
-}
-
-.hidden {
- display: none !important;
-}
-
/* ========================================
Pen Name Section - Author Identity Claim
======================================== */
@@ -760,81 +613,11 @@
box-shadow: none;
}
-/* Projects List */
+/* Projects and Account containers */
.projects-container {
margin-top: 1.5rem;
}
-.projects-list {
- display: flex;
- flex-direction: column;
- gap: 0.75rem;
-}
-
-.project-card {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 1.25rem 1.5rem;
- background: white;
- border: 2px solid var(--neutral-200);
- border-radius: 0.5rem;
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
- text-decoration: none;
- color: inherit;
- cursor: pointer;
-}
-
-.project-card:hover {
- border-color: var(--accent);
- box-shadow: var(--shadow-md);
- transform: translateX(4px);
-}
-
-.project-info {
- display: flex;
- flex-direction: column;
- gap: 0.375rem;
-}
-
-.project-name {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1.25rem;
- color: var(--text-primary);
- font-weight: normal;
-}
-
-.project-sync-date {
- font-family: 'Lora', Georgia, serif;
- font-size: 0.875rem;
- color: var(--text-secondary);
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
-
-.project-arrow {
- color: var(--neutral-400);
- font-size: 0.875rem;
- transition: all 0.2s ease;
- margin-left: 1rem;
-}
-
-.project-card:hover .project-arrow {
- color: var(--accent);
- transform: translateX(3px);
-}
-
-/* Projects Empty State */
-.projects-empty {
- text-align: center;
- padding: 3rem 2rem;
- color: var(--text-secondary);
- font-style: italic;
-}
-
-/* Account Info */
.account-container {
margin-top: 1.5rem;
}
@@ -862,56 +645,11 @@
/* Responsive Design */
@media only screen and (max-width: 768px) {
- .dashboard-page {
- padding: 1.5rem;
- }
-
- .dashboard-header {
- flex-direction: column;
- gap: 1.5rem;
- padding: 2rem 1.75rem;
- text-align: center;
- }
-
- .dashboard-header-content h1 {
- font-size: 2rem;
- }
-
- .dashboard-header-actions {
- flex-direction: column;
- gap: 0.75rem;
- width: 100%;
- }
-
.manage-server-button {
width: 100%;
text-align: center;
}
- .dashboard-section {
- padding: 2rem 1.75rem 2rem 3rem;
- }
-
- .dashboard-section::before {
- left: 1.5rem;
- }
-
- .section-header {
- flex-direction: column;
- align-items: flex-start;
- gap: 0.5rem;
- }
-
- .section-header h2 {
- font-size: 1.75rem;
- }
-
- .project-card {
- flex-direction: column;
- align-items: flex-start;
- gap: 0.75rem;
- }
-
/* Pen Name Responsive */
.pen-name-section {
padding: 1rem;
@@ -975,30 +713,12 @@
}
}
-@media only screen and (max-width: 480px) {
- .dashboard-header-content h1 {
- font-size: 1.75rem;
- }
-
- .dashboard-subtitle {
- font-size: 0.9375rem;
- }
-
- .section-header h2 {
- font-size: 1.5rem;
- }
-}
-
/* Accessibility */
@media (prefers-reduced-motion: reduce) {
- .dashboard-container,
- .dashboard-header,
- .dashboard-section,
.pen-name-edit {
animation: none;
}
- .project-card:hover,
.claim-pen-name-btn:hover,
.set-pen-name-btn:hover:not(:disabled) {
transform: none;
diff --git a/server/src/main/resources/assets/css/error.css b/server/src/main/resources/assets/css/error.css
index 6b5add6a0..1cccbb18d 100644
--- a/server/src/main/resources/assets/css/error.css
+++ b/server/src/main/resources/assets/css/error.css
@@ -1,16 +1,7 @@
/* Error Page Styles */
-.error-page {
- min-height: calc(100vh - 200px);
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 2rem;
- background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-50) 100%);
-}
-
-.error-container {
- width: 100%;
+/* Error-specific container width */
+.page__container--error {
max-width: 600px;
}
@@ -181,10 +172,6 @@
/* Responsive Design */
@media only screen and (max-width: 600px) {
- .error-page {
- padding: 1.5rem;
- }
-
.error-card {
padding: 2.5rem 2rem;
transform: rotate(0deg);
@@ -234,15 +221,6 @@
animation: fadeIn 0.3s ease-out;
}
- @keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
- }
-
.error-card::before {
animation: none;
}
diff --git a/server/src/main/resources/assets/css/home.css b/server/src/main/resources/assets/css/home.css
index a975e8cea..13475a7ff 100644
--- a/server/src/main/resources/assets/css/home.css
+++ b/server/src/main/resources/assets/css/home.css
@@ -118,17 +118,6 @@
animation: slideInDown 0.4s ease-out;
}
-@keyframes slideInDown {
- from {
- opacity: 0;
- transform: translateY(-20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
.server-message h3 {
color: #92400e;
margin-bottom: 0.75rem;
diff --git a/server/src/main/resources/assets/css/login.css b/server/src/main/resources/assets/css/login.css
index aa35d8eab..d0613be6d 100644
--- a/server/src/main/resources/assets/css/login.css
+++ b/server/src/main/resources/assets/css/login.css
@@ -1,59 +1,6 @@
-/* Login Page Styles */
-
-.login-page {
- min-height: calc(100vh - 200px);
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 2rem;
- background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-50) 100%);
-}
-
-.login-container {
- width: 100%;
- max-width: 480px;
-}
-
-.login-card {
- background: var(--surface);
- background-image: repeating-linear-gradient(
- transparent,
- transparent 31px,
- rgba(0, 0, 0, 0.03) 31px,
- rgba(0, 0, 0, 0.03) 32px
- );
- padding: 3rem 2.5rem 3rem 4rem;
- border-radius: 0.75rem;
- box-shadow: var(--shadow-xl),
- inset 0 0 0 1px rgba(0, 0, 0, 0.05);
- border-left: 4px solid var(--accent);
- position: relative;
- animation: slideInUp 0.5s ease-out;
-}
-
-@keyframes slideInUp {
- from {
- opacity: 0;
- transform: translateY(30px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-/* Red margin line like notebook paper */
-.login-card::before {
- content: '';
- position: absolute;
- left: 2.5rem;
- top: 0;
- bottom: 0;
- width: 2px;
- background: rgba(239, 68, 68, 0.2);
- pointer-events: none;
-}
+/* Login Page Styles - Page-specific overrides */
+/* Login Header (centered within card) */
.login-header {
text-align: center;
margin-bottom: 2.5rem;
@@ -73,58 +20,13 @@
margin: 0;
}
-/* Form Styles */
+/* Form Layout */
.login-form {
display: flex;
flex-direction: column;
gap: 1.75rem;
}
-.form-field {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.form-field label {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1.125rem;
- color: var(--text-primary);
- letter-spacing: 0.01em;
-}
-
-.form-field input {
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- padding: 0.875rem 1rem;
- border: 2px solid var(--neutral-300);
- border-radius: 0.5rem;
- background: white;
- color: var(--text-primary);
- transition: all var(--transition-base);
- box-shadow: var(--shadow-sm);
-}
-
-.form-field input::placeholder {
- color: var(--neutral-400);
- font-style: italic;
-}
-
-.form-field input:hover {
- border-color: var(--neutral-400);
-}
-
-.form-field input:focus {
- outline: none;
- border-color: var(--accent);
- box-shadow: var(--shadow-md),
- 0 0 0 3px rgba(217, 119, 6, 0.1);
-}
-
-.form-field input:focus::placeholder {
- color: var(--neutral-500);
-}
-
/* Error/Message Styling */
.login-message {
background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
@@ -153,7 +55,7 @@
font-size: 0.9375rem;
}
-/* Button Styles */
+/* Login Button (special styling with shimmer effect) */
.form-actions {
margin-top: 1rem;
}
@@ -205,40 +107,6 @@
outline-offset: 4px;
}
-/* Responsive Design */
-@media only screen and (max-width: 600px) {
- .login-page {
- padding: 1.5rem;
- min-height: calc(100vh - 150px);
- }
-
- .login-card {
- padding: 2rem 1.75rem 2rem 3rem;
- }
-
- .login-card::before {
- left: 1.5rem;
- }
-
- .login-header h1 {
- font-size: 2rem;
- }
-
- .login-header p {
- font-size: 0.9375rem;
- }
-
- .form-field input {
- font-size: 1rem;
- padding: 0.75rem 0.875rem;
- }
-
- .login-button {
- font-size: 1rem;
- padding: 0.875rem 1.75rem;
- }
-}
-
/* Login Info Section */
.login-info {
margin-top: 2rem;
@@ -283,12 +151,24 @@
color: #78350f;
}
-/* Accessibility */
-@media (prefers-reduced-motion: reduce) {
- .login-card {
- animation: none;
+/* Responsive Design */
+@media only screen and (max-width: 600px) {
+ .login-header h1 {
+ font-size: 2rem;
}
+ .login-header p {
+ font-size: 0.9375rem;
+ }
+
+ .login-button {
+ font-size: 1rem;
+ padding: 0.875rem 1.75rem;
+ }
+}
+
+/* Accessibility */
+@media (prefers-reduced-motion: reduce) {
.login-message {
animation: none;
}
diff --git a/server/src/main/resources/assets/css/story.css b/server/src/main/resources/assets/css/story.css
index 3b41c8db5..efd3a9d62 100644
--- a/server/src/main/resources/assets/css/story.css
+++ b/server/src/main/resources/assets/css/story.css
@@ -167,15 +167,6 @@
}
}
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
/* ========================================
Story Info Panel
Displays story metadata at a glance
@@ -703,175 +694,112 @@
}
/* ========================================
- Share Dialog (Modal)
+ Dialog Customizations for Story Page
+ Additional styling for story-specific dialogs
======================================== */
-.share-dialog-overlay {
- position: fixed;
- inset: 0;
- background: rgba(0, 0, 0, 0.5);
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 1000;
- animation: fadeIn 0.2s ease-out;
- backdrop-filter: blur(2px);
-}
-
-.share-dialog-overlay.closing {
- animation: fadeOut 0.2s ease-out forwards;
-}
-
-@keyframes fadeOut {
- from { opacity: 1; }
- to { opacity: 0; }
-}
-
-.share-dialog {
- background: linear-gradient(135deg, rgba(255, 253, 250, 0.98) 0%, rgba(255, 250, 245, 1) 100%);
- border: 2px solid var(--neutral-200);
- border-radius: 0.75rem;
- box-shadow: var(--shadow-xl), 0 0 0 1px rgba(0, 0, 0, 0.05);
- max-width: 420px;
- width: 90%;
- animation: slideInUp 0.3s ease-out;
-}
-
-@keyframes slideInUp {
- from {
- opacity: 0;
- transform: translateY(20px) scale(0.95);
- }
- to {
- opacity: 1;
- transform: translateY(0) scale(1);
- }
-}
-
-.share-dialog-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 1.25rem 1.5rem;
- border-bottom: 1px dashed var(--neutral-200);
-}
-
-.share-dialog-header h3 {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1.25rem;
- color: var(--text-primary);
- margin: 0;
-}
-
-.dialog-close-btn {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 2rem;
- height: 2rem;
- background: transparent;
- border: none;
- border-radius: 50%;
- color: var(--text-secondary);
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.dialog-close-btn:hover {
- background: var(--neutral-100);
- color: var(--text-primary);
-}
-
-.share-dialog-body {
- padding: 1.5rem;
-}
-
-.share-dialog .form-field {
- margin-bottom: 1.25rem;
-}
-
-.share-dialog .form-field:last-child {
- margin-bottom: 0;
-}
-
-.share-dialog .form-field label {
- display: block;
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.875rem;
- color: var(--text-secondary);
- margin-bottom: 0.5rem;
-}
-
-.share-dialog .form-field .optional-label {
+/* Optional label styling */
+.optional-label {
font-style: italic;
color: var(--neutral-400);
}
-.share-dialog .form-field input {
- width: 100%;
- padding: 0.75rem 1rem;
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- color: var(--text-primary);
- background: white;
- border: 2px solid var(--neutral-200);
- border-radius: 0.375rem;
- box-sizing: border-box;
- transition: border-color var(--transition-base);
+/* Warning dialog header with icon */
+.dialog__header--warning {
+ background: linear-gradient(135deg, rgba(251, 191, 36, 0.08) 0%, rgba(245, 158, 11, 0.05) 100%);
+ border-bottom: 1px dashed rgba(217, 119, 6, 0.25);
+ position: relative;
}
-.share-dialog .form-field input:focus {
- outline: none;
- border-color: var(--accent);
+.dialog__header--warning::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: linear-gradient(90deg,
+ transparent 0%,
+ rgba(245, 158, 11, 0.6) 20%,
+ rgba(217, 119, 6, 0.8) 50%,
+ rgba(245, 158, 11, 0.6) 80%,
+ transparent 100%
+ );
}
-.share-dialog .form-field input::placeholder {
- color: var(--neutral-400);
-}
-
-.share-dialog-actions {
+.warning-icon-wrapper {
display: flex;
- gap: 0.75rem;
- justify-content: flex-end;
- padding: 1rem 1.5rem;
- background: rgba(255, 255, 255, 0.5);
- border-top: 1px dashed var(--neutral-200);
+ align-items: center;
+ justify-content: center;
+ width: 2.5rem;
+ height: 2.5rem;
+ background: linear-gradient(135deg, rgba(251, 191, 36, 0.2) 0%, rgba(245, 158, 11, 0.15) 100%);
+ border: 1.5px solid rgba(217, 119, 6, 0.3);
+ border-radius: 50%;
+ flex-shrink: 0;
+ animation: warningPulse 2s ease-in-out infinite;
}
-.share-dialog .cancel-btn {
- padding: 0.625rem 1.25rem;
- background: transparent;
- color: var(--text-secondary);
- border: 2px solid var(--neutral-300);
- border-radius: 0.375rem;
- font-family: 'Kingthings Typewriter', monospace;
+@keyframes warningPulse {
+ 0%, 100% {
+ box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.3);
+ }
+ 50% {
+ box-shadow: 0 0 0 6px rgba(245, 158, 11, 0);
+ }
+}
+
+.warning-icon-wrapper i {
+ font-size: 1.125rem;
+ color: #b45309;
+}
+
+/* Warning Body Content */
+.warning-text {
+ font-family: 'Lora', Georgia, serif;
font-size: 0.9375rem;
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.share-dialog .cancel-btn:hover {
- background: var(--neutral-100);
- border-color: var(--neutral-400);
+ line-height: 1.7;
color: var(--text-primary);
+ margin: 0 0 1.25rem 0;
+ text-align: justify;
+ hyphens: auto;
}
-.share-dialog .create-access-btn {
- padding: 0.625rem 1.25rem;
- background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
- color: white;
- border: 2px solid var(--accent-dark);
- border-radius: 0.375rem;
+/* Recommendation Callout */
+.warning-recommendation {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 1rem 1.125rem;
+ background: linear-gradient(135deg, rgba(16, 185, 129, 0.06) 0%, rgba(5, 150, 105, 0.04) 100%);
+ border: 1.5px solid rgba(16, 185, 129, 0.2);
+ border-radius: 0.5rem;
+ border-left: 3px solid var(--success);
+}
+
+.warning-recommendation i {
+ font-size: 1rem;
+ color: var(--success);
+ margin-top: 0.125rem;
+ flex-shrink: 0;
+}
+
+.warning-recommendation span {
font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.9375rem;
- font-weight: 500;
- cursor: pointer;
- transition: all var(--transition-base);
+ font-size: 0.8125rem;
+ line-height: 1.5;
+ color: var(--text-secondary);
}
-.share-dialog .create-access-btn:hover {
- background: linear-gradient(135deg, var(--accent-light) 0%, var(--accent) 100%);
- transform: translateY(-1px);
+/* Publish confirm button with icon */
+.publish-confirm-btn {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.publish-confirm-btn i {
+ font-size: 0.875rem;
}
/* ========================================
@@ -1100,36 +1028,6 @@
text-align: left;
}
-.password-form .form-field {
- margin-bottom: 1rem;
-}
-
-.password-form .form-field label {
- display: block;
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.875rem;
- color: var(--text-secondary);
- margin-bottom: 0.5rem;
-}
-
-.password-form .form-field input {
- width: 100%;
- padding: 0.875rem 1rem;
- font-family: 'Lora', Georgia, serif;
- font-size: 1rem;
- color: var(--text-primary);
- background: white;
- border: 2px solid var(--neutral-200);
- border-radius: 0.375rem;
- box-sizing: border-box;
- transition: border-color var(--transition-base);
-}
-
-.password-form .form-field input:focus {
- outline: none;
- border-color: var(--accent);
-}
-
.password-error {
display: flex;
align-items: center;
@@ -1166,233 +1064,6 @@
transform: translateY(0);
}
-/* ========================================
- Publish Warning Dialog
- A thoughtful caution before public publishing
- ======================================== */
-
-.publish-warning-overlay {
- position: fixed;
- inset: 0;
- background: rgba(41, 37, 36, 0.6);
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 1000;
- animation: fadeIn 0.2s ease-out;
- backdrop-filter: blur(3px);
-}
-
-.publish-warning-overlay.closing {
- animation: fadeOut 0.2s ease-out forwards;
-}
-
-.publish-warning-dialog {
- background: linear-gradient(135deg, rgba(255, 253, 250, 0.99) 0%, rgba(255, 251, 235, 1) 100%);
- border: 2px solid var(--neutral-300);
- border-radius: 0.75rem;
- box-shadow:
- var(--shadow-xl),
- 0 0 0 1px rgba(217, 119, 6, 0.1),
- 0 0 40px rgba(217, 119, 6, 0.08);
- max-width: 480px;
- width: 90%;
- animation: warningSlideIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
- overflow: hidden;
-}
-
-@keyframes warningSlideIn {
- from {
- opacity: 0;
- transform: translateY(-20px) scale(0.95);
- }
- to {
- opacity: 1;
- transform: translateY(0) scale(1);
- }
-}
-
-/* Warning Header with Icon */
-.publish-warning-header {
- display: flex;
- align-items: center;
- gap: 0.875rem;
- padding: 1.25rem 1.5rem;
- background: linear-gradient(135deg, rgba(251, 191, 36, 0.08) 0%, rgba(245, 158, 11, 0.05) 100%);
- border-bottom: 1px dashed rgba(217, 119, 6, 0.25);
- position: relative;
-}
-
-.publish-warning-header::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 3px;
- background: linear-gradient(90deg,
- transparent 0%,
- rgba(245, 158, 11, 0.6) 20%,
- rgba(217, 119, 6, 0.8) 50%,
- rgba(245, 158, 11, 0.6) 80%,
- transparent 100%
- );
-}
-
-.warning-icon-wrapper {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 2.5rem;
- height: 2.5rem;
- background: linear-gradient(135deg, rgba(251, 191, 36, 0.2) 0%, rgba(245, 158, 11, 0.15) 100%);
- border: 1.5px solid rgba(217, 119, 6, 0.3);
- border-radius: 50%;
- flex-shrink: 0;
- animation: warningPulse 2s ease-in-out infinite;
-}
-
-@keyframes warningPulse {
- 0%, 100% {
- box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.3);
- }
- 50% {
- box-shadow: 0 0 0 6px rgba(245, 158, 11, 0);
- }
-}
-
-.warning-icon-wrapper i {
- font-size: 1.125rem;
- color: #b45309;
-}
-
-.publish-warning-header h3 {
- flex: 1;
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 1.25rem;
- color: var(--text-primary);
- margin: 0;
- letter-spacing: 0.02em;
-}
-
-.publish-warning-header .dialog-close-btn {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 2rem;
- height: 2rem;
- background: transparent;
- border: none;
- border-radius: 50%;
- color: var(--text-secondary);
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.publish-warning-header .dialog-close-btn:hover {
- background: rgba(217, 119, 6, 0.1);
- color: #b45309;
-}
-
-/* Warning Body */
-.publish-warning-body {
- padding: 1.5rem;
-}
-
-.warning-text {
- font-family: 'Lora', Georgia, serif;
- font-size: 0.9375rem;
- line-height: 1.7;
- color: var(--text-primary);
- margin: 0 0 1.25rem 0;
- text-align: justify;
- hyphens: auto;
-}
-
-/* Recommendation Callout */
-.warning-recommendation {
- display: flex;
- align-items: flex-start;
- gap: 0.75rem;
- padding: 1rem 1.125rem;
- background: linear-gradient(135deg, rgba(16, 185, 129, 0.06) 0%, rgba(5, 150, 105, 0.04) 100%);
- border: 1.5px solid rgba(16, 185, 129, 0.2);
- border-radius: 0.5rem;
- border-left: 3px solid var(--success);
-}
-
-.warning-recommendation i {
- font-size: 1rem;
- color: var(--success);
- margin-top: 0.125rem;
- flex-shrink: 0;
-}
-
-.warning-recommendation span {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.8125rem;
- line-height: 1.5;
- color: var(--text-secondary);
-}
-
-/* Warning Actions */
-.publish-warning-actions {
- display: flex;
- gap: 0.75rem;
- justify-content: flex-end;
- padding: 1rem 1.5rem;
- background: rgba(255, 255, 255, 0.6);
- border-top: 1px dashed var(--neutral-200);
-}
-
-.publish-warning-actions .cancel-btn {
- padding: 0.625rem 1.25rem;
- background: transparent;
- color: var(--text-secondary);
- border: 2px solid var(--neutral-300);
- border-radius: 0.375rem;
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.9375rem;
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.publish-warning-actions .cancel-btn:hover {
- background: var(--neutral-100);
- border-color: var(--neutral-400);
- color: var(--text-primary);
-}
-
-.publish-confirm-btn {
- display: inline-flex;
- align-items: center;
- gap: 0.5rem;
- padding: 0.625rem 1.25rem;
- background: linear-gradient(135deg, #d97706 0%, #b45309 100%);
- color: white;
- border: 2px solid #92400e;
- border-radius: 0.375rem;
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.9375rem;
- font-weight: 500;
- cursor: pointer;
- transition: all var(--transition-base);
-}
-
-.publish-confirm-btn:hover {
- background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
- transform: translateY(-1px);
- box-shadow: 0 4px 12px rgba(217, 119, 6, 0.25);
-}
-
-.publish-confirm-btn:active {
- transform: translateY(0);
-}
-
-.publish-confirm-btn i {
- font-size: 0.875rem;
-}
-
/* ========================================
Story Stats (Public Page)
Word count and reading time display
@@ -1452,50 +1123,6 @@
border-top: 1px dashed var(--neutral-300);
}
-.pagination-button {
- display: inline-flex;
- align-items: center;
- gap: 0.5rem;
- padding: 0.75rem 1.25rem;
- background: linear-gradient(135deg, var(--neutral-100) 0%, var(--neutral-200) 100%);
- color: var(--text-primary);
- border: 2px solid var(--neutral-300);
- border-radius: 0.375rem;
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.9375rem;
- font-weight: 500;
- cursor: pointer;
- transition: all var(--transition-base);
- text-decoration: none;
-}
-
-.pagination-button:hover:not(.disabled) {
- background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
- color: white;
- border-color: var(--accent-dark);
- transform: translateY(-1px);
-}
-
-.pagination-button:active:not(.disabled) {
- transform: translateY(0);
-}
-
-.pagination-button.disabled {
- opacity: 0.4;
- cursor: not-allowed;
-}
-
-.pagination-button i {
- font-size: 0.75rem;
-}
-
-.pagination-info {
- font-family: 'Kingthings Typewriter', monospace;
- font-size: 0.875rem;
- color: var(--text-secondary);
- padding: 0 1rem;
-}
-
/* Responsive pagination */
@media only screen and (max-width: 480px) {
.story-pagination {
@@ -1503,12 +1130,12 @@
gap: 0.75rem;
}
- .pagination-button {
+ .story-pagination .pagination-button {
padding: 0.625rem 1rem;
font-size: 0.875rem;
}
- .pagination-info {
+ .story-pagination .pagination-info {
width: 100%;
text-align: center;
order: -1;
diff --git a/server/src/main/resources/templates/admin-settings.mustache b/server/src/main/resources/templates/admin-settings.mustache
index 23af1c63b..519f386f9 100644
--- a/server/src/main/resources/templates/admin-settings.mustache
+++ b/server/src/main/resources/templates/admin-settings.mustache
@@ -1,24 +1,22 @@
{{> header}}
-
+
{{> partials/admin-nav}}
-