/* * ============================================================================= * SOLVERFORGE QUICKSTART TEMPLATE - APP STYLES * ============================================================================= * * Custom styles for the quickstart template UI. * This file creates the "code-link" educational UI appearance. * * CUSTOMIZATION GUIDE: * - Brand colors: Change #10b981 (green) and #3E00FF (violet) * - Card styles: Modify .kpi-card, .task-card, .resource-card * - Animations: Adjust @keyframes rules for different effects * * SECTIONS: * 1. Global styles * 2. Interactive Code clickable elements (code reveal on hover) * 3. Hero section (gradient banner) * 4. KPI cards (metrics display) * 5. Control bar (solve/stop buttons) * 6. Section cards (container panels) * 7. Task cards (planning entity visualization) * 8. Resource cards (problem fact visualization) * 9. Constraint legend (clickable constraint badges) * 10. Build tab (file navigator and code viewer) * 11. Navigation overrides * 12. Responsive adjustments */ /* ============================================================================= * 1. GLOBAL STYLES * * Base styles for the page. The light gray background (#f8fafc) provides * contrast for white cards. * ============================================================================= */ body { background: #f8fafc; } /* ============================================================================= * 2. INTERACTIVE CODE CLICKABLE ELEMENTS * * The "code-link" feature: every UI element shows a code icon on hover, * indicating it can be clicked to view the source code that generates it. * * HOW IT WORKS: * 1. Add class="code-link" to any element * 2. Add data-target="filename:section" to specify the code location * 3. CSS ::after pseudo-element creates the code icon * 4. JavaScript handles click -> navigates to Build tab * * EXAMPLE: * * ============================================================================= */ .code-link { position: relative; cursor: pointer; transition: all 0.2s ease; } /* Code icon that appears on hover (uses Font Awesome code icon) */ .code-link::after { content: '\f121'; /* fa-code unicode */ font-family: 'Font Awesome 6 Free'; font-weight: 900; position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; background: rgba(62, 0, 255, 0.9); /* SolverForge violet */ color: white; border-radius: 4px; font-size: 10px; display: flex; align-items: center; justify-content: center; opacity: 0; transform: scale(0.8); transition: all 0.2s ease; } .code-link:hover::after { opacity: 1; transform: scale(1); } /* Violet glow border on hover to indicate clickability */ .code-link:hover { box-shadow: 0 0 0 2px rgba(62, 0, 255, 0.5); } /* Tooltip that appears above code-link elements */ .code-tooltip { position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%); background: #1f2937; color: white; padding: 6px 12px; border-radius: 6px; font-size: 12px; white-space: nowrap; opacity: 0; visibility: hidden; transition: all 0.2s ease; z-index: 1000; pointer-events: none; } /* Tooltip arrow */ .code-tooltip::after { content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border: 6px solid transparent; border-top-color: #1f2937; } .code-link:hover .code-tooltip { opacity: 1; visibility: visible; } /* ============================================================================= * 3. HERO SECTION * * The prominent banner at the top of the Demo tab. Uses a gradient from * SolverForge violet to green, with a rotating shimmer effect. * * TODO: Update the gradient colors to match your brand or problem domain. * ============================================================================= */ .hero-section { background: linear-gradient(135deg, #2E1760 0%, #3E00FF 50%, #10b981 100%); position: relative; overflow: hidden; border-radius: 16px; padding: 2rem; } /* Animated shimmer effect - creates visual interest */ .hero-section::before { content: ''; position: absolute; top: -50%; right: -50%; width: 100%; height: 200%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); animation: shimmer 15s infinite linear; } @keyframes shimmer { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Small badge above the hero title */ .hero-badge { background: rgba(255,255,255,0.2); color: white; padding: 4px 12px; border-radius: 20px; font-size: 12px; display: inline-block; margin-bottom: 1rem; } /* ============================================================================= * 4. KPI CARDS * * Key Performance Indicator cards show solution metrics at a glance. * * DEFAULT KPIs (customize for your domain): * - Total Tasks: Count of planning entities * - Assigned: Count with non-null planning variable * - Violations: Count of hard constraint violations * - Score: The HardSoftScore from the solver * * COLOR CODING: * - Purple (#6366f1): Neutral/informational * - Green (#10b981): Positive/success * - Red (#ef4444): Negative/violations * - Violet (#3E00FF): Score/brand * ============================================================================= */ .kpi-card { background: white; border-radius: 12px; padding: 1.25rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); text-align: center; transition: transform 0.2s, box-shadow 0.2s; height: 100%; } /* Hover lift effect - makes cards feel interactive */ .kpi-card:hover { transform: translateY(-4px); box-shadow: 0 12px 20px -5px rgba(0, 0, 0, 0.15); } .kpi-icon { font-size: 1.5rem; margin-bottom: 0.5rem; opacity: 0.8; } .kpi-value { font-size: 2rem; font-weight: 700; line-height: 1.2; } .kpi-label { font-size: 0.75rem; color: #6b7280; text-transform: uppercase; letter-spacing: 0.05em; margin-top: 0.25rem; } /* KPI color variations - each card type has its own color */ .kpi-tasks .kpi-icon, .kpi-tasks .kpi-value { color: #6366f1; } .kpi-assigned .kpi-icon, .kpi-assigned .kpi-value { color: #10b981; } .kpi-violations .kpi-icon, .kpi-violations .kpi-value { color: #ef4444; } .kpi-score .kpi-icon, .kpi-score .kpi-value { color: #3E00FF; } /* Pulse animation when KPI value changes (applied via JavaScript) */ .kpi-pulse { animation: kpiPulse 0.5s ease; } @keyframes kpiPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } /* ============================================================================= * 5. CONTROL BAR * * Contains the Solve/Stop buttons and solving spinner. * * BUTTONS: * - #solveButton: Starts the solver (POST to /schedules) * - #stopSolvingButton: Stops the solver (DELETE to /schedules/{id}) * - #analyzeButton: Shows score breakdown (PUT to /schedules/analyze) * * The spinner (#solvingSpinner) animates while solving is active. * ============================================================================= */ .control-bar { background: white; border-radius: 12px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); padding: 1rem 1.5rem; } /* Solving spinner - hidden by default, shown when solving */ #solvingSpinner { display: none; width: 24px; height: 24px; border: 3px solid #10b981; border-top-color: transparent; border-radius: 50%; animation: spin 0.75s linear infinite; } #solvingSpinner.active { display: inline-block; } @keyframes spin { to { transform: rotate(360deg); } } /* ============================================================================= * 6. SECTION CARDS * * Container panels for grouping content (Resources, Tasks, etc.). * Consistent styling with header and body areas. * ============================================================================= */ .section-card { background: white; border-radius: 12px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); overflow: hidden; height: 100%; } .section-header { background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); padding: 1rem 1.25rem; border-bottom: 1px solid #e2e8f0; display: flex; justify-content: space-between; align-items: center; } .section-header h5 { margin: 0; font-size: 1rem; font-weight: 600; color: #334155; } .section-body { padding: 1.25rem; } /* ============================================================================= * 7. TASK CARDS * * Visualization for planning entities (what the solver assigns). * * STATES: * - Default (green border): Task is assigned * - .unassigned (orange): Task has no resource assigned * - .violation (red): Task has a constraint violation * * CUSTOMIZATION: * Modify createTaskCard() in app.js to change what's displayed. * ============================================================================= */ .task-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 1rem; } .task-card { background: #f8fafc; border-radius: 10px; padding: 1rem; border-left: 4px solid #10b981; /* Green = assigned */ transition: all 0.2s ease; } .task-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } /* Unassigned state - yellow/orange warning */ .task-card.unassigned { border-left-color: #f59e0b; background: #fffbeb; } /* Violation state - red error */ .task-card.violation { border-left-color: #ef4444; background: #fef2f2; } .task-name { font-weight: 600; color: #1e293b; margin-bottom: 0.5rem; display: flex; justify-content: space-between; align-items: center; } .task-detail { font-size: 0.8rem; color: #64748b; margin-bottom: 0.25rem; } /* Skill tag badge */ .skill-tag { display: inline-block; background: #dbeafe; color: #1d4ed8; padding: 2px 8px; border-radius: 4px; font-size: 0.7rem; font-weight: 500; } .assigned-badge { color: #10b981; font-weight: 500; } .unassigned-badge { color: #9ca3af; font-style: italic; } /* ============================================================================= * 8. RESOURCE CARDS * * Visualization for problem facts (resources that can be assigned to). * * FEATURES: * - Blue gradient background * - Capacity bar showing utilization * - Skills list * * CUSTOMIZATION: * Modify renderResources() in app.js to change the display. * ============================================================================= */ .resource-card { background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%); border-radius: 10px; padding: 1rem; margin-bottom: 0.75rem; border: 1px solid #bfdbfe; } .resource-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; } .resource-name { font-weight: 600; color: #1e40af; } .resource-stats { font-size: 0.75rem; color: #3b82f6; } /* Capacity utilization bar */ .capacity-bar { height: 6px; background: #e2e8f0; border-radius: 3px; overflow: hidden; margin-top: 0.5rem; } .capacity-fill { height: 100%; background: #10b981; /* Green = under capacity */ border-radius: 3px; transition: width 0.3s ease, background 0.3s ease; } /* Warning/danger states for capacity */ .capacity-fill.warning { background: #f59e0b; } /* 80-100% */ .capacity-fill.danger { background: #ef4444; } /* >100% overflow */ .skills-list { margin-top: 0.5rem; } /* ============================================================================= * 9. CONSTRAINT LEGEND * * Clickable badges showing active constraints from constraints.py. * * CONSTRAINT TYPES: * - Hard (red, lock icon): Must be satisfied, violations = infeasible * - Soft (green, feather icon): Optimize these, more = worse score * * Each badge has a data-target attribute pointing to the constraint * function in constraints.py. Clicking navigates to Build tab. * * TODO: Update these badges to match your constraints.py definitions. * ============================================================================= */ .constraints-legend { background: white; border-radius: 12px; padding: 1.25rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .constraint-badge { display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px; border-radius: 20px; font-size: 0.85rem; cursor: pointer; transition: all 0.2s ease; } /* Hard constraint styling - red with lock icon */ .constraint-badge.hard { background: #fef2f2; color: #dc2626; border: 1px solid #fecaca; } .constraint-badge.hard:hover { background: #fecaca; transform: translateY(-2px); } /* Soft constraint styling - green with feather icon */ .constraint-badge.soft { background: #f0fdf4; color: #16a34a; border: 1px solid #bbf7d0; } .constraint-badge.soft:hover { background: #bbf7d0; transform: translateY(-2px); } /* ============================================================================= * 10. BUILD TAB STYLES * * The Build tab is a source code viewer showing actual quickstart files. * * COMPONENTS: * - File navigator: Tree view of project files * - Code viewer: Syntax-highlighted code display * - Annotations: Jump-to-section links * * HOW IT WORKS: * 1. User clicks a file in the navigator * 2. app.js loads the source code (embedded or fetched) * 3. Prism.js highlights the syntax * 4. Annotations show key sections to jump to * ============================================================================= */ /* File navigator sidebar */ .file-nav { background: white; border-radius: 12px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); overflow: hidden; } .file-nav-header { background: #f8fafc; padding: 1rem; border-bottom: 1px solid #e2e8f0; font-weight: 600; color: #334155; } .file-tree { padding: 0.5rem; } .folder-item { padding: 0.5rem; } .folder-name { color: #64748b; font-size: 0.85rem; font-weight: 500; margin-bottom: 0.25rem; } /* File item in the tree */ .file-item { padding: 0.5rem 0.75rem; margin-left: 1rem; border-radius: 6px; cursor: pointer; display: flex; align-items: center; gap: 8px; font-size: 0.85rem; color: #475569; transition: all 0.2s ease; } .file-item:hover { background: #f1f5f9; } .file-item.active { background: #dbeafe; color: #1d4ed8; } .file-item i { width: 16px; } /* File type badge */ .file-badge { margin-left: auto; font-size: 0.65rem; background: #f1f5f9; padding: 2px 6px; border-radius: 4px; color: #64748b; } /* Main code viewer panel */ .code-viewer { background: #0f172a; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); } .code-viewer-header { background: #1e293b; padding: 0.75rem 1rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #334155; } .code-path { color: #94a3b8; font-family: monospace; font-size: 0.85rem; } .code-viewer-body { max-height: 600px; overflow-y: auto; } .code-viewer-body pre { margin: 0 !important; padding: 1rem !important; background: transparent !important; } /* Code annotations sidebar */ .code-annotations { background: white; border-radius: 12px; padding: 1rem; margin-top: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } .annotation-item { padding: 0.5rem 0.75rem; border-radius: 6px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; font-size: 0.85rem; transition: background 0.2s; } .annotation-item:hover { background: #f1f5f9; } .annotation-line { color: #94a3b8; font-size: 0.75rem; } /* ============================================================================= * 11. NAVIGATION OVERRIDES * * Custom styling for the main tab navigation. * Uses pill-style buttons with rounded corners. * ============================================================================= */ .nav-main { display: flex; gap: 0.5rem; } .nav-main .nav-link { border-radius: 8px; padding: 0.5rem 1rem; color: #475569; font-weight: 500; transition: all 0.2s ease; } .nav-main .nav-link:hover { background: #f1f5f9; color: #1e293b; } /* Active tab styling - green background */ .nav-main .nav-link.active { background: #10b981; color: white; } .nav-main .nav-link i { margin-right: 6px; } /* ============================================================================= * 12. NOTIFICATION PANEL * * Fixed position panel for showing notifications (errors, success messages). * Positioned in top-right corner. * ============================================================================= */ #notificationPanel { position: fixed; top: 1rem; right: 1rem; z-index: 1050; } /* ============================================================================= * 13. RESPONSIVE ADJUSTMENTS * * Mobile-friendly modifications for smaller screens. * ============================================================================= */ @media (max-width: 768px) { /* Single column task grid on mobile */ .task-grid { grid-template-columns: 1fr; } /* Smaller KPI values */ .kpi-value { font-size: 1.5rem; } /* Hide progress step labels on mobile */ .step-label { display: none; } }