/* ============================================================
   ENCELA Cloud Computing Theme
   ============================================================ */

/* ── Custom Properties ──────────────────────────────────────── */
:root {
  --sky-900: #0a192f;
  --sky-800: #0f2744;
  --sky-700: #1e3a5f;
  --sky-600: #1d4ed8;
  --sky-500: #0ea5e9;
  --sky-400: #38bdf8;
  --sky-300: #7dd3fc;
  --sky-200: #bae6fd;
  --sky-100: #e0f2fe;
  --sky-50:  #f0f9ff;

  --glass-bg:     rgba(255,255,255,0.10);
  --glass-bg-md:  rgba(255,255,255,0.16);
  --glass-bg-lg:  rgba(255,255,255,0.22);
  --glass-border: rgba(255,255,255,0.28);
  --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
  --glass-blur:   blur(14px);

  --text-primary: #e2e8f0;
  --text-muted:   #94a3b8;
  --text-dark:    #1e293b;

  --accent:       #38bdf8;
  --accent-hover: #0ea5e9;
  --danger:       #f43f5e;
  --warning:      #f59e0b;
  --success:      #10b981;

  --radius-xl: 20px;
  --radius-lg: 14px;
  --radius-md: 10px;
  --radius-sm:  6px;

  --transition: 0.25s ease;
  --font: 'Segoe UI', system-ui, -apple-system, sans-serif;

  /* ── Appearance customisation ── */
  --card-icon-size: 2.8rem;
  --accent-glow:    rgba(56,189,248,0.2);
  --icon-glow:      rgba(56,189,248,0.5);

  /* ── Hover text — white on dark themes, dark on light themes ── */
  --hover-text: white;

  /* ── Ambient background glows (body::before) ── */
  --glow-a: rgba(14,165,233,0.18);
  --glow-b: rgba(56,189,248,0.12);
  --glow-c: rgba(29,78,216,0.08);

  /* ── Accent alpha tints — used for rings, shadows, tinted surfaces ── */
  --accent-a08: rgba(56,189,248,0.08);
  --accent-a12: rgba(56,189,248,0.12);
  --accent-a18: rgba(56,189,248,0.18);
  --accent-a30: rgba(56,189,248,0.30);
  --accent-a35: rgba(56,189,248,0.35);
  --accent-a50: rgba(14,165,233,0.50);
  --accent-a65: rgba(56,189,248,0.65);

  /* ── Layout clearance — single source of truth for fixed element heights ── */
  /* Navbar: 60px tall + iOS notch safe area                                  */
  --navbar-h: calc(60px + env(safe-area-inset-top, 0px));
  /* Footer approximate height on desktop (font-size 0.75rem, padding 0.5rem) */
  --footer-h: 2.2rem;
  /* Total fixed-top clearance = navbar only on desktop; overridden on mobile  */
  --top-h: var(--navbar-h);
  /* Usable page height between fixed top bar and fixed footer.
     100vh fallback first; 100dvh (dynamic viewport height) override for
     browsers that support it — 100dvh shrinks when mobile browser toolbars
     appear, preventing content from sliding under the footer on iOS/Android. */
  --usable-h: calc(100vh - var(--top-h) - var(--footer-h) - env(safe-area-inset-bottom, 0px));
  --usable-h: calc(100dvh - var(--top-h) - var(--footer-h) - env(safe-area-inset-bottom, 0px));
}

/* ── Reset & Base ───────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; height: 100%; }

/* ── Continuous Background ───────────────────────────────────── */
/* Using a fixed pseudo-element instead of background-attachment:fixed,
   which is broken on iOS Safari and many Android browsers. */
html::before {
  content: '';
  position: fixed;
  inset: 0;
  background: linear-gradient(160deg, var(--sky-900) 0%, var(--sky-800) 40%, var(--sky-700) 100%);
  z-index: -2;
  pointer-events: none;
}

body {
  font-family: var(--font);
  min-height: 100vh;
  color: var(--text-primary);
  position: relative;
  padding-bottom: var(--footer-h); /* clear fixed footer */
}

/* ── Auth pages (login, OTP, register, forgot-password, email-verify) ──
   These pages render no fixed navbar and manage their own full-viewport
   layout + footer clearance internally. The shared body padding above
   (navbar clearance on mobile via --top-h, and --footer-h at all widths)
   is meant for pages WITH a navbar; on auth pages it just adds dead space
   that pushes content below the fold and forces the whole page to scroll
   even when the viewport is tall enough. Cancel it here. */
body.auth-body {
  padding-top: 0;
  padding-bottom: 0;
}

/* ── Animated Sky Overlay ────────────────────────────────────── */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse 80% 50% at 20% -10%, var(--glow-a) 0%, transparent 60%),
    radial-gradient(ellipse 60% 40% at 80% 110%, var(--glow-b) 0%, transparent 55%),
    radial-gradient(ellipse 40% 30% at 50% 50%, var(--glow-c) 0%, transparent 70%);
  pointer-events: none;
  z-index: -1;
}

body > * { position: relative; z-index: 1; }

/* ── Floating Cloud Decorations ─────────────────────────────── */
.cloud-bg {
  position: fixed;
  pointer-events: none;
  z-index: 0;
  opacity: 0.07;
}
.cloud-bg::before,
.cloud-bg::after {
  content: '';
  position: absolute;
  background: white;
  border-radius: 50px;
}
.cloud-1 { width: 320px; height: 80px; top: 8%;  left: -5%; animation: drift 28s linear infinite; }
.cloud-2 { width: 200px; height: 55px; top: 22%; right: -5%; animation: drift 22s linear infinite reverse; }
.cloud-3 { width: 260px; height: 65px; top: 58%; left: -5%; animation: drift 35s linear infinite 5s; }
.cloud-4 { width: 180px; height: 50px; top: 75%; right: -5%; animation: drift 25s linear infinite reverse 8s; }

.cloud-bg::before { width: 60%; height: 100%; top: -30%; left: 20%; }
.cloud-bg::after  { width: 45%; height: 80%;  top: -20%; left: 10%; }

@keyframes drift {
  from { transform: translateX(-120px); }
  to   { transform: translateX(calc(100vw + 120px)); }
}

/* ── Navbar ─────────────────────────────────────────────────── */
.navbar {
  display: flex;
  align-items: center;
  padding: env(safe-area-inset-top) 1.25rem 0;
  height: calc(60px + env(safe-area-inset-top));
  background: color-mix(in srgb, var(--sky-900) 85%, transparent);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--glass-border);
  position: sticky;
  top: 0;
  z-index: 300;
  gap: 0.75rem;
}

/* ── Three-section navbar layout ─────────────────────────── */
.navbar-left {
  flex: 1;
  display: flex;
  align-items: center;
  min-width: 0;
}

.navbar-center {
  flex: 1.4;
  display: flex;
  justify-content: center;
  align-items: center;
}

.navbar-right {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
}

.navbar-brand {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  text-decoration: none;
  font-weight: 800;
  font-size: clamp(0.72rem, 3.5vw, 1.2rem);
  color: var(--accent);
  letter-spacing: 0.5px;
  text-shadow: 0 0 18px var(--accent-a50);
  white-space: nowrap;
  min-width: 0;
  flex-shrink: 1;
}

.navbar-brand .brand-icon {
  font-size: 1.6rem;
  line-height: 1;
}

/* Scale the injected SVG logo down on narrow screens */
.navbar-brand svg {
  width: clamp(28px, 6vw, 44px) !important;
  height: clamp(26px, 5.5vw, 40px) !important;
  flex-shrink: 0;
}


/* Legacy navbar-links: hidden after JS restructures; kept for PHP rendering */
.navbar-links {
  display: none;
}

.navbar-user { display: none; }

/* ── Universal search bar (navbar center + mobile row) ───── */
.nav-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  max-width: 380px;
}

.nav-search-input {
  width: 100%;
  padding: 0.38rem 0.75rem 0.38rem 2.1rem;
  background: rgba(0,0,0,0.35);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: 0.82rem;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  font-family: var(--font);
}

.nav-search-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-a12);
}

.nav-search-icon {
  position: absolute;
  left: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  font-size: 0.78rem;
  pointer-events: none;
  line-height: 1;
}

/* Mobile search row: SVG icon is a flex sibling (not overlaid), reset absolute offsets */
.navbar-search-row .nav-search-icon {
  display: block;
  position: relative;
  top: auto;
  left: auto;
  transform: none;
  flex-shrink: 0;
  color: var(--text-muted);
  pointer-events: none;
}

.user-search-dropdown {
  display: none;
  /* position:fixed escapes the navbar's backdrop-filter stacking context.
     The navbar (backdrop-filter + sticky + z-index:300) caps any child's
     effective page-level z-index at 300, causing fixed panels (hamburger
     panel at z-index:700) and even the navbar avatar to render on top of
     the dropdown. Fixed positioning places the dropdown directly in the
     root stacking context at z-index:9999, above everything. */
  position: fixed;
  top: var(--navbar-h);
  left: 50%;
  transform: translateX(-50%);
  width: 380px;
  max-width: calc(100vw - 2rem);
  background: #1e293b !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border: 1px solid rgba(148,163,184,0.2);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0,0,0,0.7);
  z-index: 9999;
}

.user-search-dropdown.open { display: block; }

.usd-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.9rem;
  cursor: pointer;
  transition: background 0.12s;
  text-decoration: none;
  color: inherit;
}

.usd-item:hover { background: var(--accent-a12); }

.usd-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--glass-bg-md);
  border: 1px solid var(--glass-border);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem; font-weight: 700;
  color: var(--sky-300);
  overflow: hidden;
}

.usd-avatar img { width: 100%; height: 100%; object-fit: cover; }
.usd-info { flex: 1; min-width: 0; }
.usd-name { font-size: 0.85rem; font-weight: 600; color: var(--text-primary); }
.usd-meta { font-size: 0.72rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.usd-badge { font-size: 0.67rem; font-weight: 700; padding: 0.1rem 0.42rem; border-radius: 999px; flex-shrink: 0; }
.usd-badge.admin    { background: rgba(251,191,36,0.15); color: var(--warning); border: 1px solid rgba(251,191,36,0.25); }
.usd-badge.standard { background: rgba(148,163,184,0.1); color: var(--text-muted); border: 1px solid var(--glass-border); }
.usd-empty { padding: 0.7rem 0.9rem; font-size: 0.82rem; color: var(--text-muted); }
.usd-email-hint { line-height: 1.45; font-size: 0.8rem; border-top: 1px solid var(--glass-border); }


/* ── User Menu Dropdown (avatar-only button) ─────────────────── */
.user-menu {
  position: relative;
}

.user-menu-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 2px solid var(--glass-border);
  border-radius: 50%;
  padding: 2px;
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition);
  flex-shrink: 0;
}

.user-menu-btn:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-a18);
}

.user-menu-name   { display: none; }
.user-menu-caret  { display: none; }

.user-menu-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 200px;
  background: var(--sky-900);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--glass-shadow);
  z-index: 700;
  overflow: hidden;
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.user-menu.open .user-menu-dropdown {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.user-menu-dropdown a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 1rem;
  color: var(--text-primary);
  text-decoration: none;
  font-size: 0.88rem;
  transition: background var(--transition), color var(--transition);
}

.user-menu-dropdown a:hover {
  background: var(--glass-bg-md);
  color: var(--accent);
}

.user-menu-sep {
  height: 1px;
  background: var(--glass-border);
  margin: 0.25rem 0;
}

/* Cover photo banner at the top of the avatar dropdown */
.user-menu-cover {
  height: 76px;
  background: linear-gradient(135deg, var(--sky-700, #0369a1), var(--accent, #0ea5e9));
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
}
.user-menu-cover-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: none; /* shown via JS onload only */
}

.user-menu-header {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  padding: 0.5rem 1rem 0.9rem;
  border-bottom: 1px solid var(--glass-border);
}
.umav-header-ring {
  border: 2px solid var(--sky-500);
  border-radius: 50%;
  flex-shrink: 0;
  overflow: hidden;
  display: flex;
  position: relative;
  z-index: 1;
  margin-top: -28px; /* overlap bottom half into cover banner */
}
.user-menu-header-name {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--sky-100);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.user-menu-dropdown button {
  display: flex; align-items: center; gap: 0.6rem;
  width: 100%; padding: 0.65rem 1rem;
  background: transparent; border: none; border-radius: 0;
  font-size: 0.88rem; font-family: var(--font); font-weight: 400;
  color: var(--text-primary); text-align: left;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.user-menu-dropdown button:hover { background: var(--glass-bg-md); }
.user-menu-logout { color: #fda4af !important; }
.user-menu-logout:hover { background: rgba(244,63,94,0.15) !important; color: #fff !important; }

/* ── Page Layout ─────────────────────────────────────────────── */
.page-wrapper {
  max-width: 1400px;
  margin: 0 auto;
  padding: 2rem 1.5rem;
  min-height: calc(100vh - var(--navbar-h));
  display: flex;
  flex-direction: column;
}

.page-title {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 1.5rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.page-title .title-icon { font-size: 1.8rem; }

/* ── Glass Cards ─────────────────────────────────────────────── */
.card {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  padding: 1.75rem;
  box-shadow: var(--glass-shadow);
  transition: transform var(--transition), box-shadow var(--transition);
}

.card:hover { transform: translateY(-2px); box-shadow: 0 12px 40px rgba(0,0,0,0.4); }

.card-sm { padding: 1.25rem; border-radius: var(--radius-lg); }

/* ── Module Card Grid ────────────────────────────────────────── */
.module-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
  margin-top: 1rem;
}

.module-card {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  padding: 2rem 1.5rem;
  text-align: center;
  text-decoration: none;
  color: var(--text-primary);
  transition: all 0.3s cubic-bezier(0.34,1.56,0.64,1);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.module-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--glass-bg-md), transparent);
  opacity: 0;
  transition: opacity var(--transition);
}

.module-card:hover {
  transform: translateY(-6px) scale(1.02);
  border-color: var(--accent);
  box-shadow: 0 16px 48px var(--accent-glow), var(--glass-shadow);
  color: var(--hover-text);
}

.module-card:hover::before { opacity: 1; }

.module-card .card-icon {
  font-size: var(--card-icon-size);
  line-height: 1;
  filter: drop-shadow(0 2px 8px var(--icon-glow));
  transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1);
}
.module-card .card-icon svg {
  width: 1em;
  height: 1em;
}

.module-card:hover .card-icon { transform: scale(1.15) translateY(-3px); }

.module-card .card-label {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--sky-200);
}

.module-card:hover .card-label { color: var(--hover-text); }

.module-card .card-desc {
  font-size: 0.78rem;
  color: var(--text-muted);
  line-height: 1.4;
  text-align: center;
}

.module-card:hover .card-desc { color: var(--text-muted); }

/* ── Auth / Login ────────────────────────────────────────────── */
.auth-page {
  min-height: 100vh;
  /* 100vh on mobile is calculated against the browser's tallest possible
     viewport (address bar hidden), taller than what's actually visible —
     the card ends up centered in a box bigger than the real screen, which
     pushes it down and forces an unwanted scroll. 100dvh tracks the real,
     currently-visible viewport; kept as a second declaration (not the only
     one) so browsers without dvh support just keep the 100vh value above. */
  min-height: 100dvh;
  display: flex;
  /* "safe center" centers the card when it fits, but falls back to
     start-alignment when the card is TALLER than the viewport — plain
     "center" would still center an overflowing card, pushing equal empty
     space above it while cutting off content below (worse: you'd have to
     scroll through that wasted top space just to reach the cut-off part). */
  align-items: safe center;
  justify-content: center;
  padding: 2rem;
  overflow-y: auto;
}

.auth-card {
  width: 100%;
  max-width: 440px;
  background: var(--glass-bg-md);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  padding: 2.5rem;
  box-shadow: var(--glass-shadow);
  animation: slideUp 0.4s ease;
}

.auth-logo {
  text-align: center;
  margin-bottom: 2rem;
}

.auth-logo .logo-icon { font-size: 3.5rem; display: block; line-height: 1; }

.auth-logo h1 {
  font-size: 1.75rem;
  font-weight: 800;
  color: var(--accent);
  margin-top: 0.5rem;
  letter-spacing: -0.5px;
}

.auth-logo p {
  font-size: 0.9rem;
  color: var(--text-muted);
  margin-top: 0.25rem;
}

@keyframes slideUp {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Forms ───────────────────────────────────────────────────── */
.form-group {
  margin-bottom: 1.25rem;
}

.form-group label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--sky-200);
  margin-bottom: 0.4rem;
  letter-spacing: 0.3px;
}

.form-group input,
.form-group textarea,
.form-group select {
  width: 100%;
  background: var(--glass-bg);
  border: 1.5px solid var(--glass-border);
  border-radius: var(--radius-md);
  padding: 0.7rem 1rem;
  font-size: 0.95rem;
  color: var(--text-primary);
  font-family: var(--font);
  transition: border-color var(--transition), background var(--transition), box-shadow var(--transition);
  outline: none;
}

.form-group input::placeholder,
.form-group textarea::placeholder {
  color: var(--text-muted);
}

.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
  border-color: var(--accent);
  background: var(--accent-a08);
  box-shadow: 0 0 0 3px var(--accent-a18);
}

.form-group textarea {
  resize: vertical;
  min-height: 120px;
}

/* ── Password visibility toggle ─────────────────────────────── */
.pw-wrap {
  position: relative;
  width: 100%;
}
.pw-wrap input {
  padding-right: 2.6rem !important;
  box-sizing: border-box !important;
  width: 100% !important;
}
.pw-toggle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 2.6rem;
  z-index: 2;
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  transition: color 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.pw-toggle:hover,
.pw-toggle:focus  { color: var(--accent); outline: none; }
.pw-toggle svg    { display: block; pointer-events: none; flex-shrink: 0; }

/* ── Buttons ─────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.65rem 1.5rem;
  border: none;
  border-radius: var(--radius-md);
  font-size: 0.95rem;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  touch-action: manipulation;
  transition: all var(--transition);
  text-decoration: none;
  white-space: nowrap;
}

.btn-primary {
  background: linear-gradient(135deg, var(--sky-500), var(--sky-600));
  color: white;
  box-shadow: 0 4px 15px var(--accent-a35);
}
.btn-primary:hover {
  background: linear-gradient(135deg, var(--sky-400), var(--sky-500));
  box-shadow: 0 6px 20px var(--accent-a50);
  transform: translateY(-1px);
  color: white;
}

.btn-secondary {
  background: var(--glass-bg-md);
  border: 1px solid var(--glass-border);
  color: var(--text-primary);
}
.btn-secondary:hover {
  background: var(--glass-bg-lg);
  color: var(--text-primary);
}

.btn-cancel {
  background: transparent;
  color: var(--text-primary);
  border: 1.5px solid var(--glass-border);
  padding: 0.45rem 1rem;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: 0.9rem;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.btn-cancel:hover {
  background: rgba(255,255,255,0.08);
  border-color: var(--text-muted);
}
[data-theme="white"] .btn-cancel {
  border-color: rgba(0,0,0,0.25);
  color: #1e293b;
}
[data-theme="white"] .btn-cancel:hover {
  background: rgba(0,0,0,0.05);
  border-color: rgba(0,0,0,0.4);
}

.btn-danger {
  background: rgba(244,63,94,0.15);
  border: 1px solid rgba(244,63,94,0.35);
  color: #fda4af;
}
.btn-danger:hover {
  background: rgba(244,63,94,0.28);
  color: var(--hover-text);
}

.btn-success {
  background: rgba(16,185,129,0.18);
  border: 1px solid rgba(16,185,129,0.4);
  color: #6ee7b7;
}
.btn-success:hover {
  background: rgba(16,185,129,0.32);
  color: var(--hover-text);
}

.btn-full { width: 100%; }
.btn-sm   { padding: 0.4rem 0.9rem; font-size: 0.85rem; }
.btn-icon { padding: 0.5rem; border-radius: var(--radius-sm); }
.btn:disabled,
.btn[disabled] {
  opacity: 0.42;
  cursor: not-allowed;
  pointer-events: none;
}

/* ── Back button ─────────────────────────────────────────────── */
.encela-back-btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0;
  background: transparent;
  border: none;
  color: var(--accent);
  text-decoration: none;
  font-size: 0.84rem; font-weight: 600;
  cursor: pointer; outline: none; font-family: inherit; line-height: 1;
}
.encela-back-btn:hover { color: var(--sky-300); }
/* Idle: whole icon breathes */
.encela-back-icon {
  width: 28px; height: 28px; flex-shrink: 0;
  animation: back-breathe 2.5s ease-in-out infinite;
}
@keyframes back-breathe {
  0%, 100% { opacity: 1;   transform: scale(1);    }
  50%       { opacity: 0.5; transform: scale(0.88); }
}
/* Hover: icon nudges left + glows; overrides idle animation */
.encela-back-btn:hover .encela-back-icon {
  animation: back-nudge 0.45s ease-out forwards;
  filter: drop-shadow(0 0 7px var(--accent-a65));
}
@keyframes back-nudge {
  0%   { transform: translateX(0);    }
  35%  { transform: translateX(-6px); }
  100% { transform: translateX(0);    }
}

/* ── Alerts ──────────────────────────────────────────────────── */
.alert {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-md);
  font-size: 0.9rem;
  margin-bottom: 1rem;
  border: 1px solid transparent;
}

.alert-error   { background: rgba(244,63,94,0.12);  border-color: rgba(244,63,94,0.3);  color: #fda4af; }
.alert-success { background: rgba(16,185,129,0.12); border-color: rgba(16,185,129,0.3); color: #6ee7b7; }
.alert-info    { background: var(--accent-a12); border-color: var(--accent-a30); color: var(--sky-200); }
.alert-warn    { background: rgba(245,158,11,0.12); border-color: rgba(245,158,11,0.3); color: #fcd34d; }

/* Opt-in: wrap a conditionally-rendered .alert in this to reserve roughly
   one line's worth of space, so the page doesn't visibly jump when the
   alert appears/disappears (e.g. via data-auto-dismiss). Only applies
   where a page adds this wrapper class -- doesn't affect any existing
   .alert usage that doesn't opt in. */
.alert-slot { min-height: 3.75rem; }
.alert-slot > .alert:last-child { margin-bottom: 0; }

/* White theme: saturate alert text so it's readable on light backgrounds */
[data-theme="white"] .alert-error   { color: #b91c1c; background: rgba(244,63,94,0.08);  }
[data-theme="white"] .alert-success { color: #15803d; background: rgba(16,185,129,0.08); }
[data-theme="white"] .alert-warn    { color: #b45309; background: rgba(245,158,11,0.08); }
[data-theme="white"] .alert-info    { color: #0369a1; }

/* ── Tables ──────────────────────────────────────────────────── */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.cloud-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.cloud-table thead th {
  background: var(--accent-a12);
  color: var(--sky-300);
  font-weight: 600;
  padding: 0.85rem 1rem;
  text-align: left;
  border-bottom: 1px solid var(--glass-border);
  white-space: nowrap;
}

.cloud-table tbody tr {
  border-bottom: 1px solid rgba(255,255,255,0.06);
  transition: background var(--transition);
}

.cloud-table tbody tr:hover { background: var(--glass-bg); }

.cloud-table td {
  padding: 0.75rem 1rem;
  color: var(--text-primary);
  vertical-align: middle;
}

.cloud-table td a { color: var(--accent); text-decoration: none; }
.cloud-table td a:hover { color: var(--sky-200); text-decoration: underline; }

/* ── Split Layout (sidebar + main) ──────────────────────────── */
.split-layout {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 1.5rem;
  flex: 1;
}

.split-layout .sidebar { display: flex; flex-direction: column; gap: 1rem; }
.split-layout .main-panel { overflow: hidden; }

/* ── File Manager ────────────────────────────────────────────── */
.file-row {
  display: grid;
  grid-template-columns: 2rem 1fr 140px 80px 48px;
  align-items: center;
  gap: 0.75rem;
  padding: 0.65rem 1rem;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.file-row:hover { background: var(--glass-bg); }

.file-row .file-icon { font-size: 1.2rem; text-align: center; }
.file-row .file-name { font-size: 0.92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row.is-dir .file-name { color: var(--sky-300); font-weight: 600; }
.file-row .file-meta { color: var(--text-muted); font-size: 0.82rem; }

/* ── Upload Progress ─────────────────────────────────────────── */
.progress-bar-wrap {
  height: 8px;
  background: rgba(255,255,255,0.1);
  border-radius: 4px;
  overflow: hidden;
  margin-top: 0.5rem;
}

.progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--sky-500), var(--sky-400));
  border-radius: 4px;
  transition: width 0.2s ease;
  width: 0%;
}

/* ── Storage Bar ─────────────────────────────────────────────── */
.storage-bar-wrap {
  height: 12px;
  background: rgba(255,255,255,0.1);
  border-radius: 6px;
  overflow: hidden;
  margin: 0.5rem 0;
}

.storage-bar-fill {
  height: 100%;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--sky-500), var(--sky-400));
  transition: width 0.6s ease;
}

.storage-bar-fill.warn  { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
.storage-bar-fill.crit  { background: linear-gradient(90deg, #f43f5e, #fb7185); }

/* ── Breadcrumb / PWD ────────────────────────────────────────── */
.pwd-bar {
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
  font-family: 'Consolas', 'Courier New', monospace;
  color: var(--sky-300);
  word-break: break-all;
}

/* ── IDE ─────────────────────────────────────────────────────── */
.ide-layout {
  display: grid;
  grid-template-columns: 1fr 340px;
  grid-template-rows: auto 1fr;
  gap: 1rem;
  flex: 1;
  min-height: 0;
}

.ide-editor-wrap,
.ide-output-wrap {
  background: rgba(0,0,0,0.35);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.ide-panel-label {
  background: rgba(255,255,255,0.05);
  padding: 0.5rem 1rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--glass-border);
}

.ide-textarea {
  flex: 1;
  width: 100%;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-primary);
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 0.92rem;
  padding: 1rem;
  resize: none;
  line-height: 1.6;
}

.ide-textarea::placeholder { color: var(--text-muted); }

.ide-output-frame {
  flex: 1;
  border: none;
  background: transparent;
  width: 100%;
  min-height: 200px;
}

/* ── Forum ───────────────────────────────────────────────────── */
.thread-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-radius: var(--radius-lg);
  border: 1px solid transparent;
  transition: all var(--transition);
  cursor: pointer;
  text-decoration: none;
  color: var(--text-primary);
}

.thread-row:hover {
  background: var(--glass-bg);
  border-color: var(--glass-border);
  color: white;
}

.thread-row .thread-title { font-weight: 600; font-size: 0.95rem; color: var(--sky-200); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.thread-row .thread-meta  { font-size: 0.8rem;  color: var(--text-muted); margin-top: 0.2rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.thread-row .thread-badge {
  background: var(--accent-a12);
  border: 1px solid var(--accent-a30);
  color: var(--sky-300);
  font-size: 0.75rem;
  padding: 0.2rem 0.6rem;
  border-radius: 20px;
  white-space: nowrap;
}

/* ── Stat Cards ──────────────────────────────────────────────── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px,1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.stat-card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  text-align: center;
}

.stat-card .stat-value {
  font-size: 2rem;
  font-weight: 800;
  color: var(--accent);
  line-height: 1;
}

.stat-card .stat-label {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-top: 0.35rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* ── Footer ──────────────────────────────────────────────────── */
.footer {
  position: fixed !important;
  bottom: 0 !important; left: 0; right: 0;
  z-index: 1000;
  background: color-mix(in srgb, var(--sky-900) 95%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid rgba(255,255,255,0.06);
  text-align: center;
  /* Two-declaration safe-area pattern: the first line is the fixed fallback
     for all browsers; the second overrides it on browsers that support env().
     On devices with no physical safe area env(safe-area-inset-bottom) is 0px,
     so the result is identical to the fallback.  On notched/home-indicator
     devices the inset is added on top of the base padding.
     Critically this avoids max() — iOS Safari has a long-standing engine bug
     where max() containing env() fails to re-evaluate its resolved value
     across repeated orientation changes, causing the computed padding to
     accumulate on each portrait↔landscape switch.  calc() + env() alone does
     not trigger the bug and recomputes correctly on every style recalc. */
  padding: 0.5rem 1rem;
  padding-bottom: 0.5rem;
  padding-bottom: calc(0.5rem + env(safe-area-inset-bottom));
  color: var(--text-muted);
  font-size: 0.75rem;
  line-height: 1.4;
  /* Prevent the copyright text from ever wrapping to a second line — the
     primary cause of the footer changing height on portrait↔landscape rotation.
     At 0.75rem the text is ~350px wide; on narrow portrait viewports the
     available width is only ~366px, so it wraps at accessibility text sizes.
     nowrap + overflow:hidden locks the footer to a single rendered line. */
  white-space: nowrap;
  overflow: hidden;
}
.footer p { margin: 0; } /* neutralise default <p> margins */
@media (max-width: 480px) {
  /* Same two-declaration safe-area pattern as the base rule — see comment
     above.  Avoids max() + env() to prevent the iOS Safari accumulation bug. */
  .footer {
    font-size: 0.68rem;
    padding: 0.35rem 0.75rem;
    padding-bottom: 0.35rem;
    padding-bottom: calc(0.35rem + env(safe-area-inset-bottom));
    background: var(--sky-900);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}
@media (max-height: 500px) {
  /* Landscape phone — same two-declaration pattern; identical values to the
     portrait rule above so the footer renders at the same height in both
     orientations. */
  .footer {
    font-size: 0.68rem;
    padding: 0.35rem 0.75rem;
    padding-bottom: 0.35rem;
    padding-bottom: calc(0.35rem + env(safe-area-inset-bottom));
    background: var(--sky-900);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* ── Utilities ───────────────────────────────────────────────── */
.text-accent   { color: var(--accent); }
.text-muted    { color: var(--text-muted); }
.text-danger   { color: #fda4af; }
.text-success  { color: #6ee7b7; }
.text-center   { text-align: center; }
.mt-1 { margin-top: 0.5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.5rem; }
.mb-1 { margin-bottom: 0.5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 1.5rem; }
.flex { display: flex; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.gap-1 { gap: 0.5rem; }
.gap-2 { gap: 1rem; }
.w-full { width: 100%; }
.hidden { display: none !important; }
.scrollable { overflow-y: auto; }
.mono { font-family: 'Consolas', 'Courier New', monospace; }

/* ── Scrollbar Styling ───────────────────────────────────────── */

/* Firefox */
* { scrollbar-width: thin; scrollbar-color: var(--accent-a35) rgba(255,255,255,0.04); }

/* Webkit (Chrome, Edge, Safari) */
::-webkit-scrollbar              { width: 6px; height: 6px; }
::-webkit-scrollbar-track        { background: rgba(255,255,255,0.04); border-radius: 99px; }
::-webkit-scrollbar-track:hover  { background: rgba(255,255,255,0.07); }
::-webkit-scrollbar-thumb        { background: var(--accent-a35); border-radius: 99px;
                                    border: 1px solid var(--accent-a12); }
::-webkit-scrollbar-thumb:hover  { background: var(--accent-a65); border-color: var(--accent-a30); }
::-webkit-scrollbar-thumb:active { background: var(--accent); }
::-webkit-scrollbar-corner       { background: transparent; }

/* ── Selection ───────────────────────────────────────────────── */
::selection { background: var(--accent-a30); color: var(--hover-text); }


/* ── Hamburger button (always visible) ───────────────────────── */
.nav-waffle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  color: var(--text-primary);
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.nav-waffle:hover {
  background: var(--glass-bg-md);
  border-color: var(--accent);
  color: var(--accent);
}
.nav-waffle.active {
  background: color-mix(in srgb, var(--accent) 12%, var(--glass-bg));
  border-color: var(--accent);
  color: var(--accent);
}

/* ── App launcher panel (floating dropdown) ─────────────────── */
.nav-menu-panel {
  position: fixed;
  top: calc(var(--navbar-h) + 6px);
  right: 1rem; left: auto;
  width: 304px;
  height: 360px;
  display: flex;
  flex-direction: column;
  background: color-mix(in srgb, var(--sky-900) 98%, transparent);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  padding: 0.85rem 0.55rem 1rem;
  z-index: 700;
  transform: scale(0.95) translateY(-8px);
  transform-origin: top right;
  opacity: 0;
  visibility: hidden;
  transition: transform 0.18s ease, opacity 0.18s ease, visibility 0s linear 0.18s;
  box-shadow: 0 8px 40px rgba(0,0,0,0.55);
}
.nav-menu-panel.open {
  transform: scale(1) translateY(0);
  opacity: 1;
  visibility: visible;
  transition: transform 0.18s ease, opacity 0.18s ease, visibility 0s linear 0s;
}

/* ── Launcher icon grid ──────────────────────────────────────── */
.launcher-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.1rem;
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  align-content: start;
}
.launcher-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 0.2rem;
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: background 0.15s;
}
.launcher-tile:hover { background: rgba(255,255,255,0.07); }
[data-theme="white"] .launcher-tile:hover { background: rgba(14,165,233,0.08); }
.launcher-icon {
  width: 52px; height: 52px;
  border-radius: 50%;
  position: relative;
  flex-shrink: 0;
  font-size: 1.3rem;
}
/* Center SVG content without flex so absolutely positioned badge
   is not shifted by align-items in flex-parent browsers */
.launcher-icon > svg {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  display: block;
}
.launcher-label {
  font-size: 0.69rem;
  color: var(--text-muted);
  text-align: center;
  line-height: 1.25;
  max-width: 60px;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  word-break: break-word;
}
.launcher-tile:hover .launcher-label { color: var(--text-primary); }

/* Chat unread badge on launcher icon */
.ham-chat-badge {
  position: absolute;
  top: 0; right: 0;
  /* translate(50%, -50%) centres the badge ON the corner of .launcher-icon's
     padding box.  Using top/right:-3px instead placed the centre 7 px inside
     the visual circle because .launcher-icon has a 1.5 px border (border-box),
     shrinking the padding box by 1.5 px per side and making the badge look like
     an interior decoration rather than a corner notification. */
  transform: translate(50%, -50%);
  background: var(--accent);
  color: #04121f;            /* white on the light accent was ~2:1; dark text is >9:1 on every theme accent */
  font-size: 0.6875rem;
  font-weight: 700;
  min-width: 18px; height: 18px;
  padding: 0 0.28rem;
  border-radius: 999px;
  text-align: center;
  line-height: 16px;
  border: 2px solid var(--sky-900);
  pointer-events: none;
}

/* ── Notification Bell ───────────────────────────────────────── */
.notif-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.notif-btn {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  color: var(--text-muted);
  cursor: pointer; padding: 0; flex-shrink: 0;
  transition: color var(--transition), background var(--transition), border-color var(--transition);
}
.notif-btn:hover,
.notif-btn.has-unread { color: var(--accent); }
.notif-btn:hover { background: var(--glass-bg-md); border-color: var(--accent); }

.notif-badge {
  position: absolute; top: -5px; right: -5px;
  background: #e11d48;       /* was #f43f5e: white-on-it was 3.7:1; this is 4.7:1 */
  color: #fff;
  font-size: 0.6875rem; font-weight: 800;
  min-width: 18px; height: 18px;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 3px;
  border: 2px solid var(--sky-900);
  line-height: 1;
  pointer-events: none;
  z-index: 1;
}

.notif-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 340px;
  max-height: 420px;
  background: color-mix(in srgb, var(--sky-900) 98%, transparent);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 8px 32px rgba(0,0,0,0.55);
  z-index: 700;
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0.2s;
  /* overflow:hidden clips items at border-radius but suppresses touch-scroll in
     child elements on iOS Safari. overflow:clip provides the same visual clipping
     without creating a scroll-container boundary, so the inner list can scroll. */
  overflow: hidden;
}
@supports (overflow: clip) {
  .notif-panel { overflow: clip; }
}
.notif-panel.open {
  opacity: 1; visibility: visible; transform: translateY(0);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0s;
}

.notif-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.7rem 1rem 0.55rem;
  border-bottom: 1px solid var(--glass-border);
  flex-shrink: 0;
}
.notif-panel-title {
  font-size: 0.75rem; font-weight: 700; color: var(--text-primary);
  text-transform: uppercase; letter-spacing: 0.07em;
}
.notif-header-actions {
  display: flex; align-items: center; gap: 0.35rem;
}
.notif-header-sep {
  color: var(--text-muted); font-size: 0.7rem; opacity: 0.5; user-select: none;
}
.notif-mark-all {
  background: none; border: none; cursor: pointer;
  font-size: 0.73rem; color: var(--accent); font-weight: 600;
  padding: 0; transition: opacity 0.15s;
}
.notif-mark-all:hover { opacity: 0.75; }
.notif-clear-all {
  background: none; border: none; cursor: pointer;
  font-size: 0.73rem; color: var(--danger, #ef4444); font-weight: 600;
  padding: 0; transition: opacity 0.15s;
}
.notif-clear-all:hover { opacity: 0.75; }

.notif-list {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  -webkit-overflow-scrolling: touch; /* inertia scroll on older iOS */
  overscroll-behavior: contain;      /* stop scroll chaining to page body */
  touch-action: pan-y;               /* allow vertical touch panning */
}

.notif-empty {
  text-align: center; padding: 2rem 1rem;
  color: var(--text-muted); font-size: 0.85rem;
}

.notif-item {
  display: flex; align-items: flex-start; gap: 0.6rem;
  padding: 0.65rem 1rem;
  text-decoration: none; color: inherit;
  border-bottom: 1px solid rgba(255,255,255,0.04);
  transition: background var(--transition);
  cursor: pointer;
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: rgba(255,255,255,0.05); }
.notif-item.unread { background: var(--accent-a08); }
.notif-item.unread:hover { background: var(--accent-a12); }

.notif-item-dismiss {
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: 1rem; line-height: 1;
  padding: 0 0 0 0.4rem; flex-shrink: 0; opacity: 0;
  transition: opacity 0.15s, color 0.15s;
  align-self: center;
}
.notif-item:hover .notif-item-dismiss { opacity: 0.5; }
.notif-item-dismiss:hover { opacity: 1 !important; color: var(--danger, #ef4444); }

.notif-item-icon {
  font-size: 1.05rem; line-height: 1; flex-shrink: 0; margin-top: 0.08rem;
}
.notif-item-content { flex: 1; min-width: 0; }
.notif-item-title {
  font-size: 0.82rem; font-weight: 600; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.3;
}
.notif-item.unread .notif-item-title { color: var(--text-primary); }
.notif-item-body {
  font-size: 0.75rem; color: var(--text-muted);
  margin-top: 0.1rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.3;
  opacity: 0.75;
}
.notif-item-time {
  font-size: 0.68rem; color: var(--text-muted); margin-top: 0.2rem; opacity: 0.6;
}
.notif-item-arrow {
  font-size: 1rem; color: var(--text-muted); opacity: 0.4;
  margin-left: auto; padding-left: 0.3rem; flex-shrink: 0; align-self: center;
  line-height: 1;
}
.notif-item:hover .notif-item-arrow { opacity: 0.8; color: var(--accent); }

/* Transparent backdrop — sits under the panel but above page content.
   Covers the full viewport so tapping anywhere outside the panel (including
   the full-width mobile panel area) fires the click that closes it. */
.notif-backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 299;
  background: transparent;
}
.notif-backdrop.active { display: block; }

/* Notification detail dialog */
.notif-detail-overlay {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0);
  backdrop-filter: none;
  transition: background 0.2s ease;
  padding: 1rem;
}
.notif-detail-overlay.visible {
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(3px);
}
.notif-detail-box {
  background: color-mix(in srgb, var(--sky-900,#0c1a2e) 97%, transparent);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 16px 48px rgba(0,0,0,0.65);
  padding: 1.75rem 1.5rem 1.5rem;
  width: 100%; max-width: 400px;
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  transform: translateY(12px); opacity: 0;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.notif-detail-overlay.visible .notif-detail-box {
  transform: translateY(0); opacity: 1;
}
.notif-detail-icon {
  font-size: 2.2rem; line-height: 1; margin-bottom: 0.25rem;
}
.notif-detail-title {
  font-size: 1rem; font-weight: 700; color: var(--text-primary);
  text-align: center; line-height: 1.35;
}
.notif-detail-body {
  font-size: 0.875rem; color: var(--text-muted);
  text-align: center; line-height: 1.55;
  white-space: pre-wrap; word-break: break-word;
}
.notif-detail-time {
  font-size: 0.72rem; color: var(--text-muted); opacity: 0.55; margin-top: 0.15rem;
}
.notif-detail-btn-row {
  display: flex; gap: 0.65rem; margin-top: 0.75rem; justify-content: center; flex-wrap: wrap;
}
.notif-detail-close-btn { min-width: 100px; }
.notif-detail-view-btn  { min-width: 100px; }

@media (max-width: 600px) {
  .notif-panel {
    position: fixed;
    top: 60px;
    left: 0;
    right: 0;
    width: 100%;
    max-height: calc(100vh - 70px);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    z-index: 700;
  }
}

/* Badge on module cards (dashboard + any page with .module-card) */
.module-notif-badge {
  position: absolute; top: 0.55rem; right: 0.55rem;
  background: #e11d48; color: #fff;
  font-size: 0.6875rem; font-weight: 800;
  min-width: 20px; height: 20px;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 4px;
  border: 2px solid color-mix(in srgb, var(--sky-900) 85%, transparent);
  line-height: 1; pointer-events: none; z-index: 5;
}

/* Badge on hamburger panel links */
.pan-notif-badge {
  position: absolute;
  top: 0; right: 0;
  /* Same corner-centering fix as .ham-chat-badge above */
  transform: translate(50%, -50%);
  z-index: 1;
  background: #f43f5e; color: #fff;
  font-size: 0.6rem; font-weight: 800;
  min-width: 17px; height: 17px;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 4px;
  border: 2px solid var(--sky-900);
  pointer-events: none;
  line-height: 1;
}

/* ── Mobile search row (below navbar on small screens) ───────── */
.navbar-search-row {
  display: none;
  position: fixed;
  top: var(--navbar-h); left: 0; right: 0;
  background: color-mix(in srgb, var(--sky-900) 95%, transparent);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--glass-border);
  padding: 0.45rem 1rem;
  z-index: 299;
  align-items: center;
  gap: 0.5rem;
}

/* Legacy mobile-nav-panel kept for compatibility */
.mobile-nav-panel { display: none !important; }

/* ── Responsive ──────────────────────────────────────────────── */
@media (max-width: 900px) {
  .split-layout { grid-template-columns: 1fr; }
  .ide-layout   { grid-template-columns: 1fr; }
  .module-grid  { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .file-row { grid-template-columns: 2rem 1fr 100px 48px; }
  .thread-row { grid-template-columns: 1fr auto; }
  .thread-row .thread-badge:last-child { display: none; }
}

@media (max-width: 640px) {
  /* On mobile: navbar is fixed (60px) + search row below it (44px) = 104px total top clearance */
  :root {
    --top-h: calc(60px + env(safe-area-inset-top, 0px) + 44px);
    /* Also subtract safe-area-inset-bottom so fixed-height containers (drive, IDE, etc.)
       don't extend into the home-indicator / Android nav-bar zone */
    /* 100dvh = dynamic viewport height; updates as browser toolbars show/hide,
       so fixed-height drive/IDE containers never overflow into the browser chrome. */
    --usable-h: calc(100dvh - var(--top-h) - var(--footer-h) - env(safe-area-inset-bottom, 0px));
  }

  /* Navbar: fixed at top on mobile; search row below; safe-area for notch/Dynamic Island */
  .navbar { padding: env(safe-area-inset-top) 0.85rem 0; height: calc(60px + env(safe-area-inset-top)); position: fixed; top: 0; left: 0; right: 0; }
  .navbar-center { display: none; }          /* hide center search; use row instead */
  .navbar-search-row { display: flex; }      /* show search row */
  body { padding-top: var(--top-h); }
  .page-wrapper { min-height: calc(100vh - var(--top-h)); }

  /* Nav menu panel: full-width below both bars.
     Base rule has width:304px which must be overridden — left:0+right:0 alone
     does not stretch a fixed element that already has an explicit width. */
  .nav-menu-panel { top: var(--top-h); width: 100%; max-width: unset; left: 0; right: 0; border-radius: 0 0 var(--radius-lg) var(--radius-lg); padding-left: 0.85rem; padding-right: 0.85rem; }
  .launcher-grid { grid-template-columns: repeat(4, 1fr); }
  .launcher-tile { padding-left: 0; padding-right: 0; }
  .launcher-label { max-width: none; }

  /* Mobile search dropdown: overrides desktop centering; stretches full-width
     and anchors below the search row. position:fixed is already set by the
     base .user-search-dropdown rule. */
  #ms-search-dd {
    top: calc(var(--top-h) + 8px);
    left: 0;
    right: 0;
    width: auto;
    transform: none;
    min-width: unset;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  }

  /* User menu dropdown: fixed so it's above everything, compact right-aligned */
  .user-menu-dropdown {
    position: fixed;
    top: calc(var(--navbar-h) + 6px);
    right: 12px;
    left: auto;
    min-width: 220px;
    border-radius: var(--radius-lg);
  }

  /* Layout */
  .page-wrapper { padding: 1rem; }
  .module-grid  { grid-template-columns: 1fr; }
  .stat-grid    { grid-template-columns: repeat(2, 1fr); }
  .split-layout { grid-template-columns: 1fr; }
  .card         { padding: 1.25rem; }
  .module-card  { padding: 1.5rem 1rem; }

  /* Auth — tightened vertical spacing so longer forms (registration,
     with its CAPTCHA block) actually fit within a real mobile viewport
     instead of needing scroll to reach the submit button / footer. */
  .auth-page  { padding: 1rem; }
  .auth-card  { padding: 1.5rem 1.25rem; }
  .auth-logo  { margin-bottom: 1rem; }
  .auth-logo .logo-icon { font-size: 2.25rem; }
  .auth-logo h1 { font-size: 1.4rem; margin-top: 0.3rem; }
  .form-group { margin-bottom: 0.9rem; }

  /* Tables: horizontal scroll */
  .cloud-table { font-size: 0.82rem; }
  .cloud-table thead th,
  .cloud-table td { padding: 0.6rem 0.65rem; }

  /* File manager */
  .file-row { grid-template-columns: 2rem 1fr 48px; }
  .file-row .file-meta { display: none; }

  /* Thread rows — single column, no badge */
  .thread-row { grid-template-columns: 1fr; gap: 0.5rem; }
  .thread-row .thread-badge { display: none; }

  /* Page title */
  .page-title { font-size: 1.25rem; }
}

/* ── Collapsible sidebar ─────────────────────────────────────────── */
.sidebar-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  border: 1px solid var(--glass-border);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  transition: color var(--transition), background var(--transition), border-color var(--transition);
  align-self: flex-end;
}
.sidebar-toggle-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--glass-bg);
}

.nav-icon  { flex-shrink: 0; font-size: 1.05rem; }
.nav-label { overflow: hidden; white-space: nowrap; }

/* Hide labels + section headers when minimized */
.sidebar-minimized .nav-label,
.sidebar-minimized .section-label { display: none; }

/* Center icons in sidebar links when minimized */
.sidebar-minimized .mgmt-sidebar a,
.sidebar-minimized .forum-sidebar a {
  justify-content: center;
  padding: 0.55rem 0;
  position: relative;
}
.sidebar-minimized .sidebar-toggle-btn { align-self: center; }

/* Tooltip on icon-only links when minimized */
.sidebar-minimized .mgmt-sidebar a:hover::after,
.sidebar-minimized .forum-sidebar a:hover::after {
  content: attr(title);
  position: absolute;
  left: calc(100% + 6px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--sky-800);
  border: 1px solid var(--glass-border);
  color: var(--text-primary);
  padding: 0.3rem 0.65rem;
  border-radius: var(--radius-sm);
  font-size: 0.8rem;
  white-space: nowrap;
  z-index: 200;
  pointer-events: none;
}

/* IDE right panel — hide panels when minimized */
.sidebar-minimized .ide-side .ide-panel { display: none; }
.sidebar-minimized .ide-side {
  justify-content: flex-start;
  padding-top: 0.75rem;
  align-items: center;
}
.sidebar-minimized .ide-side .sidebar-toggle-btn { align-self: auto; }

/* ── Course tab bar (mobile only) ───────────────────────────────── */
.course-tab-bar {
  display: none;
  background: color-mix(in srgb, var(--sky-900) 90%, transparent);
  border-bottom: 1px solid var(--glass-border);
  flex-shrink: 0;
}
.course-tab {
  flex: 1;
  padding: 0.55rem 0.5rem;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  font-size: 0.88rem;
  cursor: pointer;
  font-family: var(--font);
  transition: color var(--transition), border-color var(--transition);
}
.course-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

@media (max-width: 700px) {
  .course-tab-bar { display: flex; }
  .course-frames {
    position: relative;
  }
  .course-frames .toc-frame,
  .course-frames .content-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }
  .course-frames .toc-frame {
    display: none;
    border-right: none;
    width: 100%;
  }
  .course-frames.show-toc .toc-frame  { display: block; }
  .course-frames.show-toc .content-frame { display: none; }
}

/* ── Dashboard hero — small phones ─────────────────────────────── */
@media (max-width: 480px) {
  .dash-hero { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
  .dash-hero-greeting { font-size: 1.3rem; }
  .page-title { font-size: 1.15rem; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── Rack / generic page — small phones ─────────────────────────── */
@media (max-width: 480px) {
  .rack-wrap { padding: 1rem 0.75rem 2rem; }
  .rack-header { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
  .rack-controls { flex-direction: column; align-items: flex-start; }
}

/* ── Global touch-target minimum ───────────────────────────────── */
@media (max-width: 768px) {
  /* Minimum tap target size per WCAG / Apple HIG */
  .btn, .navbar-links a, .navbar-links button,
  .module-card, .sort-btn { min-height: 44px; }

  /* Buttons inside cards go full-width on narrow screens */
  .auth-card .btn-full { font-size: 1rem; padding: 0.75rem 1rem; }

  /* Prevent horizontal page scroll on any page */
  body { overflow-x: hidden; }

  /* Info grid in user view stacks to single column on phones */
  .info-grid { grid-template-columns: 1fr !important; }

  /* Thread meta wraps gracefully */
  .thread-meta { flex-wrap: wrap !important; }
}

/* ============================================================
   ENCELA — Colour Themes
   Override the shared CSS custom properties on <html> so every
   component that uses var(--sky-*) / var(--accent) inherits
   the new palette automatically.
   ============================================================ */

/* ── Nebula (Purple) ── */
html[data-theme="nebula"] {
  --sky-900: #0f0a1e; --sky-800: #180d35; --sky-700: #2d1a5e;
  --sky-600: #5b21b6; --sky-500: #7c3aed; --sky-400: #8b5cf6;
  --sky-300: #a78bfa; --sky-200: #c4b5fd; --sky-100: #ede9fe;
  --sky-50:  #f5f3ff;
  --accent:       #a78bfa;
  --accent-hover: #8b5cf6;
  --accent-glow:  rgba(167,139,250,0.22);
  --icon-glow:    rgba(167,139,250,0.55);
}

/* ── Forest (Emerald) ── */
html[data-theme="forest"] {
  --sky-900: #052e16; --sky-800: #064e3b; --sky-700: #065f46;
  --sky-600: #047857; --sky-500: #059669; --sky-400: #10b981;
  --sky-300: #34d399; --sky-200: #6ee7b7; --sky-100: #d1fae5;
  --sky-50:  #ecfdf5;
  --accent:       #34d399;
  --accent-hover: #10b981;
  --accent-glow:  rgba(52,211,153,0.22);
  --icon-glow:    rgba(52,211,153,0.55);
}

/* ── Sunset (Amber / Orange) ── */
html[data-theme="sunset"] {
  --sky-900: #1c0a00; --sky-800: #2d1500; --sky-700: #451a03;
  --sky-600: #92400e; --sky-500: #b45309; --sky-400: #d97706;
  --sky-300: #f59e0b; --sky-200: #fde68a; --sky-100: #fef3c7;
  --sky-50:  #fffbeb;
  --accent:       #fb923c;
  --accent-hover: #f97316;
  --accent-glow:  rgba(251,146,60,0.22);
  --icon-glow:    rgba(251,146,60,0.55);
}

/* ── Rose (Pink) ── */
html[data-theme="rose"] {
  --sky-900: #1a0012; --sky-800: #2d001f; --sky-700: #4c0029;
  --sky-600: #9d174d; --sky-500: #be185d; --sky-400: #db2777;
  --sky-300: #ec4899; --sky-200: #fbcfe8; --sky-100: #fce7f3;
  --sky-50:  #fff0f7;
  --accent:       #f472b6;
  --accent-hover: #ec4899;
  --accent-glow:  rgba(244,114,182,0.22);
  --icon-glow:    rgba(244,114,182,0.55);
}

/* ── Midnight (monochrome dark) ── */
html[data-theme="midnight"] {
  --sky-900: #060606; --sky-800: #111111; --sky-700: #1c1c1c;
  --sky-600: #2a2a2a; --sky-500: #3a3a3a; --sky-400: #555555;
  --sky-300: #888888; --sky-200: #b0b0b0; --sky-100: #d8d8d8;
  --sky-50:  #f0f0f0;
  --accent:       #94a3b8;
  --accent-hover: #64748b;
  --accent-glow:  rgba(148,163,184,0.18);
  --icon-glow:    rgba(148,163,184,0.4);
}

/* ============================================================
   Dashboard Icon Sizes
   ============================================================ */
html[data-icon-size="small"]  { --card-icon-size: 1.6rem; }
html[data-icon-size="medium"] { --card-icon-size: 2.8rem; }
html[data-icon-size="large"]  { --card-icon-size: 4rem; }

/* ============================================================
   Toolbar hover tooltips (image previewer toolbars)
   Fast, theme-matched replacement for the browser's slow/unstyled
   native `title` tooltip. Wired up by initToolbarTooltips() in
   cloud-theme.js — scoped to elements inside [data-tooltip-root]
   containers only (currently: Photos' shared lightbox #lightbox and
   Drive's #modal-preview / #gallery-lb previewers), so it never
   touches the many other `title` attributes used elsewhere in the
   app. A real title/aria-label always stays in the DOM as the
   accessible name and as a no-JS fallback — see cloud-theme.js.
   ============================================================ */
.ct-tooltip {
  position: fixed;
  z-index: 100000;
  pointer-events: none;
  background: color-mix(in srgb, var(--sky-900) 94%, black 6%);
  border: 1px solid var(--glass-border);
  color: var(--text-primary);
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.3;
  padding: 0.32rem 0.62rem;
  border-radius: var(--radius-sm);
  box-shadow: 0 6px 18px rgba(0,0,0,0.45);
  white-space: normal;
  max-width: min(70vw, 240px);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.ct-tooltip.ct-tooltip-visible {
  opacity: 1;
  transform: translateY(0);
}
.ct-tooltip::after {
  content: '';
  position: absolute;
  width: 8px; height: 8px;
  left: var(--ct-tip-arrow-x, 50%);
  margin-left: -4px;
  background: color-mix(in srgb, var(--sky-900) 94%, black 6%);
  border-right: 1px solid var(--glass-border);
  border-bottom: 1px solid var(--glass-border);
  bottom: -5px;
  transform: rotate(45deg);
}
.ct-tooltip.ct-tooltip-below::after {
  bottom: auto; top: -5px;
  border-right: none; border-bottom: none;
  border-left: 1px solid var(--glass-border);
  border-top: 1px solid var(--glass-border);
}

/* ── Custom video controls bar ─────────────────────────────── */
/* Wraps <video> + the custom controls bar so both are positioned
 * relative to the same container without affecting page layout. */
/* ── Inline video wrapper (lesson pages, blog posts, drivePublic) ── */
/* Controls sit BELOW the video so no content is obscured. */
.vid-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: #000;
  line-height: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
}
.vid-wrap video {
  display: block;
  width: 100%;
  height: auto;
  flex-shrink: 0;
}
/* Fullscreen: let the video fill the wrapper and preserve aspect ratio */
.vid-wrap:-webkit-full-screen,
.vid-wrap:fullscreen { background: #000; }
.vid-wrap:-webkit-full-screen video,
.vid-wrap:fullscreen video { flex: 1; height: 0; min-height: 0; object-fit: contain; }

/* Controls bar — two-row layout.
   Row 1: full-width seek scrubber.
   Row 2: play | time | mute | volume | gear | fullscreen. */
.vid-ctrl {
  display: flex;
  flex-direction: column;
  padding: 6px 10px 8px;
  background: rgba(0, 0, 0, .88);
  opacity: 1;
  transition: opacity .25s;
  user-select: none;
  -webkit-user-select: none;
  z-index: 5;
  box-sizing: border-box;
  flex-shrink: 0;
  line-height: 1;
}
/* In modal/overlay mode (media-preview-stage.js): the video must fill the
   wrapper height so object-fit:contain can letterbox it rather than spilling
   past the wrapper and being clipped by overflow:hidden.
   Specificity 0,2,1 beats the base .vid-wrap video rule (0,1,1), so this
   correctly overrides height:auto and flex-shrink:0 for the modal case only. */
.vid-wrap.vid-overlay video {
  height: 100%;
  flex: 1;          /* grow + shrink; overrides flex-shrink:0 from base rule */
  min-height: 0;    /* flex minimum: allow shrink below intrinsic height    */
  object-fit: contain; /* letterbox — never crop */
}
/* In modal/overlay mode (media-preview-stage.js): controls overlay the video bottom */
.vid-wrap.vid-overlay .vid-ctrl {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, .88));
}
.vid-wrap.vid-overlay.ctrl-hidden .vid-ctrl {
  opacity: 0;
  pointer-events: none;
}
/* In fullscreen, always overlay regardless of mode */
.vid-wrap:-webkit-full-screen .vid-ctrl,
.vid-wrap:fullscreen .vid-ctrl {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, .88));
}
/* Row 1: scrubber spans full width */
.vid-ctrl-progress {
  width: 100%;
  height: 4px;
  accent-color: var(--accent);
  cursor: pointer;
  margin-bottom: 4px;
  flex-shrink: 0;
}
/* Row 2: button row */
.vid-ctrl-row2 {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: nowrap;
}
/* Spacer pushes right-side buttons to the far right */
.vid-ctrl-spacer { flex: 1; }
/* Base style for every icon button */
.vid-ctrl-btn {
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  padding: 4px 5px;
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
  border-radius: 3px;
  transition: background .15s;
}
.vid-ctrl-btn:hover { background: rgba(255, 255, 255, .15); }
.vid-ctrl-skip { font-size: .8rem; opacity: .85; }
.vid-ctrl-skip:hover { opacity: 1; }
/* Time display */
.vid-ctrl-time {
  color: #fff;
  font-size: .72rem;
  white-space: nowrap;
  flex-shrink: 0;
}
/* Volume slider — always visible, shrinks on narrow players */
.vid-ctrl-vol {
  width: clamp(40px, 8vw, 80px);
  height: 4px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 1;
}

/* ── Generic tooltip via data-tooltip attribute ──────────────────────────── */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
  font-size: 0.75rem;
  white-space: nowrap;
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s;
  transition-delay: 0s; /* instant hide when cursor leaves */
  z-index: 100;
}
[data-tooltip]:hover::after {
  opacity: 1;
  transition-delay: 2s; /* 2s delay before tooltip appears */
}

/* Left-edge buttons (-5s, first in controls row) — anchor tooltip to
   the left so it never overflows off-screen. */
.vid-ctrl-row2 > button:first-child[data-tooltip]::after,
.vid-ctrl-row2 > button:nth-child(2)[data-tooltip]::after {
  left: 0;
  transform: none;
}

/* Right-edge buttons (fullscreen, last in controls row) — anchor tooltip to
   the right so it never overflows off-screen. */
.vid-ctrl-row2 > button:last-child[data-tooltip]::after,
.vid-ctrl-row2 > *:last-child [data-tooltip]::after {
  left: auto;
  right: 0;
  transform: none;
}

/* Gear / quality button — lives inside the flex controls bar.
   position:relative anchors the drop-up menu against the button. */
.vid-q-btn {
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  padding: 4px 5px;
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
  border-radius: 3px;
  transition: background .15s;
  position: relative;
  display: flex;
  align-items: center;
  gap: 3px;
}
.vid-q-btn:hover { background: rgba(255, 255, 255, .15); }
.vid-q-btn .vid-q-label { font-size: .72rem; white-space: nowrap; line-height: 1; }
.vid-q-btn .vid-q-arrow { font-size: .6rem; line-height: 1; opacity: .8; }

/* Quality menu — position:fixed escapes overflow:hidden on .vid-wrap so the
   menu is never clipped; JS sets top/bottom/left/right on open. */
.vid-q-menu {
  position: fixed;
  background: rgba(15, 23, 42, .92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, .15);
  border-radius: 6px;
  overflow: hidden;
  z-index: 11;
  min-width: 140px;
  padding: 4px 0;
  box-shadow: 0 4px 20px rgba(0, 0, 0, .5);
}
.vid-q-menu[hidden] { display: none; }
.vid-q-menu button {
  display: block;
  width: 100%;
  background: none;
  border: none;
  color: #e2e8f0;
  padding: 7px 14px;
  text-align: left;
  cursor: pointer;
  font-size: .82rem;
  transition: background .15s, color .15s;
}
.vid-q-menu button:hover,
.vid-q-menu button.vid-q-active { background: rgba(14, 165, 233, .3); color: #fff; }

/* ── Encela Dialog System ─────────────────────────────────── */
.encela-dialog-overlay {
  position: fixed; inset: 0; z-index: 9000;
  background: rgba(0,0,0,0.55); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 0.2s ease; pointer-events: none;
}
.encela-dialog-overlay.visible { opacity: 1; pointer-events: all; }
/* showAppDialog/showAppAlert/showAppConfirm overlays carry both classes.
   The double-class selector (specificity 0,2,0) beats any single-class page-
   level override (.encela-dialog-overlay alone, specificity 0,1,0) so these
   programmatic dialogs always float above a lightbox (z-index 9999) even
   when a page adds its own .encela-dialog-overlay { z-index: <lower> } rule. */
.encela-dialog-overlay.enc-app-overlay { z-index: 100000; }
.encela-dialog {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-radius: var(--radius-lg);
  box-shadow: 0 25px 60px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.06);
  min-width: 340px; max-width: 520px; width: 90vw; max-height: 85vh;
  display: flex; flex-direction: column;
  transform: scale(0.94) translateY(10px);
  transition: transform 0.22s cubic-bezier(0.34,1.56,0.64,1), opacity 0.18s ease;
  opacity: 0;
}
.encela-dialog-overlay.visible .encela-dialog { transform: none; opacity: 1; }
.encela-field-error { color: var(--danger, #f87171); font-size: 0.8rem; margin-top: 0.25rem; }
.encela-field-error[hidden] { display: none; }
.encela-dialog-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 1.25rem 1.5rem 0.75rem; border-bottom: 1px solid var(--glass-border);
}
.encela-dialog-icon-title { display: flex; align-items: center; gap: 0.75rem; }
.encela-dialog-icon { font-size: 1.5rem; line-height: 1; flex-shrink: 0; }
.encela-dialog-title { font-size: 1.05rem; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
/* Red "close" treatment — same visual language as the Photos/Drive media
   lightbox's .mpl-btn-close (webPages/lib/media-preview-lightbox.css), made
   platform-wide so every module's dialogs (confirm/alert/share/album-pick/
   etc., all built on this one shared .encela-dialog-* system) use the same
   always-on red for their close button instead of a neutral icon that only
   tints on hover. flex-shrink:0 guarantees it, which already applied, is
   also what keeps it from ever being squeezed in .encela-dialog-header's
   title+close flex row. */
.encela-dialog-x {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  border: none; cursor: pointer; color: var(--danger);
  font-size: 1.1rem; line-height: 1; padding: 0.3rem 0.4rem;
  border-radius: var(--radius-sm); transition: color 0.15s, background 0.15s;
  flex-shrink: 0; margin-left: 0.5rem; margin-top: -0.1rem;
}
.encela-dialog-x:hover { color: #fff; background: color-mix(in srgb, var(--danger) 55%, transparent); }
.encela-dialog-body { padding: 1rem 1.5rem; overflow-y: auto; flex: 1; color: var(--text-primary); font-size: 0.95rem; line-height: 1.55; }
.encela-dialog-body p { margin: 0 0 0.5rem; }
.encela-dialog-body p:last-child { margin-bottom: 0; }
.encela-dialog-footer {
  padding: 0.75rem 1.5rem 1.25rem; display: flex; gap: 0.75rem; justify-content: flex-end;
  border-top: 1px solid var(--glass-border); flex-wrap: wrap;
}
.encela-dialog-input {
  width: 100%; margin-top: 0.75rem; padding: 0.5rem 0.75rem;
  background: rgba(255,255,255,0.07); border: 1px solid var(--glass-border);
  border-radius: var(--radius-sm); color: var(--text-primary); font-size: 0.95rem;
  outline: none; transition: border-color 0.15s;
}
.encela-dialog-input:focus { border-color: var(--accent); }

/* ── Dialog supplemental ── */
/* Ensure overlay pads its content and gives dialogs room to breathe */
.encela-dialog-overlay { padding: 1rem; overflow: hidden; }
/* flex column body — lets child items stack with gap instead of relying on margins */
.encela-dialog-body { display: flex; flex-direction: column; gap: 0.5rem; min-height: 0; }
/* alias so chat module can use encela-dialog-close in addition to encela-dialog-x
   — same always-on red treatment, see .encela-dialog-x above. */
.encela-dialog-close {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  border: none; cursor: pointer; color: var(--danger);
  font-size: 1.1rem; line-height: 1; padding: 0.3rem 0.4rem;
  border-radius: var(--radius-sm); transition: color 0.15s, background 0.15s;
  flex-shrink: 0; margin-left: 0.5rem;
}
.encela-dialog-close:hover { color: #fff; background: color-mix(in srgb, var(--danger) 55%, transparent); }
/* Ensure encela-dialog-header title span/h3 colour matches the dark theme */
.encela-dialog-header > span { font-weight: 600; font-size: 0.95rem; color: var(--sky-200, #bae6fd); }

/* ============================================================
   White theme — comprehensive contrast overrides
   These address components that use dark-theme hardcoded colors
   (light pastels, white-on-dark tints) which become invisible
   on the near-white light background.
   ============================================================ */

/* User search dropdown: dark card → light card */
[data-theme="white"] .user-search-dropdown {
  background: rgba(255,255,255,0.98) !important;
  border-color: rgba(14,165,233,0.35) !important;
  box-shadow: 0 8px 32px rgba(0,0,0,0.14) !important;
}

/* Logout button: light pastel pink → dark accessible red */
[data-theme="white"] .user-menu-logout { color: #be123c !important; }
[data-theme="white"] .user-menu-logout:hover {
  background: rgba(190,18,60,0.09) !important;
  color: #9f1239 !important;
}

/* Danger / success button text: light pastels → saturated dark */
[data-theme="white"] .btn-danger {
  color: #be123c;
  border-color: rgba(190,18,60,0.40);
  background: rgba(190,18,60,0.07);
}
[data-theme="white"] .btn-danger:hover { background: rgba(190,18,60,0.14); color: #be123c; }
[data-theme="white"] .btn-success {
  color: #065f46;
  border-color: rgba(6,95,70,0.40);
  background: rgba(6,95,70,0.07);
}
[data-theme="white"] .btn-success:hover { background: rgba(6,95,70,0.14); color: #065f46; }

/* Text utility classes: light pastels → dark readable */
[data-theme="white"] .text-danger  { color: #be123c; }
[data-theme="white"] .text-success { color: #065f46; }

/* Notification badges: border uses --sky-900 which is near-white on light theme
   — override to white so the badge visually pops from the navbar */
[data-theme="white"] .notif-badge     { border-color: #ffffff; }
[data-theme="white"] .pan-notif-badge { border-color: #ffffff; }

/* Dialog close button now has an always-on red tint (see .encela-dialog-x /
   .encela-dialog-close above) which reads fine unchanged on the white theme
   too — no override needed here any more; this rule used to compensate for
   a white-alpha hover state that was invisible on a white background, which
   no longer exists. */

/* Dialog text input: near-invisible white-alpha bg → light tinted surface */
[data-theme="white"] .encela-dialog-input {
  background: rgba(14,165,233,0.06);
  border-color: rgba(14,165,233,0.35);
}

/* Dialog box shadow: too faint → more visible */
[data-theme="white"] .encela-dialog {
  box-shadow: 0 12px 48px rgba(0,0,0,0.18), 0 0 0 1px rgba(14,165,233,0.15);
}

/* Table row separator: white-alpha invisible on white → dark-alpha */
[data-theme="white"] .cloud-table tbody tr { border-bottom-color: rgba(0,0,0,0.08); }

/* Table link hover: white text → dark accent */
[data-theme="white"] .cloud-table td a:hover { color: #0369a1; }

/* Progress / storage bars: white-alpha invisible → dark-alpha */
[data-theme="white"] .progress-bar-wrap,
[data-theme="white"] .storage-bar-wrap { background: rgba(0,0,0,0.09); }

/* Generic card hover (file-row, module-card hover tints, etc.):
   white-alpha nearly invisible → light accent tint */
[data-theme="white"] .file-row:hover,
[data-theme="white"] .cloud-table tbody tr:hover,
[data-theme="white"] .notif-item:hover { background: rgba(14,165,233,0.06); }

/* Notification dropdown row separator: white-alpha invisible on white → dark-alpha */
[data-theme="white"] .notif-item { border-bottom-color: rgba(0,0,0,0.08); }

/* btn-cancel border is already handled; reinforce hover state */
[data-theme="white"] .btn-cancel:hover { background: rgba(0,0,0,0.05); }

/* Navbar search box and IDE panel labels: white-alpha-on-dark background → dark-alpha */
[data-theme="white"] .nav-search-input { background: rgba(0,0,0,0.09); }
[data-theme="white"] .ide-panel-label { background: rgba(0,0,0,0.06); }

/* Existing alert overrides (already present, kept intact above) */

/* UI QA round 1 item 6: a visible keyboard focus indicator everywhere. Many components set
   outline:none for the mouse; :focus-visible only matches keyboard focus, so clicks stay clean.
   !important so a component's own outline:none cannot remove it. */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, summary:focus-visible, [tabindex]:focus-visible, [role="button"]:focus-visible,
.launcher-tile:focus-visible, .notif-mark-all:focus-visible, .notif-clear-all:focus-visible {
  outline: 2px solid var(--accent) !important;
  outline-offset: 2px;
}

/* UI QA round 2 item B: between 641 and 1024px the brand ("ENCELA Photos" etc.) is nowrap inside
   a left section that may shrink to nothing, so it overflowed into the centre search box. Here the
   left and right sections size to their content and only the search box flexes, with a gap. */
@media (min-width: 641px) and (max-width: 1024px) {
  .navbar-left  { flex: 0 0 auto; min-width: max-content; }
  .navbar-right { flex: 0 0 auto; }
  .navbar-center { flex: 1 1 0; min-width: 0; padding: 0 0.75rem; }
  .navbar-center .nav-search-wrap { max-width: 100%; min-width: 0; }
}

/* UI QA round 2 (Compress dialog screenshot): the dropdown LIST of a native <select> is drawn on
   the system's light surface, but the control's light text colour was inherited by its options,
   so every option except the highlighted one was near-invisible. Give options an explicit themed
   background and text colour (follows the active theme, including the light one). */
select option, select optgroup {
  background-color: var(--sky-900);
  color: var(--text-primary);
}

/* QA Chat round 3 item 4: notification controls had 13-16px hit areas. The padding grows the clickable area,
   the negative margins keep the visual layout where it was. */
.notif-mark-all, .notif-clear-all { padding: 0.4rem 0.35rem; margin: -0.4rem -0.35rem; min-height: 24px; }
.notif-item-dismiss { min-width: 28px; min-height: 28px; padding: 0.4rem; margin-right: -0.4rem; }
@media (pointer: coarse) {
  .notif-mark-all, .notif-clear-all { padding: 0.65rem 0.5rem; margin: -0.65rem -0.5rem; min-height: 32px; }
  .notif-item-dismiss { min-width: 40px; min-height: 40px; }
}
