/*
 * ============================================================================
 * Copyright (c) 2026 ATH SOLUTIONS (PTY) LTD. All rights reserved.
 * KwaZulu-Natal, Republic of South Africa.
 * ============================================================================
 *
 * @BEGIN Developer Log Header Block
 * @FILENAME: layout.css
 * @TITLE: PATHWRITE
 * @DESCRIPTION: App shell layout - sidebar, header, main content region, page-header pattern, mobile-responsive breakpoints, and app/auth footer. Load after base.css, before components/*.css.
 * @AUTHOR: Ary van der Pijl
 * @COMPANY: ATH SOLUTIONS (PTY) LTD
 * @WEBSITE: https://www.ath.solutions/
 * @EMAIL: info@ath.solutions
 * @COPYRIGHT: All Rights Reserved
 * @LICENSE: ATH SOLUTIONS - PROPRIETARY SOFTWARE LICENCE AGREEMENT (https://www.ath.solutions/documents/ath_solutions_software_licence_agreement.pdf)
 *
 * BEGIN CHANGELOG
 * @IMPORTANT NOTICE: Developers working on these files MUST update and maintain the Developers Change Log, failure to do is not an option:
 * !==================================================================================================================================================================
 * VERSION 1.0.10
 * - File Modified | Ary van der Pijl | 2026-09-03 | Gap Analysis v4.0 §4.0: added #sidebar-overlay's base display:none plus a .app-wrapper:has(.app-sidebar.mobile-open) #sidebar-overlay override inside the mobile breakpoint - replaces header.php's inline style="display:none!important" and fixes a real, separate bug found while removing it: no rule anywhere ever made this overlay visible, so the mobile tap-outside-to-close backdrop never actually appeared (app.js's click handlers only ever toggled .mobile-open on the sidebar itself). |
 * VERSION 1.0.9
 * - File Modified | Ary van der Pijl | 2026-09-03 | Gap Analysis v4.0 §4.2: .sidebar-section-label's opacity (.6) gave 3.43:1 contrast against --sidebar-bg, below WCAG 2.1 AA's 4.5:1 for normal text - one of the 2 named-but-unfixed color-contrast violations from the 2026-08-20 axe-core pass. Raised to .75 (4.79:1), same class of fix as VERSION 1.0.7's .app-footer-credit change below. |
 * VERSION 1.0.8
 * - File Modified | Ary van der Pijl | 2026-08-19 | Gap Analysis v2.0 Section 1 ("Avatar shown wherever user icon is used"): added .online-user-avatar img so the presence widget can render a real photo (cropped to a circle) instead of only initials. |
 * VERSION 1.0.7
 * - File Modified | Ary van der Pijl | 2026-08-18 | Gap Analysis follow-up (REQ-GAP-001 Section 12, accessibility spot-check): .app-footer-credit repointed from --color-text-subtle to --color-text-muted - the subtle token fails 4.5:1 text contrast on the surface colour and this class renders real readable text, not a decorative icon. |
 * VERSION 1.0.6
 * - File Modified | Ary van der Pijl | 2026-08-18 | Gap Analysis follow-up (REQ-GAP-001 Section 1, "online users indicator (stacked avatars)"): added .online-users-widget/.online-user-avatar/.online-users-overflow. |
 * VERSION 1.0.5
 * - File Modified | Ary van der Pijl | 2026-08-18 | Appearance & Branding P2 (ATH_PLATFORM_REQUIREMENTS.md section 1, "Add footer... with 'Developed by ATH SOLUTIONS (PTY) LTD' credit"): added .app-footer-credit - the footer already had copyright + logo, just not this literal credit phrase. |
 * VERSION 1.0.4
 * - File Modified | Ary van der Pijl | 2026-08-18 | Avatar Management P2 (ATH_PLATFORM_REQUIREMENTS.md section 1, "Fix avatar upload to display full-size avatar in top nav bar (not just small icon)"): .user-avatar's base size grew from 32px to 40px - the header dropdown trigger was already rendering the real avatar image (renderAvatar() in app.js), just too small to be recognisable, and below the 44x44 minimum touch-target guideline. |
 * VERSION 1.0.3
 * - File Modified | Ary van der Pijl | 2026-08-15 | Added .user-avatar--lg (80px, 32px font) - replaces an inline style="width:80px;height:80px;font-size:32px;border-radius:50%" (hard-constraint violation) on profile.php's large avatar preview. |
 * VERSION 1.0.2
 * - File Modified | Ary van der Pijl | 2026-08-06 | Phase 24: added a background/border-colour transition to sidebar and header so theme switches fade instead of snapping; added an accent-colour left border on the active nav item so the new per-user accent-colour preference has a visible, additive surface (doesn't retrofit any existing colour). |
 * VERSION 1.0.1
 * - File Modified | Ary van der Pijl | 2026-08-06 | Added .user-avatar img (object-fit: cover, overflow hidden on the parent) so an uploaded avatar image fills the circular avatar consistently in header/sidebar/table contexts (Phase 20 screen audit, avatar upload). |
 * VERSION 1.0.0
 * + File Created | Ary van der Pijl | 2026-08-06 | Extracted from main.css as part of the Phase 17 CSS architecture split (9-file hierarchy per STD-E). |
 * ==================================================================================================================================================================!
 * END CHANGELOG
 */

/* ─── App Shell ──────────────────────────────────────────────────────────── */

.app-wrapper {
  display: flex;
  min-height: 100vh;
}

/* ─── Sidebar ────────────────────────────────────────────────────────────── */

.app-sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--sidebar-width);
  background: var(--sidebar-bg);
  display: flex;
  flex-direction: column;
  z-index: var(--z-fixed);
  transition: width var(--transition-slow), background-color var(--transition-base);
  overflow-x: hidden;
}

.app-sidebar.collapsed {
  width: var(--sidebar-collapsed);
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5);
  height: var(--header-height);
  border-bottom: 1px solid var(--sidebar-border);
  text-decoration: none;
  overflow: hidden;
  white-space: nowrap;
}

.sidebar-logo img {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.sidebar-logo-text {
  font-size: var(--text-lg);
  font-weight: var(--fw-bold);
  color: #ffffff;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--space-4) 0;
  scrollbar-width: thin;
  scrollbar-color: var(--sidebar-border) transparent;
}

.sidebar-section-label {
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--sidebar-text);
  padding: var(--space-4) var(--space-5) var(--space-2);
  /* .6 gave 3.43:1 against --sidebar-bg (#0d0d0d), below WCAG 2.1 AA's 4.5:1 for normal text -
     Gap Analysis v4.0 §4.2. .75 gives 4.79:1, kept as low as possible above the threshold to
     preserve the de-emphasized look this label is meant to have. */
  opacity: .75;
  white-space: nowrap;
  overflow: hidden;
}

.app-sidebar.collapsed .sidebar-section-label {
  opacity: 0;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  margin: 2px var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--sidebar-text);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: all var(--transition-base);
  white-space: nowrap;
  overflow: hidden;
}

.nav-item:hover {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-text-hover);
  text-decoration: none;
}

.nav-item.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
  border-left: 3px solid var(--color-accent);
  padding-left: calc(var(--space-4) - 3px);
}

.nav-item .material-icons-round {
  font-size: 20px;
  flex-shrink: 0;
  width: 20px;
}

.nav-item-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-badge {
  margin-left: auto;
  background: rgba(255, 255, 255, .15);
  color: #fff;
  font-size: 10px;
  font-weight: var(--fw-semibold);
  padding: 2px 6px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.sidebar-footer {
  padding: var(--space-4) var(--space-4);
  border-top: 1px solid var(--sidebar-border);
}

.sidebar-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: none;
  color: var(--sidebar-text);
  cursor: pointer;
  transition: background var(--transition-base);
  margin-left: auto;
}

.sidebar-toggle:hover {
  background: var(--sidebar-hover-bg);
  color: #fff;
}

/* ─── Main ───────────────────────────────────────────────────────────────── */

.app-main {
  margin-left: var(--sidebar-width);
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  transition: margin-left var(--transition-slow);
}

.app-sidebar.collapsed~.app-main {
  margin-left: var(--sidebar-collapsed);
}

/* ─── Header ─────────────────────────────────────────────────────────────── */

.app-header {
  position: sticky;
  top: 0;
  height: var(--header-height);
  background: var(--header-bg);
  border-bottom: 1px solid var(--header-border);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-6);
  z-index: var(--z-sticky);
  box-shadow: var(--shadow-xs);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.header-breadcrumb {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.header-breadcrumb .breadcrumb-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.header-breadcrumb .breadcrumb-item.active {
  color: var(--color-text);
  font-weight: var(--fw-medium);
}

.header-breadcrumb .separator {
  color: var(--color-text-subtle);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.header-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: all var(--transition-base);
  position: relative;
}

.header-btn:hover {
  background: var(--color-surface-2);
  color: var(--color-text);
  border-color: var(--color-border);
}

.header-btn .material-icons-round {
  font-size: 20px;
}

.badge-dot {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 8px;
  height: 8px;
  background: var(--color-danger);
  border-radius: 50%;
  border: 2px solid var(--header-bg);
}

.user-menu-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid transparent;
  color: var(--color-text);
  cursor: pointer;
  transition: all var(--transition-base);
}

.user-menu-btn:hover {
  background: var(--color-surface-2);
  border-color: var(--color-border);
}

.user-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  flex-shrink: 0;
  overflow: hidden;
}

.user-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.user-avatar--lg {
  width: 80px;
  height: 80px;
  font-size: 32px;
}

/* ─── Online Users Widget (stacked avatars, Gap Analysis REQ-GAP-001 Section 1) ───────────── */

.online-users-widget {
  display: flex;
  align-items: center;
}

.online-user-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  border: 2px solid var(--color-surface);
  margin-left: -8px;
  cursor: pointer;
  flex-shrink: 0;
}

.online-user-avatar:first-child {
  margin-left: 0;
}

.online-user-avatar img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.online-users-overflow {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-surface-2);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  border: 2px solid var(--color-surface);
  margin-left: -8px;
  flex-shrink: 0;
}

.user-name {
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
}

/* ─── Page Content ───────────────────────────────────────────────────────── */

.app-content {
  flex: 1;
  padding: var(--space-6);
  max-width: 1400px;
  width: 100%;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  flex-wrap: wrap;
}

.page-title {
  font-size: var(--text-2xl);
  font-weight: var(--fw-bold);
  color: var(--color-text);
  margin: 0;
  line-height: var(--lh-tight);
}

.page-subtitle {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: var(--space-1) 0 0;
}

.page-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}


/* ─── Responsive ─────────────────────────────────────────────────────────── */

/* Base (hidden) state for header.php's #sidebar-overlay, was an inline style="display:none!important"
   (Gap Analysis v4.0 §4.0) - only ever shown inside the mobile breakpoint below. */
#sidebar-overlay {
  display: none;
}

@media (max-width: 768px) {
  .app-sidebar {
    transform: translateX(-100%);
    transition: transform var(--transition-slow);
  }

  .app-sidebar.mobile-open {
    transform: translateX(0);
  }

  /* #sidebar-overlay (header.php) starts display:none in markup, not a sibling of .app-sidebar -
     it's nested inside .app-main, itself .app-sidebar's sibling under .app-wrapper. Shown here via
     :has() on that shared ancestor, gated on the sidebar's own .mobile-open state (app.js's
     mobile-menu-btn/sidebar-overlay click handlers only ever toggle .mobile-open on the sidebar
     itself, never touch the overlay's visibility directly). Real bug found while removing the
     inline style="display:none!important" (Gap Analysis v4.0 §4.0): no rule ever made this
     overlay visible at all, so the tap-outside-to-close backdrop never appeared on mobile. */
  .app-wrapper:has(.app-sidebar.mobile-open) #sidebar-overlay {
    display: block;
  }

  .app-main {
    margin-left: 0;
  }

  .app-content {
    padding: var(--space-4);
  }

  .page-header {
    flex-direction: column;
  }
}


/* ─── Footer (portals, auth pages, brochure) ──────────────────────────────── */

.app-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-6);
  margin-top: auto;
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.app-footer-text {
  margin: 0;
}

.auth-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-6);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  text-align: center;
}

/* Footer ATH Solutions logo - sized down to a small icon */
.ath-footer-logo,
.brochure-footer-logo {
  height: 28px;
  width: auto;
  opacity: .75;
  transition: opacity var(--transition-fast);
}

.ath-footer-logo:hover,
.brochure-footer-logo:hover {
  opacity: 1;
}

.app-footer-credit {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-align: center;
}
