瀏覽代碼

Add the Smart Printer home dashboard UI.

Replace the default template window with a sidebar, quick start cards with custom 3D icons, and a create-and-print feature grid, and ignore Xcode build artifacts.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 1 月之前
父節點
當前提交
0843bdce1f

+ 32 - 0
.gitignore

@@ -0,0 +1,32 @@
+# Xcode
+DerivedData/
+.derivedData/
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata/
+*.xccheckout
+*.moved-aside
+*.xcuserstate
+*.xcscmblueprint
+
+# macOS
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Swift Package Manager
+.build/
+.swiftpm/
+
+# CocoaPods
+Pods/
+
+# Carthage
+Carthage/Build/

+ 17 - 13
smart_printer/AppDelegate.swift

@@ -2,29 +2,33 @@
 //  AppDelegate.swift
 //  smart_printer
 //
-//  Created by Mql Mac 2 on 04/06/2026.
-//
 
 import Cocoa
 
 @main
 class AppDelegate: NSObject, NSApplicationDelegate {
 
-    
-
-
-    func applicationDidFinishLaunching(_ aNotification: Notification) {
-        // Insert code here to initialize your application
+    func applicationDidFinishLaunching(_ notification: Notification) {
+        DispatchQueue.main.async {
+            self.configureMainWindow()
+        }
     }
 
-    func applicationWillTerminate(_ aNotification: Notification) {
-        // Insert code here to tear down your application
+    private func configureMainWindow() {
+        guard let window = NSApplication.shared.windows.first else { return }
+
+        window.title = "Smart Printer"
+        window.titlebarAppearsTransparent = true
+        window.titleVisibility = .hidden
+        window.styleMask.insert(.fullSizeContentView)
+        window.isMovableByWindowBackground = true
+        window.backgroundColor = AppTheme.background
+        window.setContentSize(NSSize(width: 1120, height: 720))
+        window.center()
+        window.minSize = NSSize(width: 900, height: 600)
     }
 
     func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
-        return true
+        true
     }
-
-
 }
-

+ 57 - 0
smart_printer/AppTheme.swift

@@ -0,0 +1,57 @@
+import Cocoa
+
+enum AppTheme {
+    static let sidebarWidth: CGFloat = 220
+    static let cornerRadius: CGFloat = 14
+    static let cardCornerRadius: CGFloat = 20
+    static let featureCardCornerRadius: CGFloat = 16
+
+    static let background = NSColor(calibratedWhite: 0.965, alpha: 1)
+    static let sidebarBackground = NSColor.white
+    static let cardBackground = NSColor.white
+    static let textPrimary = NSColor(calibratedWhite: 0.12, alpha: 1)
+    static let textSecondary = NSColor(calibratedWhite: 0.48, alpha: 1)
+
+    static let homeActiveBackground = NSColor(red: 0.91, green: 0.94, blue: 1.0, alpha: 1)
+    static let homeActiveForeground = NSColor(red: 0.22, green: 0.47, blue: 0.96, alpha: 1)
+    static let premiumBackground = NSColor(red: 0.95, green: 0.93, blue: 1.0, alpha: 1)
+    static let premiumForeground = NSColor(red: 0.55, green: 0.36, blue: 0.96, alpha: 1)
+
+    static let blue = NSColor(red: 0.22, green: 0.47, blue: 0.96, alpha: 1)
+    static let blueLight = NSColor(red: 0.88, green: 0.93, blue: 1.0, alpha: 1)
+    static let green = NSColor(red: 0.13, green: 0.68, blue: 0.42, alpha: 1)
+    static let greenLight = NSColor(red: 0.88, green: 0.97, blue: 0.91, alpha: 1)
+    static let orange = NSColor(red: 0.96, green: 0.52, blue: 0.18, alpha: 1)
+    static let orangeLight = NSColor(red: 1.0, green: 0.94, blue: 0.88, alpha: 1)
+    static let purple = NSColor(red: 0.55, green: 0.36, blue: 0.96, alpha: 1)
+    static let teal = NSColor(red: 0.18, green: 0.72, blue: 0.82, alpha: 1)
+
+    static func semiboldFont(size: CGFloat) -> NSFont {
+        .systemFont(ofSize: size, weight: .semibold)
+    }
+
+    static func mediumFont(size: CGFloat) -> NSFont {
+        .systemFont(ofSize: size, weight: .medium)
+    }
+
+    static func regularFont(size: CGFloat) -> NSFont {
+        .systemFont(ofSize: size, weight: .regular)
+    }
+}
+
+extension NSView {
+    func applyCardShadow() {
+        wantsLayer = true
+        layer?.shadowColor = NSColor.black.cgColor
+        layer?.shadowOpacity = 0.07
+        layer?.shadowOffset = NSSize(width: 0, height: -3)
+        layer?.shadowRadius = 14
+        layer?.masksToBounds = false
+    }
+
+    func roundCorners(_ radius: CGFloat) {
+        wantsLayer = true
+        layer?.cornerRadius = radius
+        layer?.masksToBounds = true
+    }
+}

+ 3 - 3
smart_printer/Base.lproj/Main.storyboard

@@ -683,10 +683,10 @@
         <scene sceneID="R2V-B0-nI4">
             <objects>
                 <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
-                    <window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
+                    <window key="window" title="Smart Printer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="YES" animationBehavior="default" id="IQv-IB-iLA">
                         <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
                         <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
-                        <rect key="contentRect" x="196" y="240" width="480" height="270"/>
+                        <rect key="contentRect" x="196" y="240" width="1120" height="720"/>
                         <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
                         <connections>
                             <outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
@@ -705,7 +705,7 @@
             <objects>
                 <viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
                     <view key="view" id="m2S-Jp-Qdl">
-                        <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
+                        <rect key="frame" x="0.0" y="0.0" width="1120" height="720"/>
                         <autoresizingMask key="autoresizingMask"/>
                     </view>
                 </viewController>

+ 295 - 0
smart_printer/QuickStartIcons.swift

@@ -0,0 +1,295 @@
+import Cocoa
+
+enum QuickStartIconKind {
+    case photos
+    case files
+    case importFile
+}
+
+final class QuickStartIconView: NSView {
+    private let kind: QuickStartIconKind
+
+    init(kind: QuickStartIconKind) {
+        self.kind = kind
+        super.init(frame: .zero)
+        translatesAutoresizingMaskIntoConstraints = false
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+
+    override var isFlipped: Bool { true }
+    override var isOpaque: Bool { false }
+
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+        guard let context = NSGraphicsContext.current?.cgContext else { return }
+
+        switch kind {
+        case .photos:
+            drawPhotosIcon(in: context)
+        case .files:
+            drawFilesIcon(in: context)
+        case .importFile:
+            drawImportIcon(in: context)
+        }
+    }
+
+    // MARK: - Photos
+
+    private func drawPhotosIcon(in context: CGContext) {
+        let s = min(bounds.width, bounds.height)
+        let ox = (bounds.width - s) / 2
+        let oy = (bounds.height - s) / 2
+
+        drawSoftShadow(in: context, rect: CGRect(x: ox + s * 0.30, y: oy + s * 0.52, width: s * 0.50, height: s * 0.08), radius: s * 0.04)
+
+        context.saveGState()
+        context.translateBy(x: ox + s * 0.62, y: oy + s * 0.30)
+        context.rotate(by: .pi / 7.5)
+        context.translateBy(x: -(s * 0.24), y: -(s * 0.28))
+
+        let backRect = CGRect(x: 0, y: 0, width: s * 0.48, height: s * 0.56)
+        let backPath = roundedRect(backRect, radius: s * 0.085)
+        context.setFillColor(NSColor.white.withAlphaComponent(0.92).cgColor)
+        context.addPath(backPath)
+        context.fillPath()
+
+        context.setStrokeColor(NSColor.white.cgColor)
+        context.setLineWidth(s * 0.014)
+        context.addPath(backPath)
+        context.strokePath()
+
+        drawMountainScene(
+            in: context,
+            rect: CGRect(x: backRect.minX + s * 0.05, y: backRect.minY + s * 0.07, width: backRect.width - s * 0.10, height: backRect.height - s * 0.12),
+            sunColor: NSColor(red: 0.62, green: 0.86, blue: 0.95, alpha: 1),
+            mountainColor: NSColor(red: 0.38, green: 0.80, blue: 0.90, alpha: 1)
+        )
+        context.restoreGState()
+
+        let frontRect = CGRect(x: ox + s * 0.20, y: oy + s * 0.22, width: s * 0.50, height: s * 0.58)
+        let frontPath = roundedRect(frontRect, radius: s * 0.085)
+
+        let blueTop = NSColor(red: 0.34, green: 0.62, blue: 1.0, alpha: 1)
+        let blueBottom = NSColor(red: 0.16, green: 0.40, blue: 0.94, alpha: 1)
+        fillGradient(in: context, path: frontPath, colors: [blueTop.cgColor, blueBottom.cgColor], start: CGPoint(x: frontRect.midX, y: frontRect.minY), end: CGPoint(x: frontRect.midX, y: frontRect.maxY))
+
+        drawMountainScene(
+            in: context,
+            rect: CGRect(x: frontRect.minX + s * 0.05, y: frontRect.minY + s * 0.07, width: frontRect.width - s * 0.10, height: frontRect.height - s * 0.12),
+            sunColor: .white,
+            mountainColor: .white
+        )
+
+        context.setStrokeColor(NSColor.white.withAlphaComponent(0.4).cgColor)
+        context.setLineWidth(s * 0.01)
+        context.addPath(frontPath)
+        context.strokePath()
+    }
+
+    private func drawMountainScene(in context: CGContext, rect: CGRect, sunColor: NSColor, mountainColor: NSColor) {
+        let sunRadius = rect.width * 0.09
+        context.setFillColor(sunColor.cgColor)
+        context.fillEllipse(in: CGRect(x: rect.minX + rect.width * 0.10, y: rect.minY + rect.height * 0.08, width: sunRadius * 2, height: sunRadius * 2))
+
+        let baseY = rect.maxY - rect.height * 0.10
+        context.setFillColor(mountainColor.cgColor)
+        let leftPeak = mountainPath(
+            baseY: baseY,
+            peakX: rect.minX + rect.width * 0.22,
+            peakY: rect.minY + rect.height * 0.48,
+            leftX: rect.minX,
+            rightX: rect.minX + rect.width * 0.48
+        )
+        context.addPath(leftPeak)
+        context.fillPath()
+
+        let rightPeak = mountainPath(
+            baseY: baseY,
+            peakX: rect.minX + rect.width * 0.72,
+            peakY: rect.minY + rect.height * 0.62,
+            leftX: rect.minX + rect.width * 0.34,
+            rightX: rect.maxX
+        )
+        context.addPath(rightPeak)
+        context.fillPath()
+    }
+
+    // MARK: - Files
+
+    private func drawFilesIcon(in context: CGContext) {
+        let s = min(bounds.width, bounds.height)
+        let ox = (bounds.width - s) / 2
+        let oy = (bounds.height - s) / 2
+
+        let folderRect = CGRect(x: ox + s * 0.10, y: oy + s * 0.28, width: s * 0.78, height: s * 0.52)
+        drawSoftShadow(in: context, rect: CGRect(x: folderRect.minX, y: folderRect.maxY - s * 0.04, width: folderRect.width, height: s * 0.06), radius: s * 0.03)
+
+        let backGreen = NSColor(red: 0.42, green: 0.80, blue: 0.36, alpha: 1)
+        let frontGreen = NSColor(red: 0.62, green: 0.92, blue: 0.44, alpha: 1)
+
+        let tabRect = CGRect(x: folderRect.minX + s * 0.02, y: folderRect.minY - s * 0.08, width: s * 0.30, height: s * 0.10)
+        context.setFillColor(backGreen.cgColor)
+        context.addPath(roundedRect(tabRect, radius: s * 0.025, topLeft: s * 0.025, topRight: s * 0.025, bottomLeft: 0, bottomRight: 0))
+        context.fillPath()
+
+        let backBody = CGRect(x: folderRect.minX, y: folderRect.minY, width: folderRect.width, height: folderRect.height)
+        fillGradient(in: context, path: roundedRect(backBody, radius: s * 0.055), colors: [backGreen.cgColor, NSColor(red: 0.24, green: 0.66, blue: 0.28, alpha: 1).cgColor], start: CGPoint(x: backBody.midX, y: backBody.minY), end: CGPoint(x: backBody.midX, y: backBody.maxY))
+
+        let docBack = CGRect(x: folderRect.minX + s * 0.14, y: folderRect.minY - s * 0.18, width: s * 0.32, height: s * 0.40)
+        context.setFillColor(NSColor.white.withAlphaComponent(0.85).cgColor)
+        context.addPath(roundedRect(docBack, radius: s * 0.02))
+        context.fillPath()
+
+        let docFront = CGRect(x: folderRect.minX + s * 0.22, y: folderRect.minY - s * 0.28, width: s * 0.40, height: s * 0.50)
+        context.setFillColor(NSColor.white.cgColor)
+        context.addPath(roundedRect(docFront, radius: s * 0.03))
+        context.fillPath()
+
+        let header = CGRect(x: docFront.minX, y: docFront.minY, width: docFront.width, height: s * 0.12)
+        context.setFillColor(NSColor(red: 0.20, green: 0.48, blue: 0.96, alpha: 1).cgColor)
+        context.addPath(roundedRect(header, radius: s * 0.03, topLeft: s * 0.03, topRight: s * 0.03, bottomLeft: 0, bottomRight: 0))
+        context.fillPath()
+
+        let lineColor = NSColor(red: 0.66, green: 0.74, blue: 0.98, alpha: 1)
+        for (index, widthFactor) in [0.78, 0.62, 0.70].enumerated() {
+            let lineY = docFront.minY + s * 0.18 + CGFloat(index) * s * 0.075
+            let lineRect = CGRect(x: docFront.minX + s * 0.06, y: lineY, width: docFront.width * widthFactor - s * 0.08, height: s * 0.038)
+            context.setFillColor(lineColor.cgColor)
+            context.addPath(roundedRect(lineRect, radius: s * 0.014))
+            context.fillPath()
+        }
+
+        let frontFlap = CGRect(x: folderRect.minX, y: folderRect.minY + folderRect.height * 0.38, width: folderRect.width, height: folderRect.height * 0.62)
+        fillGradient(in: context, path: roundedRect(frontFlap, radius: s * 0.055, topLeft: 0, topRight: 0, bottomLeft: s * 0.055, bottomRight: s * 0.055), colors: [frontGreen.cgColor, NSColor(red: 0.38, green: 0.76, blue: 0.32, alpha: 1).cgColor], start: CGPoint(x: frontFlap.midX, y: frontFlap.minY), end: CGPoint(x: frontFlap.midX, y: frontFlap.maxY))
+    }
+
+    // MARK: - Import
+
+    private func drawImportIcon(in context: CGContext) {
+        let s = min(bounds.width, bounds.height)
+        let ox = (bounds.width - s) / 2
+        let oy = (bounds.height - s) / 2
+
+        let folderRect = CGRect(x: ox + s * 0.08, y: oy + s * 0.30, width: s * 0.74, height: s * 0.46)
+        drawSoftShadow(in: context, rect: CGRect(x: folderRect.minX, y: folderRect.maxY - s * 0.03, width: folderRect.width, height: s * 0.05), radius: s * 0.025)
+
+        let orangeTop = NSColor(red: 1.0, green: 0.84, blue: 0.40, alpha: 1)
+        let orangeBottom = NSColor(red: 0.95, green: 0.60, blue: 0.16, alpha: 1)
+
+        let tabRect = CGRect(x: folderRect.minX + s * 0.02, y: folderRect.minY - s * 0.07, width: s * 0.28, height: s * 0.09)
+        context.setFillColor(orangeBottom.cgColor)
+        context.addPath(roundedRect(tabRect, radius: s * 0.022, topLeft: s * 0.022, topRight: s * 0.022, bottomLeft: 0, bottomRight: 0))
+        context.fillPath()
+
+        fillGradient(in: context, path: roundedRect(folderRect, radius: s * 0.048), colors: [orangeTop.cgColor, orangeBottom.cgColor], start: CGPoint(x: folderRect.midX, y: folderRect.minY), end: CGPoint(x: folderRect.midX, y: folderRect.maxY))
+
+        let paper = CGRect(x: folderRect.minX + s * 0.12, y: folderRect.minY + s * 0.08, width: folderRect.width * 0.76, height: folderRect.height * 0.38)
+        context.setFillColor(NSColor.white.withAlphaComponent(0.9).cgColor)
+        context.addPath(roundedRect(paper, radius: s * 0.018))
+        context.fillPath()
+
+        let frontFlap = CGRect(x: folderRect.minX, y: folderRect.minY + folderRect.height * 0.42, width: folderRect.width, height: folderRect.height * 0.58)
+        fillGradient(in: context, path: roundedRect(frontFlap, radius: s * 0.048, topLeft: 0, topRight: 0, bottomLeft: s * 0.048, bottomRight: s * 0.048), colors: [NSColor(red: 1.0, green: 0.90, blue: 0.50, alpha: 1).cgColor, orangeBottom.cgColor], start: CGPoint(x: frontFlap.midX, y: frontFlap.minY), end: CGPoint(x: frontFlap.midX, y: frontFlap.maxY))
+
+        let badgeRadius = s * 0.17
+        let badgeCenter = CGPoint(x: folderRect.midX, y: folderRect.maxY - s * 0.02)
+        drawSoftShadow(in: context, rect: CGRect(x: badgeCenter.x - badgeRadius, y: badgeCenter.y - badgeRadius * 0.4, width: badgeRadius * 2, height: badgeRadius * 0.5), radius: s * 0.03)
+
+        let badgeRect = CGRect(x: badgeCenter.x - badgeRadius, y: badgeCenter.y - badgeRadius, width: badgeRadius * 2, height: badgeRadius * 2)
+        let badgeColors = [NSColor(red: 0.66, green: 0.78, blue: 1.0, alpha: 1).cgColor, NSColor(red: 0.40, green: 0.56, blue: 0.96, alpha: 1).cgColor]
+        fillGradient(in: context, path: CGPath(ellipseIn: badgeRect, transform: nil), colors: badgeColors, start: CGPoint(x: badgeRect.midX, y: badgeRect.minY), end: CGPoint(x: badgeRect.midX, y: badgeRect.maxY))
+
+        drawCloudUpload(in: context, center: badgeCenter, size: badgeRadius * 1.15)
+    }
+
+    private func drawCloudUpload(in context: CGContext, center: CGPoint, size: CGFloat) {
+        let cloudColor = NSColor.white
+        let arrowColor = NSColor(red: 0.28, green: 0.42, blue: 0.86, alpha: 1)
+
+        let w = size
+        let h = size * 0.62
+        let cloudRect = CGRect(x: center.x - w / 2, y: center.y - h / 2 + size * 0.04, width: w, height: h)
+        let cloud = cloudPath(in: cloudRect)
+        context.setFillColor(cloudColor.cgColor)
+        context.addPath(cloud)
+        context.fillPath()
+
+        let arrowWidth = size * 0.14
+        let arrowHeight = size * 0.28
+        let arrowTop = center.y + size * 0.02
+        let arrow = CGMutablePath()
+        arrow.move(to: CGPoint(x: center.x, y: arrowTop + arrowHeight))
+        arrow.addLine(to: CGPoint(x: center.x - arrowWidth, y: arrowTop + arrowHeight * 0.45))
+        arrow.addLine(to: CGPoint(x: center.x - arrowWidth * 0.45, y: arrowTop + arrowHeight * 0.45))
+        arrow.addLine(to: CGPoint(x: center.x - arrowWidth * 0.45, y: arrowTop))
+        arrow.addLine(to: CGPoint(x: center.x + arrowWidth * 0.45, y: arrowTop))
+        arrow.addLine(to: CGPoint(x: center.x + arrowWidth * 0.45, y: arrowTop + arrowHeight * 0.45))
+        arrow.addLine(to: CGPoint(x: center.x + arrowWidth, y: arrowTop + arrowHeight * 0.45))
+        arrow.closeSubpath()
+        context.setFillColor(arrowColor.cgColor)
+        context.addPath(arrow)
+        context.fillPath()
+    }
+
+    // MARK: - Helpers
+
+    private func drawSoftShadow(in context: CGContext, rect: CGRect, radius: CGFloat) {
+        context.saveGState()
+        context.setFillColor(NSColor.black.withAlphaComponent(0.12).cgColor)
+        context.addPath(roundedRect(rect.offsetBy(dx: 0, dy: -radius * 0.3), radius: radius))
+        context.fillPath()
+        context.restoreGState()
+    }
+
+    private func fillGradient(in context: CGContext, path: CGPath, colors: [CGColor], start: CGPoint, end: CGPoint) {
+        context.saveGState()
+        context.addPath(path)
+        context.clip()
+        guard let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: [0, 1]) else {
+            context.restoreGState()
+            return
+        }
+        context.drawLinearGradient(gradient, start: start, end: end, options: [])
+        context.restoreGState()
+    }
+
+    private func roundedRect(_ rect: CGRect, radius: CGFloat) -> CGPath {
+        roundedRect(rect, radius: radius, topLeft: radius, topRight: radius, bottomLeft: radius, bottomRight: radius)
+    }
+
+    private func roundedRect(_ rect: CGRect, radius: CGFloat, topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat) -> CGPath {
+        let path = CGMutablePath()
+        path.move(to: CGPoint(x: rect.minX + topLeft, y: rect.maxY))
+        path.addLine(to: CGPoint(x: rect.maxX - topRight, y: rect.maxY))
+        path.addQuadCurve(to: CGPoint(x: rect.maxX, y: rect.maxY - topRight), control: CGPoint(x: rect.maxX, y: rect.maxY))
+        path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY + bottomRight))
+        path.addQuadCurve(to: CGPoint(x: rect.maxX - bottomRight, y: rect.minY), control: CGPoint(x: rect.maxX, y: rect.minY))
+        path.addLine(to: CGPoint(x: rect.minX + bottomLeft, y: rect.minY))
+        path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.minY + bottomLeft), control: CGPoint(x: rect.minX, y: rect.minY))
+        path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY - topLeft))
+        path.addQuadCurve(to: CGPoint(x: rect.minX + topLeft, y: rect.maxY), control: CGPoint(x: rect.minX, y: rect.maxY))
+        path.closeSubpath()
+        return path
+    }
+
+    private func mountainPath(baseY: CGFloat, peakX: CGFloat, peakY: CGFloat, leftX: CGFloat, rightX: CGFloat) -> CGPath {
+        let path = CGMutablePath()
+        path.move(to: CGPoint(x: leftX, y: baseY))
+        path.addLine(to: CGPoint(x: peakX, y: peakY))
+        path.addLine(to: CGPoint(x: rightX, y: baseY))
+        path.closeSubpath()
+        return path
+    }
+
+    private func cloudPath(in rect: CGRect) -> CGPath {
+        let path = CGMutablePath()
+        let r = rect.height * 0.38
+        path.addEllipse(in: CGRect(x: rect.minX + rect.width * 0.08, y: rect.minY + rect.height * 0.18, width: r * 2, height: r * 2))
+        path.addEllipse(in: CGRect(x: rect.minX + rect.width * 0.30, y: rect.minY + rect.height * 0.30, width: r * 2.1, height: r * 2.1))
+        path.addEllipse(in: CGRect(x: rect.minX + rect.width * 0.52, y: rect.minY + rect.height * 0.16, width: r * 1.9, height: r * 1.9))
+        path.addRect(CGRect(x: rect.minX + rect.width * 0.12, y: rect.minY + rect.height * 0.18, width: rect.width * 0.76, height: rect.height * 0.42))
+        return path
+    }
+}

+ 101 - 0
smart_printer/SidebarView.swift

@@ -0,0 +1,101 @@
+import Cocoa
+
+final class SidebarView: NSView {
+    init() {
+        super.init(frame: .zero)
+        wantsLayer = true
+        layer?.backgroundColor = AppTheme.sidebarBackground.cgColor
+        translatesAutoresizingMaskIntoConstraints = false
+        setup()
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+
+    private func setup() {
+        let logoContainer = NSView()
+        logoContainer.translatesAutoresizingMaskIntoConstraints = false
+
+        let logoIcon = NSImageView()
+        logoIcon.translatesAutoresizingMaskIntoConstraints = false
+        if let image = NSImage(systemSymbolName: "printer.fill", accessibilityDescription: "Smart Printer") {
+            let config = NSImage.SymbolConfiguration(pointSize: 28, weight: .medium)
+            logoIcon.image = image.withSymbolConfiguration(config)
+        }
+        logoIcon.contentTintColor = AppTheme.blue
+
+        let wifiBadge = NSImageView()
+        wifiBadge.translatesAutoresizingMaskIntoConstraints = false
+        if let image = NSImage(systemSymbolName: "wifi", accessibilityDescription: "Wi-Fi") {
+            let config = NSImage.SymbolConfiguration(pointSize: 10, weight: .bold)
+            wifiBadge.image = image.withSymbolConfiguration(config)
+        }
+        wifiBadge.contentTintColor = AppTheme.blue
+
+        let appNameLabel = NSTextField(labelWithString: "Smart Printer")
+        appNameLabel.font = AppTheme.semiboldFont(size: 15)
+        appNameLabel.textColor = AppTheme.textPrimary
+        appNameLabel.alignment = .center
+        appNameLabel.translatesAutoresizingMaskIntoConstraints = false
+
+        let navStack = NSStackView()
+        navStack.orientation = .vertical
+        navStack.spacing = 4
+        navStack.alignment = .leading
+        navStack.translatesAutoresizingMaskIntoConstraints = false
+
+        let homeItem = SidebarNavItem(title: "Home", symbolName: "house.fill", style: .active)
+        let scanItem = SidebarNavItem(title: "Scan", symbolName: "viewfinder", style: .normal)
+        let premiumItem = SidebarNavItem(title: "Premium", symbolName: "diamond.fill", style: .premium)
+
+        navStack.addArrangedSubview(homeItem)
+        navStack.addArrangedSubview(scanItem)
+        navStack.addArrangedSubview(premiumItem)
+
+        addSubview(logoContainer)
+        logoContainer.addSubview(logoIcon)
+        logoContainer.addSubview(wifiBadge)
+        addSubview(appNameLabel)
+        addSubview(navStack)
+
+        let divider = NSBox()
+        divider.boxType = .separator
+        divider.translatesAutoresizingMaskIntoConstraints = false
+        addSubview(divider)
+
+        NSLayoutConstraint.activate([
+            widthAnchor.constraint(equalToConstant: AppTheme.sidebarWidth),
+
+            logoContainer.topAnchor.constraint(equalTo: topAnchor, constant: 52),
+            logoContainer.centerXAnchor.constraint(equalTo: centerXAnchor),
+            logoContainer.widthAnchor.constraint(equalToConstant: 48),
+            logoContainer.heightAnchor.constraint(equalToConstant: 48),
+
+            logoIcon.centerXAnchor.constraint(equalTo: logoContainer.centerXAnchor),
+            logoIcon.centerYAnchor.constraint(equalTo: logoContainer.centerYAnchor),
+            logoIcon.widthAnchor.constraint(equalToConstant: 36),
+            logoIcon.heightAnchor.constraint(equalToConstant: 36),
+
+            wifiBadge.topAnchor.constraint(equalTo: logoContainer.topAnchor, constant: -2),
+            wifiBadge.trailingAnchor.constraint(equalTo: logoContainer.trailingAnchor, constant: 4),
+            wifiBadge.widthAnchor.constraint(equalToConstant: 14),
+            wifiBadge.heightAnchor.constraint(equalToConstant: 14),
+
+            appNameLabel.topAnchor.constraint(equalTo: logoContainer.bottomAnchor, constant: 8),
+            appNameLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
+
+            navStack.topAnchor.constraint(equalTo: appNameLabel.bottomAnchor, constant: 32),
+            navStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
+            navStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
+
+            homeItem.widthAnchor.constraint(equalTo: navStack.widthAnchor),
+            scanItem.widthAnchor.constraint(equalTo: navStack.widthAnchor),
+            premiumItem.widthAnchor.constraint(equalTo: navStack.widthAnchor),
+
+            divider.trailingAnchor.constraint(equalTo: trailingAnchor),
+            divider.topAnchor.constraint(equalTo: topAnchor),
+            divider.bottomAnchor.constraint(equalTo: bottomAnchor),
+            divider.widthAnchor.constraint(equalToConstant: 1),
+        ])
+    }
+}

+ 348 - 0
smart_printer/UIComponents.swift

@@ -0,0 +1,348 @@
+import Cocoa
+
+// MARK: - Gradient Card View
+
+final class GradientCardView: NSView {
+    private let gradientLayer = CAGradientLayer()
+
+    init(colors: [NSColor], startPoint: CGPoint = CGPoint(x: 0, y: 0.5), endPoint: CGPoint = CGPoint(x: 1, y: 0.5)) {
+        super.init(frame: .zero)
+        wantsLayer = true
+        gradientLayer.colors = colors.map { $0.cgColor }
+        gradientLayer.startPoint = startPoint
+        gradientLayer.endPoint = endPoint
+        gradientLayer.cornerRadius = AppTheme.cardCornerRadius
+        layer?.addSublayer(gradientLayer)
+        applyCardShadow()
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+
+    override func layout() {
+        super.layout()
+        gradientLayer.frame = bounds
+        gradientLayer.cornerRadius = AppTheme.cardCornerRadius
+    }
+}
+
+// MARK: - Wave Pattern
+
+final class WavePatternView: NSView {
+    override var isOpaque: Bool { false }
+
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+        guard let context = NSGraphicsContext.current?.cgContext else { return }
+
+        let dotColor = NSColor(calibratedWhite: 0.82, alpha: 0.55)
+        context.setFillColor(dotColor.cgColor)
+
+        let spacing: CGFloat = 14
+        let dotSize: CGFloat = 3
+        let rows = Int(bounds.height / spacing) + 2
+        let cols = Int(bounds.width / spacing) + 2
+
+        for row in 0..<rows {
+            for col in 0..<cols {
+                let wave = sin(Double(col) * 0.35 + Double(row) * 0.25) * 8
+                let x = CGFloat(col) * spacing + CGFloat(wave)
+                let y = CGFloat(row) * spacing
+                let rect = CGRect(x: x, y: y, width: dotSize, height: dotSize)
+                context.fillEllipse(in: rect)
+            }
+        }
+    }
+}
+
+// MARK: - Sidebar Nav Item
+
+final class SidebarNavItem: NSControl {
+    enum Style {
+        case normal
+        case active
+        case premium
+    }
+
+    private let iconView = NSImageView()
+    private let titleLabel = NSTextField(labelWithString: "")
+    private let container = NSView()
+    private var style: Style = .normal
+
+    init(title: String, symbolName: String, style: Style = .normal) {
+        super.init(frame: .zero)
+        self.style = style
+
+        titleLabel.stringValue = title
+        titleLabel.font = AppTheme.mediumFont(size: 14)
+        titleLabel.textColor = AppTheme.textPrimary
+
+        if let image = NSImage(systemSymbolName: symbolName, accessibilityDescription: title) {
+            let config = NSImage.SymbolConfiguration(pointSize: 15, weight: .medium)
+            iconView.image = image.withSymbolConfiguration(config)
+        }
+        iconView.contentTintColor = AppTheme.textPrimary
+
+        container.translatesAutoresizingMaskIntoConstraints = false
+        iconView.translatesAutoresizingMaskIntoConstraints = false
+        titleLabel.translatesAutoresizingMaskIntoConstraints = false
+        translatesAutoresizingMaskIntoConstraints = false
+
+        addSubview(container)
+        container.addSubview(iconView)
+        container.addSubview(titleLabel)
+
+        NSLayoutConstraint.activate([
+            heightAnchor.constraint(equalToConstant: 44),
+
+            container.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
+            container.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12),
+            container.topAnchor.constraint(equalTo: topAnchor),
+            container.bottomAnchor.constraint(equalTo: bottomAnchor),
+
+            iconView.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 12),
+            iconView.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+            iconView.widthAnchor.constraint(equalToConstant: 20),
+            iconView.heightAnchor.constraint(equalToConstant: 20),
+
+            titleLabel.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 10),
+            titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+            titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: container.trailingAnchor, constant: -12),
+        ])
+
+        applyStyle(style)
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+
+    private func applyStyle(_ style: Style) {
+        container.wantsLayer = true
+        container.layer?.cornerRadius = AppTheme.cornerRadius
+
+        switch style {
+        case .normal:
+            container.layer?.backgroundColor = NSColor.clear.cgColor
+            titleLabel.textColor = AppTheme.textPrimary
+            iconView.contentTintColor = AppTheme.textPrimary
+        case .active:
+            container.layer?.backgroundColor = AppTheme.homeActiveBackground.cgColor
+            titleLabel.textColor = AppTheme.homeActiveForeground
+            iconView.contentTintColor = AppTheme.homeActiveForeground
+        case .premium:
+            container.layer?.backgroundColor = AppTheme.premiumBackground.cgColor
+            titleLabel.textColor = AppTheme.premiumForeground
+            iconView.contentTintColor = AppTheme.premiumForeground
+        }
+    }
+
+    override func resetCursorRects() {
+        addCursorRect(bounds, cursor: .pointingHand)
+    }
+}
+
+// MARK: - Action Button
+
+final class PillButton: NSButton {
+    init(title: String, color: NSColor) {
+        super.init(frame: .zero)
+        self.title = title
+        isBordered = false
+        wantsLayer = true
+        layer?.backgroundColor = color.cgColor
+        layer?.cornerRadius = 10
+        font = AppTheme.semiboldFont(size: 13)
+        contentTintColor = .white
+
+        if let arrow = NSImage(systemSymbolName: "arrow.right", accessibilityDescription: nil) {
+            let config = NSImage.SymbolConfiguration(pointSize: 11, weight: .bold)
+            image = arrow.withSymbolConfiguration(config)
+            imagePosition = .imageTrailing
+            imageHugsTitle = true
+        }
+
+        heightAnchor.constraint(equalToConstant: 36).isActive = true
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+
+    override func resetCursorRects() {
+        addCursorRect(bounds, cursor: .pointingHand)
+    }
+}
+
+// MARK: - Quick Start Card
+
+struct QuickStartCardData {
+    let title: String
+    let subtitle: String
+    let buttonTitle: String
+    let accentColor: NSColor
+    let gradientColors: [NSColor]
+    let iconKind: QuickStartIconKind
+}
+
+final class QuickStartCardView: NSView {
+    init(data: QuickStartCardData) {
+        super.init(frame: .zero)
+        translatesAutoresizingMaskIntoConstraints = false
+
+        let gradient = GradientCardView(
+            colors: data.gradientColors,
+            startPoint: CGPoint(x: 0, y: 0.5),
+            endPoint: CGPoint(x: 1, y: 0.5)
+        )
+        gradient.translatesAutoresizingMaskIntoConstraints = false
+
+        let titleLabel = NSTextField(labelWithString: data.title)
+        titleLabel.font = AppTheme.semiboldFont(size: 22)
+        titleLabel.textColor = data.accentColor
+        titleLabel.translatesAutoresizingMaskIntoConstraints = false
+
+        let subtitleLabel = NSTextField(labelWithString: data.subtitle)
+        subtitleLabel.font = AppTheme.regularFont(size: 13)
+        subtitleLabel.textColor = AppTheme.textSecondary
+        subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
+
+        let button = PillButton(title: data.buttonTitle, color: data.accentColor)
+        button.translatesAutoresizingMaskIntoConstraints = false
+
+        let wavePattern = WavePatternView()
+        wavePattern.translatesAutoresizingMaskIntoConstraints = false
+
+        let iconView = QuickStartIconView(kind: data.iconKind)
+
+        addSubview(gradient)
+        gradient.addSubview(wavePattern)
+        gradient.addSubview(titleLabel)
+        gradient.addSubview(subtitleLabel)
+        gradient.addSubview(button)
+        gradient.addSubview(iconView)
+
+        NSLayoutConstraint.activate([
+            gradient.leadingAnchor.constraint(equalTo: leadingAnchor),
+            gradient.trailingAnchor.constraint(equalTo: trailingAnchor),
+            gradient.topAnchor.constraint(equalTo: topAnchor),
+            gradient.bottomAnchor.constraint(equalTo: bottomAnchor),
+            heightAnchor.constraint(equalToConstant: 160),
+
+            titleLabel.leadingAnchor.constraint(equalTo: gradient.leadingAnchor, constant: 24),
+            titleLabel.topAnchor.constraint(equalTo: gradient.topAnchor, constant: 28),
+
+            subtitleLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
+            subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 6),
+            subtitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: iconView.leadingAnchor, constant: -12),
+
+            button.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
+            button.bottomAnchor.constraint(equalTo: gradient.bottomAnchor, constant: -24),
+
+            wavePattern.trailingAnchor.constraint(equalTo: gradient.trailingAnchor),
+            wavePattern.bottomAnchor.constraint(equalTo: gradient.bottomAnchor),
+            wavePattern.widthAnchor.constraint(equalToConstant: 120),
+            wavePattern.heightAnchor.constraint(equalToConstant: 80),
+
+            iconView.trailingAnchor.constraint(equalTo: gradient.trailingAnchor, constant: -12),
+            iconView.centerYAnchor.constraint(equalTo: gradient.centerYAnchor),
+            iconView.widthAnchor.constraint(equalToConstant: 110),
+            iconView.heightAnchor.constraint(equalToConstant: 110),
+        ])
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+}
+
+// MARK: - Feature Card
+
+struct FeatureCardData {
+    let title: String
+    let subtitle: String
+    let accentColor: NSColor
+    let symbolName: String
+}
+
+final class FeatureCardView: NSView {
+    init(data: FeatureCardData) {
+        super.init(frame: .zero)
+        translatesAutoresizingMaskIntoConstraints = false
+        wantsLayer = true
+        layer?.backgroundColor = AppTheme.cardBackground.cgColor
+        layer?.cornerRadius = AppTheme.featureCardCornerRadius
+        applyCardShadow()
+
+        let iconBackground = NSView()
+        iconBackground.wantsLayer = true
+        iconBackground.layer?.backgroundColor = data.accentColor.withAlphaComponent(0.12).cgColor
+        iconBackground.layer?.cornerRadius = 14
+        iconBackground.translatesAutoresizingMaskIntoConstraints = false
+
+        let iconView = NSImageView()
+        iconView.translatesAutoresizingMaskIntoConstraints = false
+        if let image = NSImage(systemSymbolName: data.symbolName, accessibilityDescription: data.title) {
+            let config = NSImage.SymbolConfiguration(pointSize: 22, weight: .medium)
+            iconView.image = image.withSymbolConfiguration(config)
+        }
+        iconView.contentTintColor = data.accentColor
+
+        let titleLabel = NSTextField(labelWithString: data.title)
+        titleLabel.font = AppTheme.semiboldFont(size: 15)
+        titleLabel.textColor = AppTheme.textPrimary
+        titleLabel.translatesAutoresizingMaskIntoConstraints = false
+
+        let subtitleLabel = NSTextField(labelWithString: data.subtitle)
+        subtitleLabel.font = AppTheme.regularFont(size: 12)
+        subtitleLabel.textColor = AppTheme.textSecondary
+        subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
+
+        let arrowButton = NSButton()
+        arrowButton.isBordered = false
+        arrowButton.wantsLayer = true
+        arrowButton.layer?.backgroundColor = data.accentColor.withAlphaComponent(0.12).cgColor
+        arrowButton.layer?.cornerRadius = 16
+        arrowButton.translatesAutoresizingMaskIntoConstraints = false
+        if let arrow = NSImage(systemSymbolName: "arrow.right", accessibilityDescription: "Open") {
+            let config = NSImage.SymbolConfiguration(pointSize: 11, weight: .bold)
+            arrowButton.image = arrow.withSymbolConfiguration(config)
+        }
+        arrowButton.contentTintColor = data.accentColor
+
+        addSubview(iconBackground)
+        iconBackground.addSubview(iconView)
+        addSubview(titleLabel)
+        addSubview(subtitleLabel)
+        addSubview(arrowButton)
+
+        NSLayoutConstraint.activate([
+            heightAnchor.constraint(equalToConstant: 130),
+
+            iconBackground.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 18),
+            iconBackground.topAnchor.constraint(equalTo: topAnchor, constant: 18),
+            iconBackground.widthAnchor.constraint(equalToConstant: 48),
+            iconBackground.heightAnchor.constraint(equalToConstant: 48),
+
+            iconView.centerXAnchor.constraint(equalTo: iconBackground.centerXAnchor),
+            iconView.centerYAnchor.constraint(equalTo: iconBackground.centerYAnchor),
+
+            titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 18),
+            titleLabel.topAnchor.constraint(equalTo: iconBackground.bottomAnchor, constant: 12),
+            titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -18),
+
+            subtitleLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
+            subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
+            subtitleLabel.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor),
+
+            arrowButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
+            arrowButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16),
+            arrowButton.widthAnchor.constraint(equalToConstant: 32),
+            arrowButton.heightAnchor.constraint(equalToConstant: 32),
+        ])
+    }
+
+    @available(*, unavailable)
+    required init?(coder: NSCoder) { nil }
+
+    override func resetCursorRects() {
+        addCursorRect(bounds, cursor: .pointingHand)
+    }
+}

+ 248 - 6
smart_printer/ViewController.swift

@@ -2,25 +2,267 @@
 //  ViewController.swift
 //  smart_printer
 //
-//  Created by Mql Mac 2 on 04/06/2026.
-//
 
 import Cocoa
 
 class ViewController: NSViewController {
 
+    override func loadView() {
+        let container = NSView(frame: NSRect(x: 0, y: 0, width: 1120, height: 720))
+        container.autoresizingMask = [.width, .height]
+        container.wantsLayer = true
+        container.layer?.backgroundColor = AppTheme.background.cgColor
+        view = container
+    }
+
     override func viewDidLoad() {
         super.viewDidLoad()
+        setupLayout()
+    }
+
+    private func setupLayout() {
+        let sidebar = SidebarView()
+
+        let mainContent = NSView()
+        mainContent.translatesAutoresizingMaskIntoConstraints = false
+        mainContent.wantsLayer = true
+        mainContent.layer?.backgroundColor = AppTheme.background.cgColor
+
+        let header = makeHeader()
+        let scrollView = makeScrollView()
 
-        // Do any additional setup after loading the view.
+        let wavePattern = WavePatternView()
+        wavePattern.translatesAutoresizingMaskIntoConstraints = false
+
+        view.addSubview(sidebar)
+        view.addSubview(mainContent)
+        mainContent.addSubview(header)
+        mainContent.addSubview(scrollView)
+        mainContent.addSubview(wavePattern)
+
+        NSLayoutConstraint.activate([
+            sidebar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+            sidebar.topAnchor.constraint(equalTo: view.topAnchor),
+            sidebar.bottomAnchor.constraint(equalTo: view.bottomAnchor),
+
+            mainContent.leadingAnchor.constraint(equalTo: sidebar.trailingAnchor),
+            mainContent.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+            mainContent.topAnchor.constraint(equalTo: view.topAnchor),
+            mainContent.bottomAnchor.constraint(equalTo: view.bottomAnchor),
+
+            header.leadingAnchor.constraint(equalTo: mainContent.leadingAnchor),
+            header.trailingAnchor.constraint(equalTo: mainContent.trailingAnchor),
+            header.topAnchor.constraint(equalTo: mainContent.topAnchor, constant: 16),
+            header.heightAnchor.constraint(equalToConstant: 44),
+
+            scrollView.leadingAnchor.constraint(equalTo: mainContent.leadingAnchor),
+            scrollView.trailingAnchor.constraint(equalTo: mainContent.trailingAnchor),
+            scrollView.topAnchor.constraint(equalTo: header.bottomAnchor, constant: 8),
+            scrollView.bottomAnchor.constraint(equalTo: mainContent.bottomAnchor),
+
+            wavePattern.trailingAnchor.constraint(equalTo: mainContent.trailingAnchor),
+            wavePattern.bottomAnchor.constraint(equalTo: mainContent.bottomAnchor),
+            wavePattern.widthAnchor.constraint(equalToConstant: 280),
+            wavePattern.heightAnchor.constraint(equalToConstant: 180),
+        ])
     }
 
-    override var representedObject: Any? {
-        didSet {
-        // Update the view, if already loaded.
+    private func makeHeader() -> NSView {
+        let header = NSView()
+        header.translatesAutoresizingMaskIntoConstraints = false
+
+        let titleLabel = NSTextField(labelWithString: "Smart Printer")
+        titleLabel.font = AppTheme.semiboldFont(size: 18)
+        titleLabel.textColor = AppTheme.textPrimary
+        titleLabel.alignment = .center
+        titleLabel.translatesAutoresizingMaskIntoConstraints = false
+
+        let settingsButton = NSButton()
+        settingsButton.isBordered = false
+        settingsButton.translatesAutoresizingMaskIntoConstraints = false
+        if let image = NSImage(systemSymbolName: "gearshape", accessibilityDescription: "Settings") {
+            let config = NSImage.SymbolConfiguration(pointSize: 18, weight: .regular)
+            settingsButton.image = image.withSymbolConfiguration(config)
         }
+        settingsButton.contentTintColor = AppTheme.textSecondary
+
+        header.addSubview(titleLabel)
+        header.addSubview(settingsButton)
+
+        NSLayoutConstraint.activate([
+            titleLabel.centerXAnchor.constraint(equalTo: header.centerXAnchor),
+            titleLabel.centerYAnchor.constraint(equalTo: header.centerYAnchor),
+
+            settingsButton.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -28),
+            settingsButton.centerYAnchor.constraint(equalTo: header.centerYAnchor),
+            settingsButton.widthAnchor.constraint(equalToConstant: 32),
+            settingsButton.heightAnchor.constraint(equalToConstant: 32),
+        ])
+
+        return header
     }
 
+    private func makeScrollView() -> NSScrollView {
+        let scrollView = NSScrollView()
+        scrollView.translatesAutoresizingMaskIntoConstraints = false
+        scrollView.hasVerticalScroller = true
+        scrollView.hasHorizontalScroller = false
+        scrollView.autohidesScrollers = true
+        scrollView.drawsBackground = false
+        scrollView.borderType = .noBorder
+
+        let documentView = FlippedDocumentView()
+        documentView.translatesAutoresizingMaskIntoConstraints = false
+
+        let quickStartSection = makeQuickStartSection()
+        let createPrintSection = makeCreatePrintSection()
+
+        documentView.addSubview(quickStartSection)
+        documentView.addSubview(createPrintSection)
+        scrollView.documentView = documentView
+
+        let contentGuide = scrollView.contentView
+
+        NSLayoutConstraint.activate([
+            documentView.topAnchor.constraint(equalTo: contentGuide.topAnchor),
+            documentView.leadingAnchor.constraint(equalTo: contentGuide.leadingAnchor),
+            documentView.trailingAnchor.constraint(equalTo: contentGuide.trailingAnchor),
+            documentView.widthAnchor.constraint(equalTo: contentGuide.widthAnchor),
+
+            quickStartSection.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 32),
+            quickStartSection.trailingAnchor.constraint(equalTo: documentView.trailingAnchor, constant: -32),
+            quickStartSection.topAnchor.constraint(equalTo: documentView.topAnchor, constant: 8),
+
+            createPrintSection.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 32),
+            createPrintSection.trailingAnchor.constraint(equalTo: documentView.trailingAnchor, constant: -32),
+            createPrintSection.topAnchor.constraint(equalTo: quickStartSection.bottomAnchor, constant: 36),
+            createPrintSection.bottomAnchor.constraint(equalTo: documentView.bottomAnchor, constant: -40),
+        ])
+
+        return scrollView
+    }
 
+    private func makeSectionTitle(_ text: String) -> NSTextField {
+        let label = NSTextField(labelWithString: text)
+        label.font = AppTheme.semiboldFont(size: 20)
+        label.textColor = AppTheme.textPrimary
+        label.translatesAutoresizingMaskIntoConstraints = false
+        return label
+    }
+
+    private func makeQuickStartSection() -> NSView {
+        let section = NSView()
+        section.translatesAutoresizingMaskIntoConstraints = false
+
+        let title = makeSectionTitle("Quick Start")
+        section.addSubview(title)
+
+        let cardsStack = NSStackView()
+        cardsStack.orientation = .horizontal
+        cardsStack.spacing = 20
+        cardsStack.distribution = .fillEqually
+        cardsStack.translatesAutoresizingMaskIntoConstraints = false
+
+        let cards: [QuickStartCardData] = [
+            QuickStartCardData(
+                title: "From Photos",
+                subtitle: "Take a photo from gallery",
+                buttonTitle: "Open Gallery",
+                accentColor: AppTheme.blue,
+                gradientColors: [AppTheme.blueLight, NSColor(red: 0.82, green: 0.90, blue: 1.0, alpha: 1)],
+                iconKind: .photos
+            ),
+            QuickStartCardData(
+                title: "From Files",
+                subtitle: "Take a photo from file manager",
+                buttonTitle: "Browse Files",
+                accentColor: AppTheme.green,
+                gradientColors: [AppTheme.greenLight, NSColor(red: 0.78, green: 0.94, blue: 0.84, alpha: 1)],
+                iconKind: .files
+            ),
+            QuickStartCardData(
+                title: "Import File",
+                subtitle: "Import a file from storage",
+                buttonTitle: "Import Now",
+                accentColor: AppTheme.orange,
+                gradientColors: [AppTheme.orangeLight, NSColor(red: 1.0, green: 0.88, blue: 0.76, alpha: 1)],
+                iconKind: .importFile
+            ),
+        ]
+
+        for cardData in cards {
+            cardsStack.addArrangedSubview(QuickStartCardView(data: cardData))
+        }
+
+        section.addSubview(cardsStack)
+
+        NSLayoutConstraint.activate([
+            title.leadingAnchor.constraint(equalTo: section.leadingAnchor),
+            title.topAnchor.constraint(equalTo: section.topAnchor),
+
+            cardsStack.leadingAnchor.constraint(equalTo: section.leadingAnchor),
+            cardsStack.trailingAnchor.constraint(equalTo: section.trailingAnchor),
+            cardsStack.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 16),
+            cardsStack.bottomAnchor.constraint(equalTo: section.bottomAnchor),
+        ])
+
+        return section
+    }
+
+    private func makeCreatePrintSection() -> NSView {
+        let section = NSView()
+        section.translatesAutoresizingMaskIntoConstraints = false
+
+        let title = makeSectionTitle("Create & Print")
+        section.addSubview(title)
+
+        let features: [FeatureCardData] = [
+            FeatureCardData(title: "Scan File", subtitle: "Scan any document", accentColor: AppTheme.blue, symbolName: "scanner.fill"),
+            FeatureCardData(title: "Print Text", subtitle: "Type text and print", accentColor: AppTheme.purple, symbolName: "textformat"),
+            FeatureCardData(title: "Print Contacts", subtitle: "Print your contacts", accentColor: AppTheme.green, symbolName: "person.crop.rectangle.fill"),
+            FeatureCardData(title: "Print Website", subtitle: "Print any website", accentColor: AppTheme.teal, symbolName: "globe"),
+            FeatureCardData(title: "Draw & Print", subtitle: "Add drawings, text and more", accentColor: AppTheme.orange, symbolName: "paintpalette.fill"),
+            FeatureCardData(title: "OCR File", subtitle: "Scan and print text from images", accentColor: AppTheme.purple, symbolName: "doc.text.viewfinder"),
+        ]
+
+        let row1 = makeFeatureRow(features: Array(features[0..<3]))
+        let row2 = makeFeatureRow(features: Array(features[3..<6]))
+
+        let gridStack = NSStackView(views: [row1, row2])
+        gridStack.orientation = .vertical
+        gridStack.spacing = 16
+        gridStack.distribution = .fill
+        gridStack.translatesAutoresizingMaskIntoConstraints = false
+        section.addSubview(gridStack)
+
+        NSLayoutConstraint.activate([
+            title.leadingAnchor.constraint(equalTo: section.leadingAnchor),
+            title.topAnchor.constraint(equalTo: section.topAnchor),
+
+            gridStack.leadingAnchor.constraint(equalTo: section.leadingAnchor),
+            gridStack.trailingAnchor.constraint(equalTo: section.trailingAnchor),
+            gridStack.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 16),
+            gridStack.bottomAnchor.constraint(equalTo: section.bottomAnchor),
+        ])
+
+        return section
+    }
+
+    private func makeFeatureRow(features: [FeatureCardData]) -> NSStackView {
+        let row = NSStackView()
+        row.orientation = .horizontal
+        row.spacing = 20
+        row.distribution = .fillEqually
+        row.translatesAutoresizingMaskIntoConstraints = false
+
+        for feature in features {
+            row.addArrangedSubview(FeatureCardView(data: feature))
+        }
+
+        return row
+    }
 }
 
+private final class FlippedDocumentView: NSView {
+    override var isFlipped: Bool { true }
+}