/* ============================================================================
   Workhub — Design tokens & base styles
   Aesthetic: quiet dev-tool interface (Linear/GitHub/Jira lineage) with one
   signature: monospace "terminal tag" bug IDs + a teal/amber status language
   that stays consistent across dashboards, tables, and detail views.
   ============================================================================ */

@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');

:root {
  /* Color tokens — light */
  --bg: #F6F7F9;
  --surface: #FFFFFF;
  --surface-glass: rgba(255, 255, 255, 0.72);
  --surface-2: #F0F2F5;
  --border: #E3E6EC;
  --text: #12151C;
  --text-muted: #6B7280;
  --accent: #0F766E;      /* teal — brand / primary actions */
  --accent-soft: #CCFBF1;
  --accent-2: #B45309;    /* amber — warnings, highlights */
  --accent-2-soft: #FEF3C7;
  --danger: #DC2626;
  --danger-soft: #FEE2E2;
  --success: #16A34A;
  --success-soft: #DCFCE7;
  --info: #2563EB;
  --info-soft: #DBEAFE;
  /* Text color to use on top of a solid --accent fill. Accent is dark in
     light mode (white text reads fine) but bright/light in dark mode, so
     dark mode needs to flip to a dark text color there instead — see the
     html.dark override below. */
  --on-accent: #FFFFFF;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
  --shadow-md: 0 4px 12px rgba(16, 24, 40, 0.08);
  --shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.14);

  --font-display: 'Space Grotesk', sans-serif;
  --font-body: 'Inter', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;

  --sidebar-w: 248px;
  --sidebar-w-collapsed: 76px;
  --navbar-h: 64px;
}

html.dark {
  --bg: #0B0E14;
  --surface: #12151D;
  --surface-glass: rgba(18, 21, 29, 0.62);
  --surface-2: #1A1E29;
  --border: #262B38;
  --text: #E7E9EE;
  --text-muted: #8B93A7;
  --accent: #2DD4BF;
  --accent-soft: #0F3D3A;
  --accent-2: #F5A524;
  --accent-2-soft: #3D2E0F;
  --danger: #F87171;
  --danger-soft: #3B1616;
  --success: #4ADE80;
  --success-soft: #123420;
  --info: #60A5FA;
  --info-soft: #142B4D;
  --on-accent: #04211C;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.55);
}

* { box-sizing: border-box; }

/* Background lives on <html> so the browser doesn't propagate body's
   background up to the canvas — that propagation would otherwise paint
   var(--bg) behind everything (including the fixed, negative-z-index
   ambient blobs below) and make them invisible. */
html { background: var(--bg); }

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  transition: background-color .2s ease, color .2s ease;
}

h1, h2, h3, h4, .font-display {
  font-family: var(--font-display);
  letter-spacing: -0.01em;
}

a { color: inherit; text-decoration: none; }

::selection { background: var(--accent-soft); }

/* ----------------------------------------------------------------------
   Ambient background — soft, fixed color blobs behind everything, so the
   glassmorphism (blur + translucency) on the sidebar/navbar/cards/modals
   below has something visible to actually blur, instead of just tinting
   toward a flat color.
   ---------------------------------------------------------------------- */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(560px circle at 8% 8%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 60%),
    radial-gradient(620px circle at 92% 18%, color-mix(in srgb, var(--accent-2) 16%, transparent), transparent 60%),
    radial-gradient(680px circle at 30% 95%, color-mix(in srgb, var(--info) 14%, transparent), transparent 60%);
}

/* Shared glassmorphism treatment — frosted, translucent panels with a
   faint light-catching edge. Applied to cards, toasts, and the chat
   shell so the effect shows up everywhere a panel floats above page
   content, not just the sidebar/navbar. Modals are deliberately excluded
   — see the .tf-modal rule below for why. */
.card,
.tf-modal,
.tf-toast,
.tf-chat-shell,
.tf-skeleton-card {
  background: var(--surface-glass);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* Modals get a SOLID panel, not the translucent glass treatment above.
   A blurred/translucent background over content-dense pages (tables,
   grids) lets sharp borders bleed through as faint streaks — most
   visible when a modal opens on top of another modal's own table (e.g.
   "Link a GitHub Repo" opened from the GitHub Configure popup). Cards
   sit over a smooth page gradient so translucency reads as intentional
   glass; a modal needs to fully occlude whatever is behind it. */
.tf-modal {
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* ----------------------------------------------------------------------
   Layout shell
   ---------------------------------------------------------------------- */
.tf-app-shell {
  display: flex;
  min-height: 100vh;
}

#tf-sidebar {
  width: var(--sidebar-w);
  background: var(--surface-glass);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 40;
  transition: width .18s ease, transform .2s ease, box-shadow .18s ease;
}

/* "Rail" mode — icons only, sidebar collapsed to a narrow strip. This is
   the default going forward (see SIDEBAR_MODE_KEY in sidebar.js); "pinned"
   mode is the old always-full-width behavior. */
body.tf-sidebar-collapsed #tf-sidebar { width: var(--sidebar-w-collapsed); }
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-link span,
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-brand span { display: none; }
/* Rail mode used to hide each whole section (header + links) with
   display:none, which made every grouped nav item — HR, Engineering,
   QA/Testing, Company, etc. — disappear entirely with no way to reach
   it short of pinning the sidebar open. Now the section header stays
   visible as a single "heading icon" (label + chevron hidden, icon
   centered like a regular nav icon); only the link list underneath
   stays collapsed until that icon is clicked or the sidebar is
   hover-expanded. */
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section span,
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section-chevron { display: none; }
/* Collapsed section icons get their own tinted, bordered "chip" plus a
   small accent dot — a bare fa-solid icon by itself looked identical to
   a normal page-link icon, so there was no visual cue that this one
   opens a whole group instead of navigating straight to a page. */
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section {
  justify-content: center;
  align-self: center;
  width: 42px;
  height: 42px;
  padding: 0;
  margin: 6px 0 2px;
  border-radius: var(--radius-md);
  background: var(--surface-2);
  border: 1px solid var(--border);
  position: relative;
  transition: background .12s ease, border-color .12s ease, color .12s ease, transform .12s ease;
}
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section:hover { transform: translateY(-1px); }
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-group:first-of-type .tf-sidebar-section { margin-top: 14px; }
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section:hover,
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.open {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section::before {
  /* dot = "this expands", distinct from a plain nav icon. Uses ::before
     (not ::after) because ::after is already used by the hover tooltip
     below — both target the same element, and only one ::after can win
     the cascade. Pulses gently so it reads as alive/interactive rather
     than just decorative. */
  content: '';
  position: absolute;
  bottom: 3px;
  right: 3px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent);
  animation: tf-section-dot-pulse 2.2s ease-out infinite;
}
@keyframes tf-section-dot-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section-icon { font-size: 14px; }
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section-body { display: none; }

/* Selected rail icon: the currently-active section (the one containing
   the page you're on) gets a little "pop" on its icon plus its label
   shown directly underneath, so the active spot is glanceable without
   needing to hover for the flyout. Extra bottom margin on the section
   itself makes room for that label so it never overlaps the icon below
   it in the rail. */
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.open {
  margin-bottom: 22px;
}
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.open .tf-sidebar-section-icon {
  animation: tf-section-icon-pop .45s cubic-bezier(.34, 1.56, .64, 1);
}
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.open span {
  display: block;
  position: absolute;
  top: 100%;
  left: 50%;
  margin-top: 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--accent);
  white-space: nowrap;
  max-width: 70px;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
  pointer-events: none;
  animation: tf-label-fade-in .3s ease .1s both;
}
@keyframes tf-section-icon-pop {
  0% { transform: scale(0.6); }
  60% { transform: scale(1.18); }
  100% { transform: scale(1); }
}
@keyframes tf-label-fade-in {
  from { opacity: 0; transform: translate(-50%, -4px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
body.tf-sidebar-collapsed .tf-main { margin-left: var(--sidebar-w-collapsed); }

/* Tooltip on hover for icon-only rail links that have no flyout of their
   own — just the footer's Profile / Pin-open buttons. Section icons get
   a full flyout instead (below), which already carries its own label. */
body.tf-sidebar-collapsed .tf-sidebar-footer .tf-sidebar-link { position: relative; }
body.tf-sidebar-collapsed .tf-sidebar-footer .tf-sidebar-link:hover::after {
  content: attr(data-label);
  position: absolute;
  left: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: var(--shadow-md);
  z-index: 60;
  pointer-events: none;
}

/* Rail mode: each section's icon + its own link list are wrapped in one
   ".tf-sidebar-group". Hovering the icon (sidebar.js sets this element's
   top/left from the icon's actual position, then adds .flyout-open) pops
   out a small floating panel positioned next to that icon, containing
   ONLY that section's own links — nothing else in the sidebar changes,
   no other section's options appear, and the sidebar itself never
   widens. position:fixed (rather than absolute) is required here so the
   panel isn't clipped by .tf-sidebar-nav's overflow-x:hidden, which it
   would otherwise sit inside as a descendant. ":not(.tf-sidebar-open)"
   keeps this out of the way of the separate mobile hamburger overlay,
   which forces its own inline (non-flyout) display via !important. */
.tf-sidebar-group { position: relative; }
body.tf-sidebar-collapsed #tf-sidebar:not(.tf-sidebar-open) .tf-sidebar-group .tf-sidebar-section-body {
  position: fixed;
  min-width: 220px;
  max-width: 280px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 10px;
  z-index: 70;
  display: none;
  /* Belt-and-braces alongside the viewport-clamping in sidebar.js: on a
     very short viewport even a clamped top could leave a panel taller
     than the screen, so it also scrolls internally rather than running
     off the bottom. */
  max-height: calc(100vh - 16px);
  overflow-y: auto;
}
body.tf-sidebar-collapsed #tf-sidebar:not(.tf-sidebar-open) .tf-sidebar-group .tf-sidebar-section-body.flyout-open {
  display: flex;
  flex-direction: column;
}
/* The flyout carries its own heading (the section's title), since the
   rail icon itself never shows a label. */
body.tf-sidebar-collapsed #tf-sidebar:not(.tf-sidebar-open) .tf-sidebar-group .tf-sidebar-section-body::before {
  content: attr(data-section-label);
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 4px 10px 8px;
}
/* Link labels stay visible inside the flyout, overriding the collapsed
   rail's usual icon-only rule (which only applies to nav-level links). */
body.tf-sidebar-collapsed #tf-sidebar:not(.tf-sidebar-open) .tf-sidebar-group .tf-sidebar-section-body .tf-sidebar-link span {
  display: inline;
}

.tf-main {
  margin-left: var(--sidebar-w);
  flex: 1;
  min-width: 0;
  transition: margin-left .18s ease;
}

#tf-navbar {
  height: var(--navbar-h);
  background: var(--surface-glass);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
  position: sticky;
  top: 0;
  z-index: 30;
}

.tf-page-content {
  padding: 24px;
  max-width: 1440px;
}

/* ----------------------------------------------------------------------
   Sidebar
   ---------------------------------------------------------------------- */
.tf-sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px 20px 16px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
}
.tf-sidebar-brand i { color: var(--accent); font-size: 20px; }
.tf-sidebar-brand .tf-sidebar-logo { height: 24px; width: auto; flex: none; display: block; }

.tf-sidebar-nav { flex: 1; padding: 8px 12px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; overflow-x: hidden; }
.tf-sidebar-group { display: flex; flex-direction: column; }

/* Section headers are now clickable accordion toggles, not static labels. */
.tf-sidebar-section {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: space-between;
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 14px 12px 8px;
}
.tf-sidebar-section:hover { color: var(--text); }
.tf-sidebar-section span { flex: 1; text-align: left; }
.tf-sidebar-section-icon { width: 18px; text-align: center; font-size: 12px; flex-shrink: 0; }
.tf-sidebar-section-chevron { font-size: 10px; transition: transform .15s ease; flex-shrink: 0; }
.tf-sidebar-section.open .tf-sidebar-section-chevron { transform: rotate(180deg); }

.tf-sidebar-section-body {
  display: none;
  flex-direction: column;
  gap: 2px;
}
.tf-sidebar-section-body.open { display: flex; }

.tf-sidebar-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
}
.tf-sidebar-link i { width: 18px; text-align: center; }
.tf-sidebar-link:hover { background: var(--surface-2); color: var(--text); }
.tf-sidebar-link.active { background: var(--accent-soft); color: var(--accent); }
.tf-sidebar-upgrade { background: var(--accent-soft); color: var(--accent); font-weight: 700; margin-bottom: 4px; }
.tf-sidebar-upgrade:hover { background: var(--accent-soft); color: var(--accent); opacity: .85; }

/* Locked modules — sidebar icon/link shows a small lock instead of navigating */
.tf-sidebar-lock-badge { font-size: 10px; opacity: .6; flex-shrink: 0; width: auto !important; margin-left: auto; }
.tf-sidebar-section.is-locked, .tf-sidebar-link.is-locked { opacity: .65; }
.tf-sidebar-section.is-locked:hover, .tf-sidebar-link.is-locked:hover { opacity: .9; }

/* Rail (icon-only) mode: the lock sits on the chip's top-right corner, and the
   pulsing "this expands" dot is dropped — a locked group doesn't expand. */
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.is-locked .tf-sidebar-lock-badge {
  position: absolute; top: 3px; right: 4px; margin: 0; font-size: 9px; opacity: .95; color: var(--warning, #d97706);
}
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.is-locked::before { display: none; }
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-section.is-locked { cursor: pointer; }
/* Locked links inside an open flyout / pinned body */
.tf-sidebar-link.is-locked .tf-sidebar-lock-badge { color: var(--warning, #d97706); opacity: .9; }
.tf-sidebar-section.is-locked .tf-sidebar-lock-badge { color: var(--warning, #d97706); opacity: .9; }
/* Mobile "More" sheet */
.tf-more-link.is-locked, .tf-more-section-header.is-locked { opacity: .7; }
.tf-more-lock { margin-left: auto; font-size: 11px; color: var(--warning, #d97706); width: auto !important; }

.tf-module-lock-popover {
  width: 280px; max-width: calc(100vw - 24px); background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 12px 32px rgba(0,0,0,.18);
  padding: 16px; z-index: 200;
}
.tf-module-lock-close {
  position: absolute; top: 8px; right: 10px; background: none; border: none; font-size: 18px;
  line-height: 1; color: var(--text-muted); cursor: pointer; padding: 2px;
}
.tf-module-lock-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; padding-right: 18px; }
.tf-module-lock-icon {
  width: 36px; height: 36px; border-radius: 9px; background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;
}
.tf-module-lock-title { font-weight: 700; font-size: 14px; }
.tf-module-lock-badge { font-size: 11px; color: var(--text-muted); }
.tf-module-lock-blurb { font-size: 13px; color: var(--text-muted); margin: 0 0 14px; line-height: 1.5; }
.tf-module-lock-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.tf-module-lock-actions .btn { flex: 1 1 auto; min-width: 110px; }

/* Contact Us / Report a Bug modal (navbar user menu) — deliberately not
   dependent on forms.css, since that isn't loaded on every page but this
   modal, via the navbar, needs to work on all of them. */
.tf-fb-group { margin-bottom: 12px; }
.tf-fb-label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--text); }
.tf-fb-textarea {
  width: 100%; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--border);
  font-size: 14px; font-family: var(--font-body); background: var(--bg); color: var(--text);
  resize: vertical; min-height: 100px;
}
.tf-fb-textarea:focus { outline: none; border-color: var(--accent); }
.tf-fb-msg { font-size: 13px; margin: 8px 0 0; min-height: 1em; color: var(--text-muted); }
.tf-fb-msg.is-error { color: var(--danger); }

.tf-sidebar-footer {
  padding: 12px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tf-sidebar-collapse-btn { border: none; background: none; cursor: pointer; font-family: inherit; width: 100%; }

@media (max-width: 1024px) {
  #tf-sidebar { transform: translateX(-100%); }
  #tf-sidebar.tf-sidebar-open { transform: translateX(0); width: var(--sidebar-w) !important; }
  #tf-sidebar.tf-sidebar-open .tf-sidebar-link span,
  #tf-sidebar.tf-sidebar-open .tf-sidebar-brand span,
  #tf-sidebar.tf-sidebar-open .tf-sidebar-section span,
  #tf-sidebar.tf-sidebar-open .tf-sidebar-section-chevron,
  #tf-sidebar.tf-sidebar-open .tf-sidebar-section { display: flex !important; }
  #tf-sidebar.tf-sidebar-open .tf-sidebar-section { justify-content: space-between !important; }
  #tf-sidebar.tf-sidebar-open .tf-sidebar-section-body { display: none; }
  #tf-sidebar.tf-sidebar-open .tf-sidebar-section-body.open { display: flex !important; }
  .tf-main, body.tf-sidebar-collapsed .tf-main { margin-left: 0; }
}

/* ----------------------------------------------------------------------
   Navbar
   ---------------------------------------------------------------------- */
.tf-navbar-search {
  position: relative;
  flex: 1;
  max-width: 480px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 8px 14px;
}
.tf-navbar-search i { color: var(--text-muted); }
.tf-navbar-search input {
  border: none; outline: none; background: transparent; color: var(--text);
  font-size: 14px; width: 100%; font-family: var(--font-body);
}

.tf-search-results, .tf-notif-panel, .tf-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  background: var(--surface-glass);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 50;
  overflow: hidden;
}
.tf-search-results { left: 0; right: 0; max-height: 320px; overflow-y: auto; }
.tf-search-result-item, .tf-notif-item { display: block; padding: 10px 14px; font-size: 13px; border-bottom: 1px solid var(--border); }
.tf-notif-item { display: flex; align-items: flex-start; gap: 10px; }
.tf-notif-cat-icon { width: 26px; height: 26px; border-radius: 8px; background: var(--surface-2); color: var(--accent); display: flex; align-items: center; justify-content: center; font-size: 12px; flex-shrink: 0; margin-top: 1px; }
.tf-notif-item-body { flex: 1; min-width: 0; }
.tf-search-result-item:hover, .tf-notif-item:hover { background: var(--surface-2); }
.tf-search-result-tag { float: right; font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; }
.tf-search-empty, .tf-notif-empty { padding: 16px; text-align: center; color: var(--text-muted); font-size: 13px; }

/* Universal Search dropdown (assets/components/global-search-bar.js) —
   grouped result rows with an icon, plus a "recent searches" list and a
   "view all results" footer link shared between the navbar's compact
   dropdown and the full global-search.html page. */
.tf-search-group-label {
  padding: 10px 14px 4px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.tf-search-result-item { display: flex; align-items: center; gap: 10px; color: var(--text); text-decoration: none; }
.tf-search-result-item i { width: 16px; text-align: center; color: var(--text-muted); flex-shrink: 0; }
.tf-search-result-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.tf-search-result-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tf-search-result-text .tf-search-result-tag { float: none; align-self: flex-start; }
.tf-search-recent-item { width: 100%; text-align: left; border: none; background: none; cursor: pointer; font-family: inherit; }
.tf-search-view-all {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 14px; font-size: 12px; font-weight: 600; color: var(--accent);
  text-decoration: none; background: var(--surface-2);
}
.tf-search-view-all:hover { background: var(--accent-soft); }

.tf-navbar-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.tf-icon-btn {
  width: 38px; height: 38px; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: transparent; color: var(--text-muted);
  display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative;
}
.tf-icon-btn:hover { background: var(--surface-2); color: var(--text); }
/* Golden "this is an add-on" state — Mail icon for admins when Mail isn't on yet. */
.tf-icon-btn-gold { color: #d4a017; background: rgba(212, 160, 23, .12); border-color: rgba(212, 160, 23, .35); }
.tf-icon-btn-gold:hover { color: #f0b429; background: rgba(212, 160, 23, .2); }
.tf-gold-crown { position: absolute; top: -5px; right: -4px; font-size: 9px; color: #f0b429;
                 filter: drop-shadow(0 0 2px rgba(0,0,0,.4)); }

.tf-badge-dot {
  position: absolute; top: 6px; right: 6px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--danger); border: 2px solid var(--surface);
}
.tf-badge-dot:not(.hidden) {
  animation: tf-badge-dot-pulse 2.2s ease-out infinite;
}
@keyframes tf-badge-dot-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 55%, transparent); }
  70% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--danger) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 0%, transparent); }
}

/* Brief one-shot "something just arrived" cue for the mail/messages quick-glance
   icons — added for ~900ms when a realtime INSERT comes in, then removed, so it
   reads as a momentary bump rather than a constant distraction. */
@keyframes tf-icon-bump {
  0% { transform: scale(1); }
  30% { transform: scale(1.28); color: var(--accent); }
  55% { transform: scale(0.94); }
  100% { transform: scale(1); }
}
.tf-icon-bump { animation: tf-icon-bump 0.6s ease-out; }

.tf-notif-wrapper { position: relative; }
.tf-notif-panel { right: 0; width: 340px; max-height: 400px; overflow-y: auto; }
.tf-notif-item.unread { background: var(--accent-soft); }
.tf-notif-title { font-weight: 600; font-size: 13px; }
.tf-notif-body { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.tf-notif-time { font-size: 11px; color: var(--text-muted); margin-top: 4px; }
.tf-notif-view-all { display: block; text-align: center; padding: 10px; font-size: 12.5px; font-weight: 600; color: var(--accent); text-decoration: none; border-top: 1px solid var(--border); }
.tf-notif-view-all:hover { background: var(--surface-2); }

.tf-user-menu { position: relative; }
.tf-user-btn {
  display: flex; align-items: center; gap: 8px; background: none; border: none;
  cursor: pointer; color: var(--text); font-size: 14px; font-weight: 500; padding: 6px 8px; border-radius: var(--radius-sm);
}
.tf-user-btn:hover { background: var(--surface-2); }
.tf-user-btn i.fa-chevron-down { font-size: 10px; color: var(--text-muted); }
.tf-dropdown { right: 0; width: 200px; padding: 6px; }
.tf-dropdown a, .tf-dropdown button {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border-radius: var(--radius-sm);
  border: none; background: none; text-align: left; font-size: 13px; font-family: var(--font-body); color: var(--text); cursor: pointer;
}
.tf-dropdown a:hover, .tf-dropdown button:hover { background: var(--surface-2); }
.tf-dropdown button { color: var(--danger); }

.tf-avatar-sm {
  width: 30px; height: 30px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.tf-avatar-fallback { background: var(--accent-soft); color: var(--accent); font-weight: 700; font-size: 12px; }

/* ----------------------------------------------------------------------
   Buttons
   ---------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 16px; border-radius: var(--radius-sm); font-size: 14px; font-weight: 600;
  border: 1px solid transparent; cursor: pointer; font-family: var(--font-body);
  transition: all .15s ease;
}
.btn-primary { background: var(--accent); color: var(--on-accent); }
html.dark .btn-primary { color: var(--on-accent); }
.btn-primary:hover { filter: brightness(1.08); }
.btn-secondary { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.btn-secondary:hover { background: var(--border); }
.btn-ghost { background: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { filter: brightness(1.1); }
.btn-sm { padding: 6px 12px; font-size: 13px; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }

/* ----------------------------------------------------------------------
   Badges (severity / priority / status) — the signature visual language
   ---------------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
  padding: 3px 9px; border-radius: 100px; text-transform: uppercase; white-space: nowrap;
}
.badge-default { background: var(--surface-2); color: var(--text-muted); }

.badge-severity-blocker, .badge-status-failed { background: var(--danger-soft); color: var(--danger); }
.badge-severity-critical { background: var(--danger-soft); color: var(--danger); }
.badge-severity-major { background: var(--accent-2-soft); color: var(--accent-2); }
.badge-severity-minor { background: var(--info-soft); color: var(--info); }
.badge-severity-trivial { background: var(--surface-2); color: var(--text-muted); }
.badge-severity-enhancement { background: var(--accent-soft); color: var(--accent); }

.badge-priority-highest { background: var(--danger-soft); color: var(--danger); }
.badge-priority-high { background: var(--accent-2-soft); color: var(--accent-2); }
.badge-priority-medium { background: var(--info-soft); color: var(--info); }
.badge-priority-low, .badge-priority-lowest { background: var(--surface-2); color: var(--text-muted); }

.badge-status-new, .badge-status-open { background: var(--info-soft); color: var(--info); }
.badge-status-assigned, .badge-status-progress, .badge-status-retest { background: var(--accent-2-soft); color: var(--accent-2); }
.badge-status-fixed, .badge-status-ready, .badge-status-passed, .badge-status-closed { background: var(--success-soft); color: var(--success); }
.badge-status-rejected, .badge-status-duplicate, .badge-status-cannot-reproduce { background: var(--surface-2); color: var(--text-muted); }
.badge-status-deferred { background: var(--accent-2-soft); color: var(--accent-2); }

/* Bug ID "terminal tag" — the page's signature element */
.tf-bug-id {
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-muted);
  padding: 2px 8px; border-radius: 5px; letter-spacing: 0.02em;
}

/* ----------------------------------------------------------------------
   Cards
   ---------------------------------------------------------------------- */
.card {
  border-radius: var(--radius-lg);
}

/* ----------------------------------------------------------------------
   My Notes — personal scratchpad grid
   ---------------------------------------------------------------------- */
.tf-notes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}
.tf-note-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 16px; min-height: 150px; cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.tf-note-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.tf-note-card.pinned { border-color: var(--accent); background: var(--accent-soft); }
.tf-note-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 6px; }
.tf-note-card-title { font-weight: 700; font-size: 14.5px; font-family: var(--font-display); line-height: 1.3; }
.tf-note-card-pin { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 13px; flex: none; }
.tf-note-card.pinned .tf-note-card-pin { color: var(--accent); }
.tf-note-card-body {
  font-size: 13px; color: var(--text-muted); line-height: 1.5; flex: 1;
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden;
}
.tf-note-card-time { font-size: 11.5px; color: var(--text-muted); }
.tf-note-new-card {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 150px; border: 1.5px dashed var(--border); border-radius: var(--radius-lg);
  color: var(--text-muted); font-weight: 600; font-size: 13.5px; cursor: pointer; background: transparent;
}
.tf-note-new-card:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

/* ----------------------------------------------------------------------
   Toasts
   ---------------------------------------------------------------------- */
.tf-toast {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); padding: 12px 14px; font-size: 13px; color: var(--text);
  transform: translateX(120%); opacity: 0; transition: transform .2s ease, opacity .2s ease;
}
.tf-toast-in { transform: translateX(0); opacity: 1; }
.tf-toast-out { transform: translateX(120%); opacity: 0; }
.tf-toast-message { flex: 1; }
.tf-toast-close { background: none; border: none; color: var(--text-muted); cursor: pointer; }
.tf-toast-success i { color: var(--success); }
.tf-toast-error i { color: var(--danger); }
.tf-toast-warning i { color: var(--accent-2); }
.tf-toast-info i { color: var(--info); }

/* ----------------------------------------------------------------------
   Modal
   ---------------------------------------------------------------------- */
.tf-modal-overlay {
  position: fixed; inset: 0; background: rgba(10, 12, 18, 0.55);
  display: flex; align-items: center; justify-content: center; z-index: 100;
  opacity: 0; transition: opacity .15s ease; padding: 16px;
}
.tf-modal-overlay.tf-modal-in { opacity: 1; }
.tf-modal-overlay.tf-modal-out { opacity: 0; }
.tf-modal {
  border-radius: var(--radius-lg);
  width: 100%; max-height: 88vh; overflow-y: auto;
  transform: translateY(12px); transition: transform .15s ease;
}
.tf-modal-overlay.tf-modal-in .tf-modal { transform: translateY(0); }
.tf-modal-sm { max-width: 420px; }
.tf-modal-md { max-width: 560px; }
.tf-modal-lg { max-width: 800px; }
.tf-modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px; border-bottom: 1px solid var(--border);
}
.tf-modal-header h3 { margin: 0; font-size: 17px; }
.tf-modal-close { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 16px; }
.tf-modal-body { padding: 22px; }
.tf-modal-footer { padding: 16px 22px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 10px; }

/* ----------------------------------------------------------------------
   Skeletons + Empty states
   ---------------------------------------------------------------------- */
.tf-skeleton-card { padding: 18px; border: 1px solid var(--border); border-radius: var(--radius-lg); }
.tf-skeleton-line {
  height: 12px; border-radius: 4px; background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: tf-shimmer 1.4s infinite;
}
@keyframes tf-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

.tf-empty-state { text-align: center; padding: 48px 20px; color: var(--text-muted); }
.tf-empty-state i { font-size: 32px; margin-bottom: 12px; color: var(--border); }
.tf-empty-state h3 { color: var(--text); margin: 0 0 6px; font-size: 15px; }
.tf-empty-state p { font-size: 13px; margin: 0; }

.tf-spinner {
  display: inline-block; border: 2px solid rgba(255,255,255,0.35); border-top-color: currentColor;
  border-radius: 50%; animation: tf-spin .7s linear infinite;
}
@keyframes tf-spin { to { transform: rotate(360deg); } }

/* ----------------------------------------------------------------------
   Tabs
   ---------------------------------------------------------------------- */
.tf-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); }
.tf-tab {
  background: none; border: none; cursor: pointer; padding: 10px 16px; font-size: 13.5px; font-weight: 600;
  color: var(--text-muted); border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color .15s ease, border-color .15s ease;
}
.tf-tab:hover { color: var(--text); }
.tf-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ----------------------------------------------------------------------
   Chat (group chat + DMs)
   ---------------------------------------------------------------------- */
.tf-chat-shell { display: flex; flex-direction: column; height: 560px; border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); box-shadow: var(--shadow-sm); }
.tf-chat-shell.hidden { display: none; }
.tf-chat-header {
  display: flex; align-items: center; padding: 12px 16px; gap: 8px;
  border-bottom: 1px solid var(--border);
  /* Slight glass effect echoes the top navbar's own .tf-surface-glass
     treatment, so the thread header reads as one continuous surface with
     the messages below it rather than a plain flat bar. */
  background: var(--surface-glass);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.tf-chat-messages {
  flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px;
  /* A faint radial tint behind the messages instead of a flat surface —
     barely visible, but it keeps a long thread from feeling like a plain
     text file. */
  background: radial-gradient(circle at 15% 0%, var(--accent-soft) 0%, transparent 45%), var(--bg);
}
.tf-chat-bubble-row { display: flex; gap: 8px; max-width: 78%; align-items: flex-end; }
.tf-chat-bubble-row.own { align-self: flex-end; flex-direction: row-reverse; }
.tf-chat-bubble {
  background: var(--surface-2); border-radius: 16px 16px 16px 4px; padding: 9px 13px;
  font-size: 13.5px; line-height: 1.45; word-break: break-word; box-shadow: var(--shadow-sm);
}
.tf-chat-bubble a { color: var(--accent); text-decoration: underline; word-break: break-all; }
.tf-chat-bubble-row.own .tf-chat-bubble a { color: var(--on-accent); text-decoration-color: currentColor; opacity: 1; }
.tf-chat-bubble-row.own .tf-chat-bubble {
  background: var(--accent); color: var(--on-accent); border-radius: 16px 16px 4px 16px;
  /* color-mix isn't supported in every browser; if it's not, this whole
     declaration is dropped and the plain var(--accent) above still applies
     — a flat accent bubble is a fine fallback for a subtle gradient. */
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 78%, black 18%));
}
.tf-chat-meta { font-size: 10.5px; color: var(--text-muted); margin-top: 3px; }
.tf-chat-bubble-row.own .tf-chat-meta { text-align: right; }
.tf-chat-input-row { display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--border); background: var(--surface); }
.tf-chat-input-row input { flex: 1; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-2); padding: 10px 16px; font-size: 13.5px; color: var(--text); }
.tf-chat-input-row input:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.tf-chat-send {
  width: 38px; height: 38px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: transform 0.12s ease;
}
.tf-chat-send:active { transform: scale(0.92); }
/* Hidden on desktop — the conversation list sits right next to the thread
   there, so there's nothing to "go back" to. Shown under the phone-width
   breakpoint (see .tf-list-detail in responsive.css), where the thread
   covers the full screen. */
.tf-chat-back {
  display: none; width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  align-items: center; justify-content: center; border: none; background: var(--surface-2);
  color: var(--text); cursor: pointer; font-size: 13px;
}
.tf-chat-back:active { background: var(--accent-soft); }

.tf-conv-list-item { display: flex; align-items: center; gap: 10px; padding: 12px; border-radius: var(--radius-md); cursor: pointer; text-decoration: none; color: inherit; border: 1px solid transparent; transition: background 0.12s ease; }
.tf-conv-list-item:hover { background: var(--surface-2); }
.tf-conv-list-item.active { background: var(--accent-soft); border-color: var(--accent); }
.tf-conv-unread-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }

.tf-announcement-card { border-left: 3px solid var(--border); padding: 16px 18px; }
.tf-announcement-card.pinned { border-left-color: var(--accent-2); background: var(--accent-2-soft); }

/* ----------------------------------------------------------------------
   Calendar (Phase 6)
   ---------------------------------------------------------------------- */
.tf-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.tf-cal-dow { background: var(--surface-2); padding: 8px 0; text-align: center; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.tf-cal-cell { background: var(--surface); min-height: 92px; padding: 6px; cursor: pointer; display: flex; flex-direction: column; gap: 3px; transition: background .1s ease; }
.tf-cal-cell:hover { background: var(--surface-2); }
.tf-cal-cell.tf-cal-outside { opacity: 0.35; }
.tf-cal-cell.tf-cal-today .tf-cal-daynum { background: var(--accent); color: var(--on-accent); }
.tf-cal-cell.tf-cal-selected { outline: 2px solid var(--accent); outline-offset: -2px; }
.tf-cal-daynum { width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; }
.tf-cal-chip { font-size: 10px; padding: 1px 5px; border-radius: 4px; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tf-cal-more { font-size: 10px; color: var(--text-muted); padding-left: 4px; }
.tf-cal-legend { display: flex; flex-wrap: wrap; gap: 12px; }
.tf-cal-legend-item { display: flex; align-items: center; gap: 6px; font-size: 12.5px; cursor: pointer; user-select: none; }
.tf-cal-legend-item.off { opacity: 0.35; }
.tf-cal-legend-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.tf-cal-day-event { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.tf-cal-day-event:last-child { border-bottom: none; }
.tf-cal-day-icon { width: 32px; height: 32px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; color: #fff; flex-shrink: 0; }

/* Meeting-booking slot grid (see calendar.html's openNewMeetingModal) */
.tf-slot-grid { display: flex; flex-wrap: wrap; gap: 6px; max-height: 180px; overflow-y: auto; padding: 2px; }
.tf-slot-btn { border: 1px solid var(--border); background: var(--surface); border-radius: var(--radius-sm); padding: 5px 10px; font-size: 12.5px; cursor: pointer; color: var(--text); transition: background .1s ease, border-color .1s ease; }
.tf-slot-btn:hover:not(:disabled) { background: var(--surface-2); border-color: var(--accent); }
.tf-slot-btn.tf-slot-selected { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tf-slot-btn:disabled { opacity: 0.4; cursor: not-allowed; text-decoration: line-through; }

.tf-dm-placeholder {
  height: 560px; display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 8px; color: var(--text-muted);
}
.tf-dm-placeholder.hidden { display: none; }

.tf-dropdown button.tf-dropdown-danger { color: var(--danger); }
.tf-dropdown-divider { height: 1px; background: var(--border); margin: 6px 2px; }

/* ---------------------------------------------------------------------------
   Fallback for the `hidden` utility. It normally comes from the Tailwind CDN;
   if that script is slow or blocked on a device, popups (notifications, profile
   menu, search results) would otherwise stay open permanently.
   --------------------------------------------------------------------------- */
.tf-search-results.hidden, .tf-notif-panel.hidden, .tf-dropdown.hidden,
.tf-badge-dot.hidden, .tf-icon-btn.hidden { display: none !important; }
.hidden:not([class*="sm:"]):not([class*="md:"]):not([class*="lg:"]):not([class*="xl:"]) { display: none; }
@media (min-width: 1024px) { .lg\:hidden { display: none; } }

/* "A software developed by Pandora Softwares" credit at the bottom of the sidebar */
.tf-sidebar-devby { padding: 8px 14px 4px; font-size: 11px; line-height: 1.35; color: var(--text-muted); text-align: left; }
.tf-sidebar-devby a { color: inherit; text-decoration: underline; }
body.tf-sidebar-collapsed #tf-sidebar .tf-sidebar-devby { display: none; }
