Pārlūkot izejas kodu

Unify the home shell so sidebar, title bar, and content read as one surface.

Remove floating top-bar/sidebar card cues and use subtle internal dividers so the layout matches Zoom's continuous panel structure.

Made-with: Cursor
huzaifahayat12 3 mēneši atpakaļ
vecāks
revīzija
2f751d4e5f
1 mainītis faili ar 240 papildinājumiem un 97 dzēšanām
  1. 240 97
      zoom_app/ViewController.swift

+ 240 - 97
zoom_app/ViewController.swift

@@ -20,6 +20,14 @@ class ViewController: NSViewController {
     private let sidebarActiveBackground = NSColor(calibratedRed: 22 / 255, green: 23 / 255, blue: 26 / 255, alpha: 1)
     private let cardBackground = NSColor(calibratedRed: 20 / 255, green: 21 / 255, blue: 24 / 255, alpha: 1)
     private let secondaryCardBackground = NSColor(calibratedRed: 26 / 255, green: 28 / 255, blue: 33 / 255, alpha: 1)
+    private let appShellBackground = NSColor(calibratedRed: 13 / 255, green: 14 / 255, blue: 17 / 255, alpha: 1)
+    private let contentShellBackground = NSColor(calibratedRed: 14 / 255, green: 15 / 255, blue: 19 / 255, alpha: 1)
+    private let topStripBackground = NSColor(calibratedRed: 28 / 255, green: 30 / 255, blue: 36 / 255, alpha: 1)
+    private let searchPillBackground = NSColor.white.withAlphaComponent(0.06)
+    private let meetingCardBackground = NSColor(calibratedRed: 38 / 255, green: 43 / 255, blue: 58 / 255, alpha: 1)
+    private let titleBarControlBackground = NSColor.white.withAlphaComponent(0.04)
+    private let titleBarLightControlBackground = NSColor.white.withAlphaComponent(0.02)
+    private let appShellCornerRadius: CGFloat = 20
     private let accentBlue = NSColor(calibratedRed: 56 / 255, green: 132 / 255, blue: 255 / 255, alpha: 1)
     private let accentOrange = NSColor(calibratedRed: 241 / 255, green: 116 / 255, blue: 49 / 255, alpha: 1)
     private let primaryText = NSColor(calibratedWhite: 0.98, alpha: 1)
@@ -48,6 +56,11 @@ class ViewController: NSViewController {
     private var lastScrollEdgeRefreshAt = Date.distantPast
     private let meetingsRefreshInterval: TimeInterval = 8
     private let scrollRefreshCooldown: TimeInterval = 3
+    
+    private enum SidebarStyle {
+        case login
+        case home
+    }
 
     override func viewDidLoad() {
         super.viewDidLoad()
@@ -209,6 +222,10 @@ class ViewController: NSViewController {
         persistLoggedInState(false)
         showLoginView()
     }
+    
+    @objc private func topBarPlaceholderTapped() {
+        // Reserved for future titlebar control actions.
+    }
 
     private func startMeetingsAutoRefresh() {
         meetingsRefreshTimer?.invalidate()
@@ -520,7 +537,7 @@ class ViewController: NSViewController {
 
     private func makeLoginView() -> NSView {
         let root = NSView()
-        let sidebar = makeSidebar(items: ["Home", "Chat", "Phone", "Docs", "Whiteboards", "Clips", "More"], selected: "Home")
+        let sidebar = makeSidebar(items: ["Home", "Chat", "Phone", "Docs", "Whiteboards", "Clips", "More"], selected: "Home", style: .login)
         let content = NSView()
 
         root.addSubview(sidebar)
@@ -625,53 +642,91 @@ class ViewController: NSViewController {
 
     private func makeHomeView(profile: GoogleUserProfile?) -> NSView {
         let root = NSView()
-        let sidebar = makeSidebar(items: ["Home", "Meetings", "Chat", "Scheduler", "Hub", "More"], selected: "Home")
+        let shell = NSView()
+        shell.wantsLayer = true
+        shell.layer?.backgroundColor = appShellBackground.cgColor
+        shell.layer?.cornerRadius = appShellCornerRadius
+        shell.layer?.borderWidth = 1
+        shell.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
+        let sidebar = makeSidebar(items: ["Home", "Meetings", "Chat", "Scheduler", "Hub", "More"], selected: "Home", style: .home)
         let content = NSView()
+        content.wantsLayer = true
+        content.layer?.backgroundColor = NSColor.clear.cgColor
 
-        root.addSubview(sidebar)
-        root.addSubview(content)
+        root.addSubview(shell)
+        shell.addSubview(sidebar)
+        shell.addSubview(content)
+        shell.translatesAutoresizingMaskIntoConstraints = false
         sidebar.translatesAutoresizingMaskIntoConstraints = false
         content.translatesAutoresizingMaskIntoConstraints = false
 
         NSLayoutConstraint.activate([
-            sidebar.leadingAnchor.constraint(equalTo: root.leadingAnchor),
-            sidebar.topAnchor.constraint(equalTo: root.topAnchor),
-            sidebar.bottomAnchor.constraint(equalTo: root.bottomAnchor),
+            shell.leadingAnchor.constraint(equalTo: root.leadingAnchor, constant: 10),
+            shell.trailingAnchor.constraint(equalTo: root.trailingAnchor, constant: -10),
+            shell.topAnchor.constraint(equalTo: root.topAnchor, constant: 10),
+            shell.bottomAnchor.constraint(equalTo: root.bottomAnchor, constant: -10),
+            sidebar.leadingAnchor.constraint(equalTo: shell.leadingAnchor),
+            sidebar.topAnchor.constraint(equalTo: shell.topAnchor),
+            sidebar.bottomAnchor.constraint(equalTo: shell.bottomAnchor),
             sidebar.widthAnchor.constraint(equalToConstant: sidebarWidth),
             content.leadingAnchor.constraint(equalTo: sidebar.trailingAnchor),
-            content.trailingAnchor.constraint(equalTo: root.trailingAnchor),
-            content.topAnchor.constraint(equalTo: root.topAnchor),
-            content.bottomAnchor.constraint(equalTo: root.bottomAnchor)
+            content.trailingAnchor.constraint(equalTo: shell.trailingAnchor),
+            content.topAnchor.constraint(equalTo: shell.topAnchor),
+            content.bottomAnchor.constraint(equalTo: shell.bottomAnchor)
         ])
 
         let topBar = NSView()
         topBar.wantsLayer = true
-        topBar.layer?.backgroundColor = cardBackground.cgColor
-        topBar.layer?.cornerRadius = 12
-        topBar.layer?.borderWidth = 1
-        topBar.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
+        topBar.layer?.backgroundColor = topStripBackground.withAlphaComponent(0.88).cgColor
+        
+        let topBarDivider = NSView()
+        topBarDivider.wantsLayer = true
+        topBarDivider.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.06).cgColor
 
         let searchPill = NSView()
         searchPill.wantsLayer = true
-        searchPill.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.05).cgColor
-        searchPill.layer?.cornerRadius = 9
-        let search = makeLabel("Search meetings, people (\u{2318}E)", size: 13, color: mutedText, weight: .regular, centered: false)
-
-        let profileChip = NSView()
+        searchPill.layer?.backgroundColor = searchPillBackground.cgColor
+        searchPill.layer?.cornerRadius = 10
+        let search = makeLabel("Search (\u{2318}E)", size: 13, color: mutedText, weight: .regular, centered: true)
+        
+        let brandStack = NSStackView()
+        brandStack.orientation = .vertical
+        brandStack.spacing = 0
+        brandStack.alignment = .leading
+        let brandTop = makeLabel("zoom", size: 14, color: primaryText, weight: .semibold, centered: false)
+        let brandBottom = makeLabel("Workplace", size: 27, color: primaryText, weight: .bold, centered: false)
+        brandBottom.font = .systemFont(ofSize: 14, weight: .bold)
+        [brandTop, brandBottom].forEach { brandStack.addArrangedSubview($0) }
+        
+        let leftTopBarCluster = NSStackView()
+        leftTopBarCluster.orientation = .horizontal
+        leftTopBarCluster.spacing = 10
+        leftTopBarCluster.alignment = .centerY
+        let backButton = makeTopBarGlyphButton(symbol: "chevron.left", action: #selector(topBarPlaceholderTapped))
+        let forwardButton = makeTopBarGlyphButton(symbol: "chevron.right", action: #selector(topBarPlaceholderTapped))
+        let historyButton = makeTopBarGlyphButton(symbol: "clock.arrow.circlepath", action: #selector(topBarPlaceholderTapped))
+        [backButton, forwardButton, historyButton].forEach { leftTopBarCluster.addArrangedSubview($0) }
+        
+        let rightTopBarCluster = NSStackView()
+        rightTopBarCluster.orientation = .horizontal
+        rightTopBarCluster.spacing = 8
+        rightTopBarCluster.alignment = .centerY
+        let plusButton = makeTopBarGlyphButton(symbol: "plus", action: #selector(topBarPlaceholderTapped))
+        let notificationButton = makeTopBarGlyphButton(symbol: "bell", action: #selector(topBarPlaceholderTapped))
+        let appsButton = makeTopBarIconButton(symbol: "square.grid.2x2", action: #selector(topBarPlaceholderTapped))
+
+        let profileChip = NSButton(title: String((profile?.name ?? "H").prefix(1)).uppercased(), target: self, action: #selector(logoutTapped))
+        profileChip.isBordered = false
         profileChip.wantsLayer = true
-        profileChip.layer?.backgroundColor = accentBlue.withAlphaComponent(0.22).cgColor
-        profileChip.layer?.cornerRadius = 9
-        let name = makeLabel(profile?.name ?? "User", size: 13, color: primaryText, weight: .semibold, centered: false)
-        let logoutButton = NSButton(title: "Logout", target: self, action: #selector(logoutTapped))
-        logoutButton.isBordered = false
-        logoutButton.font = .systemFont(ofSize: 13, weight: .semibold)
-        logoutButton.contentTintColor = primaryText
-        logoutButton.wantsLayer = true
-        logoutButton.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.07).cgColor
-        logoutButton.layer?.cornerRadius = 8
+        profileChip.layer?.backgroundColor = accentBlue.withAlphaComponent(0.75).cgColor
+        profileChip.layer?.cornerRadius = 10
+        profileChip.contentTintColor = primaryText
+        profileChip.font = .systemFont(ofSize: 14, weight: .bold)
+        profileChip.toolTip = "Profile (click to logout)"
+        [plusButton, notificationButton, appsButton, profileChip].forEach { rightTopBarCluster.addArrangedSubview($0) }
 
         let welcome = makeLabel("Home", size: 15, color: secondaryText, weight: .medium, centered: false)
-        let timeTitle = makeLabel("--:--", size: 50, color: primaryText, weight: .bold, centered: true)
+        let timeTitle = makeLabel("--:--", size: 56, color: primaryText, weight: .bold, centered: true)
         let dateTitle = makeLabel("-", size: 16, color: secondaryText, weight: .regular, centered: true)
 
         let actions = NSStackView(views: [
@@ -688,14 +743,19 @@ class ViewController: NSViewController {
 
         let panel = NSView()
         panel.wantsLayer = true
-        panel.layer?.backgroundColor = secondaryCardBackground.cgColor
+        panel.layer?.backgroundColor = secondaryCardBackground.withAlphaComponent(0.94).cgColor
         panel.layer?.cornerRadius = 16
         panel.layer?.borderWidth = 1
         panel.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
+        
+        let panelHeaderStrip = NSView()
+        panelHeaderStrip.wantsLayer = true
+        panelHeaderStrip.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
+        panelHeaderStrip.layer?.cornerRadius = 12
 
         let todaysDateFormatter = DateFormatter()
         todaysDateFormatter.dateFormat = "EEEE, MMM d"
-        let panelHeader = makeLabel(todaysDateFormatter.string(from: Date()), size: 22, color: primaryText, weight: .semibold, centered: false)
+        let panelHeader = makeLabel(todaysDateFormatter.string(from: Date()), size: 21, color: primaryText, weight: .semibold, centered: false)
         let meetingsStatus = makeLabel("Upcoming meetings", size: 12, color: secondaryText, weight: .medium, centered: false)
         let noMeeting = makeLabel("No meetings scheduled for today.", size: 18, color: secondaryText, weight: .regular, centered: true)
         let meetingsScrollView = NSScrollView()
@@ -714,7 +774,7 @@ class ViewController: NSViewController {
         openRecordings.font = .systemFont(ofSize: 14, weight: .semibold)
         openRecordings.contentTintColor = primaryText
         openRecordings.wantsLayer = true
-        openRecordings.layer?.backgroundColor = NSColor(calibratedRed: 31 / 255, green: 33 / 255, blue: 39 / 255, alpha: 1).cgColor
+        openRecordings.layer?.backgroundColor = NSColor(calibratedRed: 36 / 255, green: 39 / 255, blue: 46 / 255, alpha: 1).cgColor
         openRecordings.layer?.cornerRadius = 11
         openRecordings.layer?.borderWidth = 1
         openRecordings.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
@@ -723,7 +783,7 @@ class ViewController: NSViewController {
         contentColumn.translatesAutoresizingMaskIntoConstraints = false
         content.addSubview(contentColumn)
 
-        [topBar, searchPill, search, profileChip, name, logoutButton, welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
+        [topBar, topBarDivider, brandStack, leftTopBarCluster, rightTopBarCluster, searchPill, search, welcome, timeTitle, dateTitle, actions, panel, panelHeaderStrip, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
             $0.translatesAutoresizingMaskIntoConstraints = false
             contentColumn.addSubview($0)
         }
@@ -735,64 +795,72 @@ class ViewController: NSViewController {
         NSLayoutConstraint.activate([
             contentColumn.topAnchor.constraint(equalTo: content.topAnchor),
             contentColumn.bottomAnchor.constraint(equalTo: content.bottomAnchor),
-            contentColumn.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 20),
-            contentColumn.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -20),
-
-            topBar.topAnchor.constraint(equalTo: contentColumn.topAnchor, constant: 12),
-            topBar.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 12),
-            topBar.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -12),
-            topBar.heightAnchor.constraint(equalToConstant: 50),
-
-            searchPill.leadingAnchor.constraint(equalTo: topBar.leadingAnchor, constant: 12),
+            contentColumn.leadingAnchor.constraint(equalTo: content.leadingAnchor),
+            contentColumn.trailingAnchor.constraint(equalTo: content.trailingAnchor),
+
+            topBar.topAnchor.constraint(equalTo: contentColumn.topAnchor),
+            topBar.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor),
+            topBar.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor),
+            topBar.heightAnchor.constraint(equalToConstant: 48),
+            topBarDivider.topAnchor.constraint(equalTo: topBar.bottomAnchor),
+            topBarDivider.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor),
+            topBarDivider.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor),
+            topBarDivider.heightAnchor.constraint(equalToConstant: 1),
+
+            brandStack.leadingAnchor.constraint(equalTo: topBar.leadingAnchor, constant: 12),
+            brandStack.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
+
+            leftTopBarCluster.leadingAnchor.constraint(equalTo: brandStack.trailingAnchor, constant: 18),
+            leftTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
+            rightTopBarCluster.trailingAnchor.constraint(equalTo: topBar.trailingAnchor, constant: -12),
+            rightTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
+
+            searchPill.centerXAnchor.constraint(equalTo: topBar.centerXAnchor),
             searchPill.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
             searchPill.heightAnchor.constraint(equalToConstant: 32),
             searchPill.widthAnchor.constraint(equalToConstant: 320),
+            searchPill.leadingAnchor.constraint(greaterThanOrEqualTo: leftTopBarCluster.trailingAnchor, constant: 12),
+            searchPill.trailingAnchor.constraint(lessThanOrEqualTo: rightTopBarCluster.leadingAnchor, constant: -12),
             search.leadingAnchor.constraint(equalTo: searchPill.leadingAnchor, constant: 12),
             search.trailingAnchor.constraint(equalTo: searchPill.trailingAnchor, constant: -12),
             search.centerYAnchor.constraint(equalTo: searchPill.centerYAnchor),
+            profileChip.widthAnchor.constraint(equalToConstant: 34),
+            profileChip.heightAnchor.constraint(equalToConstant: 34),
 
-            profileChip.trailingAnchor.constraint(equalTo: topBar.trailingAnchor, constant: -10),
-            profileChip.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
-            profileChip.heightAnchor.constraint(equalToConstant: 32),
-            profileChip.widthAnchor.constraint(greaterThanOrEqualToConstant: 92),
-            name.leadingAnchor.constraint(equalTo: profileChip.leadingAnchor, constant: 12),
-            name.trailingAnchor.constraint(equalTo: profileChip.trailingAnchor, constant: -12),
-            name.centerYAnchor.constraint(equalTo: profileChip.centerYAnchor),
-
-            logoutButton.trailingAnchor.constraint(equalTo: profileChip.leadingAnchor, constant: -10),
-            logoutButton.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
-            logoutButton.widthAnchor.constraint(equalToConstant: 76),
-            logoutButton.heightAnchor.constraint(equalToConstant: 32),
-
-            welcome.topAnchor.constraint(equalTo: topBar.bottomAnchor, constant: 18),
+            welcome.topAnchor.constraint(equalTo: topBar.bottomAnchor, constant: 22),
             welcome.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
 
-            timeTitle.topAnchor.constraint(equalTo: welcome.bottomAnchor, constant: 14),
+            timeTitle.topAnchor.constraint(equalTo: welcome.bottomAnchor, constant: 12),
             timeTitle.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
             dateTitle.topAnchor.constraint(equalTo: timeTitle.bottomAnchor, constant: 6),
             dateTitle.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
 
-            actions.topAnchor.constraint(equalTo: dateTitle.bottomAnchor, constant: 30),
+            actions.topAnchor.constraint(equalTo: dateTitle.bottomAnchor, constant: 28),
             actions.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
             actions.leadingAnchor.constraint(greaterThanOrEqualTo: contentColumn.leadingAnchor, constant: 18),
             actions.trailingAnchor.constraint(lessThanOrEqualTo: contentColumn.trailingAnchor, constant: -18),
-            actions.heightAnchor.constraint(equalToConstant: 96),
+            actions.heightAnchor.constraint(equalToConstant: 100),
 
-            panel.topAnchor.constraint(equalTo: actions.bottomAnchor, constant: 24),
-            panel.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 28),
-            panel.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -28),
-            panel.heightAnchor.constraint(equalToConstant: 300),
+            panel.topAnchor.constraint(equalTo: actions.bottomAnchor, constant: 22),
+            panel.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 26),
+            panel.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -26),
+            panel.heightAnchor.constraint(equalToConstant: 316),
             panel.bottomAnchor.constraint(lessThanOrEqualTo: contentColumn.bottomAnchor, constant: -20),
-
-            panelHeader.topAnchor.constraint(equalTo: panel.topAnchor, constant: 16),
-            panelHeader.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 18),
-            meetingsStatus.centerYAnchor.constraint(equalTo: panelHeader.centerYAnchor),
-            meetingsStatus.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -18),
+            
+            panelHeaderStrip.topAnchor.constraint(equalTo: panel.topAnchor, constant: 10),
+            panelHeaderStrip.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 10),
+            panelHeaderStrip.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -10),
+            panelHeaderStrip.heightAnchor.constraint(equalToConstant: 44),
+
+            panelHeader.centerYAnchor.constraint(equalTo: panelHeaderStrip.centerYAnchor),
+            panelHeader.leadingAnchor.constraint(equalTo: panelHeaderStrip.leadingAnchor, constant: 14),
+            meetingsStatus.centerYAnchor.constraint(equalTo: panelHeaderStrip.centerYAnchor),
+            meetingsStatus.trailingAnchor.constraint(equalTo: panelHeaderStrip.trailingAnchor, constant: -14),
             noMeeting.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 18),
             noMeeting.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -18),
             noMeeting.centerYAnchor.constraint(equalTo: panel.centerYAnchor),
 
-            meetingsScrollView.topAnchor.constraint(equalTo: panel.topAnchor, constant: 58),
+            meetingsScrollView.topAnchor.constraint(equalTo: panelHeaderStrip.bottomAnchor, constant: 10),
             meetingsScrollView.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
             meetingsScrollView.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
             meetingsScrollView.bottomAnchor.constraint(equalTo: openRecordings.topAnchor, constant: -14),
@@ -806,7 +874,7 @@ class ViewController: NSViewController {
             openRecordings.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
             openRecordings.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
             openRecordings.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
-            openRecordings.heightAnchor.constraint(equalToConstant: 38)
+            openRecordings.heightAnchor.constraint(equalToConstant: 40)
         ])
 
         timeLabel = timeTitle
@@ -839,14 +907,27 @@ class ViewController: NSViewController {
 
     // MARK: - Shared UI
 
-    private func makeSidebar(items: [String], selected: String) -> NSView {
+    private func makeSidebar(items: [String], selected: String, style: SidebarStyle = .login) -> NSView {
         let sidebar = NSView()
         sidebar.wantsLayer = true
-        sidebar.layer?.backgroundColor = sidebarBackground.cgColor
+        sidebar.layer?.backgroundColor = (style == .home ? appShellBackground.withAlphaComponent(0.98) : sidebarBackground).cgColor
+        if style == .home {
+            let divider = NSView()
+            divider.wantsLayer = true
+            divider.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.06).cgColor
+            divider.translatesAutoresizingMaskIntoConstraints = false
+            sidebar.addSubview(divider)
+            NSLayoutConstraint.activate([
+                divider.topAnchor.constraint(equalTo: sidebar.topAnchor),
+                divider.bottomAnchor.constraint(equalTo: sidebar.bottomAnchor),
+                divider.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor),
+                divider.widthAnchor.constraint(equalToConstant: 1)
+            ])
+        }
 
         let stack = NSStackView()
         stack.orientation = .vertical
-        stack.spacing = 16
+        stack.spacing = style == .home ? 12 : 16
         stack.alignment = .centerX
         stack.translatesAutoresizingMaskIntoConstraints = false
         sidebar.addSubview(stack)
@@ -856,46 +937,106 @@ class ViewController: NSViewController {
             row.translatesAutoresizingMaskIntoConstraints = false
             row.wantsLayer = true
             let selectedRow = item == selected
-            row.layer?.backgroundColor = selectedRow ? sidebarActiveBackground.cgColor : NSColor.clear.cgColor
-            row.layer?.cornerRadius = 10
-            row.widthAnchor.constraint(equalToConstant: 70).isActive = true
+            row.layer?.backgroundColor = selectedRow ? sidebarActiveBackground.withAlphaComponent(0.95).cgColor : NSColor.clear.cgColor
+            row.layer?.cornerRadius = style == .home ? 12 : 10
+            row.widthAnchor.constraint(equalToConstant: style == .home ? 68 : 70).isActive = true
 
-            let icon = makeLabel(selectedRow ? "⌂" : "◻︎", size: 15, color: primaryText, weight: .regular, centered: true)
-            let label = makeLabel(item, size: 11, color: selectedRow ? primaryText : secondaryText, weight: .regular, centered: true)
+            let icon = makeLabel(selectedRow ? "⌂" : "◻︎", size: style == .home ? 14 : 15, color: primaryText, weight: .regular, centered: true)
+            let label = makeLabel(item, size: style == .home ? 10 : 11, color: selectedRow ? primaryText : secondaryText, weight: .regular, centered: true)
             [icon, label].forEach {
                 $0.translatesAutoresizingMaskIntoConstraints = false
                 row.addSubview($0)
             }
             NSLayoutConstraint.activate([
-                icon.topAnchor.constraint(equalTo: row.topAnchor, constant: 10),
+                icon.topAnchor.constraint(equalTo: row.topAnchor, constant: style == .home ? 8 : 10),
                 icon.centerXAnchor.constraint(equalTo: row.centerXAnchor),
-                label.topAnchor.constraint(equalTo: icon.bottomAnchor, constant: 5),
+                label.topAnchor.constraint(equalTo: icon.bottomAnchor, constant: style == .home ? 4 : 5),
                 label.centerXAnchor.constraint(equalTo: row.centerXAnchor),
-                label.bottomAnchor.constraint(equalTo: row.bottomAnchor, constant: -8)
+                label.bottomAnchor.constraint(equalTo: row.bottomAnchor, constant: style == .home ? -7 : -8)
             ])
             stack.addArrangedSubview(row)
         }
+        
+        if style == .home {
+            let spacer = NSView()
+            spacer.translatesAutoresizingMaskIntoConstraints = false
+            spacer.heightAnchor.constraint(greaterThanOrEqualToConstant: 12).isActive = true
+            stack.addArrangedSubview(spacer)
+            
+            let settingsBadge = NSView()
+            settingsBadge.wantsLayer = true
+            settingsBadge.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
+            settingsBadge.layer?.cornerRadius = 12
+            settingsBadge.translatesAutoresizingMaskIntoConstraints = false
+            settingsBadge.widthAnchor.constraint(equalToConstant: 40).isActive = true
+            settingsBadge.heightAnchor.constraint(equalToConstant: 40).isActive = true
+            let gear = makeLabel("⚙︎", size: 14, color: secondaryText, weight: .regular, centered: true)
+            gear.translatesAutoresizingMaskIntoConstraints = false
+            settingsBadge.addSubview(gear)
+            NSLayoutConstraint.activate([
+                gear.centerXAnchor.constraint(equalTo: settingsBadge.centerXAnchor),
+                gear.centerYAnchor.constraint(equalTo: settingsBadge.centerYAnchor)
+            ])
+            stack.addArrangedSubview(settingsBadge)
+        }
 
         NSLayoutConstraint.activate([
-            stack.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: 18),
+            stack.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: style == .home ? 16 : 18),
             stack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 4),
             stack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor, constant: -4)
         ])
+        if style == .home {
+            stack.bottomAnchor.constraint(lessThanOrEqualTo: sidebar.bottomAnchor, constant: -18).isActive = true
+        }
 
         return sidebar
     }
+    
+    private func makeTopBarIconButton(symbol: String, action: Selector?) -> NSButton {
+        let button = NSButton(title: "", target: action == nil ? nil : self, action: action)
+        button.isBordered = false
+        button.wantsLayer = true
+        button.layer?.backgroundColor = titleBarControlBackground.cgColor
+        button.layer?.cornerRadius = 10
+        button.layer?.borderWidth = 1
+        button.layer?.borderColor = NSColor.white.withAlphaComponent(0.05).cgColor
+        button.contentTintColor = secondaryText
+        button.image = NSImage(systemSymbolName: symbol, accessibilityDescription: symbol)
+        button.imageScaling = .scaleProportionallyUpOrDown
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.widthAnchor.constraint(equalToConstant: 30).isActive = true
+        button.heightAnchor.constraint(equalToConstant: 30).isActive = true
+        return button
+    }
+    
+    private func makeTopBarGlyphButton(symbol: String, action: Selector?) -> NSButton {
+        let button = NSButton(title: "", target: action == nil ? nil : self, action: action)
+        button.isBordered = false
+        button.wantsLayer = true
+        button.layer?.backgroundColor = titleBarLightControlBackground.cgColor
+        button.layer?.cornerRadius = 9
+        button.layer?.borderWidth = 1
+        button.layer?.borderColor = NSColor.white.withAlphaComponent(0.03).cgColor
+        button.contentTintColor = secondaryText
+        button.image = NSImage(systemSymbolName: symbol, accessibilityDescription: symbol)
+        button.imageScaling = .scaleProportionallyUpOrDown
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.widthAnchor.constraint(equalToConstant: 26).isActive = true
+        button.heightAnchor.constraint(equalToConstant: 26).isActive = true
+        return button
+    }
 
     private func makeActionTile(title: String, symbol: String, color: NSColor, action: Selector? = nil) -> NSView {
         let root = NSView()
         root.translatesAutoresizingMaskIntoConstraints = false
-        root.widthAnchor.constraint(equalToConstant: 100).isActive = true
-        root.heightAnchor.constraint(equalToConstant: 96).isActive = true
+        root.widthAnchor.constraint(equalToConstant: 104).isActive = true
+        root.heightAnchor.constraint(equalToConstant: 100).isActive = true
 
         let iconButton = NSButton(title: "", target: action == nil ? nil : self, action: action)
         iconButton.isBordered = false
         iconButton.wantsLayer = true
         iconButton.layer?.backgroundColor = color.cgColor
-        iconButton.layer?.cornerRadius = 18
+        iconButton.layer?.cornerRadius = 20
         iconButton.layer?.shadowOpacity = 0.2
         iconButton.layer?.shadowRadius = 7
         iconButton.layer?.shadowOffset = NSSize(width: 0, height: -1)
@@ -911,9 +1052,9 @@ class ViewController: NSViewController {
         NSLayoutConstraint.activate([
             iconButton.topAnchor.constraint(equalTo: root.topAnchor),
             iconButton.centerXAnchor.constraint(equalTo: root.centerXAnchor),
-            iconButton.widthAnchor.constraint(equalToConstant: 62),
-            iconButton.heightAnchor.constraint(equalToConstant: 62),
-            label.topAnchor.constraint(equalTo: iconButton.bottomAnchor, constant: 9),
+            iconButton.widthAnchor.constraint(equalToConstant: 64),
+            iconButton.heightAnchor.constraint(equalToConstant: 64),
+            label.topAnchor.constraint(equalTo: iconButton.bottomAnchor, constant: 10),
             label.centerXAnchor.constraint(equalTo: root.centerXAnchor),
             label.bottomAnchor.constraint(equalTo: root.bottomAnchor)
         ])
@@ -923,10 +1064,12 @@ class ViewController: NSViewController {
     private func makeMeetingRowCard(_ meeting: ScheduledMeeting) -> NSView {
         let card = NSView()
         card.wantsLayer = true
-        card.layer?.backgroundColor = NSColor(calibratedRed: 35 / 255, green: 40 / 255, blue: 56 / 255, alpha: 1).cgColor
-        card.layer?.cornerRadius = 14
+        card.layer?.backgroundColor = meetingCardBackground.cgColor
+        card.layer?.cornerRadius = 13
+        card.layer?.borderWidth = 1
+        card.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
         card.translatesAutoresizingMaskIntoConstraints = false
-        card.heightAnchor.constraint(equalToConstant: 110).isActive = true
+        card.heightAnchor.constraint(equalToConstant: 116).isActive = true
 
         let dateFormatter = DateFormatter()
         dateFormatter.dateFormat = "EEE, MMM d"
@@ -936,7 +1079,7 @@ class ViewController: NSViewController {
         let endText = meeting.end.map { timeFormatter.string(from: $0) } ?? ""
         let range = endText.isEmpty ? startText : "\(startText) - \(endText)"
 
-        let title = makeLabel(meeting.title, size: 17, color: primaryText, weight: .semibold, centered: false)
+        let title = makeLabel(meeting.title, size: 26, color: primaryText, weight: .regular, centered: false)
         let detail = makeLabel("\(dateFormatter.string(from: meeting.start))\n\(range)", size: 14, color: secondaryText, weight: .regular, centered: false)
         detail.maximumNumberOfLines = 2
         let host = makeLabel("Host: \(meeting.host) • \(meeting.source)", size: 13, color: secondaryText, weight: .regular, centered: false)
@@ -947,15 +1090,15 @@ class ViewController: NSViewController {
         }
 
         NSLayoutConstraint.activate([
-            title.topAnchor.constraint(equalTo: card.topAnchor, constant: 12),
-            title.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
+            title.topAnchor.constraint(equalTo: card.topAnchor, constant: 11),
+            title.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 16),
             title.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -14),
 
-            detail.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 6),
+            detail.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 3),
             detail.leadingAnchor.constraint(equalTo: title.leadingAnchor),
             detail.trailingAnchor.constraint(equalTo: title.trailingAnchor),
 
-            host.topAnchor.constraint(equalTo: detail.bottomAnchor, constant: 6),
+            host.topAnchor.constraint(equalTo: detail.bottomAnchor, constant: 7),
             host.leadingAnchor.constraint(equalTo: title.leadingAnchor),
             host.trailingAnchor.constraint(equalTo: title.trailingAnchor)
         ])