/* Duwam design tokens + shared styles
   Brand: Emerald — chosen as a single, ownable identity that reads premium
   without veering into "WhatsApp green" or "government green". Light mode
   uses Emerald 600 (#059669); dark mode uses Emerald 400 (#34D399) so the
   accent stays readable on near-black without glowing. Success is unified
   with the brand on purpose: two greens on the same screen looks broken. */
:root {
  /* Dark canvas — near-black with a *barely* perceptible warm-green shift,
     so the surface feels like part of the brand rather than a neutral
     dropped behind it. Two-tone elevation preserved: bg = canvas,
     bg-2 / card = elevated surfaces, bg-3 / card-2 = hover/nested. */
  --bg: #0E1211;
  --bg-2: #161A18;
  --bg-3: #1F2421;
  --card: #161A18;
  --card-2: #1F2421;
  --border: rgba(255, 255, 255, 0.08);
  --border-2: rgba(255, 255, 255, 0.15);
  --text: #F3F5F4;
  --text-2: #B6BCB8;
  --text-3: #8B9290;
  /* Brand (Emerald) — dark-mode tier.
     `--accent` is the historical token used everywhere; `--brand` is an
     alias so newer code can read more semantically without breaking old
     references. `--accent-fg` is a deep emerald so text on the bright
     mint button feels like jewel-on-glass, not white-on-mint (which
     reads cheap). */
  --accent: #34D399;
  --accent-fg: #052E27;
  --accent-2: #6EE7B7;
  --accent-grad: var(--accent);
  --accent-soft: rgba(52, 211, 153, 0.12);
  --accent-soft-border: rgba(52, 211, 153, 0.30);
  --brand: var(--accent);
  --brand-hover: #6EE7B7;
  --brand-pressed: #10B981;
  --brand-soft: var(--accent-soft);
  /* Success unified with brand — see header note. */
  --success: var(--accent);
  --warn: #F59E0B;
  --danger: #F87171;
  --info: #38BDF8;
  /* Legacy aliases — some pages (super/companies, admin/integrations) reference
     --panel/--panel-muted/--primary. Map them onto the real tokens so they
     flip correctly between dark and light. */
  --panel: var(--card);
  --panel-muted: var(--bg-3);
  --primary: var(--accent);
  --radius: 16px;
  --radius-lg: 24px;
  --topbar-h: 62px;
  --shadow-1: 0 4px 24px rgba(0, 0, 0, 0.35);
  --shadow-2: 0 10px 40px rgba(0, 0, 0, 0.45);
  --blur: 16px;
  --ring: rgba(52, 211, 153, 0.85);
  --ring-glow: rgba(52, 211, 153, 0.18);
}
:root.light {
  /* Light canvas — off-white with a hair of warmth. Pure #ffffff next to
     emerald reads "medical/clinical"; the very slight greige softens it
     into "premium SaaS". */
  --bg: #FAFBFA;
  --bg-2: #F4F6F4;
  --bg-3: #EAEFEC;
  --card: #FFFFFF;
  --card-2: #F4F6F4;
  --border: #E3E8E5;
  --border-2: #D4DBD7;
  --text: #0F1F1A;
  --text-2: #475A52;
  --text-3: #7B8A82;
  --shadow-1: 0 1px 3px rgba(15, 31, 26, 0.06);
  --shadow-2: 0 8px 24px rgba(15, 31, 26, 0.08);
  /* Brand (Emerald) — light-mode tier. Emerald 600 hits WCAG AA on white
     for both UI text and 3:1 graphic contrast. */
  --accent: #059669;
  --accent-fg: #FFFFFF;
  --accent-2: #047857;
  --accent-grad: var(--accent);
  --accent-soft: rgba(5, 150, 105, 0.10);
  --accent-soft-border: rgba(5, 150, 105, 0.28);
  --brand: var(--accent);
  --brand-hover: #047857;
  --brand-pressed: #065F46;
  --brand-soft: var(--accent-soft);
  --success: var(--accent);
  --danger: #DC2626;
  --ring: #059669;
  --ring-glow: rgba(5, 150, 105, 0.22);
}
* { box-sizing: border-box; }

/* ──────────────────────────────────────────────────────────────────────
   Brand scrollbar — applied globally so every overflowing surface (modals,
   side panels, sub-containers) gets the same subtle, on-brand chrome
   instead of the OS default. Resting state uses --border-2 (low-contrast
   token that already shifts with light/dark theme); hover and active
   states tint emerald to echo the rest of the UI's interaction language.
   Component-specific overrides further down keep their own widths but
   inherit the colour treatment via these defaults.
   ────────────────────────────────────────────────────────────────────── */
html { scrollbar-width: thin; scrollbar-color: var(--border-2) transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; background: transparent; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-2);
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background-color .15s ease;
}
*::-webkit-scrollbar-thumb:hover { background-color: var(--accent); }
*::-webkit-scrollbar-thumb:active { background-color: var(--brand-hover, var(--accent-2)); }
*::-webkit-scrollbar-corner { background: transparent; }
/* Firefox honours scrollbar-color but doesn't repaint on :hover of the
   bar itself — so we tint the whole element's scrollbar when the user is
   actively pointing at the surface. Subtle but matches Webkit's hover. */
*:hover { scrollbar-color: var(--border-2) transparent; }

/* Lock the browser viewport to a single pane: the <body> never scrolls.
   Vertical scrolling happens INSIDE the <main> element (see .shell > main
   below) so the sidebar + topbar stay pinned while only content scrolls.
   overflow-x: hidden on body is a safety net against any child leaking a
   horizontal scrollbar onto the page. */
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text); font-family: 'Cairo', 'Inter', system-ui, -apple-system, sans-serif; height: 100vh; overflow: hidden; }
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  /* Subtle ambient glow tied to the accent so the backdrop shifts
     theme with the rest of the UI instead of staying purple forever. */
  background:
    radial-gradient(700px circle at 92% 8%, var(--accent-soft), transparent 55%),
    radial-gradient(600px circle at 8% 92%, var(--accent-soft), transparent 60%);
}
:root.light body::before { background: none; }
body > * { position: relative; z-index: 1; }
a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Global form-control color inheritance.
   Browsers default `<button>` / `<input>` / `<select>` / `<textarea>` to the
   user-agent system color (buttontext / fieldtext) which doesn't follow our
   theme tokens — that's why dark-on-dark "invisible text" bugs appear on
   every inline-styled <button> we draw with `style="background:var(--bg-2)"`.
   Forcing `color: inherit` makes form controls follow the body's --text by
   default, so every button picks up the right contrast unless a class
   explicitly overrides it (e.g. .btn-primary using --accent-fg). */
button, input, select, textarea {
  color: inherit;
  font-family: inherit;
}

/* Glassmorphic cards */
.card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  backdrop-filter: blur(var(--blur)); -webkit-backdrop-filter: blur(var(--blur));
  box-shadow: var(--shadow-1);
}
.card-lg { border-radius: var(--radius-lg); box-shadow: var(--shadow-2); }

/* Collapsible company group cards (super admin Users page) */
.company-group { transition: box-shadow .15s ease; }
.company-group[open] { box-shadow: var(--shadow-2); }
.company-group > summary { list-style: none; cursor: pointer; user-select: none; }
.company-group > summary::-webkit-details-marker { display: none; }
.company-group-head {
  display: flex; align-items: center; gap: .75rem;
  padding: .9rem 1rem; border-radius: var(--radius);
  transition: background .15s ease;
}
.company-group-head:hover { background: var(--bg-3); }
.company-group[open] > summary > .company-group-head { border-bottom: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; }
.company-group-head::after {
  content: '▾'; font-size: .8rem; color: var(--text-2); margin-inline-start: .25rem;
  transition: transform .15s ease;
}
.company-group[open] > summary > .company-group-head::after { transform: rotate(180deg); }

/* Buttons — flat, GHL-inspired. No gradients, no lift-on-hover. Hover
   is communicated via a subtle background/border tone shift + a soft
   box-shadow (no transform). Keeps the UI calm at scale — hundreds of
   buttons don't all lift/shake on a single pointer move. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .55rem 1rem; border-radius: 10px; font-weight: 500; font-size: .9rem;
  border: 1px solid var(--border); background: var(--bg-2); color: var(--text);
  cursor: pointer; transition: background .12s, border-color .12s, color .12s, box-shadow .12s;
  line-height: 1.2;
}
.btn:hover:not(:disabled) { background: var(--bg-3); border-color: var(--border-2); }
.btn:active:not(:disabled) { background: var(--card-2); }
.btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }

.btn-primary {
  background: var(--accent); color: var(--accent-fg); border-color: var(--accent);
  font-weight: 600;
}
.btn-primary:hover:not(:disabled) {
  background: var(--accent); border-color: var(--accent);
  filter: brightness(.94); box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-ghost:hover:not(:disabled) { background: var(--bg-2); border-color: var(--border); color: var(--text); }
.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger); font-weight: 600; }
.btn-danger:hover:not(:disabled) { filter: brightness(.94); box-shadow: 0 1px 3px rgba(0,0,0,.15); border-color: var(--danger); background: var(--danger); }
.btn-info { background: var(--info); color: #fff; border-color: var(--info); font-weight: 600; }
.btn-info:hover:not(:disabled) { filter: brightness(.94); box-shadow: 0 1px 3px rgba(0,0,0,.15); border-color: var(--info); background: var(--info); }
.btn-success { background: var(--success); color: #fff; border-color: var(--success); font-weight: 600; }
.btn-success:hover:not(:disabled) { filter: brightness(.94); box-shadow: 0 1px 3px rgba(0,0,0,.15); border-color: var(--success); background: var(--success); }
.btn-sm { padding: .35rem .7rem; font-size: .85rem; border-radius: 10px; }
.btn-icon { padding: .5rem; border-radius: 10px; }
.btn:disabled { opacity: .6; cursor: not-allowed; }

/* Inputs */
.input, select.input, textarea.input {
  width: 100%; padding: .65rem .9rem; border-radius: 12px; border: 1px solid var(--border-2);
  background: var(--bg-2); color: var(--text); font-family: inherit; font-size: .95rem; outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.input:focus, select.input:focus, textarea.input:focus { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.label { display: block; font-size: .8rem; color: var(--text-2); margin-bottom: .35rem; font-weight: 600; }

/* Native date/time inputs render their placeholder (e.g. "dd/mm/yyyy",
   "يوم/شهر/سنة") as LTR-ordered tokens. When the surrounding page is RTL
   (dir="rtl"), the browser visually reverses those character runs which
   produces mangled text like "موي/رهش/قنس". Pin these inputs to LTR so the
   placeholder renders correctly in both Arabic and English locales, while
   keeping the surrounding form layout in the page's natural direction. */
input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"] {
  direction: ltr;
  text-align: start;
}
html[dir="rtl"] input[type="date"],
html[dir="rtl"] input[type="time"],
html[dir="rtl"] input[type="datetime-local"],
html[dir="rtl"] input[type="month"],
html[dir="rtl"] input[type="week"] {
  text-align: right;
}

/* Layout */
/* Shell layout — sidebar floats as a glass card with breathing room.
   The 12px padding-block + padding-inline-start creates the gap between
   the card and the viewport edge; the 12px column gap separates sidebar
   from main. Main keeps its inline-end edge flush with the viewport so
   wide content (kanban boards, tables) still has room. */
.shell {
  display: grid;
  grid-template-columns: 272px minmax(0, 1fr);
  height: 100vh;
  padding-block: 12px;
  padding-inline-start: 12px;
  gap: 12px;
  transition: grid-template-columns .22s ease;
}
.shell.sidebar-collapsed { grid-template-columns: 80px minmax(0, 1fr); }
/* The <main> column is the page's scroll container. Topbar inside it is
   sticky so it stays pinned as the user scrolls content below. Horizontal
   overflow is clipped here so a wide kanban can't push the main column
   past its 1fr allocation (it scrolls inside its own .tasks-viewport). */
.shell > main {
  min-width: 0; min-height: 0;
  overflow-x: hidden; overflow-y: auto;
  display: flex; flex-direction: column;
  scrollbar-width: thin;
}
.shell > main::-webkit-scrollbar { width: 8px; }
.shell > main::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.shell > main > .main { flex: 1 0 auto; min-width: 0; }
/* Sidebar — floating glass card. Semi-transparent fill + backdrop blur
   so the body's emerald ambient glow bleeds through; deep shadow + soft
   inset highlight at the top edge gives the "lifted glass" read.
   Light/dark variants tuned separately because shadow tone matters more
   on white than on near-black. */
.sidebar {
  position: relative;
  /* Lift the sidebar above the sticky topbar (z-index: 10) so collapsed-
     mode tooltips that extend out of the sidebar paint *over* the topbar
     instead of behind it. z-index: 20 keeps us safely above the topbar
     yet below dropdown panels (z-index: 60+) and modals. */
  z-index: 20;
  height: 100%;
  padding: .8rem .6rem 1rem;
  background: color-mix(in srgb, var(--card) 78%, transparent);
  border: 1px solid var(--border);
  border-radius: 20px;
  /* `overflow: visible` is required so the collapsed-mode tooltip
     (rendered as a ::after pseudo-element on each icon) can extend past
     the sidebar's rounded edge into the main column. The card's clipped
     look comes from `border-radius` + child sizing — no actual content
     bleeds past the corners since every child fits within the padding. */
  display: flex; flex-direction: column; overflow: visible;
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.42),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
/* Fallback for the 4% of browsers without backdrop-filter — solid card
   background so the layout still reads correctly without ghost-like
   transparency. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .sidebar { background: var(--card); }
}
.sidebar-head { display: flex; align-items: center; gap: .5rem; padding: .2rem .4rem .9rem; }
.sidebar-toggle {
  background: transparent; border: none; border-radius: 8px;
  width: 36px; height: 36px; color: var(--text-2); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background .15s, color .15s;
}
.sidebar-toggle:hover { background: var(--card-2); color: var(--text); }
.sidebar-toggle .lucide-ic { width: 20px; height: 20px; }
/* Brand wordmark — pairs with the checkmark mark to form the full Duwam
   logo lockup. Cairo (Arabic) and Inter (Latin) both have weight 800
   loaded; tighter letter-spacing + slightly larger size makes the lockup
   read as a *brand* (Linear, Notion, Vercel territory) rather than just
   a header label. The mark + wordmark gap is intentionally a bit roomier
   so neither feels cramped. */
.sidebar .brand {
  font-weight: 800;
  font-size: 1.18rem;
  letter-spacing: -0.025em;
  display: flex; align-items: center; gap: .65rem; min-width: 0;
}
.sidebar .brand-text {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  line-height: 1;
}

/* ── Duwam brand mark ──────────────────────────────────────────────────
   Rounded emerald square hosting a stylized "د" glyph (Cairo Black). The
   gradient (top-left → bottom-right, light → dark) gives a "lit-from-above"
   depth; the inset highlight on the top edge sells the glass-jewel feel.
   The mark is theme-aware via --brand-* tokens so it shifts shade in
   light vs dark mode without re-coding.
   See public/assets/js/shell.js _brandMark() for the SVG markup. */
.duwam-mark {
  --mk-size: 32px;
  width: var(--mk-size); height: var(--mk-size);
  border-radius: 9px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--brand-hover) 0%, var(--brand-pressed) 100%);
  color: #FFFFFF;
  box-shadow:
    0 6px 14px -4px color-mix(in srgb, var(--brand) 55%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 -1px 0 rgba(0, 0, 0, 0.10);
  transition: transform .2s ease, box-shadow .25s ease;
  position: relative;
  overflow: hidden;
}
.duwam-mark > svg {
  width: 100%; height: 100%; display: block; pointer-events: none;
}
.duwam-mark-sm { --mk-size: 26px; border-radius: 7px; }
/* Subtle lift when the mark sits inside an interactive container (sidebar
   header, mobile topbar). Pure cosmetic — signals "alive". */
.brand:hover .duwam-mark,
.topbar-brand:hover .duwam-mark { transform: translateY(-1px); }
/* Light mode — soften shadow tint (white canvas amplifies green bleed)
   and bump the inner highlight a hair brighter. */
html.light .duwam-mark {
  box-shadow:
    0 4px 10px -3px color-mix(in srgb, var(--brand) 40%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.30),
    inset 0 -1px 0 rgba(0, 0, 0, 0.06);
}
.sidebar .nav { flex: 1; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; }
.sidebar .nav::-webkit-scrollbar { width: 6px; }
.sidebar .nav::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 3px; }
/* Visual divider inside the nav — used to separate the employee's
   personal items from their permission-gated admin sections, and again
   before Settings at the very bottom. */
.nav .nav-sep {
  height: 1px; background: var(--border); margin: .55rem .3rem;
}
.shell.sidebar-collapsed .nav .nav-sep { margin: .55rem .45rem; }
/* When two separators end up adjacent (e.g., no admin extensions → only
   the Settings separator renders), collapse the second one to avoid a
   double line. */
.nav .nav-sep + .nav-sep { display: none; }

.nav a {
  display: flex; align-items: center; gap: .6rem; padding: .35rem .5rem; border-radius: 10px; color: var(--text-2);
  text-decoration: none; margin-bottom: .15rem; font-weight: 500; font-size: .9rem; white-space: nowrap;
  border: 1px solid transparent;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
  /* No `overflow: hidden` here — that clipped the collapsed-mode ::after
     tooltip so it never escaped the link box. Label truncation is already
     handled at .nav-label below, so removing it from the link is safe. */
}
/* Hover = quiet row tint + matching tint on the icon container so the row
   previews the active treatment without committing to it. */
.nav a:hover {
  background: color-mix(in srgb, var(--brand) 6%, transparent);
  color: var(--text);
}
html.light .sidebar .nav a:hover { background: color-mix(in srgb, var(--brand) 8%, transparent); }
/* Active row: filled brand container around the icon is the focal point;
   the row carries a soft brand tint to anchor it visually. The container
   lifts with a tinted shadow that matches the brand for a "premium" read.
   See public/assets/css/duwam.css :root for the Emerald palette. */
.nav a.active {
  background: color-mix(in srgb, var(--brand) 9%, transparent);
  color: var(--text); font-weight: 600;
}

/* Light mode glass — slightly more opaque than dark (white surfaces need
   more body to read as glass instead of haze) and a softer cool shadow
   that matches the off-white canvas. */
html.light .sidebar {
  background: color-mix(in srgb, var(--card) 72%, transparent);
  border-color: rgba(15, 31, 26, 0.06);
  box-shadow:
    0 18px 44px rgba(15, 31, 26, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  html.light .sidebar { background: var(--bg-2); }
}
/* Icon container — 32x32 rounded square. Inactive: transparent (icon
   sits as outline glyph). Hover: faint brand tint. Active: filled brand
   square with the inverse-text color, casting a tinted shadow. */
.nav a .ic {
  width: 32px; height: 32px; border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  background: transparent; color: var(--text-2);
  transition: background .18s ease, color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.nav a:hover .ic {
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--text);
}
.nav a.active .ic {
  background: var(--brand);
  color: var(--accent-fg);
  box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--brand) 65%, transparent);
}
.nav a .ic .lucide-ic, .nav a .ic svg { width: 18px; height: 18px; stroke-width: 2; }
.nav a .nav-label { overflow: hidden; text-overflow: ellipsis; flex: 1; }

/* Color-coded admin items — each Admin-section nav item carries an
   inline `--item-color` (set in shell.js navFor()). The icon container
   tints faintly with that color so the eye can scan and group items
   without reading labels. Active state still wins and shows the brand
   container — the color "transfers" to brand on click, signaling
   selection unambiguously. */
.nav a.nav-colored .ic {
  background: color-mix(in srgb, var(--item-color) 14%, transparent);
  color: var(--item-color);
}
.nav a.nav-colored:hover .ic {
  background: color-mix(in srgb, var(--item-color) 22%, transparent);
  color: var(--item-color);
}
.nav a.nav-colored.active .ic {
  background: var(--brand);
  color: var(--accent-fg);
  box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--brand) 65%, transparent);
}

/* Collapsed state — icons only.
   `.sidebar` is normally `overflow: hidden` to clip content to the rounded
   glass-card edges, and `.nav` clips horizontally to keep label text from
   spilling. Both clip the icon tooltip when collapsed, so it never reaches
   the user. We relax both axes only in collapsed mode — labels are
   `display:none` here, so nothing else needs the clip. The trade-off is
   losing nav vertical-scroll in collapsed mode (CSS forbids
   `overflow-y: auto` together with `overflow-x: visible`); ten icons at
   40px fit any reasonable viewport, so this is acceptable. */
.shell.sidebar-collapsed .sidebar { overflow: visible; }
.shell.sidebar-collapsed .sidebar .nav { overflow: visible; }
.shell.sidebar-collapsed .sidebar { padding-inline: .45rem; }
.shell.sidebar-collapsed .sidebar-head { padding-inline: .2rem; gap: .3rem; flex-direction: column; align-items: center; }
.shell.sidebar-collapsed .sidebar .brand-text,
.shell.sidebar-collapsed .nav a .nav-label { display: none; }
.shell.sidebar-collapsed .nav a { justify-content: center; padding: .6rem .4rem; }
.shell.sidebar-collapsed .nav a .nav-badge { position: absolute; top: 2px; inset-inline-end: 2px; margin: 0; min-width: 16px; padding: 0 4px; font-size: .62rem; }
.nav a { position: relative; }
.nav-badge {
  margin-inline-start: auto; background: var(--danger); color: #fff; font-size: .7rem;
  font-weight: 700; padding: 1px 7px; border-radius: 999px; line-height: 1.4; min-width: 20px;
  text-align: center;
}
.nav a.active .nav-badge { background: var(--accent); color: var(--accent-fg); box-shadow: none; }
.lucide-ic { display: inline-flex; align-items: center; justify-content: center; width: 1em; height: 1em; vertical-align: -0.15em; color: currentColor; }
.lucide-ic svg { width: 1em; height: 1em; stroke-width: 2; }
.btn .lucide-ic { width: 1.05em; height: 1.05em; }
.btn-icon .lucide-ic { width: 1.15rem; height: 1.15rem; }
.chip .lucide-ic { width: .95em; height: .95em; }
/* Section header inside the nav — quiet uppercase label that doubles as
   a visual break (replaces the old .nav-sep thin line). The section name
   itself does the separation, so no border/divider is needed. */
.nav-section {
  font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-3);
  padding: 1rem .8rem .35rem;
  user-select: none; pointer-events: none;
}
.nav-section > span { display: inline-block; }
/* First section in the nav doesn't need top padding — it already has
   sidebar-head padding above it. */
.nav > .nav-section:first-child { padding-top: .25rem; }
/* Collapsed: label text disappears, leaves a faint centered hairline so
   the user still feels the grouping when scanning vertically. */
.shell.sidebar-collapsed .nav-section {
  padding: .5rem .35rem;
  display: flex; align-items: center; justify-content: center;
}
.shell.sidebar-collapsed .nav-section > span { display: none; }
.shell.sidebar-collapsed .nav-section::after {
  content: ''; display: block;
  height: 1px; width: 60%;
  background: var(--border);
}

/* ── Mobile bottom-nav ─────────────────────────────────────────────────
   Floating glass pill at the bottom of the viewport, mobile-only. The
   sidebar is hidden entirely on small screens — bottom-nav replaces it
   for the 4 most-used destinations per role. Active state mirrors the
   sidebar's brand-container pattern so the visual language stays unified
   when the user switches between desktop and mobile. */
.bottom-nav {
  display: none;
  position: fixed;
  bottom: max(14px, calc(env(safe-area-inset-bottom) + 8px));
  /* Stretch to span the viewport with comfortable side margins (16px
     min, expands with safe-area-inset-left/right on devices with side
     cutouts). Items inside space evenly via justify-content so each
     destination gets a generous tap target instead of clustering in a
     tight pill at the centre. */
  left: max(16px, calc(env(safe-area-inset-left) + 16px));
  right: max(16px, calc(env(safe-area-inset-right) + 16px));
  z-index: 50;
  padding: 6px 10px;
  background: color-mix(in srgb, var(--card) 78%, transparent);
  border: 1px solid var(--border);
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.45),
              inset 0 1px 0 rgba(255, 255, 255, 0.06);
  align-items: center;
  justify-content: space-around;
  gap: 4px;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .bottom-nav { background: var(--card); }
}
html.light .bottom-nav {
  border-color: rgba(15, 31, 26, 0.06);
  box-shadow: 0 14px 32px rgba(15, 31, 26, 0.12),
              inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
.bottom-nav-item {
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  padding: .35rem .6rem .3rem;
  min-width: 64px;
  /* Grow to share available width evenly when the nav stretches across
     the viewport — each tab gets a generous, thumb-comfortable tap zone
     instead of clustering tight in a pill. */
  flex: 1 1 0;
  border-radius: 999px;
  color: var(--text-2);
  text-decoration: none;
  font-size: .7rem; font-weight: 600;
  transition: color .18s ease;
}
.bottom-nav-item:hover { color: var(--text); text-decoration: none; }
.bottom-nav-ic {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px;
  background: transparent;
  transition: background .2s ease, color .2s ease, box-shadow .2s ease;
}
.bottom-nav-ic .lucide-ic, .bottom-nav-ic svg { width: 20px; height: 20px; stroke-width: 2; }
.bottom-nav-item.active { color: var(--brand); }
.bottom-nav-item.active .bottom-nav-ic {
  background: var(--brand);
  color: var(--accent-fg);
  box-shadow: 0 6px 14px -4px color-mix(in srgb, var(--brand) 60%, transparent);
}
.bottom-nav-label {
  max-width: 64px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Mobile breakpoint — bottom-nav appears, floating sidebar disappears.
   Shell collapses to a single column so main content gets full width.
   Topbar padding tightens so action cluster doesn't overflow. Main gets
   bottom padding (incl. safe-area inset) so its content doesn't tuck
   under the floating pill or the Android gesture bar. */
@media (max-width: 720px) {
  .shell, .shell.sidebar-collapsed {
    grid-template-columns: minmax(0, 1fr);
    padding: 0;
    gap: 0;
  }
  .sidebar { display: none; }
  .bottom-nav { display: inline-flex; }
  .shell > main > .main {
    padding-bottom: calc(110px + env(safe-area-inset-bottom));
  }
  .topbar { padding-inline: .8rem; }
}

/* ── Sidebar shift card (employee only) ────────────────────────────────
   Compact at-a-glance "are you on shift?" pill above the theme switch.
   Rendered by shell.js _renderShiftCard; live duration ticked once a
   minute by bindShiftCard. Whole card is a link to /app/shift.html for
   full controls. */
.sidebar-shift {
  display: flex; align-items: center; gap: .55rem;
  padding: .5rem .6rem;
  margin-bottom: .15rem;
  border-radius: 12px;
  background: var(--bg-3);
  border: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.sidebar-shift:hover {
  background: color-mix(in srgb, var(--brand) 8%, var(--bg-3));
  border-color: color-mix(in srgb, var(--brand) 25%, var(--border));
  text-decoration: none;
}
/* Status dot — green pulsing when on shift, gray when off. */
.sidebar-shift-dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
  background: var(--text-3);
  box-shadow: 0 0 0 0 transparent;
}
.sidebar-shift[data-state="on"] .sidebar-shift-dot {
  background: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
  animation: shift-pulse 2s ease-in-out infinite;
}
/* Paused — same amber as the attendance ring's paused state. Steady
   (no pulse) because the timer is frozen; pulsing would imply active flow. */
.sidebar-shift[data-state="paused"] .sidebar-shift-dot {
  background: #f59e0b;
  box-shadow: 0 0 0 3px color-mix(in srgb, #f59e0b 20%, transparent);
}
.sidebar-shift[data-state="paused"] .sidebar-shift-label,
.sidebar-shift[data-state="paused"] .sidebar-shift-time { color: #f59e0b; }
@keyframes shift-pulse {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--brand)  8%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .sidebar-shift[data-state="on"] .sidebar-shift-dot { animation: none; }
}
.sidebar-shift-body {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: baseline; gap: .35rem;
  font-size: .8rem; line-height: 1.2;
}
.sidebar-shift-label { font-weight: 600; color: var(--text); }
.sidebar-shift-time {
  font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--brand);
}
.sidebar-shift-time:not(:empty)::before {
  content: '•'; margin-inline-end: .35rem; color: var(--text-3); font-weight: 400;
}
.sidebar-shift[data-state="off"] .sidebar-shift-time { display: none; }
.sidebar-shift-ic {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-3); flex-shrink: 0;
}
.sidebar-shift-ic .lucide-ic, .sidebar-shift-ic svg { width: 15px; height: 15px; }
/* Loading state — render a quiet skeleton until first fetch arrives. */
.sidebar-shift[data-state="loading"] .sidebar-shift-label,
.sidebar-shift[data-state="loading"] .sidebar-shift-time {
  color: var(--text-3);
}
/* Collapsed sidebar: shrink to a single status dot — full text would
   wrap and crowd a 80px column. The dot still pulses if on-shift, so the
   user keeps the at-a-glance signal. */
.shell.sidebar-collapsed .sidebar-shift {
  padding: .5rem;
  justify-content: center;
}
.shell.sidebar-collapsed .sidebar-shift-body,
.shell.sidebar-collapsed .sidebar-shift-ic { display: none; }

/* ── Trial card (sidebar bottom, admins only) ─────────────────────────
   Asana-style countdown: ring + label + days, with a CTA button below.
   Tones shift emerald → amber → danger as the trial nears its end so
   the urgency reads without having to fire a popup. The whole card
   collapses to ring-only in the narrow sidebar. */
.sidebar-trial {
  margin: .35rem .55rem .15rem;
  padding: .6rem .65rem .55rem;
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, currentColor 22%, var(--border));
  background: color-mix(in srgb, currentColor 6%, transparent);
  display: flex; flex-direction: column; gap: .45rem;
  transition: background .15s, border-color .15s;
}
/* Tone definitions consolidated below — they set both parent color (for
   ring/border via currentColor) and the CTA bg/fg pair. */
.sidebar-trial-row {
  display: flex; align-items: center; gap: .55rem;
  text-decoration: none; color: inherit;
}
.sidebar-trial-ring { flex-shrink: 0; color: inherit; }
.sidebar-trial-body {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: .05rem;
  line-height: 1.15;
}
.sidebar-trial-label {
  font-size: .68rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3);
}
.sidebar-trial-days {
  font-size: .85rem; color: var(--text);
}
.sidebar-trial-days b {
  font-size: 1rem; font-weight: 800; color: inherit;
  font-variant-numeric: tabular-nums;
  margin-inline-end: .15rem;
}
.sidebar-trial.tone-urgent .sidebar-trial-days b,
.sidebar-trial.tone-warning .sidebar-trial-days b { color: currentColor; }
.sidebar-trial-cta {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .45rem .65rem; border-radius: 8px;
  /* Each tone supplies its own --cta-bg / --cta-fg pair below. We can't
     `background: currentColor` and then override `color` on the same
     element — the override propagates back into the bg, leaving the
     button invisible (bg = fg). Using two custom properties keeps the
     two values cleanly decoupled. */
  background: var(--cta-bg, var(--accent));
  color: var(--cta-fg, var(--accent-fg));
  font-size: .78rem; font-weight: 700; text-decoration: none;
  letter-spacing: .01em;
  border: 0;
  transition: filter .15s, transform .12s;
}
.sidebar-trial.tone-normal  { color: var(--accent); --cta-bg: var(--accent); --cta-fg: var(--accent-fg); }
.sidebar-trial.tone-warning { color: var(--warn);   --cta-bg: var(--warn);   --cta-fg: #1a1408; }
.sidebar-trial.tone-urgent  { color: var(--danger); --cta-bg: var(--danger); --cta-fg: #ffffff; }
.sidebar-trial-cta:hover { filter: brightness(1.06); transform: translateY(-1px); }
/* Collapsed sidebar: hide labels + CTA, keep ring as a quiet status dot. */
.shell.sidebar-collapsed .sidebar-trial {
  padding: .45rem;
  align-items: center;
}
.shell.sidebar-collapsed .sidebar-trial-body,
.shell.sidebar-collapsed .sidebar-trial-cta { display: none; }
.shell.sidebar-collapsed .sidebar-trial-row { justify-content: center; }
body.focus-mode .sidebar-trial { display: none; }

/* ── Theme pill (sidebar bottom) ───────────────────────────────────────
   Two-segment pill that flips Light/Dark instantly. The active option
   reads as a "raised tab" (white card + tiny shadow) inside a recessed
   track — same metaphor as macOS segmented controls. Keyboard accessible
   via the underlying <button>s. */
.theme-pill {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--bg-3); border: 1px solid var(--border);
  border-radius: 999px; width: 100%;
  margin: .35rem 0;
}
.theme-pill-opt {
  flex: 1 1 0; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
  padding: .4rem .55rem; border: 0; border-radius: 999px;
  background: transparent; color: var(--text-2);
  font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer;
  transition: background .18s ease, color .18s ease, box-shadow .18s ease;
}
.theme-pill-opt:hover { color: var(--text); }
.theme-pill-opt[aria-pressed="true"] {
  background: var(--card);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(0,0,0,.18), 0 0 0 1px var(--border-2);
}
html.light .theme-pill-opt[aria-pressed="true"] {
  box-shadow: 0 1px 2px rgba(15,31,26,.10), 0 0 0 1px var(--border-2);
}
.theme-pill-opt .lucide-ic, .theme-pill-opt svg { width: 14px; height: 14px; }
/* Collapsed: hide labels, keep only the two icon buttons stacked side by
   side. Pill stays as a 2-icon switch so the user keeps the same mental
   model in both states. */
.shell.sidebar-collapsed .theme-pill { padding: 2px; }
.shell.sidebar-collapsed .theme-pill-opt { padding: .35rem; }
.shell.sidebar-collapsed .theme-pill-opt > span { display: none; }

/* ── Sidebar user card (sidebar bottom) ────────────────────────────────
   Click → opens a popover above the card with profile/settings/logout.
   Mirrors the topbar avatar menu so users have two equivalent entry
   points (sidebar = primary, topbar = quick action). */
.sidebar-user {
  margin-top: .25rem;
  padding-top: .55rem;
  border-top: 1px solid var(--border);
  position: relative;
}
.sidebar-user-btn {
  display: flex; align-items: center; gap: .55rem; width: 100%;
  padding: .45rem .55rem; border-radius: 12px;
  background: transparent; border: 1px solid transparent;
  color: var(--text); cursor: pointer; text-align: start;
  font: inherit;
  transition: background .15s ease, border-color .15s ease;
}
.sidebar-user-btn:hover { background: var(--bg-3); border-color: var(--border); }
.sidebar-user-btn .avatar { width: 34px; height: 34px; font-size: .78rem; flex-shrink: 0; }
.sidebar-user-id { flex: 1 1 auto; min-width: 0; line-height: 1.25; }
.sidebar-user-name {
  font-weight: 700; font-size: .85rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar-user-role {
  font-size: .72rem; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar-user-caret {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-3); flex-shrink: 0;
  transition: transform .2s ease, color .15s ease;
}
.sidebar-user-caret .lucide-ic, .sidebar-user-caret svg { width: 16px; height: 16px; }
.sidebar-user-btn:hover .sidebar-user-caret { color: var(--text-2); }
.sidebar-user-btn[aria-expanded="true"] .sidebar-user-caret { transform: rotate(180deg); }
/* Popover anchored above the card; expanded sidebar = same width as card,
   collapsed sidebar = floats to the side as a compact menu. */
.sidebar-user-menu {
  position: absolute; bottom: calc(100% + .4rem);
  inset-inline-start: .15rem; inset-inline-end: .15rem;
  background: var(--card); border: 1px solid var(--border-2); border-radius: 12px;
  padding: .35rem; box-shadow: var(--shadow-2);
  display: none; z-index: 60;
  flex-direction: column; gap: 1px;
}
.sidebar-user-menu.open { display: flex; }
.sidebar-user-menu > a, .sidebar-user-menu > button {
  display: flex; align-items: center; gap: .55rem;
  padding: .5rem .65rem; border-radius: 8px;
  color: var(--text); text-decoration: none; font-size: .85rem; font-weight: 500;
  background: transparent; border: 0; cursor: pointer; text-align: start;
  font-family: inherit; width: 100%;
  transition: background .15s ease, color .15s ease;
}
.sidebar-user-menu > a:hover, .sidebar-user-menu > button:hover {
  background: var(--bg-3);
}
.sidebar-user-menu > a .lucide-ic,
.sidebar-user-menu > button .lucide-ic { width: 16px; height: 16px; color: var(--text-2); }
.sidebar-user-menu .sidebar-user-sep { height: 1px; background: var(--border); margin: .25rem .15rem; }
.sidebar-user-menu .sidebar-user-danger { color: var(--danger); }
.sidebar-user-menu .sidebar-user-danger:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }
.sidebar-user-menu .sidebar-user-danger .lucide-ic { color: var(--danger); }

/* Collapsed: card shrinks to just the avatar; popover floats to the side. */
.shell.sidebar-collapsed .sidebar-user-btn { padding: .35rem; justify-content: center; }
.shell.sidebar-collapsed .sidebar-user-id,
.shell.sidebar-collapsed .sidebar-user-caret { display: none; }
.shell.sidebar-collapsed .sidebar-user-menu {
  inset-inline-start: calc(100% + .4rem); inset-inline-end: auto;
  bottom: 0; min-width: 220px;
}

/* Topbar — slim glass strip that matches the floating sidebar aesthetic.
   Semi-transparent fill + backdrop blur so content scrolling beneath is
   gently softened (not hidden) as it passes under. Bottom border kept
   intentionally faint so the bar reads as "edge of viewport" rather than
   "framed component". */
/* Three-zone topbar: left cluster (brand/title/trial) — centered search
   — right cluster (actions). The flex children with `flex: 1 1 0` on
   the outer clusters keep them visually balanced so the search field
   centers regardless of trial-chip presence or the role's icon count. */
.topbar {
  display: flex; align-items: center; gap: .8rem;
  padding: .55rem 1.1rem;
  /* Safe-area top inset keeps the topbar's content below the Android
     status bar in edge-to-edge mode (the WebView paints behind it). On
     desktop browsers the inset resolves to 0 so the layout is unchanged. */
  padding-top: calc(.55rem + env(safe-area-inset-top));
  padding-inline-start: calc(1.1rem + env(safe-area-inset-left));
  padding-inline-end: calc(1.1rem + env(safe-area-inset-right));
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  position: sticky; top: 0; z-index: 10;
  min-height: 56px;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar { background: var(--bg); }
}
/* Asymmetric flex on the side clusters intentionally pulls the centered
   search slightly toward the brand cluster: the right (in RTL) / left
   (in LTR) side typically holds just a brief page title while the actions
   cluster carries many icons. Equal flex would visually pin the search
   too far from the brand; 1 vs 1.5 keeps it "near the title, not floating
   alone". */
.topbar-left { flex: 1 1 0; min-width: 0; }
.topbar-actions {
  flex: 1.5 1 0; min-width: 0;
  display: flex; align-items: center; justify-content: flex-end; gap: .5rem;
  position: relative;
}
/* Each topbar slot wraps a button + its dropdown panel so the panel
   anchors under its own button instead of the whole topbar row. */
.topbar-slot { position: relative; display: inline-flex; }
/* Brand in the topbar — only shown on mobile widths where the sidebar
   collapses out of view. Reuses the same .logo + .brand-text styling so
   it visually matches the sidebar header. */
.topbar-brand {
  display: none; align-items: center; gap: .55rem;
  font-weight: 800; letter-spacing: -0.025em;
  color: var(--text);
}
.topbar-brand .brand-text { font-size: 1rem; line-height: 1; }
@media (max-width: 720px) {
  .topbar-brand { display: inline-flex; }
  /* When the brand shows, hide the page title to save space — title is
     duplicated by the active sidebar nav item anyway. */
  .page-title { display: none; }
}

/* Trial chip lives in the left cluster (after the title). It must hug
   to the right edge of that cluster but never push the title or the
   actions area off-screen. */
/* Page title — shows a faint placeholder bar until Page.setTitle()
   stamps the real text. Prevents the topbar from looking half-empty
   on first paint. The ::before is a 2px emerald "upperline" anchored
   above the title text — a quiet identity mark that says "you are
   here", echoing the active-tab pattern from the iconbar reference.
   Hidden while the title is empty (placeholder state) so it doesn't
   float over the shimmer skeleton. */
.page-title { font-weight: 700; min-width: 110px; min-height: 1.1em; position: relative; }
.page-title:not(:empty)::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 5px);
  inset-inline-start: 0;
  width: 28px; height: 2px;
  border-radius: 1px;
  background: var(--brand);
  opacity: .9;
}
.page-title:empty {
  background: linear-gradient(90deg, var(--bg-3) 25%, var(--border) 50%, var(--bg-3) 75%);
  background-size: 200% 100%;
  border-radius: 6px;
  animation: pt-shimmer 1.4s ease-in-out infinite;
  color: transparent;
}
@keyframes pt-shimmer { 0% { background-position: 200% 0 } 100% { background-position: -200% 0 } }
@media (prefers-reduced-motion: reduce) {
  .page-title:empty { animation: none; background: var(--bg-3); }
}

/* Topbar action buttons — "ghost" style. Transparent at rest so the glass
   topbar reads as a clean strip; pillow lifts on hover with a soft tinted
   surface + matching ring. Keeps focal weight on bell badges and content,
   not on the chrome. */
.topbar-bell {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 10px;
  background: transparent; border: 1px solid transparent; color: var(--text-2);
  cursor: pointer; transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.topbar-bell:hover {
  background: color-mix(in srgb, var(--brand) 8%, transparent);
  color: var(--text);
  border-color: color-mix(in srgb, var(--brand) 25%, var(--border));
}
.topbar-bell:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.topbar-bell .lucide-ic { width: 1.1rem; height: 1.1rem; }
/* Urgent trigger inherits the neutral ghost color at rest so the topbar
   reads as one calm cluster; the amber accent only surfaces on hover to
   signal "this is the urgent broadcast channel" without shouting. */
#topbar-urgent:hover {
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border-color: color-mix(in srgb, var(--warn) 35%, var(--border));
  color: var(--warn);
}

/* Bell badge — sits above the icon. We bump z-index and use the page bg
   colour for the ring so the badge reads as "floating" instead of glued
   to a neighbouring button when icons cluster. */
.bell-badge {
  position: absolute; top: -5px; inset-inline-end: -5px;
  min-width: 18px; height: 18px; padding: 0 5px;
  background: var(--danger); color: #fff; font-size: .65rem; font-weight: 700;
  border-radius: 999px;
  /* Ring uses --card so it reads as a clean halo on the new transparent
     topbar. Solid topbar background would have hidden a --bg ring. */
  box-shadow: 0 0 0 2px var(--card);
  display: inline-flex; align-items: center; justify-content: center;
  z-index: 2; pointer-events: none;
}
.bell-badge.hidden { display: none; }

/* ── Topbar quick-search trigger (⌘K) ──────────────────────────────────
   Slim "search box"-shaped button sitting at the start of the actions
   cluster. The kbd hint is hidden on narrow screens and on devices
   without a hardware keyboard so it doesn't lie about the shortcut. */
/* Centered global search — the visual primary action of the topbar.
   Pill-shaped, wide (caps at 520px so it doesn't crowd the action icons
   on narrow desktops), with a search icon on the inline-start, faded
   placeholder text in the middle, and a ⌘K hint on the inline-end.
   Click → opens the cmdk overlay (same handler as before since we kept
   the `id="topbar-cmdk"`). On mobile it collapses to an icon-only pill
   so the topbar stays uncluttered when the bottom-nav is the primary
   navigation surface. */
.topbar-search {
  flex: 0 1 520px;
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .5rem .85rem;
  background: var(--bg-2); border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-3);
  font: inherit; font-size: .85rem; font-weight: 500;
  cursor: text; text-align: start;
  min-width: 0;
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.topbar-search:hover,
.topbar-search:focus-visible {
  background: var(--bg-3);
  border-color: color-mix(in srgb, var(--brand) 30%, var(--border));
  color: var(--text);
  outline: none;
}
.topbar-search:focus-visible {
  box-shadow: 0 0 0 3px var(--ring-glow);
}
.topbar-search-ic {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-3); flex-shrink: 0;
}
.topbar-search-ic .lucide-ic, .topbar-search-ic svg { width: 16px; height: 16px; }
.topbar-search-placeholder {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-3);
}
.topbar-search:hover .topbar-search-placeholder,
.topbar-search:focus-visible .topbar-search-placeholder { color: var(--text-2); }
.topbar-search-kbd {
  font-family: ui-sans-serif, system-ui, sans-serif;
  font-size: .68rem; font-weight: 600; letter-spacing: .02em;
  padding: 2px 6px; border-radius: 5px;
  background: var(--card); color: var(--text-3);
  border: 1px solid var(--border);
  flex-shrink: 0;
}
@media (max-width: 720px) {
  /* Collapse to icon-only on narrow screens — the bottom-nav handles
     primary navigation and the kbd hint is misleading on touch devices. */
  .topbar-search {
    flex: 0 0 38px;
    width: 38px; padding: 0;
    border-radius: 10px;
    justify-content: center;
  }
  .topbar-search-placeholder,
  .topbar-search-kbd { display: none; }
}

/* ── Command Palette modal (⌘K) ────────────────────────────────────────
   Centered card on top of a blurred backdrop. The list mirrors the
   bell-panel aesthetic so it feels native to the rest of the shell.
   The whole stack lives at z-index 200 so it sits above the bell /
   user-menu / panels — those auto-close when the modal opens because
   ⌘K steals focus into the cmdk input. */
.cmdk-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(2, 6, 23, 0); backdrop-filter: blur(0);
  -webkit-backdrop-filter: blur(0);
  display: none; align-items: flex-start; justify-content: center;
  padding-top: 12vh;
  transition: background .2s ease, backdrop-filter .2s ease;
}
.cmdk-overlay.is-open {
  display: flex;
  background: rgba(2, 6, 23, .55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.cmdk-modal {
  width: min(640px, calc(100vw - 24px));
  max-height: 70vh; overflow: hidden;
  background: var(--card); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
  display: flex; flex-direction: column;
  animation: cmdk-in .18s ease-out;
}
@keyframes cmdk-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } }
.cmdk-input-row {
  display: flex; align-items: center; gap: .65rem;
  padding: .9rem 1rem; border-bottom: 1px solid var(--border);
}
.cmdk-input-ic { color: var(--text-3); display: inline-flex; }
.cmdk-input-ic .lucide-ic { width: 1.1rem; height: 1.1rem; }
.cmdk-input {
  flex: 1; appearance: none; border: 0; background: transparent;
  font: inherit; font-size: 1rem; color: var(--text);
  outline: none; padding: 0;
}
.cmdk-input::placeholder { color: var(--text-3); }
.cmdk-esc {
  font-family: ui-sans-serif, system-ui, sans-serif;
  font-size: .7rem; font-weight: 600; padding: 2px 6px; border-radius: 4px;
  background: var(--bg-3); color: var(--text-3); border: 1px solid var(--border);
}
.cmdk-list {
  list-style: none; margin: 0; padding: .35rem;
  overflow-y: auto; flex: 1;
}
.cmdk-empty {
  padding: 2rem 1rem; text-align: center;
  color: var(--text-3); font-size: .9rem;
}
.cmdk-item {
  display: flex; align-items: center; gap: .75rem;
  padding: .65rem .8rem; border-radius: 10px;
  cursor: pointer; user-select: none;
}
.cmdk-item.is-selected {
  background: color-mix(in srgb, var(--brand) 12%, var(--bg-3));
}
.cmdk-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--bg-3); color: var(--text-2); flex-shrink: 0;
}
.cmdk-ic .lucide-ic { width: 14px; height: 14px; }
.cmdk-item.is-selected .cmdk-ic {
  background: color-mix(in srgb, var(--brand) 22%, transparent);
  color: var(--brand);
}
.cmdk-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.cmdk-label {
  font-weight: 600; font-size: .92rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmdk-sub {
  color: var(--text-3); font-size: .76rem; margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmdk-kind {
  flex-shrink: 0;
  font-size: .68rem; font-weight: 700; letter-spacing: .02em;
  padding: 2px 8px; border-radius: 999px;
  background: var(--bg-3); color: var(--text-3);
  text-transform: uppercase;
}
.cmdk-foot {
  display: flex; gap: 1rem; justify-content: flex-end;
  padding: .55rem .9rem; border-top: 1px solid var(--border);
  background: var(--bg-2); color: var(--text-3); font-size: .72rem;
}
.cmdk-foot kbd {
  font-family: ui-sans-serif, system-ui, sans-serif;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 4px; padding: 1px 5px; margin-inline-end: .25rem;
  font-size: .7rem; color: var(--text-2);
}
body.cmdk-locked { overflow: hidden; }
@media (max-width: 480px) {
  .cmdk-overlay { padding-top: 6vh; }
  .cmdk-foot { display: none; }
  .cmdk-kind { display: none; }
}

/* ── Focus mode toggle ─────────────────────────────────────────────────
   Quiets the topbar without silencing notifications themselves. When
   active, badges + ticker + trial chip fade out so the user can read /
   plan / write without the bell counter pulling at their eye. The
   button reuses the .topbar-bell ghost shell so it sits in the same
   visual cluster as the bell/contact/urgent triggers. */
.topbar-focus { position: relative; }
.topbar-focus .focus-dot {
  position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--brand);
  opacity: 0; transition: opacity .15s ease;
}
.topbar-focus[aria-pressed="true"] {
  color: var(--brand);
  border-color: color-mix(in srgb, var(--brand) 35%, var(--border));
  background: color-mix(in srgb, var(--brand) 10%, transparent);
}
.topbar-focus[aria-pressed="true"] .focus-dot { opacity: 1; }
body.focus-mode .bell-badge { display: none !important; }
body.focus-mode #ticker-mount { display: none; }

/* Severity tints — JS toggles .is-info (blue, routine) / .is-urgent (red,
   needs attention). Default class stays red so old call-sites still work. */
.bell-badge.is-info   { background: var(--info); }
.bell-badge.is-urgent { background: var(--danger); }

/* Bell ping — short pulse on the trigger when an urgent admin message
   arrives. Soft and quick: peace-of-mind, not anxiety. */
@keyframes bell-ping { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 55%, transparent); } 70% { box-shadow: 0 0 0 10px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
.topbar-bell.bell-ping { animation: bell-ping 1.1s ease-out 2; }

.bell-panel {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0;
  width: min(380px, calc(100vw - 24px));
  /* Solid card surface so notification text is crisp. Heavier blur on
     the backdrop adds glass feel at the seam between the panel and
     the page beneath without sacrificing legibility. */
  background: var(--card);
  border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 18px 48px -8px rgba(0, 0, 0, .42), 0 0 0 1px rgba(0, 0, 0, .04);
  backdrop-filter: blur(28px) saturate(180%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  z-index: 60; display: none; overflow: hidden;
}
.bell-panel.open { display: block; animation: bell-panel-in .18s ease; }
@keyframes bell-panel-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }

/* Page-level floating overlays (sticky memos on /app/shift, future
   widgets) defocus the moment the user opens a topbar panel — bell,
   contact, urgent, account menu. We blur each card instead of hiding
   the layer so the notes stay as visual anchors (the page doesn't
   "empty out") while their text becomes unreadable — depth-of-field
   effect signalling "this isn't your focus right now", and a small
   privacy bonus if someone glances over your shoulder while a
   notification opens. The body class is set and cleared by
   watchTopbarPanels() in shell.js. */
/* ── Sticky memo cards (shared between /app/shift.html's full editor
   and the global PinnedMemos layer that follows the user across
   pages). The full editor on shift.html still inlines its own copies
   of these rules — harmless duplication. Placed here so cards
   render correctly on every page that mounts the PinnedMemos layer. */
.note-card {
  position: absolute;
  width: 200px;
  padding: .85rem .85rem 2.1rem;
  border-radius: 4px;
  min-height: 130px;
  color: #1f2937;
  font-size: .88rem;
  line-height: 1.5;
  box-shadow: 0 6px 14px -8px rgba(0,0,0,.35), 0 2px 0 rgba(0,0,0,.04);
  transition: box-shadow .18s ease;
  cursor: grab;
  word-break: break-word;
  user-select: none;
  touch-action: none;
  transform: rotate(var(--note-tilt, 0deg));
}
.note-card:hover { box-shadow: 0 12px 24px -10px rgba(0,0,0,.4); z-index: 4; }
.note-card.pinned { transform: rotate(0); box-shadow: 0 10px 18px -10px rgba(0,0,0,.42), 0 0 0 2px rgba(255,255,255,.3) inset; }
.note-card.dragging {
  cursor: grabbing;
  z-index: 9;
  transform: rotate(0) scale(1.03);
  box-shadow: 0 18px 38px -14px rgba(0,0,0,.55);
  transition: none;
}
.note-card.color-yellow { background: #fde68a; }
.note-card.color-pink   { background: #fbcfe8; }
.note-card.color-green  { background: #bbf7d0; }
.note-card.color-blue   { background: #bfdbfe; }
.note-card.color-red    { background: #fecaca; }
.note-card.color-purple { background: #ddd6fe; }
.note-card .note-title { font-weight: 800; margin-bottom: .25rem; font-size: .92rem; }
.note-card .note-body  { white-space: pre-wrap; }
.note-actions { position: absolute; top: .35rem; inset-inline-end: .4rem; display: inline-flex; gap: .15rem; opacity: .35; transition: opacity .2s ease; }
.note-card:hover .note-actions, .note-card.pinned .note-actions { opacity: 1; }
.note-actions button {
  all: unset; cursor: pointer; padding: .2rem .35rem; border-radius: 6px;
  color: rgba(0,0,0,.55);
  transition: background .15s, color .15s;
}
.note-actions button:hover { background: rgba(0,0,0,.1); color: rgba(0,0,0,.85); }
.note-actions button:active { transform: scale(.92); transition: transform .08s; }
/* One-shot flick: all action icons play together the instant the CARD is
   first hovered, then settle back to rest. Triggering on the card (not
   on each button) means the cursor moving between icons doesn't replay
   the animation three times — it fires once per card-hover, then stops. */
.note-card:hover .note-actions button {
  animation: note-icon-flick .22s ease-out;
}
@keyframes note-icon-flick {
  0%   { transform: rotate(0)    scale(1); }
  50%  { transform: rotate(-8deg) scale(1.12); }
  100% { transform: rotate(0)    scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .note-card:hover .note-actions button { animation: none; }
}
.note-pin-icon.active { color: #b91c1c; }
.note-card.priority-urgent::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: 0 0 0 2px #ef4444 inset;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .note-card, .note-card:hover { transition: none; }
}

/* Global pinned-memos layer (PinnedMemos module) — fixed positioning
   so cards float above page content like the shift-page board, and
   reuses the .note-card styling so a memo looks identical on either
   surface. The layer itself doesn't capture pointer events; only the
   cards do, so clicks on empty page area pass through. */
.pinned-memos-layer { position: fixed; inset: 0; pointer-events: none; z-index: 3; }
.pinned-memos-layer .note-card { pointer-events: auto; }

/* Resize handle — small SE-corner grip (BL in RTL since the card is
   mirrored by its parent dir). The arrow shape is drawn purely with
   borders so we don't ship an extra SVG for one icon. */
.note-card .note-resize {
  position: absolute;
  bottom: 4px;
  inset-inline-end: 4px;
  width: 14px; height: 14px;
  cursor: nwse-resize;
  opacity: .35;
  background:
    linear-gradient(135deg, transparent 0 65%, rgba(0,0,0,.55) 65% 75%, transparent 75% 85%, rgba(0,0,0,.55) 85% 95%, transparent 95%);
  border-radius: 0 0 3px 0;
  transition: opacity .15s ease;
}
[dir="rtl"] .note-card .note-resize {
  /* In RTL the handle is mirrored to the bottom-LEFT corner via
     inset-inline-end. The cursor must follow — nesw-resize points along
     the diagonal from this corner up-and-to-the-right, matching how the
     card actually grows when dragged. */
  cursor: nesw-resize;
  background:
    linear-gradient(225deg, transparent 0 65%, rgba(0,0,0,.55) 65% 75%, transparent 75% 85%, rgba(0,0,0,.55) 85% 95%, transparent 95%);
  border-radius: 0 0 0 3px;
}
.note-card:hover .note-resize { opacity: .85; }
.note-card.resizing { transition: none; }

/* Inline edit affordance — when a title or body becomes editable, give
   it a subtle inset ring so the user sees they're now typing into
   that field. Uses currentColor against the sticky background so it
   reads on every paper colour. */
.note-card .note-title[contenteditable="true"],
.note-card .note-body[contenteditable="true"] {
  outline: none;
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .25);
  border-radius: 4px;
  background: rgba(255, 255, 255, .35);
}
body.topbar-panel-open .notes-layer { pointer-events: none; }
/* Pointer-events on the parent layer alone aren't enough — the cards
   set pointer-events:auto themselves so clicks through them would
   still hijack the contact / urgent / bell panels. Disable on the
   cards too while a topbar panel is open. */
body.topbar-panel-open .notes-layer .note-card,
body.topbar-panel-open .notes-layer .note-add-tile {
  /* Push memos far enough out of focus that their colors don't compete
     with the topbar panel's content. They stay as a faint hint of the
     layer underneath rather than legible shapes. */
  filter: blur(14px);
  opacity: .25;
  pointer-events: none;
  transition: filter .2s ease, opacity .2s ease;
}
@media (prefers-reduced-motion: reduce) {
  body.topbar-panel-open .notes-layer .note-card,
  body.topbar-panel-open .notes-layer .note-add-tile {
    transition: none;
  }
}
/* Urgent panel hosts a form (label + select + textarea + button) — the
   default 380px feels cramped. Give it 420px and let it relax. */
.urgent-panel { width: min(420px, calc(100vw - 24px)); }
.urgent-counter { font-variant-numeric: tabular-nums; transition: color .15s ease; }
.urgent-counter.warn { color: var(--warn); font-weight: 600; }
.urgent-counter.over { color: var(--danger); font-weight: 700; }
.bell-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: .8rem 1rem; border-bottom: 1px solid var(--border);
}
.bell-panel-head h4 { margin: 0; font-size: .95rem; font-weight: 700; }
/* Mark-all-read — was a flat link, now a soft pill so it reads as an
   action, not a hint. */
.bell-mark-all {
  background: color-mix(in srgb, var(--accent-2) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent-2) 25%, var(--border));
  color: var(--accent-2);
  cursor: pointer; font-size: .78rem; font-weight: 600;
  padding: .3rem .65rem; border-radius: 999px;
  transition: background .15s ease, border-color .15s ease;
}
.bell-mark-all:hover { background: color-mix(in srgb, var(--accent-2) 18%, transparent); border-color: color-mix(in srgb, var(--accent-2) 45%, var(--border)); }
.bell-panel-tabs {
  display: flex; gap: .4rem; padding: .6rem 1rem;
  border-bottom: 1px solid var(--border);
}
.bell-tab {
  appearance: none; background: transparent; border: 0;
  padding: .4rem .9rem; border-radius: 10px; cursor: pointer;
  font-size: .85rem; font-weight: 600; color: var(--text-2);
  transition: background .15s ease, color .15s ease;
}
.bell-tab:hover { background: var(--bg-3); color: var(--text); }
.bell-tab.active { background: var(--accent); color: var(--accent-fg); }
.bell-panel-list { max-height: 480px; overflow-y: auto; }
.bell-panel-empty { padding: 2rem 1rem; text-align: center; color: var(--text-3); font-size: .9rem; }

/* ── Topbar user menu ──────────────────────────────────────────────────
   Avatar button at the end of the topbar opens a small menu (profile,
   settings, sign out). Reuses the .bell-panel base for the dropdown so
   it matches the bell/urgent/contact panels visually. */
.topbar-user {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0;
  background: transparent; border: 1px solid var(--border); border-radius: 50%;
  cursor: pointer; overflow: hidden;
  transition: border-color .15s ease, transform .15s ease;
}
.topbar-user:hover { border-color: var(--text-3); }
.topbar-user .avatar { width: 100%; height: 100%; border-radius: 50%; font-size: .72rem; }
.topbar-user:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.user-menu { width: 240px; padding: .35rem; }
.user-menu-head {
  display: flex; align-items: center; gap: .65rem;
  padding: .65rem .55rem .8rem; border-bottom: 1px solid var(--border);
}
.user-menu-name { font-weight: 700; font-size: .92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-sub  { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: .1rem; }
.user-menu-item {
  display: flex; align-items: center; gap: .65rem;
  padding: .55rem .65rem; margin: .1rem 0;
  background: transparent; border: 0; width: 100%; text-align: start;
  font-size: .88rem; font-weight: 500; color: var(--text);
  text-decoration: none; cursor: pointer; border-radius: 8px;
  transition: background .12s ease;
}
.user-menu-item:hover { background: var(--bg-3); }
.user-menu-item .lucide-ic { width: 1rem; height: 1rem; color: var(--text-2); }
.user-menu-sep { height: 1px; background: var(--border); margin: .25rem .25rem; }
.user-menu-danger { color: var(--danger); }
.user-menu-danger .lucide-ic { color: var(--danger); }
.user-menu-danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }

/* ── Avatar crop modal ────────────────────────────────────────────────
   The stage is a square clip-area with the canvas behind a circle mask,
   so the user always sees what the round avatar will look like. The
   overlay draws the circle and a soft dimmer over the corners. */
.avatar-crop-stage {
  position: relative; overflow: hidden; border-radius: 16px;
  background: #000; cursor: grab; user-select: none; touch-action: none;
}
.avatar-crop-stage.is-dragging { cursor: grabbing; }
.avatar-crop-canvas { display: block; }
.avatar-crop-overlay {
  position: absolute; inset: 0; pointer-events: none;
  /* Dim everything outside the circle (radial mask via box-shadow). */
  border-radius: 50%;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55);
  outline: 1px dashed rgba(255, 255, 255, 0.35);
  outline-offset: -2px;
}

/* ── Topbar mobile layout ──────────────────────────────────────────────
   Below 640px the topbar would otherwise overflow horizontally
   (ticker chips + 3 icon buttons + company chip + page title). We:
     • Hide the company chip's id, keep its name truncated.
     • Tighten the gap and reduce icon button size by 4px.
     • Allow the actions row to shrink (page title can ellipsize).         */
@media (max-width: 720px) {
  .topbar {
    padding-top: calc(.55rem + env(safe-area-inset-top));
    padding-bottom: .55rem;
    padding-inline-start: calc(.8rem + env(safe-area-inset-left));
    padding-inline-end: calc(.8rem + env(safe-area-inset-right));
  }
  .topbar-actions { gap: .35rem; }
  .topbar-bell { width: 34px; height: 34px; border-radius: 9px; }
  .topbar-bell .lucide-ic { width: 1rem; height: 1rem; }
  .bell-panel { width: min(340px, calc(100vw - 16px)); }
}
@media (max-width: 480px) {
  .topbar-bell { width: 32px; height: 32px; }
  .bell-panel { width: calc(100vw - 16px); inset-inline-end: -8px; }
}
.bell-item {
  position: relative;
  display: flex; gap: .7rem;
  padding: .75rem 2rem .75rem 1rem;
  padding-inline-start: 1rem; padding-inline-end: 2rem;
  border-bottom: 1px solid var(--border); cursor: pointer;
  transition: background .15s ease;
}
.bell-item:last-child { border-bottom: 0; }
.bell-item:hover { background: var(--bg-3); }
.bell-item::after {
  content: '';
  position: absolute; top: 50%; inset-inline-end: 14px; transform: translateY(-50%);
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--accent-2); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-2) 25%, transparent);
  opacity: 0; transition: opacity .2s ease, transform .2s ease;
  pointer-events: none;
}
.bell-item.unread::after { opacity: 1; }
.bell-item-icon {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--card-2); border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent-2); flex-shrink: 0;
}
.bell-item.attendance-started .bell-item-icon { color: var(--success); background: color-mix(in srgb, var(--success) 12%, var(--card-2)); }
.bell-item.attendance-ended .bell-item-icon { color: #f59e0b; background: color-mix(in srgb, #f59e0b 12%, var(--card-2)); }
.bell-item.task-created .bell-item-icon { color: var(--accent-2); background: color-mix(in srgb, var(--accent-2) 12%, var(--card-2)); }
.bell-item.task-waiting_approval .bell-item-icon { color: #f59e0b; background: color-mix(in srgb, #f59e0b 12%, var(--card-2)); }
.bell-item.task-needs_changes .bell-item-icon { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, var(--card-2)); }
.bell-item.task-approved .bell-item-icon { color: var(--success); background: color-mix(in srgb, var(--success) 12%, var(--card-2)); }
.bell-item-body { flex: 1; min-width: 0; }
.bell-item-title { font-weight: 600; font-size: .88rem; margin: 0 0 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bell-item-sub { font-size: .8rem; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bell-item-time { font-size: .7rem; color: var(--text-3); margin-top: 2px; }
.main { padding: 1.2rem; }

.chip { display: inline-flex; align-items: center; gap: .35rem; padding: .25rem .55rem; border-radius: 999px; border: 1px solid var(--border-2); background: var(--card-2); font-size: .78rem; color: var(--text-2); }
.chip.primary { background: var(--accent); color: var(--accent-fg); border: 0; }
.chip.success { background: rgba(34,197,94,.15); color: var(--success); border: 1px solid rgba(34,197,94,.3); }
.chip.warn { background: rgba(245,158,11,.15); color: var(--warn); border: 1px solid rgba(245,158,11,.3); }
.chip.danger { background: rgba(239,68,68,.15); color: var(--danger); border: 1px solid rgba(239,68,68,.3); }

.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.stat {
  padding: 1rem 1.1rem; border-radius: var(--radius); background: var(--card); border: 1px solid var(--border);
  backdrop-filter: blur(var(--blur));
}
.stat .label { font-size: .75rem; color: var(--text-3); text-transform: uppercase; letter-spacing: .05em; }
.stat .value { font-size: 1.8rem; font-weight: 800; margin-top: .25rem; }

/* Compact KPI row atop the Attendance tab — keeps the table above the fold. */
.att-kpis .stat { padding: .6rem .8rem; }
.att-kpis .stat .label { font-size: .7rem; }
.att-kpis .stat .value { font-size: 1.25rem; margin-top: .1rem; }
.att-kpis [data-kpi] .stat { transition: transform .12s ease, border-color .12s ease; }
.att-kpis [data-kpi]:hover .stat { transform: translateY(-1px); border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); }
.att-kpis [data-kpi]:focus { outline: none; }
.att-kpis [data-kpi]:focus .stat { border-color: color-mix(in srgb, var(--danger) 55%, var(--border)); }

.table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.table th, .table td { text-align: start; padding: .7rem .75rem; border-bottom: 1px solid var(--border); }
.table th { color: var(--text-3); font-weight: 600; text-transform: uppercase; font-size: .74rem; letter-spacing: .05em; }
.table tr:hover td { background: var(--card-2); }

.modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.55); backdrop-filter: blur(6px); display: none; align-items: center; justify-content: center; z-index: 100; padding: 1rem; overflow-y: auto; }
.modal-backdrop.open { display: flex; }
.modal { background: var(--bg-2); border: 1px solid var(--border-2); border-radius: var(--radius-lg); padding: 1.5rem; max-width: 480px; width: 90%; box-shadow: var(--shadow-2); max-height: calc(100vh - 2rem); overflow-y: auto; }

/* Permissions modal (admin / employees) */
.btn-xs { padding: .2rem .55rem; font-size: .72rem; border-radius: 8px; font-weight: 600; }
.perm-modal {
  width: min(900px, 96vw);
  height: min(92vh, 940px); max-height: min(92vh, 940px);
  display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--border-2);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-2);
  overflow: hidden;
}
.perm-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem 1.2rem; border-bottom: 1px solid var(--border); gap: 1rem;
  flex-shrink: 0;
}
.perm-head-user { display: flex; align-items: center; gap: .8rem; min-width: 0; flex: 1; }
.perm-head-user-text { min-width: 0; flex: 1; }
.perm-head-title { font-weight: 700; font-size: 1rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perm-head-sub { display: flex; align-items: center; gap: .4rem; margin-top: .25rem; font-size: .78rem; color: var(--text-3); }
.perm-close {
  appearance: none; background: transparent; border: 0; cursor: pointer;
  width: 34px; height: 34px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-2); transition: background .15s ease, color .15s ease;
  flex-shrink: 0;
}
.perm-close:hover { background: var(--bg-3); color: var(--text); }
.perm-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1rem 1.2rem; display: flex; flex-direction: column; gap: .9rem; scrollbar-width: thin; scrollbar-color: var(--border-2) transparent; }
.perm-body::-webkit-scrollbar { width: 8px; }
.perm-body::-webkit-scrollbar-track { background: transparent; }
.perm-body::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.perm-body::-webkit-scrollbar-thumb:hover { background: var(--text-3); }
.perm-body-split { flex-direction: row; padding: 0; gap: 0; overflow: hidden; }
.perm-sidebar {
  flex: 0 0 240px; min-width: 240px;
  border-inline-end: 1px solid var(--border);
  background: var(--card-2);
  padding: .6rem .5rem;
  overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-2) transparent;
  display: flex; flex-direction: column; gap: 2px;
}
.perm-sidebar::-webkit-scrollbar { width: 6px; }
.perm-sidebar::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 3px; }
.perm-sidebar-item {
  appearance: none; background: transparent; border: 0; border-radius: 10px;
  padding: .65rem .7rem; cursor: pointer; text-align: start;
  display: flex; align-items: center; gap: .65rem;
  color: var(--text-2); font: inherit; font-weight: 600;
  transition: background .15s ease, color .15s ease;
  width: 100%;
}
.perm-sidebar-item:hover { background: var(--bg-3); color: var(--text); }
.perm-sidebar-item.active { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--text); }
.perm-sidebar-item.active .perm-sidebar-icon { color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, var(--bg-2)); }
.perm-sidebar-icon {
  width: 30px; height: 30px; border-radius: 9px;
  background: var(--bg-3); color: var(--text-2);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background .15s ease, color .15s ease;
}
.perm-sidebar-label { flex: 1; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perm-sidebar-count {
  font-size: .72rem; font-weight: 700; color: var(--text-3);
  background: var(--bg-2); border: 1px solid var(--border);
  padding: .12rem .45rem; border-radius: 999px;
  font-variant-numeric: tabular-nums; flex-shrink: 0;
}
.perm-sidebar-item.active .perm-sidebar-count { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.perm-content {
  flex: 1 1 auto; min-width: 0; overflow-y: auto;
  padding: 1rem 1.2rem; display: flex; flex-direction: column; gap: .65rem;
  scrollbar-width: thin; scrollbar-color: var(--border-2) transparent;
}
.perm-content::-webkit-scrollbar { width: 8px; }
.perm-content::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.perm-content-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; padding-bottom: .8rem; margin-bottom: .2rem;
  border-bottom: 1px solid var(--border);
}
.perm-content-head h4 { margin: 0 0 .2rem; font-size: 1.02rem; font-weight: 700; }
.perm-content-head p { margin: 0; font-size: .82rem; color: var(--text-3); line-height: 1.45; }
.perm-content-actions { display: flex; gap: .3rem; flex-shrink: 0; }
@media (max-width: 720px) {
  .perm-body-split { flex-direction: column; }
  .perm-sidebar { flex: 0 0 auto; min-width: 0; width: 100%; border-inline-end: 0; border-bottom: 1px solid var(--border); flex-direction: row; overflow-x: auto; overflow-y: hidden; padding: .5rem .5rem; }
  .perm-sidebar-item { width: auto; flex-shrink: 0; }
  .perm-sidebar-label { max-width: 140px; }
}
.perm-group {
  background: var(--card); border: 1px solid var(--border);
  border-radius: 14px; overflow: hidden;
}
.perm-group-head {
  display: flex; align-items: center; gap: .6rem;
  padding: .7rem .9rem; border-bottom: 1px solid var(--border);
  background: var(--card-2);
}
.perm-group-icon {
  width: 32px; height: 32px; border-radius: 10px;
  background: color-mix(in srgb, var(--accent-2) 10%, var(--bg-2));
  color: var(--accent-2);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.perm-group-head h4 { margin: 0; font-size: .9rem; font-weight: 700; }
.perm-group-count { font-size: .75rem; color: var(--text-3); font-variant-numeric: tabular-nums; flex: 1; margin-inline-start: .2rem; }
.perm-group-actions { display: flex; gap: .3rem; flex-shrink: 0; }
.perm-group-body { display: flex; flex-direction: column; padding: .35rem .45rem .5rem; }
.perm-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .7rem .8rem; border-radius: 10px; cursor: pointer;
  transition: background .15s ease;
  width: 100%; box-sizing: border-box;
}
.perm-row + .perm-row { margin-top: 2px; }
.perm-row:hover { background: var(--bg-3); }
.perm-row:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.perm-row-text { min-width: 0; flex: 1; }
.perm-row-title { font-weight: 600; font-size: .9rem; }
.perm-row-desc { font-size: .78rem; color: var(--text-3); margin-top: 2px; line-height: 1.35; }

/* Permissions toggle (button-based, RTL-safe, no input-absolute trick) */
.perm-switch {
  appearance: none; -webkit-appearance: none;
  border: 1px solid var(--border); background: var(--bg-3);
  width: 44px; height: 24px; border-radius: 999px; padding: 0;
  position: relative; cursor: pointer; flex-shrink: 0;
  transition: background .18s ease, border-color .18s ease;
  display: inline-block; vertical-align: middle;
}
.perm-switch-thumb {
  position: absolute; top: 1px; inset-inline-start: 1px;
  width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3);
  transition: inset-inline-start .18s ease;
  pointer-events: none;
}
.perm-switch.on { background: var(--accent); border-color: var(--accent); }
.perm-switch.on .perm-switch-thumb { inset-inline-start: 22px; background: var(--accent-fg); }
.perm-switch:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }

.perm-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: .9rem 1.2rem; border-top: 1px solid var(--border);
  background: var(--bg-2); flex-shrink: 0;
}
.perm-foot-summary { font-size: .85rem; color: var(--text-2); font-weight: 600; font-variant-numeric: tabular-nums; }
.modal h3 { margin: 0 0 .5rem; }

/* Workspace tabs (segmented horizontal pill) */
.ws-tabs { display: flex; gap: .25rem; padding: .35rem; background: var(--card-2); border: 1px solid var(--border); border-radius: 14px; margin-bottom: 1.1rem; overflow-x: auto; scrollbar-width: none; }
.ws-tabs::-webkit-scrollbar { display: none; }
.ws-tab { appearance: none; border: 0; background: transparent; padding: .6rem 1rem; border-radius: 10px; font-weight: 600; font-size: .9rem; color: var(--text-2); cursor: pointer; transition: background .15s ease, color .15s ease; white-space: nowrap; display: inline-flex; align-items: center; gap: .5rem; flex-shrink: 0; font-family: inherit; }
.ws-tab .lucide-ic, .ws-tab svg { width: 16px; height: 16px; }
.ws-tab:hover { color: var(--text); background: var(--bg-3); }
.ws-tab.active { background: var(--bg); color: var(--text); box-shadow: 0 1px 2px rgba(0,0,0,.18); }
html.light .ws-tab.active { box-shadow: 0 1px 3px rgba(15,23,42,.08); }

.kbd { font-family: ui-monospace, SF Mono, Menlo, monospace; font-size: .85rem; padding: 2px 6px; background: var(--bg-3); border: 1px solid var(--border); border-radius: 6px; }

.toast { position: fixed; bottom: 24px; inset-inline-end: 24px; background: var(--bg-2); border: 1px solid var(--border-2); padding: .9rem 1.1rem; border-radius: 12px; box-shadow: var(--shadow-2); z-index: 200; opacity: 0; transform: translateY(8px); transition: opacity .2s, transform .2s; }
.toast.show { opacity: 1; transform: translateY(0); }
.toast.error { border-inline-start: 4px solid var(--danger); }
.toast.success { border-inline-start: 4px solid var(--success); }

.top-toast-host { position: fixed; top: 14px; inset-inline: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; z-index: 300; pointer-events: none; }
.top-toast { background: var(--bg-2); border: 1px solid var(--border-2); box-shadow: var(--shadow-2); padding: .6rem 1rem; border-radius: 999px; display: inline-flex; align-items: center; gap: .6rem; max-width: 90vw; font-weight: 600; opacity: 0; transform: translateY(-12px); transition: opacity .25s, transform .25s; pointer-events: auto; }
.top-toast.show { opacity: 1; transform: translateY(0); }
.top-toast.success { border-inline-start: 4px solid var(--success); }
.top-toast.info { border-inline-start: 4px solid var(--info, #4ea1ff); }
.top-toast-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--success); box-shadow: 0 0 0 3px rgba(0,200,120,.18); animation: top-toast-pulse 1.4s ease-out infinite; }
.top-toast.info .top-toast-dot { background: var(--info, #4ea1ff); box-shadow: 0 0 0 3px rgba(78,161,255,.18); }
@keyframes top-toast-pulse { 0% { box-shadow: 0 0 0 0 rgba(0,200,120,.35); } 100% { box-shadow: 0 0 0 10px rgba(0,200,120,0); } }

.status-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--bg-3); margin-inline-end: .4rem; vertical-align: middle; }
.status-dot.working { background: var(--success); box-shadow: 0 0 0 0 rgba(0,200,120,.55); animation: top-toast-pulse 1.6s ease-out infinite; }
.status-dot.paused { background: var(--warn); }
.status-dot.ended { background: var(--text-subtle, #888); }
.status-dot.completed { background: var(--success); }
.status-dot.overtime { background: var(--info); box-shadow: 0 0 0 0 rgba(78,161,255,.55); animation: top-toast-pulse 1.6s ease-out infinite; }
.status-dot.due { background: var(--warn); box-shadow: 0 0 0 0 rgba(245,158,11,.55); animation: top-toast-pulse 1.4s ease-out infinite; }

/* Shift pill — compact ribbon above the attendance card on the employee
   shift page. Carries a status-dot on the left and a short dynamic label on
   the right. Variants tint the background so the viewer can read state at
   a glance without reading text. */
.shift-pill {
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .5rem .85rem; border-radius: 999px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  font-size: .88rem; font-weight: 600; color: var(--text);
  max-width: 100%;
}
.shift-pill .shift-pill-sub { color: var(--text-2); font-weight: 500; margin-inline-start: .3rem; }
.shift-pill.due {
  border-color: color-mix(in srgb, var(--warn) 55%, var(--border));
  background: color-mix(in srgb, var(--warn) 10%, var(--bg-2));
}
.shift-pill.working {
  border-color: color-mix(in srgb, var(--success) 45%, var(--border));
  background: color-mix(in srgb, var(--success) 10%, var(--bg-2));
}
.shift-pill.completed, .shift-pill.ended {
  border-color: color-mix(in srgb, var(--info) 35%, var(--border));
  background: color-mix(in srgb, var(--info) 8%, var(--bg-2));
}
.shift-pill.overtime {
  border-color: color-mix(in srgb, var(--info) 55%, var(--border));
  background: color-mix(in srgb, var(--info) 12%, var(--bg-2));
}

/* Segmented control — used in admin schedule card to toggle between
   "fixed shift" and "flexible hours" modes. */
.segmented {
  display: inline-flex;
  padding: .25rem;
  border-radius: .6rem;
  background: var(--bg-3);
  border: 1px solid var(--border);
  gap: .25rem;
}
.segmented .seg-btn {
  appearance: none;
  border: 0; background: transparent; cursor: pointer;
  padding: .45rem .9rem; border-radius: .45rem;
  font: inherit; font-weight: 600; color: var(--text-2);
  transition: background .15s ease, color .15s ease;
}
.segmented .seg-btn.is-active {
  background: var(--bg-1, var(--bg-2));
  color: var(--text);
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
}
.segmented .seg-btn:hover:not(.is-active) { color: var(--text); }

/* Auth / splash */
.splash { min-height: 100vh; display: grid; place-items: center; padding: 1.25rem; }
.auth-card { width: 100%; max-width: 440px; padding: 2rem; }
.auth-card h1 { margin: 0 0 .5rem; font-size: 1.7rem; }
.auth-card p.sub { color: var(--text-2); margin: 0 0 1.5rem; }

/* ── Auth split layout (Linear/Notion style) ───────────────────────────
   Two-column login: brand panel on the leading edge (visually right in
   RTL, left in LTR), form on the trailing edge. The brand panel carries
   a deep emerald gradient, soft aurora glows, the logo, a mission quote,
   and tiny social-proof stats. On phones the brand panel collapses and
   a compact mobile brand block at the top of the form replaces it. */
.auth-split {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1.05fr; /* form panel slightly wider for breathing room */
  background: var(--bg);
  color: var(--text);
}

/* ── Aside: brand + quote + stats ─────────────────────────────────── */
.auth-aside {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 3rem 3.2rem;
  color: #ecfdf5;
  /* Layered emerald gradient — a deep base diagonal, then two radial
     glows that hint at depth without leaning on heavy shadows. The glows
     read as "atmosphere" rather than decoration. */
  background:
    radial-gradient(circle at 18% 22%, color-mix(in srgb, #34d399 30%, transparent), transparent 55%),
    radial-gradient(circle at 82% 78%, color-mix(in srgb, #10b981 22%, transparent), transparent 55%),
    linear-gradient(135deg, #022c22 0%, #064e3b 38%, #047857 100%);
  isolation: isolate;
}
/* Slow drifting aurora — adds life without distracting from the quote.
   Disabled for users who prefer reduced motion. */
.auth-aside::before,
.auth-aside::after {
  content: '';
  position: absolute;
  width: 70%;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  filter: blur(80px);
  opacity: .55;
  z-index: 0;
  pointer-events: none;
  animation: auth-aurora 22s ease-in-out infinite alternate;
}
.auth-aside::before {
  inset-inline-start: -10%;
  top: -20%;
  background: radial-gradient(circle, #34d399 0%, transparent 70%);
}
.auth-aside::after {
  inset-inline-end: -15%;
  bottom: -20%;
  background: radial-gradient(circle, #059669 0%, transparent 70%);
  animation-delay: -11s;
}
@keyframes auth-aurora {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(2%, -3%) scale(1.06); }
  100% { transform: translate(-2%, 3%) scale(.98); }
}
@media (prefers-reduced-motion: reduce) {
  .auth-aside::before,
  .auth-aside::after { animation: none; }
}

.auth-aside > * { position: relative; z-index: 1; }

.auth-brand {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}
.auth-brand-logo {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  display: grid;
  place-items: center;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .25);
}
.auth-brand-logo img,
.auth-brand-logo svg { width: 28px; height: 28px; }
.auth-brand-name {
  font-size: 1.5rem;
  font-weight: 800;
  margin: 0;
  letter-spacing: -0.01em;
  color: #fff;
}
.auth-brand-tagline {
  font-size: 0.8rem;
  font-weight: 500;
  opacity: 0.78;
  margin: 0.1rem 0 0;
}

.auth-quote {
  margin: 0;
  padding: 0;
  max-width: 540px;
}
.auth-quote-mark {
  font-family: 'Georgia', serif;
  font-size: 5rem;
  line-height: 0.6;
  opacity: 0.28;
  margin-bottom: 0.4rem;
  display: block;
  font-weight: 700;
}
.auth-quote-text {
  font-size: 1.55rem;
  font-weight: 700;
  line-height: 1.55;
  color: #fff;
  margin: 0 0 1.5rem;
  letter-spacing: -0.005em;
}
.auth-quote-cite {
  font-style: normal;
  display: block;
  font-size: 0.95rem;
  font-weight: 700;
  opacity: 0.92;
}
.auth-quote-cite small {
  display: block;
  font-size: 0.78rem;
  font-weight: 500;
  opacity: 0.65;
  margin-top: 0.2rem;
}

.auth-stats {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-size: 0.78rem;
  font-weight: 600;
  opacity: 0.78;
  flex-wrap: wrap;
}
.auth-stats-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.55;
}

/* ── Main: form ───────────────────────────────────────────────────── */
.auth-main {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 2rem 3rem;
}
.auth-main-actions {
  position: absolute;
  top: 1.4rem;
  inset-inline-end: 1.4rem;
  display: flex;
  gap: 0.35rem;
  z-index: 2;
}
.auth-main-actions .btn-icon {
  width: 36px;
  height: 36px;
  border-radius: 10px;
}

.auth-mobile-brand {
  display: none; /* hidden on desktop — aside owns the brand there */
}

.auth-form {
  margin: auto 0;
  width: 100%;
  max-width: 380px;
  align-self: center;
}
.auth-form-title {
  margin: 0 0 0.4rem;
  font-size: 1.7rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--text);
}
.auth-form-sub {
  margin: 0 0 2rem;
  font-size: 0.92rem;
  color: var(--text-3);
}
.auth-form .label { font-size: 0.78rem; font-weight: 600; color: var(--text-2); margin-bottom: 0.4rem; }
.auth-form .input { font-size: 0.95rem; padding: 0.7rem 0.85rem; }

.auth-footer {
  margin-top: auto;
  padding-top: 1.5rem;
  font-size: 0.75rem;
  color: var(--text-3);
  text-align: center;
}

/* ── Mobile (<= 900px): collapse the aside, show compact brand on top ── */
@media (max-width: 900px) {
  .auth-split {
    grid-template-columns: 1fr;
    min-height: 100dvh; /* dvh = real viewport height (handles iOS chrome) */
  }
  .auth-aside {
    display: none;
  }
  .auth-main {
    padding: 1.6rem 1.5rem 2rem;
    min-height: 100dvh;
    justify-content: center;
  }
  .auth-mobile-brand {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    justify-content: center;
    margin-bottom: 2rem;
  }
  .auth-mobile-brand .auth-brand-logo {
    width: 44px;
    height: 44px;
    border-radius: 12px;
    background: var(--accent-grad, linear-gradient(135deg, #059669, #34d399));
    border: none;
  }
  .auth-mobile-brand .auth-brand-name { color: var(--text); font-size: 1.25rem; }
  .auth-mobile-brand .auth-brand-tagline { color: var(--text-3); }
  .auth-form-title { font-size: 1.4rem; text-align: center; }
  .auth-form-sub { text-align: center; }
}

/* Tighter for very small phones */
@media (max-width: 380px) {
  .auth-main { padding: 1.2rem 1rem 1.6rem; }
  .auth-form-title { font-size: 1.25rem; }
}

/* Avatar */
/* Avatars get an inline `background: hsl(...)` from UI.avatarColor in
   almost all cases, where white initials read well on the medium-lightness
   colored backgrounds. The default fallback (no name hashed yet) uses the
   accent color; --accent-fg keeps initials legible when accent is white. */
.avatar { width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 700; color: #fff; background: var(--accent); flex-shrink: 0; font-size: .85rem; }
.avatar:not([style*="background"]) { color: var(--accent-fg); }
.avatar.lg { width: 48px; height: 48px; font-size: 1rem; }

/* ── Task stages settings panel ───────────────────────────────────────
   The "choose how stages look" section at /admin/settings.html#stages.
   Three preview cards + table of status rows with color + toggle + drag. */
.stage-mode-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: .6rem;
}
@media (max-width: 720px) { .stage-mode-grid { grid-template-columns: 1fr; } }
.stage-mode-card {
  background: var(--card); border: 1.5px solid var(--border);
  border-radius: 12px; padding: .8rem .9rem; cursor: pointer;
  display: flex; flex-direction: column; gap: .4rem; align-items: stretch;
  text-align: start; transition: all .15s;
}
.stage-mode-card:hover { border-color: var(--border-2); }
.stage-mode-card.selected { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.stage-mode-preview {
  display: flex; align-items: center; gap: .4rem;
  padding: .5rem .7rem; border-radius: 8px;
  background: var(--bg-2); border: 1px solid var(--border);
}
.stage-mode-preview-default .stage-mode-dot { display: none; }
.stage-mode-preview-dot .stage-mode-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--brand); display: inline-block; flex: 0 0 auto;
}
.stage-mode-preview-tint {
  background: color-mix(in srgb, var(--brand) 18%, var(--bg-2));
  border-color: color-mix(in srgb, var(--brand) 35%, var(--border));
}
.stage-mode-preview-tint .stage-mode-dot { display: none; }
.stage-mode-name { font-size: .85rem; color: var(--text); font-weight: 600; }
.stage-mode-label { font-size: .85rem; font-weight: 700; color: var(--text); }
.stage-mode-hint { font-size: .72rem; color: var(--text-3); line-height: 1.45; }

/* Search field inside stages section */
.stage-search {
  position: relative; min-width: 220px; flex: 1 1 240px; max-width: 360px;
}
.stage-search > input {
  width: 100%; padding: .45rem .7rem .45rem 2.1rem;
  border-radius: 8px; background: var(--bg-2);
  border: 1px solid var(--border); color: var(--text);
  outline: none; font-size: .85rem;
}
html[dir="rtl"] .stage-search > input { padding: .45rem 2.1rem .45rem .7rem; }
.stage-search > input:focus { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.stage-search > .lucide-ic {
  position: absolute; top: 50%; transform: translateY(-50%);
  inset-inline-start: .7rem; width: 1rem; height: 1rem;
  color: var(--text-3); pointer-events: none;
}

/* Stage table */
.stage-table {
  border: 1px solid var(--border); border-radius: 10px;
  overflow: hidden; background: var(--card);
}
.stage-table-head, .stage-row {
  display: grid; grid-template-columns: 30px 1fr 80px 140px;
  gap: .6rem; align-items: center;
  padding: .5rem .7rem;
}
.stage-table-head {
  background: var(--bg-2); font-size: .75rem; color: var(--text-3);
  font-weight: 600; border-bottom: 1px solid var(--border);
}
.stage-row {
  border-bottom: 1px solid var(--border);
  transition: background .12s;
}
.stage-row:last-child { border-bottom: none; }
.stage-row:hover { background: var(--bg-2); }
.stage-row.drag-over { background: var(--bg-3); outline: 2px dashed var(--ring); outline-offset: -4px; }
.td-handle {
  cursor: grab; color: var(--text-3); user-select: none;
  text-align: center; font-size: 1rem; line-height: 1;
}
.td-handle:active { cursor: grabbing; }
.td-name {
  display: flex; align-items: center; gap: .55rem;
  color: var(--text); font-size: .88rem; font-weight: 500;
}
.td-name .stage-dot {
  width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
}
.color-swatch {
  display: inline-block; width: 34px; height: 28px;
  border-radius: 6px; cursor: pointer;
  border: 1.5px solid var(--border-2);
  position: relative; overflow: hidden;
}
.color-swatch > input[type="color"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: none;
}
.td-reports { display: flex; align-items: center; }

/* ── Kanban: per-status colors + display modes ─────────────────────
   Columns read the active display mode from `.kanban[data-mode]` set
   by the render code, and per-column colors from an inline
   `--col-color` CSS variable so the three modes (default/dot/tint)
   share the same DOM but look entirely different. */
/* Tint mode: colored accent bar on top of the header box (GHL-style)
   + gentle tint on the column body. Border stays the neutral gray so the
   rectangle shape remains consistent across all three modes. */
.kanban[data-mode="tint"] .kanban-col > h4 {
  border-top-width: 3px;
  border-top-color: var(--col-color, var(--border-2));
}
.kanban[data-mode="tint"] .kanban-col .col-body {
  background: color-mix(in srgb, var(--col-color, transparent) 6%, transparent);
  border-radius: 8px;
}
/* Dot mode: inline colored dot inside the header, before the label. */
.kanban[data-mode="dot"] .kanban-col > h4::before {
  content: ""; display: inline-block;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--col-color, var(--border-2));
  flex: 0 0 auto;
}
/* Default mode has no color accent — just the plain header box. */
/* Default mode has no color accents — just the plain header text */

/* Tasks page layout — Asana-inspired. The whole board lives inside a
   viewport-bounded flex column so the kanban scrolls internally (per-col)
   instead of pushing the sidebar/topbar around. The columns themselves are
   "containerless" — no border, no card bg — letting task cards float over
   the page background with clean typography-first column headers. */
.tasks-board {
  height: calc(100vh - var(--topbar-h) - 2.4rem);
  display: flex; flex-direction: column; gap: .8rem;
  min-height: 0; min-width: 0; width: 100%; max-width: 100%;
}
.tasks-toolbar { flex: 0 0 auto; }
.tasks-viewport {
  flex: 1 1 auto; min-height: 0; min-width: 0; width: 100%;
  display: flex; overflow: hidden;
}

/* View-toggle tabs — flat, underline-on-active, no boxes. */
.view-tabs { display: flex; align-items: center; gap: .2rem; }
.view-tab {
  background: transparent; border: none;
  padding: .45rem .85rem;
  color: var(--text-2); font-size: .92rem; font-weight: 500;
  cursor: pointer; border-radius: 8px;
  position: relative; transition: color .15s, background .15s;
}
.view-tab:hover { background: var(--bg-2); color: var(--text); }
.view-tab.active { color: var(--text); font-weight: 700; }
.view-tab.active::after {
  content: ""; position: absolute; left: 12%; right: 12%; bottom: -2px;
  height: 2px; background: var(--accent-grad); border-radius: 2px;
}

/* Kanban — borderless columns, clean headers, cards are the only visible
   surfaces. This matches the Asana/Linear aesthetic where "empty columns
   are invisible" and the focus is on the tasks themselves. */
.kanban {
  display: grid; grid-auto-flow: column; grid-auto-columns: 288px;
  gap: 1.2rem;
  overflow-x: auto; overflow-y: hidden;
  flex: 1 1 auto; height: 100%; padding-bottom: 4px;
  scrollbar-width: thin;
}
.kanban::-webkit-scrollbar { height: 8px; }
.kanban::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.kanban-col {
  background: transparent; border: none; padding: 0;
  display: flex; flex-direction: column;
  max-height: 100%; min-height: 0;
}
.kanban-col h4 {
  /* Column header styled as a thin rounded card (GHL-inspired): soft
     border, subtle background tint, modest corner radius. Stays legible
     in both light + dark via the theme tokens. */
  margin: 0 0 .7rem;
  padding: .5rem .75rem;
  font-size: .92rem; font-weight: 700; text-transform: none; letter-spacing: 0;
  color: var(--text);
  display: flex; justify-content: space-between; align-items: center; gap: .5rem;
  flex: 0 0 auto;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-2);
}
.kanban-col h4 .col-count {
  background: transparent; border: none;
  color: var(--text-3); font-weight: 500; font-size: .82rem;
  padding: 0; margin: 0;
}
.kanban-col .col-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  padding: 2px 2px 4px;
  scrollbar-width: thin;
}
.kanban-col .col-body::-webkit-scrollbar { width: 6px; }
.kanban-col .col-body::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 3px; }

/* Task card — subtle bg, very light border, soft shadow on hover.
   The "floating" feel comes from shadow not border weight. */
.kanban-task {
  position: relative;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: .75rem .85rem;
  margin-bottom: .55rem;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s, transform .12s;
}
.kanban-task:hover {
  border-color: var(--border-2);
  box-shadow: 0 2px 10px rgba(0,0,0,.18);
  transform: translateY(-1px);
}
.kanban-task.dragging { opacity: .4; }
.kanban-task .t-title { font-weight: 600; margin-bottom: .3rem; font-size: .92rem; line-height: 1.35; padding-inline-end: 1.6rem; }
.kanban-task .t-meta {
  display: flex; justify-content: space-between; align-items: center;
  color: var(--text-3); font-size: .76rem;
  margin-top: .4rem;
}

/* Hover action icons (pen / like) — appear top-left in RTL, top-right in LTR. */
.kanban-task .t-actions {
  position: absolute; top: .55rem; inset-inline-end: .55rem;
  display: flex; gap: .25rem;
  opacity: 0; transition: opacity .15s;
}
.kanban-task:hover .t-actions { opacity: 1; }
.kanban-task .t-act {
  width: 24px; height: 24px; border-radius: 6px;
  background: var(--bg-2); border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-2); cursor: pointer;
  transition: background .12s, color .12s;
}
.kanban-task .t-act:hover { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
.kanban-task .t-act .lucide-ic { width: .85rem; height: .85rem; }

/* Empty-column placeholder — even lighter now. */
.kanban-col .col-empty {
  font-size: .78rem; color: var(--text-3); text-align: center;
  padding: 1.2rem .4rem; opacity: .5;
}

/* ── Task filter bar (search + dropdowns + active chips) ──────────────
   Lives inside .tasks-toolbar as a second row; collapses active filter
   chips below the search field so the user can scan what's applied. */
.task-filter-bar {
  display: flex; align-items: center; gap: .5rem;
  flex-wrap: wrap; width: 100%;
}
.task-filter-search {
  flex: 1 1 260px; min-width: 200px; max-width: 380px;
  position: relative;
}
.task-filter-search > input {
  width: 100%; padding: .5rem .75rem .5rem 2.1rem;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg-2); color: var(--text);
  outline: none; font-size: .88rem;
  transition: border-color .12s, box-shadow .12s;
}
html[dir="rtl"] .task-filter-search > input { padding: .5rem 2.1rem .5rem .75rem; }
.task-filter-search > input:focus { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.task-filter-search > .lucide-ic {
  position: absolute; top: 50%; transform: translateY(-50%);
  inset-inline-start: .7rem; color: var(--text-3);
  width: 1rem; height: 1rem; pointer-events: none;
}
.task-filter-search > button.clear {
  position: absolute; top: 50%; transform: translateY(-50%);
  inset-inline-end: .5rem; background: transparent; border: none;
  color: var(--text-3); cursor: pointer; padding: .2rem; border-radius: 6px;
  display: inline-flex;
}
.task-filter-search > button.clear:hover { color: var(--text); background: var(--bg-3); }

.task-filter-dropdown { position: relative; }
.task-filter-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem .75rem; background: var(--bg-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px;
  cursor: pointer; font-size: .88rem;
}
.task-filter-btn:hover { border-color: var(--border-2); }
.task-filter-btn .count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; border-radius: 999px;
  background: var(--accent); color: var(--accent-fg);
  font-size: .7rem; font-weight: 700; padding: 0 5px;
}
.task-filter-menu {
  position: absolute; top: calc(100% + 6px); inset-inline-start: 0;
  min-width: 280px; max-width: 380px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: 0 14px 40px rgba(0,0,0,.35);
  padding: .8rem; z-index: 40;
  animation: fade-in .14s ease;
}
.task-filter-menu > .group { margin-bottom: .8rem; }
.task-filter-menu > .group:last-child { margin-bottom: 0; }
.task-filter-menu > .group > .label {
  font-size: .78rem; color: var(--text-3); margin-bottom: .35rem;
  font-weight: 600;
}
.task-filter-menu .chip-row { display: flex; flex-wrap: wrap; gap: .3rem; }
.task-filter-menu .chip-row > button {
  padding: .25rem .55rem; background: var(--bg-2); color: var(--text-2);
  border: 1px solid var(--border); border-radius: 999px;
  font-size: .76rem; cursor: pointer; transition: all .12s;
}
.task-filter-menu .chip-row > button.on {
  background: var(--accent); color: var(--accent-fg); border-color: transparent;
}
.task-filter-menu select, .task-filter-menu input[type="date"] {
  width: 100%; padding: .4rem .55rem; border-radius: 8px;
  background: var(--bg-2); border: 1px solid var(--border);
  color: var(--text); outline: none; font-size: .85rem;
}
.task-filter-menu .range { display: grid; grid-template-columns: 1fr 1fr; gap: .4rem; }
.task-filter-menu .menu-foot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: .7rem; padding-top: .7rem; border-top: 1px solid var(--border);
}

.task-filter-active {
  display: flex; flex-wrap: wrap; gap: .3rem;
  margin-top: .5rem; width: 100%;
}
.task-filter-active > .chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .2rem .55rem; background: color-mix(in srgb, var(--accent) 14%, var(--bg-2));
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
  color: var(--text); font-size: .76rem;
}
.task-filter-active > .chip > button {
  background: transparent; border: none; color: var(--text-2);
  cursor: pointer; padding: 0; line-height: 1; font-size: .9rem;
}
.task-filter-active > .chip > button:hover { color: var(--text); }

/* ── Completed column: monthly groups ─────────────────────────────────
   Current month's tasks show inline (list of cards). Older months
   collapse into <details> accordions labeled "Month Year · N" so the
   column stays tidy once a team has hundreds of finished tasks. */
.completed-month-group {
  margin-bottom: .55rem; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--border);
}
.completed-month-group > summary {
  list-style: none; cursor: pointer; user-select: none;
  padding: .5rem .65rem;
  display: flex; align-items: center; justify-content: space-between;
  font-size: .82rem; font-weight: 600; color: var(--text-2);
  background: var(--bg-2);
  transition: background .12s;
}
.completed-month-group > summary::-webkit-details-marker { display: none; }
.completed-month-group > summary:hover { background: var(--bg-3); color: var(--text); }
.completed-month-group > summary::before {
  content: "▸"; margin-inline-end: .5rem; font-size: .7rem;
  transition: transform .15s; display: inline-block;
}
html[dir="rtl"] .completed-month-group > summary::before { content: "◂"; }
.completed-month-group[open] > summary::before { transform: rotate(90deg); }
html[dir="rtl"] .completed-month-group[open] > summary::before { transform: rotate(-90deg); }
.completed-month-group > summary > .mg-count {
  background: var(--bg-3); padding: .05rem .45rem; border-radius: 999px;
  font-size: .72rem; color: var(--text-3); font-weight: 500;
}
.completed-month-group > .mg-body { padding: .55rem .35rem .3rem; }

/* Current month — same accordion but with a subtle accent on the header
   so the admin can tell at a glance which month is "live" without
   reading dates. Still collapsible on click. */
.completed-month-group.current > summary {
  background: color-mix(in srgb, var(--success) 8%, var(--bg-2));
  color: var(--text);
}
.completed-month-group.current > summary:hover {
  background: color-mix(in srgb, var(--success) 14%, var(--bg-2));
}

/* Bottom "+ Add task" row inside each column — Asana-style subtle button. */
.kanban-col .col-add {
  margin-top: .35rem; padding: .55rem .6rem;
  background: transparent; border: 1px dashed transparent;
  color: var(--text-3); font-size: .82rem;
  display: flex; align-items: center; gap: .4rem;
  cursor: pointer; border-radius: 10px;
  transition: background .12s, color .12s, border-color .12s;
}
.kanban-col .col-add:hover {
  background: var(--bg-2); color: var(--text); border-color: var(--border-2);
}

/* ── Baton bar (pipeline task visualization) ───────────────────────────
   A row of dots connected by lines, one per stage. Works inside task
   cards (compact) and task detail modals (with labels below). Uses logical
   properties so it mirrors correctly in RTL/LTR. */
.baton-bar { display: flex; align-items: center; gap: 0; margin-top: .55rem; }
.baton-bar.with-labels { flex-wrap: wrap; }
.baton-seg { flex: 1 1 0; display: flex; align-items: center; min-width: 0; }
.baton-seg:last-child { flex: 0 0 auto; }
.baton-dot {
  width: 14px; height: 14px; border-radius: 50%;
  background: transparent; border: 2px solid var(--border-2);
  flex: 0 0 auto; position: relative; transition: all .2s;
}
.baton-dot.done {
  background: linear-gradient(135deg, var(--brand), var(--brand-pressed)); border-color: transparent;
  box-shadow: 0 2px 6px color-mix(in srgb, var(--brand) 35%, transparent);
}
.baton-dot.active {
  background: var(--accent); border-color: transparent;
  box-shadow: 0 0 0 4px var(--ring-glow);
  animation: baton-pulse 1.8s ease-in-out infinite;
}
.baton-dot.submitted {
  background: linear-gradient(135deg, #f59e0b, #d97706); border-color: transparent;
  box-shadow: 0 0 0 4px rgba(245, 158, 11, .22);
  animation: baton-pulse-amber 1.8s ease-in-out infinite;
}
@keyframes baton-pulse-amber {
  0%,100% { box-shadow: 0 0 0 4px rgba(245, 158, 11, .22); }
  50%     { box-shadow: 0 0 0 7px rgba(245, 158, 11, .08); }
}
.baton-dot.returned {
  background: rgba(239,68,68,.15); border-color: #ef4444;
}
@keyframes baton-pulse {
  0%,100% { box-shadow: 0 0 0 4px var(--ring-glow); }
  50%     { box-shadow: 0 0 0 7px var(--accent-soft); }
}
.baton-line {
  flex: 1 1 auto; height: 2px; background: var(--border-2); margin: 0 2px;
  min-width: 10px;
}
.baton-line.done { background: linear-gradient(90deg, var(--brand), var(--brand-pressed)); }
html[dir="rtl"] .baton-line.done { background: linear-gradient(270deg, var(--brand), var(--brand-pressed)); }

/* Labels under baton bar (used in modal, not in card) */
.baton-labels {
  display: flex; gap: 2px; margin-top: .35rem;
  font-size: .72rem; color: var(--text-3);
}
.baton-labels > span {
  flex: 1 1 0; min-width: 0; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  padding: 0 .15rem;
}
.baton-labels > span.active { color: var(--text); font-weight: 600; }

/* Stage chip on the card (shows "Now at: [stage name]") */
.stage-now-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .2rem .5rem; border-radius: 8px;
  background: var(--accent-soft); color: var(--text);
  border: 1px solid var(--accent-soft-border);
  font-size: .72rem; font-weight: 600;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stage-now-chip.sla-breached {
  background: rgba(239,68,68,.12); color: #ef4444;
  border-color: rgba(239,68,68,.3);
}

/* Team task progress (N/M completed) */
.team-progress { display: flex; align-items: center; gap: .4rem; font-size: .75rem; color: var(--text-2); }
.team-progress .bar { flex: 1 1 auto; height: 4px; background: var(--border-2); border-radius: 2px; overflow: hidden; min-width: 40px; }
.team-progress .bar > span { display: block; height: 100%; background: var(--accent-grad); border-radius: 2px; transition: width .3s; }

/* ── Task-type picker (3-mode modal) ───────────────────────────────── */
.mode-pick { display: grid; grid-template-columns: repeat(3, 1fr); gap: .7rem; margin-bottom: 1rem; }
@media (max-width: 720px) { .mode-pick { grid-template-columns: 1fr; } }
.mode-card {
  border: 1.5px solid var(--border); border-radius: 14px; padding: 1rem .8rem;
  background: var(--card); cursor: pointer; text-align: center;
  transition: all .18s; display: flex; flex-direction: column; gap: .35rem;
  align-items: center;
}
.mode-card:hover { border-color: var(--ring); transform: translateY(-1px); }
.mode-card.selected {
  border-color: var(--ring); background: var(--bg-2);
  box-shadow: 0 0 0 3px var(--ring-glow);
}
/* Mode-card icon — was raw emoji; now hosts a Lucide SVG via UI.icon().
   Wrapped in a brand-tinted rounded square so the picker echoes the
   sidebar's active-nav-state pattern (consistent visual language). The
   selected card swaps to a filled brand container — see selector below. */
.mode-card .mode-icon {
  width: 44px; height: 44px;
  margin: 0 auto .4rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
  transition: background .18s ease, color .18s ease, box-shadow .2s ease;
}
.mode-card .mode-icon .lucide-ic,
.mode-card .mode-icon svg { width: 22px; height: 22px; stroke-width: 2; }
.mode-card:hover .mode-icon { background: color-mix(in srgb, var(--brand) 20%, transparent); }
.mode-card.selected .mode-icon {
  background: var(--brand);
  color: var(--accent-fg);
  box-shadow: 0 6px 14px -4px color-mix(in srgb, var(--brand) 55%, transparent);
}
.mode-card .mode-title { font-weight: 700; font-size: .95rem; }
.mode-card .mode-desc { font-size: .78rem; color: var(--text-2); line-height: 1.45; }
.mode-card .mode-example { font-size: .72rem; color: var(--text-3); font-style: italic; margin-top: .3rem; }

/* ── Bonus category picker (admin → Employees → Rewards → إكرامية) ───
   3-column chip grid (collapses to 2 on narrow). Each chip carries its
   category color via a CSS variable on the icon container; selecting a
   chip lifts the whole card to the brand-tinted "active" state so the
   choice reads instantly. Colors mirror the admin section nav palette
   for cross-app consistency. */
.bonus-cats {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: .5rem; margin-bottom: .35rem;
}
@media (max-width: 480px) { .bonus-cats { grid-template-columns: repeat(2, 1fr); } }
.bonus-cat {
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
  padding: .65rem .4rem;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--card);
  color: var(--text-2);
  cursor: pointer; font: inherit; font-size: .78rem; font-weight: 600;
  transition: background .15s ease, border-color .15s ease, color .15s ease, transform .12s ease;
}
.bonus-cat:hover { transform: translateY(-1px); border-color: var(--text-3); color: var(--text); }
.bonus-cat:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.bonus-cat-ic {
  width: 36px; height: 36px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--cat-color, var(--brand)) 14%, transparent);
  color: var(--cat-color, var(--brand));
  transition: background .18s ease, color .18s ease, box-shadow .2s ease;
}
.bonus-cat-ic .lucide-ic, .bonus-cat-ic svg { width: 18px; height: 18px; stroke-width: 2; }
.bonus-cat-lbl { line-height: 1.2; }
/* Selected — chip becomes a tinted "card" with the category color, and
   its icon container fills solid for unmistakable focus. */
.bonus-cat.selected {
  background: color-mix(in srgb, var(--cat-color, var(--brand)) 10%, var(--card));
  border-color: color-mix(in srgb, var(--cat-color, var(--brand)) 45%, var(--border));
  color: var(--text);
}
.bonus-cat.selected .bonus-cat-ic {
  background: var(--cat-color, var(--brand));
  color: #FFFFFF;
  box-shadow: 0 4px 10px -3px color-mix(in srgb, var(--cat-color, var(--brand)) 50%, transparent);
}
/* Per-category color tokens — applied via attribute selector so the JS
   only needs to set data-cat (no inline style needed). Hues curated to
   match the admin section nav palette for visual cohesion. */
.bonus-cat[data-cat="excellence"]   { --cat-color: #F59E0B; }
.bonus-cat[data-cat="attendance"]   { --cat-color: var(--brand); }
.bonus-cat[data-cat="innovation"]   { --cat-color: #8B5CF6; }
.bonus-cat[data-cat="teamwork"]     { --cat-color: #6366F1; }
.bonus-cat[data-cat="appreciation"] { --cat-color: #EC4899; }
.bonus-cat[data-cat="growth"]       { --cat-color: #0891B2; }

/* Industry template picker grid */
.industry-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .55rem; }
.industry-card {
  border: 1px solid var(--border); border-radius: 12px; padding: .7rem .5rem;
  background: var(--card); cursor: pointer; text-align: center;
  transition: all .15s; display: flex; flex-direction: column; gap: .2rem;
  align-items: center; position: relative;
}
.industry-card:hover:not(.disabled) { border-color: var(--ring); transform: translateY(-1px); }
.industry-card.selected { border-color: var(--ring); background: var(--bg-2); box-shadow: 0 0 0 3px var(--ring-glow); }
.industry-card.disabled { opacity: .5; cursor: not-allowed; }
.industry-card .ic-icon { font-size: 1.6rem; }
.industry-card .ic-name { font-weight: 600; font-size: .82rem; }
.industry-card .ic-badge {
  position: absolute; top: 4px; inset-inline-end: 4px;
  background: var(--warn); color: #fff; font-size: .6rem;
  padding: 1px 5px; border-radius: 999px; font-weight: 700;
}

/* Pipeline list inside template detail */
.pipeline-row {
  padding: .65rem .8rem; border: 1px solid var(--border); border-radius: 10px;
  cursor: pointer; margin-bottom: .4rem; background: var(--card);
  transition: all .15s;
}
.pipeline-row:hover { border-color: var(--ring); transform: translateY(-1px); }
.pipeline-row .pr-name { font-weight: 700; margin-bottom: .25rem; }
.pipeline-row .pr-desc { font-size: .78rem; color: var(--text-3); margin-bottom: .35rem; }
.pipeline-row .pr-stages { display: flex; flex-wrap: wrap; gap: .3rem; font-size: .72rem; color: var(--text-2); }
.pipeline-row .pr-stages > span { padding: .15rem .5rem; background: var(--bg-2); border: 1px solid var(--border-2); border-radius: 6px; }

/* Stage editor — compact row layout (Trello-style): each stage is a click-
   target that opens a rich detail modal. The row shows enough context to
   reorder/scan (number + name + team chip + SLA chip + completion signals)
   without cluttering the creation flow with every sub-field inline. */
.stage-editor { display: flex; flex-direction: column; gap: .5rem; }
.stage-editor-row {
  display: flex; align-items: center; gap: .6rem;
  padding: .6rem .7rem;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
  cursor: pointer; transition: border-color .12s, box-shadow .12s, transform .1s;
  position: relative;
}
.stage-editor-row:hover {
  border-color: var(--border-2);
  box-shadow: 0 2px 8px rgba(0,0,0,.12);
}
.stage-editor-row.warning {
  border-color: rgba(245,158,11,.5);
  background: rgba(245,158,11,.04);
}
.stage-editor-row .se-num {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent); color: var(--accent-fg);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: .78rem; flex: 0 0 auto;
}
.stage-editor-row .se-body {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: .25rem;
}
.stage-editor-row .se-title {
  font-weight: 600; font-size: .92rem; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stage-editor-row .se-title.empty { color: var(--text-3); font-style: italic; }
.stage-editor-row .se-meta {
  display: flex; flex-wrap: wrap; gap: .3rem;
  font-size: .74rem; color: var(--text-3);
}
.stage-editor-row .se-meta > span {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .1rem .45rem; border-radius: 6px;
  background: var(--bg-2); border: 1px solid var(--border);
}
.stage-editor-row .se-meta > span.warn {
  background: rgba(245,158,11,.1); color: var(--warn);
  border-color: rgba(245,158,11,.35);
}
.stage-editor-row .se-del {
  background: transparent; border: none; color: var(--text-3);
  cursor: pointer; padding: .35rem; border-radius: 6px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
}
.stage-editor-row .se-del:hover { color: #ef4444; background: var(--bg-2); }
.stage-editor-row .se-edit-hint {
  color: var(--text-3); font-size: 1rem; flex: 0 0 auto;
  opacity: 0; transition: opacity .12s;
}
.stage-editor-row:hover .se-edit-hint { opacity: 1; }

.stage-editor-add {
  display: flex; gap: .45rem; align-items: center;
  padding: .5rem .65rem;
  border: 1px dashed var(--border-2); border-radius: 10px;
  background: transparent; color: var(--text-3); cursor: pointer;
  font-size: .85rem; justify-content: center;
  transition: all .15s;
}
.stage-editor-add:hover { color: var(--text); border-color: var(--ring); background: var(--bg-2); }

.stage-editor-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: .6rem;
}
.stage-editor-head > strong { font-size: .95rem; }
.stage-editor-head .back-btn {
  background: transparent; border: none; color: var(--text-3);
  font-size: .82rem; cursor: pointer; padding: .2rem .5rem; border-radius: 6px;
}
.stage-editor-head .back-btn:hover { color: var(--text); background: var(--bg-2); }

/* ── Side panel (task detail) ─────────────────────────────────────────
   Slides in from the inline-end side (left in RTL, right in LTR) instead
   of a modal. Keeps the kanban visible so the user sees where the task
   sits in the flow. ESC + overlay click to close. */
.side-panel-backdrop {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(0,0,0,.45); backdrop-filter: blur(2px);
  animation: fade-in .18s ease;
}
.side-panel {
  position: fixed; top: 0; bottom: 0; inset-inline-end: 0;
  width: min(720px, 95vw);
  background: var(--bg); border-inline-start: 1px solid var(--border);
  box-shadow: -12px 0 40px rgba(0,0,0,.35);
  display: flex; flex-direction: column;
  animation: side-slide .22s cubic-bezier(.2,.8,.2,1);
  z-index: 1001;
}
html[dir="rtl"] .side-panel { box-shadow: 12px 0 40px rgba(0,0,0,.35); }
@keyframes side-slide {
  from { transform: translateX(var(--slide-from, 100%)); }
  to   { transform: translateX(0); }
}
html[dir="rtl"] .side-panel { --slide-from: -100%; }
@keyframes fade-in { from { opacity: 0 } to { opacity: 1 } }

.side-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: .75rem 1rem; border-bottom: 1px solid var(--border);
  gap: .5rem; flex-wrap: wrap;
}
.side-panel-head .sp-actions { display: flex; gap: .3rem; }
.side-panel-head .sp-close {
  background: transparent; border: none; color: var(--text-2);
  width: 34px; height: 34px; border-radius: 8px; cursor: pointer;
}
.side-panel-head .sp-close:hover { background: var(--bg-2); color: var(--text); }

.side-panel-body {
  flex: 1 1 auto; overflow-y: auto; padding: 1rem 1.2rem 2rem;
  scrollbar-width: thin;
}
.side-panel-body::-webkit-scrollbar { width: 7px; }
.side-panel-body::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }

/* Title input (inline-editable) — Trello-inspired: big, soft-bordered. */
.sp-title {
  font-size: 1.75rem; font-weight: 800; line-height: 1.25;
  background: transparent; border: 2px solid transparent;
  color: var(--text); width: 100%; padding: .5rem .6rem;
  border-radius: 10px; margin-bottom: 1.1rem; outline: none;
  transition: background .15s, border-color .15s;
  font-family: inherit;
}
.sp-title:hover { background: var(--bg-2); }
.sp-title:focus { background: var(--bg-2); border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.sp-title.empty::before { content: attr(data-placeholder); color: var(--text-3); }

/* Field rows — label on start, value on end, aligned on baseline */
.sp-field {
  display: grid; grid-template-columns: 120px 1fr; gap: .8rem;
  align-items: center; padding: .5rem 0;
  border-bottom: 1px solid transparent;
}
.sp-field:hover { border-bottom-color: var(--border); }
.sp-field > .sp-label {
  color: var(--text-3); font-size: .82rem; font-weight: 500;
}
.sp-field > .sp-value {
  font-size: .9rem; color: var(--text);
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
}
.sp-field > .sp-value .chip { font-size: .78rem; }
.sp-field > .sp-value > button { all: unset; cursor: pointer; color: var(--text-3); font-size: .85rem; }
.sp-field > .sp-value > button:hover { color: var(--accent); }

.sp-section {
  margin-top: 1.3rem; padding-top: 1rem; border-top: 1px solid var(--border);
}
.sp-section > h4 {
  font-size: .95rem; font-weight: 700; margin: 0 0 .6rem;
}

/* ── Date / time picker popover ─────────────────────────────────────── */
.date-picker {
  position: absolute; z-index: 1100;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 18px 48px rgba(0,0,0,.35);
  padding: .9rem 1rem; width: 320px;
  font-size: .88rem;
  animation: fade-in .14s ease;
}
.date-picker-tabs { display: flex; gap: .3rem; margin-bottom: .8rem; }
.date-picker-tab {
  flex: 1; padding: .45rem .55rem; background: transparent;
  border: 1.5px solid var(--border); border-radius: 8px;
  color: var(--text-2); font-size: .83rem; font-weight: 500;
  cursor: pointer; transition: all .15s;
  display: flex; align-items: center; justify-content: center; gap: .3rem;
}
.date-picker-tab:hover { border-color: var(--border-2); color: var(--text); }
.date-picker-tab.active { border-color: var(--ring); color: var(--text); }
.date-picker-tab .dpt-val { color: var(--text); font-weight: 600; margin-inline-start: .35rem; }
.date-picker-month {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: .5rem; padding: 0 .2rem;
}
.date-picker-month > span { font-weight: 700; font-size: .95rem; }
.date-picker-month > button {
  background: transparent; border: none; color: var(--text-2);
  width: 28px; height: 28px; border-radius: 6px; cursor: pointer;
}
.date-picker-month > button:hover { background: var(--bg-2); color: var(--text); }
.date-picker-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
  font-size: .82rem;
}
.date-picker-grid .dpg-h {
  text-align: center; padding: .35rem 0; color: var(--text-3);
  font-weight: 500; font-size: .72rem;
}
.date-picker-grid .dpg-d {
  text-align: center; padding: .45rem 0; cursor: pointer;
  border-radius: 50%; color: var(--text);
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  margin: 0 auto; transition: background .12s;
}
.date-picker-grid .dpg-d:hover { background: var(--bg-2); }
.date-picker-grid .dpg-d.dim { color: var(--text-3); opacity: .55; }
.date-picker-grid .dpg-d.today {
  border: 1.5px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  font-weight: 600;
}
.date-picker-grid .dpg-d.selected {
  background: var(--accent); color: var(--accent-fg); font-weight: 700;
  border-color: var(--accent);
}
.date-picker-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .5rem; margin-bottom: .7rem; padding-bottom: .55rem;
  border-bottom: 1px solid var(--border);
}
.date-picker-head .dp-head-label {
  color: var(--text-3); font-size: .78rem; font-weight: 500;
  letter-spacing: .02em; text-transform: uppercase;
}
.date-picker-head .dp-head-value { color: var(--text); font-weight: 700; font-size: .92rem; }
.date-picker-head .dp-head-value.is-empty { color: var(--text-3); font-weight: 500; }
.date-picker-foot {
  display: flex; justify-content: space-between; align-items: center;
  padding-top: .7rem; margin-top: .7rem; border-top: 1px solid var(--border);
  gap: .5rem;
}
.date-picker-foot .dp-foot-left { display: inline-flex; align-items: center; gap: .4rem; }
.date-picker-foot .dp-clear {
  background: transparent; border: none; color: var(--text-2);
  font-size: .85rem; font-weight: 500; cursor: pointer;
  padding: .3rem .5rem; border-radius: 6px;
}
.date-picker-foot .dp-clear:hover { color: var(--text); background: var(--bg-2); }
.date-picker-foot .dp-time-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  background: var(--bg-2); border: 1px solid var(--border);
  padding: .3rem .55rem; border-radius: 8px; color: var(--text-2);
  cursor: pointer; font-size: .82rem;
}
.date-picker-foot .dp-time-chip.active { background: var(--accent-soft); color: var(--text); border-color: var(--accent-soft-border); }
.date-picker-foot .dp-save:disabled,
.date-picker-foot .dp-save[disabled] { opacity: .55; cursor: not-allowed; }
.date-picker-time-list {
  margin-top: .5rem; max-height: 140px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 8px;
  scrollbar-width: thin;
}
.date-picker-time-list .dpt-item {
  padding: .4rem .7rem; cursor: pointer; font-size: .85rem;
}
.date-picker-time-list .dpt-item:hover { background: var(--bg-2); }
.date-picker-time-list .dpt-item.selected { background: var(--accent-soft); color: var(--text); font-weight: 600; }

/* ── Assignee picker (search + sticky footer) ───────────────────────── */
.assign-picker {
  width: 280px; padding: 0; display: flex; flex-direction: column;
  max-height: min(70vh, 440px);
}
.assign-picker .ap-head {
  padding: .55rem .6rem; border-bottom: 1px solid var(--border);
}
.assign-picker .ap-search {
  width: 100%; padding: .4rem .6rem; font-size: .85rem;
  border-radius: 8px;
}
.assign-picker .ap-list {
  flex: 1 1 auto; overflow-y: auto; padding: .35rem .35rem;
  scrollbar-width: thin;
}
.assign-picker .ap-list::-webkit-scrollbar { width: 7px; }
.assign-picker .ap-list::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.assign-picker .ap-item {
  display: flex; align-items: center; gap: .55rem;
  padding: .45rem .55rem; cursor: pointer;
  border-radius: 8px;
}
.assign-picker .ap-item:hover { background: var(--bg-2); }
.assign-picker .ap-item input[type="checkbox"] { accent-color: var(--accent); cursor: pointer; }
.assign-picker .ap-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.assign-picker .ap-empty {
  padding: 1rem; text-align: center; color: var(--text-3); font-size: .85rem;
}
.assign-picker .ap-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; padding: .55rem .6rem;
  border-top: 1px solid var(--border);
  background: var(--card);
  border-radius: 0 0 14px 14px;
}

/* ── Task side-panel: Trello-style sections ─────────────────────────── */
.sp-quick-row {
  display: flex; gap: .4rem; flex-wrap: wrap; margin: 0 0 1rem;
}
.sp-quick-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .45rem .7rem; border-radius: 8px;
  background: var(--bg-2); border: 1px solid var(--border);
  color: var(--text-2); font-size: .82rem; font-weight: 500;
  cursor: pointer; transition: all .15s;
}
.sp-quick-btn:hover { background: var(--card); color: var(--text); border-color: var(--border-2); }
.sp-quick-btn.on { background: var(--accent-soft); color: var(--text); border-color: var(--accent-soft-border); }
.sp-quick-btn .lucide-ic { width: .95rem; height: .95rem; }

/* Labels bar */
.sp-labels { display: flex; flex-wrap: wrap; gap: .3rem; margin: .25rem 0; }
.sp-label {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .18rem .55rem; border-radius: 6px;
  font-size: .76rem; font-weight: 600; color: #fff;
  cursor: default;
}
.sp-label > button {
  all: unset; cursor: pointer; opacity: .7; font-size: .8rem;
}
.sp-label > button:hover { opacity: 1; }

.sp-label-add {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .18rem .55rem; border-radius: 6px;
  background: var(--bg-2); border: 1px dashed var(--border-2);
  color: var(--text-3); font-size: .76rem; cursor: pointer;
}
.sp-label-add:hover { color: var(--text); border-color: var(--ring); }

.sp-label-palette {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: .3rem;
  margin-top: .4rem; margin-bottom: .5rem;
}
.sp-label-swatch {
  width: 100%; aspect-ratio: 1; border-radius: 6px;
  border: 2px solid transparent; cursor: pointer;
  transition: transform .12s, border-color .12s;
}
.sp-label-swatch:hover { transform: scale(1.06); }
.sp-label-swatch.selected { border-color: var(--text); }

/* Description block */
.sp-desc-view {
  padding: .6rem .7rem; border-radius: 10px;
  background: transparent; border: 1px solid transparent;
  color: var(--text-2); cursor: pointer; min-height: 70px;
  white-space: pre-wrap; word-break: break-word;
  transition: background .15s, border-color .15s;
  font-size: .9rem; line-height: 1.55;
}
.sp-desc-view:hover { background: var(--bg-2); }
.sp-desc-view.empty { color: var(--text-3); font-style: italic; }
.sp-desc-edit {
  width: 100%; min-height: 120px;
  padding: .6rem .7rem; border-radius: 10px;
  background: var(--bg-2); border: 1px solid var(--ring);
  color: var(--text); resize: vertical; outline: none;
  font-family: inherit; font-size: .9rem; line-height: 1.55;
  box-shadow: 0 0 0 3px var(--ring-glow);
}
.sp-desc-actions { display: flex; gap: .4rem; margin-top: .5rem; justify-content: flex-end; }

/* Checklist */
.sp-checklist-progress {
  height: 6px; border-radius: 3px; background: var(--border-2);
  overflow: hidden; margin-bottom: .6rem;
}
.sp-checklist-progress > span {
  display: block; height: 100%; background: linear-gradient(90deg, var(--brand), var(--brand-pressed));
  transition: width .3s;
}
.sp-checklist-item {
  display: flex; align-items: center; gap: .55rem;
  padding: .4rem .15rem; border-radius: 6px;
  transition: background .12s;
}
.sp-checklist-item:hover { background: var(--bg-2); }
.sp-checklist-item > input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer; }
.sp-checklist-item > .cli-text {
  flex: 1 1 auto; font-size: .9rem; color: var(--text);
  background: transparent; border: none; outline: none;
}
.sp-checklist-item.done > .cli-text { text-decoration: line-through; color: var(--text-3); }
.sp-checklist-item > .cli-del {
  opacity: 0; background: transparent; border: none; color: var(--text-3);
  cursor: pointer; padding: .2rem; border-radius: 4px;
  transition: opacity .12s, color .12s;
}
.sp-checklist-item:hover > .cli-del { opacity: 1; }
.sp-checklist-item > .cli-del:hover { color: #ef4444; }

.sp-checklist-add {
  display: flex; gap: .4rem; margin-top: .3rem;
}
.sp-checklist-add > input {
  flex: 1 1 auto; padding: .45rem .65rem; border-radius: 8px;
  background: var(--bg-2); border: 1px solid var(--border);
  color: var(--text); outline: none; font-size: .88rem;
}
.sp-checklist-add > input:focus { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }

/* Attachments */
.sp-attachments { display: grid; gap: .5rem; }
.sp-att-item {
  display: flex; align-items: center; gap: .7rem;
  padding: .55rem .7rem; border: 1px solid var(--border);
  border-radius: 10px; background: var(--card);
  transition: border-color .15s, box-shadow .15s;
}
.sp-att-item:hover { border-color: var(--border-2); box-shadow: 0 2px 8px rgba(0,0,0,.15); }
.sp-att-thumb {
  width: 48px; height: 48px; border-radius: 8px; flex: 0 0 auto;
  background: var(--bg-2);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; color: var(--text-2); font-size: 1.3rem;
}
.sp-att-thumb > img { width: 100%; height: 100%; object-fit: cover; }
.sp-att-info { flex: 1 1 auto; min-width: 0; }
.sp-att-name {
  font-weight: 600; font-size: .88rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sp-att-meta { font-size: .75rem; color: var(--text-3); }
.sp-att-actions { display: flex; gap: .3rem; flex: 0 0 auto; }
.sp-att-actions a, .sp-att-actions button {
  all: unset; cursor: pointer; color: var(--text-2);
  padding: .35rem; border-radius: 6px; display: inline-flex;
}
.sp-att-actions a:hover { color: var(--accent); background: var(--bg-2); }
.sp-att-actions button:hover { color: #ef4444; background: var(--bg-2); }

.sp-att-dropzone {
  padding: 1.1rem .8rem; border: 2px dashed var(--border-2);
  border-radius: 12px; text-align: center; color: var(--text-3);
  cursor: pointer; transition: all .15s; font-size: .85rem;
}
.sp-att-dropzone:hover, .sp-att-dropzone.drag-over {
  background: var(--bg-2); border-color: var(--ring); color: var(--text);
}

/* Comments */
.sp-comment {
  display: flex; gap: .7rem; padding: .6rem 0;
  border-bottom: 1px solid var(--border);
}
.sp-comment:last-child { border-bottom: none; }
.sp-comment-body { flex: 1 1 auto; min-width: 0; }
.sp-comment-head {
  display: flex; align-items: baseline; gap: .5rem;
  margin-bottom: .25rem;
}
.sp-comment-author { font-weight: 600; font-size: .88rem; }
.sp-comment-time { font-size: .72rem; color: var(--text-3); }
.sp-comment-text { font-size: .88rem; color: var(--text); white-space: pre-wrap; word-break: break-word; }

.sp-comment-add {
  display: flex; gap: .6rem; margin-top: .7rem; align-items: flex-start;
}
.sp-comment-add > textarea {
  flex: 1 1 auto; min-height: 44px; max-height: 180px;
  padding: .55rem .7rem; border-radius: 10px;
  background: var(--bg-2); border: 1px solid var(--border);
  color: var(--text); outline: none; font-family: inherit;
  font-size: .88rem; resize: vertical;
}
.sp-comment-add > textarea:focus { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }

/* ── Stage history timeline inside task modal ─────────────────────── */
.stage-timeline { display: flex; flex-direction: column; gap: .55rem; margin-top: .5rem; }
.stage-timeline-item {
  padding: .65rem .8rem; border-radius: 10px; border: 1px solid var(--border);
  background: var(--card);
}
.stage-timeline-item.done { border-left: 3px solid var(--brand); }
html[dir="rtl"] .stage-timeline-item.done { border-left: 1px solid var(--border); border-right: 3px solid var(--brand); }
.stage-timeline-item.active { border-left: 3px solid var(--accent); background: var(--accent-soft); }
html[dir="rtl"] .stage-timeline-item.active { border-left: 1px solid var(--border); border-right: 3px solid var(--accent); background: var(--accent-soft); }
.stage-timeline-item.submitted { border-left: 3px solid #f59e0b; background: rgba(245,158,11,.06); }
html[dir="rtl"] .stage-timeline-item.submitted { border-left: 1px solid var(--border); border-right: 3px solid #f59e0b; background: rgba(245,158,11,.06); }
.stage-timeline-item.returned { border-left: 3px solid #ef4444; background: rgba(239,68,68,.05); }
html[dir="rtl"] .stage-timeline-item.returned { border-left: 1px solid var(--border); border-right: 3px solid #ef4444; background: rgba(239,68,68,.05); }
.stage-timeline-item .st-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: .25rem; }
.stage-timeline-item .st-name { font-weight: 700; font-size: .92rem; }
.stage-timeline-item .st-status { font-size: .72rem; color: var(--text-3); }
.stage-timeline-item .st-meta { font-size: .76rem; color: var(--text-2); }
.stage-timeline-item .st-notes { margin-top: .4rem; padding-top: .35rem; border-top: 1px dashed var(--border-2); font-size: .78rem; color: var(--text-2); }
.stage-timeline-item .st-note { padding: .15rem 0; }
.stage-timeline-item .st-note.return { color: #ef4444; }

/* Gantt */
.gantt { display: grid; grid-template-columns: 220px 1fr; overflow: auto; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); }
.gantt .rows { display: contents; }
.gantt .row-label { padding: .55rem .8rem; border-bottom: 1px solid var(--border); font-size: .85rem; background: var(--card-2); position: sticky; inset-inline-start: 0; z-index: 2; }
.gantt .row-track { position: relative; border-bottom: 1px solid var(--border); height: 38px; background:
  repeating-linear-gradient(to right, transparent 0, transparent calc(var(--cell) - 1px), var(--border) calc(var(--cell) - 1px), var(--border) var(--cell));
}
.gantt .bar { position: absolute; top: 6px; bottom: 6px; background: var(--accent); border-radius: 8px; color: var(--accent-fg); padding: 0 .5rem; font-size: .78rem; display: flex; align-items: center; box-shadow: 0 2px 8px rgba(0,0,0,.2); }
.gantt .bar.overdue { background: linear-gradient(135deg, #ef4444, #b91c1c); }
.gantt .bar.completed { background: linear-gradient(135deg, var(--brand), var(--brand-pressed)); }
.gantt .today { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--warn); }

/* Chat layout — Phase 1 */
/* Use 100dvh on mobile so the composer doesn't get hidden behind the
   browser's collapsing address bar / Android gesture bar. Falling back
   to 100vh keeps desktop / older browsers unchanged. */
main:has(.chat-shell) { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 100vh; min-height: 100dvh; overflow: hidden; }
main:has(.chat-shell) > .main { flex: 1; min-height: 0; padding: 0; display: flex; }
.chat-shell { display: grid; grid-template-columns: var(--chat-sb-w, 240px) 1fr; height: 100%; width: 100%; min-height: 0; }
.chat-sidebar { border-inline-end: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; min-height: 0; position: relative; }
/* Unified sidebar (Slack/GHL-style): single scroll area with a pinned
   search box at the top and collapsible Channels + Direct-messages
   sections below. Replaces the old dual-section layout. */
.chat-sidebar-unified { padding: 0; }
.chat-sidebar-search {
  position: relative; padding: .7rem .75rem;
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}
.chat-sidebar-search > input {
  width: 100%;
  /* Extra inline-end padding leaves room for the two icon buttons
     (bookmarks + scheduled) anchored at the trailing edge. */
  padding: .5rem 4rem .5rem 2.1rem;
  border-radius: 8px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text); font-size: .88rem; outline: none;
}
html[dir="rtl"] .chat-sidebar-search > input { padding: .5rem 2.1rem .5rem 4rem; }
.chat-sidebar-search > input:focus { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.chat-sidebar-search-icon {
  position: absolute; top: 50%; transform: translateY(-50%);
  inset-inline-start: 1.1rem; color: var(--text-3);
  pointer-events: none; display: inline-flex;
}
.chat-sidebar-search-icon .lucide-ic { width: 1rem; height: 1rem; }
.chat-list-empty { padding: 1rem; text-align: center; font-size: .85rem; }
.chat-sidebar-resize { position: absolute; top: 0; bottom: 0; inset-inline-end: -3px; width: 6px; cursor: col-resize; z-index: 5; user-select: none; }
.chat-sidebar-resize::before { content: ''; position: absolute; top: 0; bottom: 0; inset-inline-end: 2px; width: 2px; background: transparent; transition: background .15s ease; }
.chat-sidebar-resize:hover::before, body.chat-sb-dragging .chat-sidebar-resize::before { background: var(--accent, #6c5ce7); }
body.chat-sb-dragging { cursor: col-resize !important; user-select: none; }
body.chat-sb-dragging * { cursor: col-resize !important; }
.chat-sidebar-section { display: flex; flex-direction: column; min-height: 0; flex: 1 1 0; border-bottom: 1px solid var(--border); overflow: hidden; }
.chat-sidebar-section:last-child { border-bottom: 0; }
.chat-sidebar-section:not(.open) { flex: 0 0 auto; }
.chat-sidebar-section:not(.open) .chat-sidebar-body { display: none; }
.chat-sidebar-body { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; overflow: hidden; }
.chat-sidebar-title {
  display: flex; align-items: center; justify-content: space-between; gap: .4rem;
  padding: .55rem .8rem; font-weight: 700; font-size: .8rem;
  letter-spacing: .02em; color: var(--text-2);
  background: var(--card-2); border: 0; border-bottom: 1px solid var(--border);
  cursor: pointer; user-select: none; flex: 0 0 auto; width: 100%; text-align: start; font-family: inherit;
}
.chat-sidebar-title:hover { background: var(--bg-3); color: var(--text); }
.chat-sidebar-chev { display: inline-flex; transition: transform .18s ease; color: var(--text-3); }
.chat-sidebar-chev .lucide-ic { width: 1rem; height: 1rem; }
.chat-sidebar-section.open > .chat-sidebar-title .chat-sidebar-chev { transform: rotate(180deg); }
.chat-sidebar-body .input { margin: .4rem .6rem; width: calc(100% - 1.2rem); font-size: .85rem; padding: .45rem .7rem; flex: 0 0 auto; }
.chat-list-inner { overflow-y: auto; overflow-x: hidden; flex: 1 1 0; min-height: 0; scrollbar-width: thin; }
.chat-list-inner::-webkit-scrollbar { width: 8px; }
.chat-list-inner::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 4px; }
.chat-list-inner::-webkit-scrollbar-track { background: transparent; }

.chat-row { padding: .6rem .9rem; border-bottom: 1px solid var(--border); cursor: pointer; display: flex; gap: .6rem; align-items: center; transition: background .15s; }
.chat-row:hover { background: var(--card-2); }
.chat-row.active { background: var(--card-2); }
.chat-row-info { flex: 1; min-width: 0; }
.chat-row-top { display: flex; justify-content: space-between; gap: .3rem; align-items: center; }
.chat-row-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-row-time { font-size: .7rem; color: var(--text-3); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.chat-row-bottom { display: flex; justify-content: space-between; gap: .4rem; align-items: center; }
.chat-row-preview { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); font-size: .85rem; flex: 1 1 auto; min-width: 0; }
.chat-row-unread {
  flex-shrink: 0;
  min-width: 18px; height: 18px;
  padding: 0 .35rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand);
  color: var(--accent-fg);
  border-radius: 999px;
  font-size: .7rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.chat-row.active .chat-row-name { color: var(--brand); }

/* Mobile: WhatsApp / Telegram-style large rows so each contact is a
   comfortable thumb target with name + last message + time at a glance. */
@media (max-width: 720px) {
  .chat-row {
    padding: .8rem 1rem;
    gap: .85rem;
    min-height: 64px;
  }
  .chat-row > .avatar,
  .chat-row > .chat-avatar,
  .chat-row .avatar {
    width: 48px; height: 48px;
    font-size: .95rem;
    flex-shrink: 0;
  }
  .chat-row-hash {
    width: 48px; height: 48px;
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: color-mix(in srgb, var(--brand) 14%, var(--card-2));
    color: var(--brand);
    font-size: 1.4rem; font-weight: 800;
  }
  .chat-row-name { font-size: 1rem; }
  .chat-row-preview { font-size: .88rem; }
  .chat-row-time { font-size: .72rem; }
  /* Empty channels list: collapse to a single hint row instead of the
     "No channels" box taking ~80px. The auto-collapse rule in JS hides
     the body entirely; this just keeps the empty fallback compact when
     the user manually opens it. */
  .chat-list-empty { padding: .6rem .9rem; font-size: .82rem; }
  /* Member row mirrors the chat-row sizing so the DM section reads
     uniformly when it includes both initiated DMs + uninitiated peers. */
  .member-row {
    padding: .8rem 1rem;
    gap: .85rem;
    min-height: 64px;
  }
  .member-row .avatar { width: 48px; height: 48px; font-size: .95rem; }
  .member-name { font-size: 1rem; font-weight: 600; }
}

.member-row { padding: .5rem .9rem; cursor: pointer; display: flex; gap: .6rem; align-items: center; border-bottom: 1px solid var(--border); transition: background .15s; }
.member-row:hover { background: var(--card-2); }
.member-info { flex: 1; min-width: 0; }
.member-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chat-body { display: flex; flex-direction: column; min-height: 0; }
.chat-header { padding: .7rem 1rem; border-bottom: 1px solid var(--border); background: var(--card-2); min-height: 56px; display: flex; align-items: center; }
.chat-header-info { display: flex; align-items: center; gap: .6rem; cursor: pointer; padding: .2rem .3rem; border-radius: 8px; transition: background .15s; user-select: none; flex: 1; min-width: 0; }
.chat-header-info:hover { background: var(--card); }
.chat-header-info:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.chat-header-actions { display: flex; align-items: center; gap: .25rem; margin-inline-start: auto; }

/* In-chat search */
.chat-search-bar { border-bottom: 1px solid var(--border); background: var(--card-2); display: flex; flex-direction: column; max-height: 50%; }
.csb-input-wrap { display: flex; align-items: center; gap: .5rem; padding: .5rem .8rem; border-bottom: 1px solid var(--border); }
.csb-input-wrap .lucide-ic { color: var(--text-3); width: 18px; height: 18px; flex-shrink: 0; }
.csb-input-wrap input { flex: 1; border: 0; background: transparent; color: var(--text); font: inherit; outline: none; padding: .3rem 0; font-size: .95rem; }
.csb-close { background: transparent; border: 0; cursor: pointer; color: var(--text-2); width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; }
.csb-close:hover { background: var(--card); color: var(--text); }
.csb-results { overflow-y: auto; flex: 1; max-height: 320px; }

/* Advanced search — filter chips row + collapsible sender/date panel.
   Chips are mutually exclusive (radio behaviour) so the active type
   is always visible at a glance. The filter button toggles the
   secondary row underneath; on mobile the chips row scrolls
   horizontally to keep the bar from wrapping. */
.csb-filter-btn {
  background: transparent; border: 0; cursor: pointer;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-3); border-radius: 6px;
  flex-shrink: 0;
}
.csb-filter-btn:hover { color: var(--brand); background: var(--bg-3); }
.csb-filter-btn.active { color: var(--brand); background: var(--bg-3); }
.csb-filter-btn .lucide-ic { width: 16px; height: 16px; }

.csb-types {
  display: flex;
  gap: .35rem;
  padding: .5rem .8rem;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--card-2) 65%, var(--card));
}
.csb-types::-webkit-scrollbar { display: none; }
.csb-type-chip {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .35rem .75rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-2);
  font: inherit;
  font-size: .82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
  white-space: nowrap;
}
.csb-type-chip:hover {
  background: color-mix(in srgb, var(--brand) 8%, var(--card));
  border-color: color-mix(in srgb, var(--brand) 30%, var(--border));
}
.csb-type-chip.active {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--accent-fg);
}
.csb-type-chip .lucide-ic { width: 14px; height: 14px; }

.csb-filters {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr auto;
  gap: .55rem .65rem;
  padding: .65rem .8rem .75rem;
  border-bottom: 1px solid var(--border);
  background: var(--card-2);
  align-items: end;
}
.csb-filter { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.csb-filter-lbl {
  font-size: .72rem;
  font-weight: 600;
  color: var(--text-3);
}
.csb-filter .input { padding: .35rem .55rem; font-size: .82rem; min-width: 0; }
.csb-filters .csb-clear {
  align-self: end; padding: .4rem .6rem; font-size: .78rem;
}

.csb-hit-tag {
  display: inline-block;
  padding: .15rem .55rem;
  border-radius: 999px;
  background: var(--card-2);
  font-size: .78rem;
  color: var(--text-2);
  font-weight: 600;
}

@media (max-width: 720px) {
  .csb-filters {
    grid-template-columns: 1fr 1fr;
  }
  .csb-filter:nth-child(1) { grid-column: 1 / -1; } /* sender full width */
  .csb-filters .csb-clear { grid-column: 1 / -1; align-self: stretch; }
  .csb-types { padding: .4rem .65rem; }
  .csb-type-chip { font-size: .78rem; padding: .3rem .65rem; }
}
.csb-empty { padding: 1rem; text-align: center; font-size: .88rem; }
.csb-hit { display: block; width: 100%; text-align: start; background: transparent; border: 0; border-bottom: 1px solid var(--border); padding: .55rem .9rem; cursor: pointer; color: inherit; font: inherit; }
.csb-hit:hover { background: var(--card); }
.csb-hit-top { display: flex; justify-content: space-between; gap: .5rem; margin-bottom: .15rem; }
.csb-hit-name { font-weight: 600; font-size: .85rem; color: var(--accent); }
.csb-hit-snippet { font-size: .88rem; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.csb-hit-snippet mark { background: var(--accent-soft); color: var(--text); padding: 0 2px; border-radius: 3px; }

.pinned-banner { display: flex; align-items: center; gap: .5rem; padding: .5rem .9rem; background: var(--card-2); border-bottom: 1px solid var(--border); color: var(--text-2); font-size: .85rem; }
.pinned-banner .lucide-ic { color: var(--accent); }
.chat-messages, .msgs { flex: 1; overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: .35rem; scrollbar-width: thin; background-image: url('/assets/img/chat-bg-dark.jpg'); background-repeat: repeat; background-size: 420px auto; background-attachment: local; }
html.light .chat-messages, html.light .msgs { background-image: url('/assets/img/chat-bg-light.jpg'); }
.chat-messages::-webkit-scrollbar, .msgs::-webkit-scrollbar { width: 10px; }
.chat-messages::-webkit-scrollbar-thumb, .msgs::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 5px; }
.chat-messages::-webkit-scrollbar-track, .msgs::-webkit-scrollbar-track { background: transparent; }

.msg-row { display: flex; gap: .5rem; align-items: flex-end; }
.msg-row.mine { flex-direction: row-reverse; }
.msg-row .avatar { width: 28px; height: 28px; font-size: .75rem; flex-shrink: 0; }
.msg-avatar-btn { appearance: none; background: transparent; border: 0; padding: 0; border-radius: 50%; cursor: pointer; display: inline-flex; flex-shrink: 0; transition: transform .12s ease, box-shadow .12s ease; }
.msg-avatar-btn:hover { transform: scale(1.08); box-shadow: 0 0 0 2px var(--accent) inset; }
.msg-avatar-btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }

.msg { max-width: 70%; padding: .5rem .8rem; border-radius: 14px; background: var(--card-2); border: 1px solid var(--border-2); position: relative; word-wrap: break-word; }
.msg.mine { margin-inline-start: auto; background: var(--accent); color: var(--accent-fg); border: 0; }
.msg .sender-name { font-size: .75rem; font-weight: 600; margin-bottom: .15rem; opacity: .85; color: var(--accent); }
.msg .msg-text { white-space: pre-wrap; word-break: break-word; }
.msg .meta { font-size: .7rem; opacity: .75; margin-top: .25rem; display: flex; gap: .3rem; align-items: center; justify-content: flex-end; }
.msg .ticks { display: inline-flex; align-items: center; color: rgba(255,255,255,.85); }
.msg .ticks svg { width: 16px; height: 16px; stroke-width: 2.5; }
.msg .ticks.double svg { color: #fff; }
.msg.deleted { opacity: .6; font-style: italic; }

.typing-indicator { font-size: .8rem; opacity: .7; padding: .25rem 1rem; font-style: italic; min-height: 1.2rem; }
.composer { border-top: 1px solid var(--border); padding: .6rem .7rem; display: flex; gap: .5rem; align-items: flex-end; background: var(--card-2); }
.composer textarea { flex: 1; resize: none; min-height: 38px; max-height: 120px; padding: .5rem .7rem; border-radius: 10px; border: 1px solid var(--border); background: var(--card); color: inherit; font: inherit; line-height: 1.4; }
.composer textarea:focus { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }

/* Chat Phase 2: context menu, reactions, reply, edit */
.msg-dots { position: absolute; top: 4px; inset-inline-end: 4px; background: transparent; border: 0; cursor: pointer; color: inherit; opacity: 0; font-size: 1rem; padding: 0 .3rem; border-radius: 4px; line-height: 1; }
.msg:hover .msg-dots { opacity: .7; }
.msg-dots:hover { opacity: 1 !important; background: rgba(0,0,0,.15); }
.msg-ctx-menu { position: absolute; z-index: 50; background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: .3rem; min-width: 160px; box-shadow: 0 6px 20px rgba(0,0,0,.18); display: flex; flex-direction: column; }
.msg-ctx-menu button { background: transparent; border: 0; padding: .5rem .7rem; text-align: start; cursor: pointer; color: inherit; border-radius: 6px; display: flex; gap: .5rem; align-items: center; font: inherit; }
.msg-ctx-menu button:hover { background: var(--card-2); }
.msg-ctx-menu button.danger { color: #ef4444; }
.reaction-picker { position: absolute; top: -40px; inset-inline-end: 0; background: var(--card); border: 1px solid var(--border); border-radius: 20px; padding: .3rem .5rem; display: flex; gap: .3rem; box-shadow: 0 4px 12px rgba(0,0,0,.15); z-index: 20; }
.reaction-picker button { background: transparent; border: 0; font-size: 1.15rem; cursor: pointer; padding: 0 .2rem; }
.msg .reactions { display: flex; gap: .25rem; flex-wrap: wrap; margin-top: .3rem; }
.msg .reaction-chip { background: rgba(0,0,0,.15); border-radius: 12px; padding: .1rem .45rem; font-size: .78rem; cursor: pointer; user-select: none; }
.msg .reaction-chip.mine { background: rgba(124,58,237,.45); }
.msg.mine .reaction-chip { background: rgba(255,255,255,.22); }
.msg.mine .reaction-chip.mine { background: rgba(255,255,255,.4); }
.msg .reply-quote { display: flex; gap: .5rem; align-items: center; border-inline-start: 3px solid currentColor; padding: .3rem .5rem; margin-bottom: .3rem; font-size: .85rem; border-radius: 6px; background: rgba(0,0,0,.12); cursor: pointer; }
.msg.mine .reply-quote { background: rgba(255,255,255,.15); }
.reply-thumb { flex-shrink: 0; width: 36px; height: 36px; border-radius: 6px; overflow: hidden; display: inline-flex; align-items: center; justify-content: center; background: rgba(0,0,0,.2); }
.reply-thumb img { width: 100%; height: 100%; object-fit: cover; }
.reply-thumb-icon { font-size: 1.2rem; }
.reply-quote-body { min-width: 0; flex: 1; }
.reply-quote-name { font-weight: 700; font-size: .8rem; opacity: .95; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reply-quote-text { opacity: .85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg .edited-tag { font-size: .68rem; opacity: .7; font-style: italic; }
.reply-preview { padding: .4rem .8rem; background: var(--card-2); border-inline-start: 3px solid var(--accent); display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.reply-preview .close { background: transparent; border: 0; cursor: pointer; color: inherit; padding: .2rem .4rem; border-radius: 4px; }
.reply-preview .close:hover { background: rgba(0,0,0,.1); }

/* Jump-to-message flash */
.msg.flash { animation: msg-flash 1.4s ease-out; }
@keyframes msg-flash {
  0% { box-shadow: 0 0 0 3px rgba(124,58,237,.7); background-color: rgba(124,58,237,.25); }
  100% { box-shadow: 0 0 0 0 rgba(124,58,237,0); background-color: transparent; }
}

/* Drag & drop overlay */
.chat-body { position: relative; }
.chat-body .drop-overlay { position: absolute; inset: 0; z-index: 30; display: none; align-items: center; justify-content: center; background: rgba(124,58,237,.18); border: 3px dashed var(--accent); border-radius: 12px; margin: .5rem; pointer-events: none; }
.chat-body.dragging .drop-overlay { display: flex; }
.chat-body .drop-hint { display: flex; flex-direction: column; align-items: center; gap: .5rem; color: var(--accent); font-weight: 700; font-size: 1.1rem; background: var(--card); padding: 1rem 1.5rem; border-radius: 10px; box-shadow: 0 4px 14px rgba(0,0,0,.2); }
.chat-body .drop-hint svg { width: 28px; height: 28px; }

/* Telegram-style voice player */
.voice-msg { display: flex; align-items: center; gap: .6rem; min-width: 240px; padding: .15rem 0; }
.voice-msg .voice-play { flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%; border: 0; cursor: pointer; background: #fff; color: var(--accent); display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 1px 3px rgba(0,0,0,.2); }
.msg:not(.mine) .voice-msg .voice-play { background: var(--accent); color: var(--accent-fg); }
.voice-msg .voice-play svg { width: 18px; height: 18px; }
.voice-msg .voice-body { flex: 1; display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.voice-msg .voice-wave { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 2px; height: 28px; cursor: pointer; overflow: hidden; }
.voice-msg .voice-wave .vb { display: inline-block; width: 2.5px; min-height: 4px; border-radius: 2px; background: rgba(255,255,255,.55); transition: background .1s; flex: 0 0 auto; }
.msg:not(.mine) .voice-msg .voice-wave .vb { background: rgba(124,58,237,.35); }
.voice-msg .voice-progress { position: absolute; inset-block: 0; inset-inline-start: 0; width: 0%; background: rgba(255,255,255,.25); pointer-events: none; border-radius: 3px; mix-blend-mode: overlay; }
.msg:not(.mine) .voice-msg .voice-progress { background: rgba(124,58,237,.25); }
.voice-msg .voice-meta { display: flex; align-items: center; gap: .3rem; font-size: .75rem; font-variant-numeric: tabular-nums; opacity: .85; }
.voice-msg .voice-time { font-weight: 600; }

/* Telegram-style composer */
.tg-composer { align-items: center; gap: .5rem; padding: .35rem .55rem; background: var(--card-2); border: 0; border-radius: 28px; margin: .6rem 1rem 1rem; box-shadow: 0 2px 10px rgba(0,0,0,.18); }
.tg-composer textarea { border: 0; background: transparent; padding: .4rem .2rem; }
.tg-composer textarea:focus { outline: none; }
.comp-btn { background: transparent; border: 0; width: 38px; height: 38px; border-radius: 50%; cursor: pointer; color: var(--text-2); font-size: 1.2rem; display: inline-flex; align-items: center; justify-content: center; transition: background .12s, color .12s; }
.comp-btn:hover { background: var(--border); color: var(--text); }
.comp-primary { color: var(--accent); }
.comp-primary.is-send { color: var(--accent-fg); background: var(--accent); }
.comp-primary.recording { color: var(--accent-fg); background: var(--accent); }
@keyframes pulse-rec { 0%,100% { box-shadow:0 0 0 0 rgba(239,68,68,.6); } 50% { box-shadow:0 0 0 8px rgba(239,68,68,0); } }
.comp-cancel { color: #ef4444; }
.comp-cancel:hover { background: rgba(239,68,68,.12); color: #ef4444; }
.rec-ui { flex: 1; display: flex; align-items: center; gap: .6rem; padding: .4rem .2rem; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--text); }
.rec-ui #rec-time { margin-inline-start: auto; }
.rec-dot { width: 10px; height: 10px; border-radius: 50%; background: #ef4444; animation: rec-blink 1s infinite; flex-shrink: 0; }
@keyframes rec-blink { 0%,100% { opacity: 1; } 50% { opacity: .3; } }

.attach-menu { position: absolute; bottom: 72px; inset-inline-end: 50px; background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: .4rem; box-shadow: 0 8px 22px rgba(0,0,0,.2); z-index: 40; flex-direction: column; min-width: 190px; }
.attach-menu button { background: transparent; border: 0; padding: .6rem .8rem; text-align: start; cursor: pointer; color: inherit; display: flex; gap: .6rem; align-items: center; border-radius: 8px; font: inherit; }
.attach-menu button:hover { background: var(--card-2); }

.emoji-pop { position: fixed; background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: .35rem; box-shadow: 0 8px 22px rgba(0,0,0,.2); display: grid; grid-template-columns: repeat(8, 1fr); gap: .15rem; z-index: 60; max-width: 320px; }
.emoji-pop button { background: transparent; border: 0; font-size: 1.25rem; cursor: pointer; padding: .25rem; border-radius: 6px; }
.emoji-pop button:hover { background: var(--card-2); }

/* Date separator */
.date-sep { display: flex; justify-content: center; margin: .6rem 0; }
.date-sep span { background: rgba(0,0,0,.45); color: #fff; font-size: .78rem; padding: .2rem .7rem; border-radius: 12px; font-weight: 600; backdrop-filter: blur(4px); }
html.light .date-sep span { background: rgba(31,35,40,.75); color: #fff; }

/* Telegram-style context menu wrap (reactions row + actions) */
.msg-ctx-wrap { position: absolute; z-index: 60; display: flex; flex-direction: column; gap: .4rem; align-items: flex-start; }
.msg-ctx-wrap .msg-ctx-menu { position: static; }
.ctx-reactions { display: flex; gap: .2rem; background: var(--card); border: 1px solid var(--border); border-radius: 22px; padding: .3rem .5rem; box-shadow: 0 6px 18px rgba(0,0,0,.2); align-self: flex-start; }
.ctx-reactions button { background: transparent; border: 0; font-size: 1.25rem; cursor: pointer; padding: .15rem .25rem; border-radius: 50%; transition: transform .12s; }
.ctx-reactions button:hover { transform: scale(1.25); }

/* Attachment styles */
.att-image { max-width: 280px; max-height: 320px; border-radius: 10px; display: block; cursor: pointer; }
.att-video { max-width: 320px; max-height: 320px; border-radius: 10px; display: block; }
.att-file { display: flex; align-items: center; gap: .5rem; padding: .4rem .6rem; background: rgba(0,0,0,.12); border-radius: 8px; color: inherit; text-decoration: none; }
.att-file:hover { background: rgba(0,0,0,.2); }
.forwarded-tag { font-size: .75rem; opacity: .7; font-style: italic; margin-bottom: .2rem; }

/* Utilities */
.flex { display: flex; } .items-center { align-items: center; } .justify-between { justify-content: space-between; }
.gap-1 { gap: .25rem; } .gap-2 { gap: .5rem; } .gap-3 { gap: .75rem; } .gap-4 { gap: 1rem; }
.w-full { width: 100%; } .text-sm { font-size: .88rem; } .text-xs { font-size: .78rem; }
.mt-1 { margin-top: .25rem; } .mt-2 { margin-top: .5rem; } .mt-3 { margin-top: .75rem; } .mt-4 { margin-top: 1rem; } .mt-6 { margin-top: 1.5rem; }
.mb-2 { margin-bottom: .5rem; } .mb-3 { margin-bottom: .75rem; } .mb-4 { margin-bottom: 1rem; }
.text-muted { color: var(--text-2); } .text-subtle { color: var(--text-3); }
.hidden { display: none !important; }
.spinner { width: 20px; height: 20px; border: 2px solid transparent; border-top-color: var(--accent); border-right-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── App loader: three wave dots in accent color + subtle label ────── */
.app-loader {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .75rem;
  padding: 2rem 1rem;
  animation: app-loader-fade .3s ease both;
}
.app-loader-inline { padding: 0; gap: 0; flex-direction: row; }

.app-loader-dots {
  display: inline-flex;
  align-items: flex-end;
  gap: .45em;
  font-size: 10px; /* controls dot size; overridden per size variant below */
  line-height: 0;
}
.app-loader-dots > span {
  display: inline-block;
  width: 1em;
  height: 1em;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 45%, transparent);
  animation: app-loader-wave 1s ease-in-out infinite;
}
.app-loader-dots > span:nth-child(1) { animation-delay: 0s; }
.app-loader-dots > span:nth-child(2) { animation-delay: .16s; }
.app-loader-dots > span:nth-child(3) { animation-delay: .32s; }

.app-loader-sm .app-loader-dots { font-size: 7px; gap: .4em; }
.app-loader-md .app-loader-dots { font-size: 10px; }
.app-loader-lg .app-loader-dots { font-size: 14px; gap: .5em; }

.app-loader-text {
  font-size: .85rem; font-weight: 500; letter-spacing: .02em;
  color: var(--text-3);
  opacity: .85;
}

@keyframes app-loader-wave {
  0%, 60%, 100% { transform: translateY(0); opacity: .45; }
  30%           { transform: translateY(-0.7em); opacity: 1; }
}
@keyframes app-loader-fade { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .app-loader-dots > span {
    animation: app-loader-pulse-reduced 1.4s ease-in-out infinite;
    transform: none;
  }
}
@keyframes app-loader-pulse-reduced {
  0%, 100% { opacity: .45; }
  50%      { opacity: 1; }
}

/* ── Offline banner ─────────────────────────────────────────────────────
   Slim status pill that drops in from the top when the device loses
   connectivity. Phase-1 offline-shell UX: the app keeps working,
   navigation still works, but the user sees a clear "why data isn't
   refreshing" hint instead of a blank screen or a generic error toast.
   Hidden by default; shell.js adds .is-visible when offline. */
.duwam-offline-banner {
  position: fixed; top: 0; left: 50%; transform: translate(-50%, -120%);
  z-index: 9999;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .55rem 1rem; margin-top: .55rem;
  border-radius: 999px;
  background: var(--warn);
  color: #1a1408;
  font-weight: 700; font-size: .85rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
  pointer-events: none; user-select: none;
  /* Hidden by default — opacity:0 prevents the box-shadow from leaking
     into the viewport while the element sits just above the top edge.
     Without this you can see a faint horizontal shadow band near the
     top of the page even when fully connected. */
  opacity: 0;
  transition: transform .35s cubic-bezier(.2,.8,.2,1), opacity .25s ease-out;
}
.duwam-offline-banner.is-visible { transform: translate(-50%, 0); opacity: 1; }

/* Read-only mode: any control that creates/sends/deletes data should
   carry data-needs-online, and gets dimmed + click-blocked while the
   device is offline. Read flows (filtering, scrolling cached lists,
   navigating between pages) stay fully interactive. */
body.is-offline [data-needs-online] {
  opacity: .45;
  pointer-events: none;
  filter: saturate(.6);
  cursor: not-allowed;
}
.duwam-offline-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #1a1408;
  box-shadow: 0 0 0 0 rgba(26, 20, 8, .6);
  animation: duwam-offline-pulse 1.6s ease-out infinite;
}
@keyframes duwam-offline-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(26, 20, 8, .55); }
  70%  { box-shadow: 0 0 0 7px rgba(26, 20, 8, 0); }
  100% { box-shadow: 0 0 0 0 rgba(26, 20, 8, 0); }
}

/* ── Skeleton screens ───────────────────────────────────────────────────
   Shaped placeholders that mirror the layout of the content about to land
   (Asana / Notion / Linear style). Tuned to be quiet — base sits at --bg-2
   (only a hair above the canvas, so the bar feels "missing content" not
   "loading effect") and the shimmer is a 4% neutral sweep at a relaxed
   2.2s cadence. Crucially we use --text mixed into the bg, NOT the brand
   emerald, so the loading state never competes with real interactive
   accents on the page. */
.sk {
  position: relative; overflow: hidden;
  background: var(--bg-2);
  display: block;
}
.sk::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--text) 4%, transparent) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: sk-shimmer 2.2s ease-in-out infinite;
}
.sk-bar { /* alias so existing markup stays clean */ }
.sk-card { border: 1px solid var(--border); }
.sk-list .sk-row:last-child { border-bottom: 0; }

@keyframes sk-shimmer {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
/* RTL: shimmer should sweep right→left to match reading direction. */
html[dir="rtl"] .sk::before { animation-direction: reverse; }

@media (prefers-reduced-motion: reduce) {
  .sk::before {
    animation: sk-pulse-reduced 2.4s ease-in-out infinite;
    transform: none;
    background: color-mix(in srgb, var(--text) 4%, transparent);
  }
}
@keyframes sk-pulse-reduced {
  0%, 100% { opacity: .25; }
  50%      { opacity: .8;  }
}

/* In-button spinner used while an action is in flight. Inherits color so
   it works on .btn-primary (white), ghost/outline variants, icon buttons. */
.btn-spinner {
  display: inline-block;
  width: 1.05em;
  height: 1.05em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -0.2em;
  animation: btn-spin .6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
.btn-busy { cursor: progress !important; opacity: .92; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .btn-spinner { animation-duration: 1.4s; }
}

.fade-in { animation: fadeIn .25s ease both; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* Chat info side panel */
.info-panel {
  position: absolute; top: 0; bottom: 0; inset-inline-end: 0; width: 340px; max-width: 90%;
  background: var(--bg-2); border-inline-start: 1px solid var(--border);
  display: flex; flex-direction: column; z-index: 40;
  transform: translateX(100%); transition: transform .22s ease;
  box-shadow: -8px 0 24px rgba(0,0,0,.18);
}
html[dir="rtl"] .info-panel { transform: translateX(-100%); }
.info-panel.open,
html[dir="rtl"] .info-panel.open { transform: translateX(0); }
.info-panel-head { display: flex; align-items: center; gap: .6rem; padding: .7rem 1rem; border-bottom: 1px solid var(--border); background: var(--card-2); min-height: 56px; }
.info-panel-title { font-weight: 700; font-size: 1rem; flex: 1; min-width: 0; }
.info-close { background: transparent; border: 0; cursor: pointer; color: var(--text); width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; }
.info-close:hover { background: var(--card); }
/* Mobile-only: relocates the call action that used to live in the chat
   header. Kept invisible on desktop because the chat header already
   carries its own call button there — duplicating would just add noise. */
.info-call-btn { display: none; background: transparent; border: 0; cursor: pointer; color: var(--brand); width: 38px; height: 38px; border-radius: 50%; align-items: center; justify-content: center; transition: background .15s ease; }
.info-call-btn:hover { background: color-mix(in srgb, var(--brand) 12%, transparent); }
.info-call-btn .lucide-ic { width: 18px; height: 18px; }
@media (max-width: 768px) { .info-call-btn { display: inline-flex; } }
.info-panel-body { flex: 1; overflow-y: auto; padding: 1rem; }
.info-hero { display: flex; flex-direction: column; align-items: center; text-align: center; gap: .4rem; padding: 1rem 0 1.2rem; border-bottom: 1px solid var(--border); }
.info-hero .avatar.lg { width: 96px; height: 96px; font-size: 2rem; }
.info-hero .avatar.lg img, .info-hero img.avatar.lg { width: 96px; height: 96px; object-fit: cover; }
.info-avatar-btn { position: relative; padding: 0; border: 0; background: transparent; cursor: pointer; border-radius: 50%; line-height: 0; }
.info-avatar-btn .avatar.lg { display: block; }
.info-avatar-overlay { position: absolute; inset: 0; border-radius: 50%; background: rgba(0,0,0,.45); color: #fff; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity .15s ease; }
.info-avatar-overlay svg { width: 26px; height: 26px; }
.info-avatar-btn:hover .info-avatar-overlay, .info-avatar-btn:focus-visible .info-avatar-overlay { opacity: 1; }
.info-title { font-size: 1.25rem; font-weight: 700; }
.info-title-row { display: flex; align-items: center; justify-content: center; gap: .5rem; flex-wrap: wrap; }
.info-rename-btn { background: transparent; border: 0; cursor: pointer; color: var(--text-3); width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; }
.info-rename-btn:hover { background: var(--card-2); color: var(--text); }
.info-rename-btn svg { width: 16px; height: 16px; }
.info-rename-input { max-width: 220px; text-align: center; font-weight: 600; }
.info-subtitle { color: var(--text-3); font-size: .85rem; }
.info-section-title { font-size: .75rem; text-transform: uppercase; color: var(--text-3); letter-spacing: .08em; margin: 1rem 0 .4rem; font-weight: 700; }
.msg-system { display: flex; justify-content: center; margin: .5rem 0; }
.msg-system span { background: var(--card-2); color: var(--text-3); border: 1px solid var(--border); border-radius: 12px; padding: .25rem .7rem; font-size: .8rem; max-width: 80%; text-align: center; }
.att-image { cursor: zoom-in; }
.lightbox { position: fixed; inset: 0; background: rgba(0,0,0,.92); z-index: 9999; display: flex; align-items: center; justify-content: center; }
.lightbox-stage { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; cursor: zoom-out; }
.lightbox-img { max-width: 92vw; max-height: 92vh; object-fit: contain; transition: transform .15s ease; user-select: none; -webkit-user-drag: none; will-change: transform; }
.lightbox-toolbar { position: absolute; top: 14px; right: 14px; display: flex; gap: .35rem; z-index: 2; }
.lightbox-toolbar button { background: rgba(255,255,255,.08); border: 0; color: #fff; width: 38px; height: 38px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; font-size: .85rem; }
.lightbox-toolbar button:hover { background: rgba(255,255,255,.18); }
.lightbox-toolbar svg { width: 18px; height: 18px; }
.lightbox-nav { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,.08); border: 0; color: #fff; width: 44px; height: 44px; border-radius: 50%; cursor: pointer; font-size: 1.6rem; line-height: 1; z-index: 2; }
.lightbox-nav:hover { background: rgba(255,255,255,.18); }
.lightbox-nav.prev { left: 18px; }
.lightbox-nav.next { right: 18px; }
.lightbox-counter { position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,.8); font-size: .85rem; background: rgba(0,0,0,.4); padding: .25rem .6rem; border-radius: 12px; }
html[dir="rtl"] .lightbox-toolbar { right: auto; left: 14px; }
html[dir="rtl"] .lightbox-nav.prev { left: auto; right: 18px; }
html[dir="rtl"] .lightbox-nav.next { right: auto; left: 18px; }
.info-section-row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin: 1rem 0 .4rem; }
.info-section-row .info-section-title { margin: 0; }
.info-add-btn { display: inline-flex; align-items: center; gap: .3rem; background: transparent; border: 1px solid var(--border); color: var(--text); border-radius: 8px; padding: .25rem .55rem; cursor: pointer; font-size: .8rem; }
.info-add-btn:hover { background: var(--card-2); }
.info-add-btn svg { width: 14px; height: 14px; }
.info-details { display: flex; flex-direction: column; gap: .5rem; }
.info-row { padding: .5rem .6rem; background: var(--card-2); border-radius: 10px; border: 1px solid var(--border); }
.info-row-label { font-size: .7rem; color: var(--text-3); text-transform: uppercase; letter-spacing: .05em; }
.info-row-value { font-size: .95rem; color: var(--text); word-break: break-word; }
.info-members { display: flex; flex-direction: column; gap: .2rem; }
.info-member { display: flex; align-items: center; gap: .6rem; padding: .5rem .4rem; border-radius: 8px; }
.info-member:hover { background: var(--card-2); }
.info-member-info { flex: 1; min-width: 0; }
.info-member-av { background: transparent; border: 0; padding: 0; line-height: 0; border-radius: 50%; }
.info-member-dm { cursor: pointer; transition: transform .12s ease, box-shadow .12s ease; }
.info-member-dm:hover { transform: scale(1.06); box-shadow: 0 0 0 2px var(--accent, #6c5ce7) inset; }
.info-member-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.info-member-remove { background: transparent; border: 0; color: var(--text-3); width: 28px; height: 28px; border-radius: 50%; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; opacity: 0; transition: opacity .15s ease, background .15s ease; }
.info-member-remove svg { width: 14px; height: 14px; }
.info-member:hover .info-member-remove { opacity: 1; }
.info-member-remove:hover { background: color-mix(in srgb, var(--danger, #e25), 15% transparent); color: var(--danger, #e25); }
.info-member-promote { background: transparent; border: 0; color: var(--text-3); width: 28px; height: 28px; border-radius: 50%; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; opacity: 0; transition: opacity .15s ease, background .15s ease, color .15s ease; }
.info-member-promote svg { width: 15px; height: 15px; }
.info-member:hover .info-member-promote { opacity: 1; }
.info-member-promote[data-state="on"] { color: var(--accent, #6c5ce7); opacity: 1; }
.info-member-promote:hover { background: var(--card-2); color: var(--accent, #6c5ce7); }
.info-member-badge { display: inline-block; font-size: .65rem; font-weight: 700; padding: .1rem .4rem; border-radius: 8px; margin-inline-start: .35rem; vertical-align: middle; }
.info-member-badge.owner { background: color-mix(in srgb, var(--accent, #6c5ce7), 80% transparent); color: var(--accent, #6c5ce7); border: 1px solid color-mix(in srgb, var(--accent, #6c5ce7), 60% transparent); }
.info-member-badge.admin { background: color-mix(in srgb, var(--accent, #6c5ce7), 88% transparent); color: var(--accent, #6c5ce7); }

/* Telegram-style delete chat dialog */
.delete-chat-backdrop { background: rgba(0,0,0,.55); backdrop-filter: blur(6px); }
.delete-chat-dialog {
  background: #1f232b; color: #fff; border-radius: 14px; padding: 1.1rem 1.25rem 0;
  width: min(92vw, 420px); box-shadow: var(--shadow-2); overflow: hidden;
}
html.light .delete-chat-dialog { background: #fff; color: var(--text); }
.delete-chat-dialog .dcd-head { display: flex; align-items: center; gap: .7rem; margin-bottom: .7rem; }
.delete-chat-dialog .dcd-head .avatar { width: 44px; height: 44px; font-size: 1rem; }
.delete-chat-dialog .dcd-title { font-size: 1.15rem; font-weight: 700; }
.delete-chat-dialog .dcd-body { font-size: .95rem; line-height: 1.4; opacity: .92; padding-bottom: .5rem; }
.delete-chat-dialog .dcd-actions { display: flex; flex-direction: column; align-items: stretch; margin: 0 -1.25rem; }
.delete-chat-dialog .dcd-btn {
  background: transparent; border: 0; padding: .95rem 1.25rem; text-align: end;
  font: inherit; font-weight: 700; font-size: .95rem; letter-spacing: .04em;
  text-transform: uppercase; cursor: pointer; color: var(--accent);
  border-top: 1px solid rgba(255,255,255,.06);
}
html.light .delete-chat-dialog .dcd-btn { border-top-color: rgba(0,0,0,.08); }
.delete-chat-dialog .dcd-btn:hover { background: rgba(255,255,255,.04); }
html.light .delete-chat-dialog .dcd-btn:hover { background: rgba(0,0,0,.04); }
.delete-chat-dialog .dcd-btn.danger { color: #ef4444; }
.delete-chat-dialog .dcd-btn.primary { color: var(--accent); }

/* Day chips (work / vacation toggles) */
.day-chips { display: flex; gap: .35rem; flex-wrap: wrap; }
.day-chip {
  appearance: none; border: 1px solid var(--border); background: var(--card-2);
  color: var(--text-2); padding: .4rem .7rem; border-radius: 999px;
  font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .12s ease;
  user-select: none;
}
.day-chip:hover { transform: translateY(-1px); }
.day-chip.on {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.day-chip.off {
  background: var(--card-2); color: var(--text-3);
  border-color: var(--border); opacity: .85;
  text-decoration: line-through;
}

/* Chat compose FAB (lives in chat header) */
.chat-shell { position: relative; }
.chat-header-side { display: inline-flex; align-items: center; gap: .35rem; }
.chat-fab {
  width: 38px; height: 38px; border-radius: 50%; border: 0;
  background: var(--accent); color: var(--accent-fg); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent);
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
  flex-shrink: 0;
}
.chat-fab:hover { transform: translateY(-1px) scale(1.05); box-shadow: 0 8px 18px color-mix(in srgb, var(--accent) 55%, transparent); }
.chat-fab:active { transform: scale(0.96); }
.chat-fab .lucide-ic { width: 18px; height: 18px; }
.chat-fab-sm { width: 36px; height: 36px; }
.chat-fab-menu {
  position: absolute; top: calc(100% + 6px); inset-inline-end: 0; z-index: 30;
  min-width: 200px; background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,.28);
  padding: .35rem; opacity: 0; pointer-events: none; transform: translateY(-4px);
  transition: opacity .14s ease, transform .14s ease;
}
.chat-fab-menu.open { opacity: 1; pointer-events: auto; transform: translateY(0); }
.chat-fab-menu button {
  display: flex; align-items: center; gap: .55rem; width: 100%;
  padding: .55rem .7rem; border: 0; background: transparent; color: var(--text);
  border-radius: 8px; cursor: pointer; font: inherit; text-align: start;
}
.chat-fab-menu button:hover { background: var(--card-2); color: var(--accent); }
.chat-fab-menu button .lucide-ic { width: 18px; height: 18px; flex-shrink: 0; }

/* Member picker (used by new-group / new-chat modals) */
.new-chat-modal { display: flex; flex-direction: column; max-height: 70vh; }
.pick-list {
  border: 1px solid var(--border); border-radius: 10px;
  max-height: 320px; overflow-y: auto; background: var(--card-2);
}
.pick-list .pick-row {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .7rem; border-bottom: 1px solid var(--border);
  cursor: pointer; transition: background .12s ease;
}
.pick-list .pick-row:last-child { border-bottom: 0; }
.pick-list .pick-row:hover { background: var(--card); }
.pick-row input[type="checkbox"] { flex-shrink: 0; }
.pick-row-av .avatar { width: 32px; height: 32px; font-size: .8rem; }
.pick-row-info { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.pick-row-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-row-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-row-btn { width: 100%; border: 0; background: transparent; color: inherit; font: inherit; text-align: start; }

/* ── Push-to-talk mic button (admin) ─────────────────────────────────── */
.mic-btn { user-select: none; touch-action: none; transition: background .15s ease, color .15s ease, transform .12s ease; }
.mic-btn:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); }
.mic-btn.recording { background: var(--danger); color: white; transform: scale(1.05); animation: ptt-pulse 1.2s ease-out infinite; }
@keyframes ptt-pulse { 0% { box-shadow: 0 0 0 0 rgba(255,72,72,.55); } 100% { box-shadow: 0 0 0 14px rgba(255,72,72,0); } }

/* Admin HUD shown while holding the mic button */
.ptt-hud { position: fixed; inset: auto 0 1.2rem 0; display: grid; place-items: center; z-index: 110; pointer-events: none; }
.ptt-hud-card {
  pointer-events: auto;
  background: var(--bg-2); border: 1px solid var(--border-2); border-radius: 14px;
  padding: .7rem 1rem; box-shadow: var(--shadow-2);
  display: flex; align-items: center; gap: .8rem;
}
.ptt-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--danger); box-shadow: 0 0 0 0 rgba(255,72,72,.55); animation: ptt-pulse 1.2s ease-out infinite; }
.ptt-text { display: flex; flex-direction: column; min-width: 0; }
.ptt-time { font-family: ui-monospace, monospace; font-weight: 700; font-size: 1.05rem; }
.ptt-hint { font-size: .75rem; color: var(--text-3); margin-inline-start: .4rem; }

/* Overlay the employee sees while admin talks */
.admin-voice-overlay {
  position: fixed; inset: 1rem; top: 1rem; left: 50%; transform: translateX(-50%);
  z-index: 200; display: flex; align-items: flex-start; justify-content: center;
  pointer-events: none;
}
.admin-voice-overlay .avl-card {
  pointer-events: auto; min-width: 320px; max-width: 460px;
  background: var(--bg-2); border: 1px solid var(--accent);
  border-radius: 16px; padding: 1rem 1.1rem;
  box-shadow: 0 8px 32px rgba(0,0,0,.35);
  display: grid; grid-template-columns: auto 1fr auto; gap: .8rem; align-items: center; position: relative;
}
.admin-voice-overlay .avl-pulse {
  position: absolute; inset-inline-start: 1rem; top: 1rem; width: 48px; height: 48px; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 50%, transparent) 0%, transparent 70%);
  animation: ptt-pulse 1.4s ease-out infinite; pointer-events: none;
}
.admin-voice-overlay .avl-avatar { position: relative; }
.admin-voice-overlay .avl-title { font-weight: 700; font-size: .95rem; }
.admin-voice-overlay .avl-name { font-size: .85rem; color: var(--text-2); }
.admin-voice-overlay .avl-status { font-size: .75rem; color: var(--accent); margin-top: .2rem; }
.admin-voice-overlay .avl-close { appearance: none; background: transparent; border: 0; color: var(--text-2); width: 30px; height: 30px; border-radius: 8px; cursor: pointer; }
.admin-voice-overlay .avl-close:hover { background: var(--bg-3); }
.admin-voice-overlay .avl-play { grid-column: 1 / -1; margin-top: .5rem; }

/* Contact admin panel (employee topbar) */
.contact-panel .bell-panel-list { padding: .3rem .3rem .1rem; }
.contact-row {
  display: flex; align-items: center; gap: .7rem;
  padding: .55rem .7rem; border-radius: 10px;
  transition: background .12s ease;
}
.contact-row + .contact-row { border-top: 1px solid var(--border); }
.contact-row:hover { background: var(--bg-3); }
.contact-row-av .avatar { width: 34px; height: 34px; font-size: .82rem; }
.contact-row-info { flex: 1; min-width: 0; }
.contact-row-name { font-weight: 600; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-row-sub { font-size: .72rem; color: var(--text-3); }
.contact-panel-hint {
  padding: .55rem .9rem; border-top: 1px solid var(--border);
  font-size: .72rem; color: var(--text-3); text-align: center; background: var(--card-2);
}
.contact-group + .contact-group { margin-top: .2rem; border-top: 1px solid var(--border); }
.contact-group-head {
  width: 100%; display: flex; align-items: center; gap: .5rem;
  padding: .6rem .9rem; border: 0; background: var(--card-2);
  font-weight: 700; font-size: .82rem; color: var(--text-2); cursor: pointer;
  text-align: start; font-family: inherit;
  transition: background .12s ease;
}
.contact-group-head:hover { background: var(--bg-3); }
.contact-group-title { flex: 1; }
.contact-group-count {
  background: var(--bg-2); border: 1px solid var(--border);
  padding: .08rem .5rem; border-radius: 999px;
  font-size: .72rem; font-weight: 700; color: var(--text-3);
}
.contact-group-caret { color: var(--text-3); transform: rotate(0); transition: transform .18s ease; }
.contact-group-caret .lucide-ic { width: .95rem; height: .95rem; }
.contact-group-head.collapsed .contact-group-caret { transform: rotate(-90deg); }
.contact-group-body { padding: .15rem 0; }

/* Urgent message — admin send panel */
.urgent-panel .urgent-body { padding: .9rem 1rem 1rem; }
.urgent-panel textarea.input { resize: vertical; min-height: 90px; max-height: 240px; }

/* Urgent message — employee-side pinned stack (bottom-inline-end) */
.urgent-stack {
  position: fixed; bottom: 1rem; inset-inline-end: 1rem;
  display: flex; flex-direction: column; gap: .6rem;
  z-index: 180; max-width: min(380px, calc(100vw - 2rem));
  pointer-events: none;
}
.urgent-card {
  pointer-events: auto;
  background: var(--bg-2);
  border: 1px solid var(--danger);
  border-inline-start: 4px solid var(--danger);
  border-radius: 14px; padding: .85rem 1rem;
  box-shadow: 0 10px 32px rgba(0,0,0,.35);
  animation: urgent-in .22s ease;
  display: flex; flex-direction: column; gap: .6rem;
}
@keyframes urgent-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.urgent-card-head { display: flex; align-items: center; gap: .6rem; }
.urgent-card-who { min-width: 0; flex: 1; }
.urgent-card-name { font-weight: 700; font-size: .92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.urgent-card-sub { font-size: .72rem; color: var(--danger); font-weight: 600; }
.urgent-card-text { font-size: .92rem; line-height: 1.45; white-space: pre-wrap; word-break: break-word; color: var(--text); }
.urgent-card-actions { display: flex; gap: .4rem; justify-content: flex-end; }
.urgent-card .btn-primary { background: var(--danger); border-color: var(--danger); }
.urgent-card .btn-primary:hover { filter: brightness(1.08); }

/* Monthly payroll/attendance report table — sticky header + highlighted totals */
.report-table thead th {
  position: sticky;
  top: var(--topbar-h);
  background: var(--card-2);
  z-index: 5;
  font-size: .75rem; letter-spacing: .04em; text-transform: uppercase; color: var(--text-3);
  box-shadow: 0 1px 0 var(--border), 0 6px 12px -10px rgba(0,0,0,.4);
}
.report-table tbody td { vertical-align: middle; }
.report-table tfoot .report-totals td {
  position: sticky; bottom: 0; z-index: 4;
  background: color-mix(in srgb, var(--accent) 8%, var(--card-2));
  border-top: 2px solid var(--border-2);
  padding-top: .85rem; padding-bottom: .85rem;
  font-size: .92rem;
  box-shadow: 0 -6px 12px -10px rgba(0,0,0,.4);
}

@media print {
  body * { visibility: hidden; }
  #rep-table-wrap, #rep-table-wrap * { visibility: visible; }
  #rep-table-wrap { position: absolute; left: 0; top: 0; width: 100%; }
  .topbar, .sidebar, .ws-tabs { display: none !important; }

  /* Free-tier watermark — only renders when shell.js sets
     body[data-watermark="1"] (mirrors planLimits.hasWatermark on the
     server). Lives in @media print so it appears on browser-print → PDF
     and on physical paper, but never during normal screen viewing. The
     ::after element overrides the parent's `visibility: hidden` so it's
     visible alongside the report content above. Bilingual + URL by
     design — Saudi printouts often circulate beyond the originating
     organization, so we keep the brand and the destination both
     readable in any context. */
  body[data-watermark="1"]::after {
    content: 'مدعوم من دوام  ·  Powered by Duwam  ·  duwam.com';
    visibility: visible !important;
    position: fixed; bottom: 8mm; left: 0; right: 0;
    text-align: center; font-size: 8pt; font-weight: 600;
    color: #6B7280; letter-spacing: 0.02em;
    padding-top: 4mm;
    border-top: 1px solid #D1D5DB;
  }
}

/* ── Date range picker (GHL-inspired) ─────────────────────────────── */
.dr-wrap { position: relative; display: inline-flex; align-items: center; gap: .5rem; direction: ltr; }
.dr-field {
  display: inline-flex; align-items: center; gap: .6rem;
  background: var(--card); border: 1.5px solid var(--accent);
  border-radius: 10px; padding: .35rem .7rem; cursor: pointer;
  font-family: ui-monospace, monospace; font-weight: 600; font-size: .9rem;
}
.dr-field:hover { background: var(--card-2); }
.dr-date { color: var(--text); min-width: 9ch; text-align: center; }
.dr-arrow { color: var(--text-3); display: inline-flex; }
.dr-arrow .lucide-ic { width: .9rem; height: .9rem; transform: rotate(-90deg); }
.dr-toggle {
  appearance: none; background: transparent; border: 0; padding: .2rem;
  color: var(--text-2); cursor: pointer; display: inline-flex;
}
.dr-toggle:hover { color: var(--text); }
.dr-reload {
  appearance: none; border: 0; background: var(--accent); color: var(--accent-fg);
  width: 38px; height: 38px; border-radius: 10px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: filter .15s ease;
}
.dr-reload:hover { filter: brightness(1.08); }
.dr-popover {
  position: absolute; top: calc(100% + 8px); inset-inline-start: 0;
  z-index: 80; direction: ltr;
  background: var(--card); border: 1px solid var(--border-2);
  border-radius: 14px; box-shadow: 0 14px 40px rgba(0,0,0,.32);
  padding: .75rem; min-width: 500px; max-width: 92vw;
  max-height: min(520px, 85vh); overflow-y: auto;
}
.dr-popover.dr-pop-flip-x { inset-inline-start: auto; inset-inline-end: 0; }
.dr-popover.dr-pop-flip-y { top: auto; bottom: calc(100% + 8px); }
.dr-calendars { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; margin-bottom: .6rem; }
.dr-cal { min-width: 0; }
.dr-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .35rem; gap: .3rem; }
.dr-cal-title { font-weight: 700; font-size: .88rem; color: var(--text); }
.dr-cal-nav {
  appearance: none; background: transparent; border: 0; padding: .2rem; border-radius: 6px;
  color: var(--text-2); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
}
.dr-cal-nav:hover { background: var(--bg-3); color: var(--text); }
.dr-cal-nav .lucide-ic { width: .9rem; height: .9rem; }
.dr-cal-nav[data-nav="-1"] .lucide-ic { transform: rotate(90deg); }
.dr-cal-nav[data-nav="1"] .lucide-ic { transform: rotate(-90deg); }
.dr-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
.dr-dow { font-size: .68rem; color: var(--text-3); text-align: center; padding: .25rem 0 .2rem; font-weight: 600; }
.dr-day {
  appearance: none; background: transparent; border: 0;
  padding: .3rem 0; font: inherit; font-size: .8rem; color: var(--text);
  cursor: pointer; border-radius: 6px; text-align: center;
  transition: background .1s ease, color .1s ease;
  min-width: 0;
}
.dr-day:hover { background: var(--bg-3); }
.dr-day.outside { color: var(--text-3); opacity: .45; }
.dr-day.in-range { background: var(--accent-soft); border-radius: 0; color: var(--text); }
.dr-day.start, .dr-day.end {
  background: var(--accent); color: var(--accent-fg); font-weight: 700;
}
.dr-day.start { border-start-end-radius: 0; border-end-end-radius: 0; }
.dr-day.end { border-start-start-radius: 0; border-end-start-radius: 0; }
.dr-day.single { border-radius: 999px; }
.dr-presets {
  display: flex; gap: .3rem; flex-wrap: wrap;
  padding: .55rem 0 .4rem; border-top: 1px solid var(--border);
  margin-top: .3rem;
}
.dr-preset {
  appearance: none; background: var(--card-2); border: 1px solid var(--border);
  border-radius: 999px; padding: .3rem .7rem; font: inherit; font-size: .76rem;
  color: var(--text-2); cursor: pointer; transition: background .12s ease, color .12s ease, border-color .12s ease;
  white-space: nowrap;
}
.dr-preset:hover { background: var(--bg-3); color: var(--text); border-color: var(--border-2); }
.dr-footer { display: flex; justify-content: flex-end; gap: .4rem; padding-top: .45rem; border-top: 1px solid var(--border); }
.dr-footer .btn { padding: .4rem .9rem; font-size: .82rem; }

@media (max-width: 560px) {
  .dr-popover { min-width: 280px; }
  .dr-calendars { grid-template-columns: 1fr; }
}

/* ── Single-day picker (DayPicker) ─────────────────────────────────────
   Same visual language as the range picker but with a single selection,
   a compact popover, and the brand's light-blue accent (--accent-2). */
.dp-wrap { position: relative; display: inline-flex; align-items: center; }
.dp-field {
  display: inline-flex; align-items: center; gap: .5rem;
  background: color-mix(in srgb, var(--accent-2) 12%, var(--card));
  border: 1.5px solid color-mix(in srgb, var(--accent-2) 55%, var(--border-2));
  color: var(--text);
  border-radius: 999px; padding: .35rem .9rem;
  font: inherit; font-size: .85rem; font-weight: 600;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .08s ease;
}
.dp-field:hover {
  background: color-mix(in srgb, var(--accent-2) 20%, var(--card));
  border-color: var(--accent-2);
}
.dp-field:active { transform: translateY(1px); }
.dp-field .dp-icon { color: var(--accent-2); display: inline-flex; }
.dp-field .dp-icon .lucide-ic { width: 1rem; height: 1rem; }
.dp-field .dp-chev { color: var(--accent-2); display: inline-flex; opacity: .8; }
.dp-field .dp-chev .lucide-ic { width: .85rem; height: .85rem; }
.dp-label { white-space: nowrap; }

.dp-popover {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0;
  z-index: 80; direction: ltr;
  background: var(--card); border: 1px solid var(--border-2);
  border-radius: 14px; box-shadow: 0 14px 40px rgba(0,0,0,.32);
  padding: .7rem; min-width: 280px; max-width: 92vw;
}
.dp-popover.dp-pop-flip-x { inset-inline-end: auto; inset-inline-start: 0; }
.dp-popover.dp-pop-flip-y { top: auto; bottom: calc(100% + 8px); }
.dp-cal { min-width: 0; }
.dp-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .4rem; gap: .3rem; }
.dp-cal-title { font-weight: 700; font-size: .9rem; color: var(--text); }
.dp-cal-nav {
  appearance: none; background: transparent; border: 0; padding: .2rem; border-radius: 6px;
  color: var(--text-2); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
}
.dp-cal-nav:hover { background: color-mix(in srgb, var(--accent-2) 15%, transparent); color: var(--accent-2); }
.dp-cal-nav .lucide-ic { width: .95rem; height: .95rem; }
.dp-cal-nav[data-nav="-1"] .lucide-ic { transform: rotate(90deg); }
.dp-cal-nav[data-nav="1"] .lucide-ic { transform: rotate(-90deg); }
.dp-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-dow { font-size: .68rem; color: var(--text-3); text-align: center; padding: .25rem 0 .3rem; font-weight: 600; }
.dp-day {
  appearance: none; background: transparent; border: 0;
  padding: .4rem 0; font: inherit; font-size: .82rem; color: var(--text);
  cursor: pointer; border-radius: 8px; text-align: center;
  transition: background .12s ease, color .12s ease;
  min-width: 0;
}
.dp-day:hover:not(.disabled):not(.selected) {
  background: color-mix(in srgb, var(--accent-2) 18%, transparent);
  color: var(--accent-2);
}
.dp-day.outside { color: var(--text-3); opacity: .45; }
.dp-day.selected {
  background: var(--accent); color: var(--accent-fg); font-weight: 700;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 35%, transparent);
}
.dp-day.disabled { color: var(--text-3); opacity: .3; cursor: not-allowed; }

.dp-presets {
  display: flex; gap: .3rem; flex-wrap: wrap;
  padding-top: .55rem; margin-top: .45rem;
  border-top: 1px solid var(--border);
}
.dp-preset {
  appearance: none; background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px; padding: .28rem .7rem;
  font: inherit; font-size: .75rem; color: var(--text-2);
  cursor: pointer; white-space: nowrap;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.dp-preset:hover {
  background: color-mix(in srgb, var(--accent-2) 15%, transparent);
  color: var(--accent-2);
  border-color: color-mix(in srgb, var(--accent-2) 50%, var(--border));
}
.dp-preset.active {
  background: color-mix(in srgb, var(--accent-2) 22%, transparent);
  color: var(--accent-2);
  border-color: var(--accent-2);
  font-weight: 600;
}

/* ── Employee multiselect (GHL-inspired) ───────────────────────────── */
/* Employee multiselect — always-visible inline panel (GHL-style). */
.emp-multi { display: block; width: 100%; }
.emp-multi-panel {
  background: var(--card-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: .55rem;
  display: flex; flex-direction: column; gap: .5rem;
}
.emp-multi-head {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
}
.emp-multi-summary {
  display: inline-flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  flex: 0 0 auto;
}
.emp-multi-search-wrap {
  position: relative;
  flex: 1 1 240px; min-width: 200px; order: 1;
}
.emp-multi-toggle {
  appearance: none; background: var(--card); border: 1px solid var(--border);
  border-radius: 10px; width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-3); cursor: pointer; flex: 0 0 auto; order: 2;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.emp-multi-toggle:hover { background: var(--bg-3); color: var(--text); border-color: var(--border-2); }
.emp-multi-toggle .lucide-ic {
  width: 1.05rem; height: 1.05rem;
  transition: transform .2s ease;
}
.emp-multi-panel.expanded .emp-multi-toggle {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
}
.emp-multi-panel.expanded .emp-multi-toggle .lucide-ic { transform: rotate(180deg); }
.emp-multi-search-icon {
  position: absolute; top: 50%; inset-inline-start: .7rem;
  transform: translateY(-50%);
  color: var(--text-3); pointer-events: none;
  display: inline-flex; align-items: center;
}
.emp-multi-search-icon .lucide-ic { width: 1rem; height: 1rem; }
.emp-multi-search {
  font-size: .9rem; border-radius: 10px; background: var(--card);
  padding-inline-start: 2.1rem;
}
.emp-multi-chip {
  display: inline-flex; align-items: center;
  background: var(--card); color: var(--text-2);
  border: 1px solid var(--border);
  border-radius: 999px; padding: .3rem .8rem;
  font-size: .82rem; font-weight: 600; line-height: 1.1;
  white-space: nowrap;
}
.emp-multi-chip.all {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
}
.emp-multi-chip.selected-count {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
}
.emp-multi-clear {
  appearance: none; background: transparent; border: 0; padding: .2rem .4rem;
  color: var(--text-3); font: inherit; font-size: .82rem;
  cursor: pointer; text-decoration: underline;
}
.emp-multi-clear:hover { color: var(--text); }

.emp-multi-list {
  display: flex; flex-direction: column;
  max-height: 260px; overflow-y: auto;
  padding: .15rem;
  border-top: 1px solid var(--border);
  scrollbar-width: thin; scrollbar-color: var(--border-2) transparent;
}
.emp-multi-panel:not(.expanded) .emp-multi-list { display: none; }
.emp-multi-empty { text-align: center; padding: 1.2rem .5rem; font-size: .85rem; }
.emp-multi-list::-webkit-scrollbar { width: 6px; }
.emp-multi-list::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 3px; }
.emp-multi-row {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .65rem; border-radius: 8px; cursor: pointer;
  transition: background .1s ease;
  margin: 1px 0;
}
.emp-multi-row:hover { background: var(--bg-3); }
.emp-multi-row input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; border-radius: 5px;
  border: 1.5px solid var(--border-2); background: var(--card);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0; transition: background .15s ease, border-color .15s ease;
  position: relative;
}
.emp-multi-row input[type="checkbox"]:checked {
  background: var(--accent); border-color: var(--accent);
}
.emp-multi-row input[type="checkbox"]:checked::after {
  content: ""; position: absolute;
  width: 5px; height: 9px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg); top: 1px; left: 5px;
}
.emp-multi-row .avatar { width: 30px; height: 30px; font-size: .76rem; flex-shrink: 0; }
.emp-multi-row .emp-multi-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: .88rem; font-weight: 500; color: var(--text);
}
.emp-multi-row.all-row {
  border-bottom: 1px solid var(--border);
  padding-bottom: .6rem; margin-bottom: .2rem;
  font-weight: 600;
}
.emp-multi-row.all-row .emp-multi-name { font-weight: 700; }

/* Login "Keep me signed in" checkbox */
.login-remember {
  display: flex; align-items: center; gap: .55rem;
  cursor: pointer; user-select: none;
  font-size: .88rem; color: var(--text-2);
  padding: .3rem 0;
}
.login-remember input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; border-radius: 5px;
  border: 1.5px solid var(--border-2); background: var(--card);
  cursor: pointer; flex-shrink: 0; position: relative;
  transition: background .15s ease, border-color .15s ease;
}
.login-remember input[type="checkbox"]:checked {
  background: var(--accent); border-color: var(--accent);
}
.login-remember input[type="checkbox"]:checked::after {
  content: ""; position: absolute;
  width: 5px; height: 9px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg); top: 1px; left: 5px;
}
.login-remember:hover { color: var(--text); }

/* ── Staff table (GHL-inspired) ─────────────────────────────────── */
.staff-bar {
  display: grid;
  grid-template-columns: minmax(180px, 240px) 1fr auto;
  gap: .8rem;
  align-items: center;
}
.staff-role { font-weight: 600; }
.staff-search {
  display: flex; align-items: center; gap: .5rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 10px; padding: 0 .8rem;
  transition: border-color .15s ease;
}
.staff-search:focus-within { border-color: var(--ring); box-shadow: 0 0 0 3px var(--ring-glow); }
.staff-search .lucide-ic { width: 1rem; height: 1rem; color: var(--text-3); flex-shrink: 0; }
.staff-search .input {
  background: transparent; border: 0; padding: .6rem 0;
  font-size: .92rem; flex: 1; outline: none; color: var(--text);
}
.staff-add { padding: .6rem 1.3rem; font-weight: 700; }

.staff-table thead th {
  padding: .9rem 1rem; font-size: .82rem; color: var(--text-3);
  text-transform: none; letter-spacing: 0;
  background: var(--card-2);
}
.staff-table tbody td { padding: .9rem 1rem; vertical-align: middle; }
.staff-table tbody tr + tr td { border-top: 1px solid var(--border); }
.staff-row-off { opacity: .55; }
.staff-name-cell { display: flex; align-items: center; gap: .7rem; min-width: 0; }
.staff-name { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px; }
.staff-muted { color: var(--text-2); font-size: .9rem; }

.staff-role-tag {
  display: inline-block; padding: .28rem .7rem;
  background: var(--card-2); color: var(--text-2);
  border: 1px solid var(--border); border-radius: 999px;
  font-size: .72rem; font-weight: 700; letter-spacing: .04em;
}
.staff-role-tag.admin {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 38%, var(--border));
}

.staff-actions { display: inline-flex; gap: .35rem; }
.staff-icon-btn {
  appearance: none; background: transparent; border: 0;
  width: 34px; height: 34px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-2); cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.staff-icon-btn:hover { background: var(--bg-3); color: var(--text); }
.staff-icon-btn.danger:hover { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.staff-icon-btn .lucide-ic { width: 1.05rem; height: 1.05rem; }

.staff-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: .7rem 1rem; border-top: 1px solid var(--border);
  background: var(--card-2);
  gap: .8rem; flex-wrap: wrap;
}
.staff-pager { display: inline-flex; gap: .35rem; }
.staff-pager .btn-sm { min-width: 36px; }

@media (max-width: 780px) {
  .staff-bar { grid-template-columns: 1fr; }
  .staff-table tbody td { padding: .75rem .6rem; }
  .staff-name { max-width: 140px; }
}

/* ── Edit employee modal extras ─────────────────────────────────── */
.edit-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: .8rem 1rem;
}
.edit-grid .label { margin-bottom: .25rem; }
.edit-grid > div { min-width: 0; }
@media (max-width: 680px) { .edit-grid { grid-template-columns: 1fr; } }

/* Bank / passport grouping inside the Payment tab */
.pay-bank-card {
  border: 1px solid var(--border);
  background: var(--card-2);
  border-radius: 14px;
  padding: .9rem 1rem 1.1rem;
}
.pay-bank-head {
  font-weight: 700; font-size: .95rem;
  color: var(--text); margin-bottom: .7rem;
  padding-bottom: .5rem; border-bottom: 1px dashed var(--border);
}

/* Permission groups as tabs inside the Permissions section */
.perm-group-tabs {
  display: flex; gap: .35rem; flex-wrap: wrap;
  padding: .3rem; margin-bottom: .7rem;
  background: var(--card-2); border: 1px solid var(--border); border-radius: 12px;
}
.perm-group-tab {
  appearance: none; background: transparent; border: 0;
  padding: .45rem .7rem; border-radius: 8px; cursor: pointer;
  display: inline-flex; align-items: center; gap: .4rem;
  font: inherit; font-size: .82rem; font-weight: 600; color: var(--text-2);
  transition: background .12s ease, color .12s ease;
}
.perm-group-tab:hover { background: var(--bg-3); color: var(--text); }
.perm-group-tab.active {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent);
}
.perm-group-tab .lucide-ic { width: .9rem; height: .9rem; }
.perm-group-tab .chip { background: var(--bg-2); color: var(--text-3); font-size: .7rem; padding: .1rem .4rem; }
.perm-group-tab.active .chip { background: var(--bg-2); color: var(--accent); }

/* ── Settings shell (sectioned sidebar, GHL-inspired) ─────────────── */
.settings-shell {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 1.2rem;
  align-items: start;
}
/* Sticky aside: stays pinned just below the topbar while the content
   column scrolls. `top` must clear the topbar (also sticky at top:0)
   otherwise the aside would slide *under* it. The +.5rem keeps a small
   visual breathing gap between topbar and aside. */
.settings-aside {
  position: sticky; top: calc(var(--topbar-h) + .5rem);
  background: var(--bg-2); border: 1px solid var(--border); border-radius: 16px;
  padding: .4rem;
  max-height: calc(100vh - var(--topbar-h) - 1.5rem);
  overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: var(--border-2) transparent;
}
.settings-aside-head {
  padding: .7rem .9rem .5rem;
  display: flex; flex-direction: column; align-items: flex-start; gap: .45rem;
}
.settings-aside-head h3 { font-size: 1.1rem; font-weight: 800; }
/* Back button mirrors the interaction pattern of .settings-nav-item below
   it — full-width pill, leading accent bar, blue-tint hover, forward slide.
   Negative inline margin pulls the pill out past the aside-head padding so
   it aligns with the nav-item pills beneath. */
.settings-back {
  appearance: none; background: transparent; border: 0;
  align-self: stretch;
  margin-inline: -.7rem;
  padding: .45rem .7rem; border-radius: 10px;
  display: flex; align-items: center; gap: .6rem;
  color: var(--text-3); cursor: pointer; font: inherit; font-size: .85rem;
  position: relative;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
/* Slide-back instead of forward — the direction is inverted vs. the nav
   items below, so the motion itself hints "go back" (LTR: left, RTL:
   right). Semantic motion = free UX hint. */
.settings-back:hover {
  color: var(--text);
  background: color-mix(in srgb, var(--accent-2) 6%, transparent);
  transform: translateX(-2px);
}
html[dir="rtl"] .settings-back:hover { transform: translateX(2px); }
.settings-back::before {
  content: ""; position: absolute; inset-inline-start: -.4rem; top: 25%; bottom: 25%;
  width: 3px; border-radius: 2px; background: var(--accent-2);
  opacity: 0; transition: opacity .15s ease;
  pointer-events: none;
}
.settings-back:hover::before { opacity: .6; }
.settings-back .sb-arrow {
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--bg-3); color: var(--text-2);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background .12s ease, color .12s ease;
}
.settings-back:hover .sb-arrow {
  background: color-mix(in srgb, var(--accent-2) 18%, var(--bg-3));
  color: var(--accent-2);
}
.settings-back .lucide-ic { width: 1rem; height: 1rem; }
html[dir="rtl"] .settings-back .lucide-ic { transform: scaleX(-1); }

/* When the settings page is active we want the settings sidebar to
   replace the main app sidebar entirely. The page-level `.settings-focus`
   body class toggles the main sidebar off + reclaims the space. */
body.settings-focus .shell { grid-template-columns: 1fr; }
body.settings-focus .shell .sidebar { display: none; }

/* Employee settings page uses wrappers keyed by [data-section] so the
   sidebar can switch one at a time instead of showing all four forms at
   once. Scoped with [data-section] so it doesn't collide with the admin
   settings page, which also uses a `.settings-section` class for its
   section headers. */
.settings-main > .settings-section[data-section] { display: none; }
.settings-main > .settings-section[data-section].active { display: block; }
.settings-nav { display: flex; flex-direction: column; gap: 1px; padding: .2rem; }
.settings-group-label {
  padding: .7rem .7rem .35rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .08em;
  color: var(--text-3); text-transform: uppercase;
}
.settings-nav-item {
  appearance: none; background: transparent; border: 0; border-radius: 10px;
  padding: .55rem .7rem; cursor: pointer; text-align: start;
  display: flex; align-items: center; gap: .6rem;
  color: var(--text-2); font: inherit; font-weight: 600; font-size: .9rem;
  transition: background .12s ease, color .12s ease, transform .12s ease;
  position: relative;
}
.settings-nav-item:hover {
  background: color-mix(in srgb, var(--accent-2) 6%, transparent);
  color: var(--text); transform: translateX(2px);
}
html[dir="rtl"] .settings-nav-item:hover { transform: translateX(-2px); }
.settings-nav-item.active {
  background: color-mix(in srgb, var(--accent-2) 14%, transparent);
  color: var(--accent-2);
}
/* Accent bar behaves like the main-nav one: transparent by default, fades
   in on hover, full opacity on active. */
.settings-nav-item::before {
  content: ""; position: absolute; inset-inline-start: -.4rem; top: 25%; bottom: 25%;
  width: 3px; border-radius: 2px; background: var(--accent-2);
  opacity: 0; transition: opacity .15s ease;
  pointer-events: none;
}
.settings-nav-item:hover::before { opacity: .6; }
.settings-nav-item.active::before { opacity: 1; }
.settings-nav-icon {
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--bg-3); color: var(--text-2);
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background .12s ease, color .12s ease;
}
.settings-nav-item.active .settings-nav-icon {
  background: color-mix(in srgb, var(--accent-2) 18%, var(--bg-2));
  color: var(--accent-2);
}
.settings-nav-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Settings content fills the column flush with the sidebar (GHL-style)
   instead of centering itself behind a 960px cap — small single-card
   sections were leaving large empty bands on wide screens. The aside
   (260px sticky) sits on the left, this column claims the rest.
   Applies to both the admin layout (.settings-content) and the employee
   layout (.settings-main). */
.settings-content,
.settings-main { min-width: 0; max-width: none; margin-inline: 0; width: 100%; }

.settings-section { animation: fade-in .2s ease; }
/* Drop per-card inline max-widths inside any settings section so each
   card stretches across the full content width — matches the GHL layout
   where every card claims its column instead of floating mid-gutter.
   Sections that want a multi-column tile wrap their cards in
   .settings-grid / .settings-cols (which have their own grid). */
.settings-section > .card { max-width: none !important; width: 100%; }

/* Payment section (employee /app/settings#payment): cards intentionally
   occupy the inline-start half of the content area, leaving the other
   half reserved for upcoming cards (international transfer presets,
   tax forms, etc.). Anchoring with margin-inline-end:auto keeps them
   flush against the settings aside in both RTL and LTR.
   Math: width = (100% - column gap) / 2  →  calc(50% - .6rem), where
   1.2rem is the planned gap between this column and the next. */
.settings-section[data-section="payment"] > .card,
.settings-section[data-section="payment"] > #pay-add-second-wrap {
  width: calc(50% - .6rem) !important;
  max-width: none !important;
  margin-inline-end: auto;
}
@media (max-width: 1024px) {
  /* Sub-1024px: a 50% column drops below ~400px, too cramped for a
     bank-form with side-by-side IBAN / SWIFT inputs. Restore full width. */
  .settings-section[data-section="payment"] > .card,
  .settings-section[data-section="payment"] > #pay-add-second-wrap {
    width: 100% !important;
  }
}

/* Two-column "masonry" layout for multi-card settings pages (Rewards,
   Schedule, etc.). Uses CSS multi-column instead of CSS grid so cards
   of differing heights pack vertically with no whitespace gaps — grid
   would force a uniform row height and leave a tail under shorter
   cards.
   Math: column-count fixes the layout at exactly 2 columns regardless
   of viewport (no auto-fit jumping to 3 cols on wide screens, which
   leaves the 4th card stranded in its own row). break-inside: avoid
   keeps each .card whole inside its column. The browser balances total
   column height automatically by reflowing cards between the two
   columns — matches GHL's settings-page rhythm. */
.settings-grid {
  column-count: 2;
  column-gap: 1.2rem;
}
.settings-grid > * {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  margin-bottom: 1.2rem;
  /* Force block context so margin-bottom + break-inside behave
     consistently across Chromium / WebKit / Firefox. */
  display: block;
}
.settings-grid .card { max-width: none !important; width: 100%; }
@media (max-width: 760px) {
  .settings-grid { column-count: 1; }
}

/* Explicit two-column layout: each column is its own vertical stack so
   cards inside align to the column's start (like GHL's split layouts).
   Use this when you want to *deliberately* group cards into left/right
   piles instead of letting auto-fit decide. */
.settings-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.2rem;
  align-items: start;
}
.settings-col {
  display: flex; flex-direction: column; gap: 1.2rem; min-width: 0;
}
.settings-cols .card { max-width: none !important; }
@media (max-width: 760px) {
  .settings-cols { grid-template-columns: 1fr; }
}
.settings-section-head { margin-bottom: 1rem; }
.settings-section-head h2 { margin: 0 0 .25rem; font-size: 1.35rem; font-weight: 800; }
.settings-section-head p { margin: 0; color: var(--text-3); font-size: .88rem; line-height: 1.5; }

@keyframes fade-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }

@media (max-width: 780px) {
  .settings-shell { grid-template-columns: 1fr; }
  .settings-aside { position: static; max-height: none; }
  .settings-nav { flex-direction: row; flex-wrap: wrap; gap: .3rem; }
  .settings-group-label { width: 100%; padding: .4rem .5rem .2rem; }
  .settings-nav-item { flex: 1 1 auto; }
  .settings-nav-item.active::before { display: none; }
}

/* ── Past-7-days strip (shift page) ── */
.p7-strip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: .45rem;
}
.p7-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: .45rem .25rem .4rem;
  background: var(--bg-3);
  border: 1px solid var(--border);
  border-radius: 10px;
  min-height: 96px;
}
.p7-dow { font-size: .7rem; color: var(--text-3); font-weight: 600; letter-spacing: .02em; }
.p7-day { font-size: .95rem; color: var(--text); font-weight: 800; margin-bottom: .25rem; }
.p7-bar {
  width: 8px;
  flex: 1;
  background: color-mix(in srgb, var(--border-2) 60%, transparent);
  border-radius: 4px;
  position: relative;
  overflow: hidden;
  margin: .15rem 0;
  min-height: 34px;
  display: flex;
  align-items: flex-end;
}
.p7-bar span {
  display: block;
  width: 100%;
  background: var(--success);
  border-radius: 4px 4px 2px 2px;
  transition: height .4s ease;
}
.p7-hrs { font-size: .68rem; color: var(--text-3); font-variant-numeric: tabular-nums; margin-top: .2rem; }
.p7-ok .p7-bar span { background: var(--success); }
.p7-miss .p7-bar span { background: var(--danger); }
.p7-off .p7-bar span { background: var(--text-3); opacity: .4; }
.p7-ok { border-color: color-mix(in srgb, var(--success) 35%, var(--border)); }
.p7-miss { border-color: color-mix(in srgb, var(--danger) 30%, var(--border)); }

/* ── Live earnings ticker (topbar chips, money + points) ─────────────── */
/* Sits between the page title and the action icons. Two pill-shaped
   chips share a host so they can be moved/resized as a unit; clicking
   either chip opens the breakdown popover. The cents column uses tabular
   numerals so the digits don't dance as they tick.

   Points are styled gold (banking-grade contrast on both themes) and the
   user can mask both chips behind dots via the eye button (.tk-eye) —
   preference is persisted per-device. */
:root {
  /* Bright gold on the dark navy canvas — high contrast, premium. */
  --tk-gold:        #fbbf24;
  --tk-gold-soft:   rgba(251, 191, 36, 0.16);
}
:root.light {
  /* Deeper amber on white — passes WCAG AA for the chip text size. */
  --tk-gold:        #b45309;
  --tk-gold-soft:   rgba(180, 83, 9, 0.10);
}
.tk-host { position: relative; display: inline-flex; align-items: center; gap: .35rem; }
.tk-chips {
  appearance: none; background: transparent; border: 0; padding: 0;
  display: inline-flex; gap: .35rem; cursor: pointer; font: inherit;
}
.tk-chip {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem .8rem; border-radius: 999px;
  background: var(--bg-2); border: 1px solid var(--border);
  font-size: .82rem; font-weight: 600; color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: background .15s ease, border-color .15s ease, transform .15s ease, color .25s ease;
}
.tk-chip .tk-ico { width: 14px; height: 14px; display: inline-flex; flex-shrink: 0; }
.tk-chip .tk-ico svg { width: 14px; height: 14px; }
/* Colour signals *value* not clock-state. A real balance keeps its brand
   colour even when frozen; only zero-balance chips drop to gray. */
.tk-chip.tk-money  { color: var(--success, #16a34a); border-color: color-mix(in srgb, var(--success, #16a34a) 25%, var(--border)); }
.tk-chip.tk-points { color: var(--tk-gold);           border-color: color-mix(in srgb, var(--tk-gold) 30%, var(--border)); background: color-mix(in srgb, var(--tk-gold-soft) 100%, var(--bg-2)); }
.tk-chip.tk-zero   { color: var(--text-3); border-color: var(--border); background: var(--bg-2); }
/* Per-chip hover — each pill reacts independently (so hovering points
   doesn't lift the money chip and vice-versa). Both still trigger the
   same popover on click because they share the parent .tk-chips button. */
.tk-chip:hover { background: var(--bg-3); transform: translateY(-1px); }
.tk-chip.tk-money:not(.tk-zero):hover  { border-color: color-mix(in srgb, var(--success, #16a34a) 55%, var(--border)); }
.tk-chip.tk-points:not(.tk-zero):hover { border-color: color-mix(in srgb, var(--tk-gold) 60%, var(--border)); background: color-mix(in srgb, var(--tk-gold-soft) 140%, var(--bg-3)); }
/* Off-clock: subtle opacity reduction only — the colour stays so a
   non-zero balance still reads as money/points, not as "inactive". */
.tk-host.tk-frozen .tk-chip { opacity: .75; }

/* Eye toggle — same chip-button aesthetic as the bell, slightly smaller.
   Hides/shows both money and points (banking convention: one switch
   controls the whole "balance" cluster). */
.tk-eye {
  appearance: none; cursor: pointer;
  width: 38px; height: 38px; padding: 0; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent;
  color: var(--text-2);
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease;
}
.tk-eye svg { width: 1.05rem; height: 1.05rem; }
/* No translate / scale on the eye — it's a privacy switch, not a CTA, so
   it should feel quiet. Hover lifts a soft brand-tinted pillow so it
   matches the bell/contact ghost buttons in the same row. */
.tk-eye:hover {
  background: color-mix(in srgb, var(--brand) 8%, transparent);
  color: var(--text);
  border-color: color-mix(in srgb, var(--brand) 25%, var(--border));
}
.tk-eye:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.tk-eye[aria-pressed="true"] {
  color: var(--tk-gold);
  border-color: color-mix(in srgb, var(--tk-gold) 45%, var(--border));
  background: color-mix(in srgb, var(--tk-gold-soft) 90%, var(--bg-2));
}

/* Masked state — show dots in place of digits without resizing the pill.
   Each number reserves a min-width so swapping "•••••" ↔ "$1,011.00"
   doesn't shift the chip's footprint (the eye click feels silent). */
.tk-money-num  { min-width: 5.2ch; text-align: center; display: inline-block; }
.tk-points-num { min-width: 3.8ch; text-align: center; display: inline-block; }

/* Breakdown popover — opens on click. Anchored under the chips so the
   layout stays predictable even at the topbar's narrowest. */
.tk-pop {
  position: absolute; top: calc(100% + .5rem); inset-inline-end: 0;
  width: 280px; padding: 1rem;
  background: var(--bg); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .12);
  z-index: 60;
  animation: tk-pop-in .18s ease-out;
}
@keyframes tk-pop-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
.tk-pop-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: .55rem 0; border-bottom: 1px solid var(--border);
}
.tk-pop-row:last-of-type { border-bottom: 0; }
.tk-pop-label { color: var(--text-3); font-size: .82rem; }
.tk-pop-val { font-weight: 700; font-size: 1rem; font-variant-numeric: tabular-nums; }
.tk-pop-val .tk-pop-sub { color: var(--text-3); font-weight: 500; font-size: .78rem; margin-inline-start: .35rem; }
.tk-pop-rate { padding: .55rem 0; color: var(--text-3); font-size: .75rem; border-top: 1px solid var(--border); margin-top: .25rem; }
.tk-pop-link {
  display: block; margin-top: .65rem; padding: .55rem .75rem;
  text-align: center; font-weight: 600; font-size: .85rem;
  background: var(--accent); color: var(--accent-fg);
  border-radius: 9px; text-decoration: none;
  transition: filter .15s ease;
}
.tk-pop-link:hover { filter: brightness(1.05); }

/* ── Spotlight celebration ──────────────────────────────────────────── */
/* Full-screen overlay with three layers (back to front):
     1. backdrop dim                                  → focus the eye
     2. radial spotlight beam pulsing from above      → premium, theatrical
     3. card with the bonus details + counter         → the message
   Confetti is generated dynamically in JS and animated by `sp-fall`. */
.sp-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(2, 6, 23, 0); /* fades in via class */
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; pointer-events: auto;
  transition: background .32s ease;
}
.sp-overlay.sp-show { background: rgba(2, 6, 23, .72); backdrop-filter: blur(6px); }
.sp-overlay.sp-hide { background: rgba(2, 6, 23, 0); }

/* Light-mode tweak: dim less aggressively so the page outlines stay
   visible behind the celebration. */
html.light .sp-overlay.sp-show { background: rgba(15, 23, 42, .58); }

.sp-beam {
  position: absolute; top: -10vh; left: 50%; transform: translateX(-50%);
  width: 120vw; height: 110vh;
  background: radial-gradient(closest-side, rgba(255, 220, 130, .22), rgba(255, 220, 130, .08) 35%, transparent 60%);
  pointer-events: none;
  animation: sp-beam-pulse 3.6s ease-in-out infinite;
  opacity: 0;
  transition: opacity .4s ease .1s;
}
.sp-overlay.sp-show .sp-beam { opacity: 1; }
@keyframes sp-beam-pulse {
  0%, 100% { transform: translateX(-50%) scale(1); }
  50%      { transform: translateX(-50%) scale(1.06); }
}

/* The card itself — rounded, glassy, with a subtle gold-tinged edge that
   says "this is special" without screaming. */
.sp-card {
  position: relative; z-index: 2;
  width: min(420px, 92vw); padding: 2.2rem 1.6rem 1.6rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow:
    0 30px 80px rgba(0, 0, 0, .5),
    0 0 0 1px rgba(251, 191, 36, .25),
    inset 0 1px 0 rgba(255, 255, 255, .06);
  text-align: center;
  transform: translateY(40px) scale(.92); opacity: 0;
  transition: transform .42s cubic-bezier(.22, 1.18, .36, 1), opacity .32s ease;
}
.sp-overlay.sp-show .sp-card { transform: translateY(0) scale(1); opacity: 1; }

.sp-eyebrow {
  font-size: .72rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase;
  color: #fbbf24; /* gold — universally reads as celebration */
}
.sp-from { margin-top: .4rem; font-size: .9rem; color: var(--text-2); }
.sp-from b { color: var(--text); font-weight: 700; }
.sp-occasion { margin-top: .15rem; font-size: .82rem; color: var(--text-3); }

.sp-amount {
  margin: 1.1rem 0 .25rem;
  display: flex; align-items: baseline; justify-content: center; gap: .45rem;
}
.sp-points-num {
  font-size: 4rem; font-weight: 800; line-height: 1;
  background: linear-gradient(135deg, #fbbf24, #f97316);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  font-variant-numeric: tabular-nums;
}
.sp-points-lbl { font-size: 1rem; font-weight: 600; color: var(--text-2); }
.sp-usd { font-size: .92rem; color: var(--text-3); font-weight: 500; font-variant-numeric: tabular-nums; }
.sp-message {
  margin: 1.1rem auto 0; max-width: 320px;
  font-size: .95rem; color: var(--text); font-style: italic;
  line-height: 1.5;
  padding: .7rem 1rem;
  background: var(--bg-2); border-radius: 12px;
}
.sp-cta {
  margin-top: 1.4rem;
  appearance: none; border: 0; cursor: pointer;
  padding: .7rem 1.6rem; border-radius: 999px;
  background: var(--accent); color: var(--accent-fg);
  font: inherit; font-weight: 700; font-size: .95rem;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--accent) 40%, transparent);
  transition: transform .15s ease, filter .15s ease;
}
.sp-cta:hover { transform: translateY(-1px); filter: brightness(1.05); }
.sp-cta:active { transform: translateY(0); }

.sp-close {
  position: absolute; top: 18px; inset-inline-end: 22px;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255, 255, 255, .08); color: rgba(255, 255, 255, .9);
  border: 0; cursor: pointer; font-size: 1.4rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s ease;
  z-index: 3;
}
.sp-close:hover { background: rgba(255, 255, 255, .16); }

/* Confetti — each piece falls with a slight rotation. We give them
   `--sp-rot` as a CSS variable from JS so the keyframe can read it. */
.sp-confetti {
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none; overflow: hidden;
}
.sp-piece {
  position: absolute; top: -20px;
  border-radius: 2px;
  animation: sp-fall linear forwards;
  opacity: 0;
}
@keyframes sp-fall {
  0%   { transform: translateY(-20px) rotate(0deg);    opacity: 0; }
  10%  { opacity: 1; }
  100% { transform: translateY(110vh) rotate(var(--sp-rot, 360deg)); opacity: 1; }
}

/* Mobile: keep the card readable, drop the spotlight beam to a subtler
   gradient so the smaller screen doesn't look washed out. */
@media (max-width: 480px) {
  .sp-card { padding: 1.7rem 1.2rem 1.3rem; border-radius: 18px; }
  .sp-points-num { font-size: 3rem; }
  .sp-beam { background: radial-gradient(closest-side, rgba(255, 220, 130, .18), transparent 55%); }
}

/* ──────────────────────────────────────────────────────────────────────
   Chat — Slack/Gather flat layout overrides.
   Replaces the Telegram-style bubble look with a clean, flat list
   (avatar column + content column, name + timestamp header, grouped
   consecutive messages). Sidebar uses `# channel` glyph for channels
   and small avatars for DMs. Composer becomes a soft outlined bar.
   ────────────────────────────────────────────────────────────────────── */

.chat-shell { grid-template-columns: var(--chat-sb-w, 260px) 1fr; }

/* Sidebar polish */
.chat-sidebar { background: var(--bg-2); }
.chat-sidebar-search { padding: .65rem .7rem .35rem; }
.chat-sidebar-search > input { background: var(--card); border-color: var(--border); }
.chat-sidebar-title {
  padding: .35rem .9rem;
  font-size: .72rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-3);
  font-weight: 700;
}
.chat-sidebar-title:hover { background: transparent; color: var(--text-2); }
.chat-sidebar-section { border-bottom: 0; }
.chat-sidebar-body { padding: 0 .35rem .4rem; }
.chat-list-inner { padding: 0; }

/* Title row: collapsible title + small "+" action (Slack convention).
   The "+" stays subtle until you hover the section, matching established
   chat-app patterns and avoiding visual noise on the empty state. */
.chat-sidebar-title-row {
  display: flex;
  align-items: center;
  gap: .15rem;
  padding-inline-end: .45rem;
}
.chat-sidebar-title-row .chat-sidebar-title { flex: 1; min-width: 0; }
.chat-sidebar-add {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  background: transparent;
  border: 0;
  color: var(--text-3);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: .7;
  transition: opacity .12s, background .12s, color .12s;
  flex-shrink: 0;
}
.chat-sidebar-section:hover .chat-sidebar-add,
.chat-sidebar-add:focus-visible { opacity: 1; }
.chat-sidebar-add:hover { background: var(--bg-3); color: var(--text); opacity: 1; }
.chat-sidebar-add .lucide-ic { width: 14px; height: 14px; }

/* Compact rounded chat rows (Slack-style) */
.chat-row,
.member-row {
  padding: .35rem .55rem;
  border-bottom: 0;
  border-radius: 8px;
  margin: 1px 0;
  gap: .55rem;
  align-items: center;
  color: var(--text-2);
}
.chat-row:hover,
.member-row:hover { background: var(--bg-3); color: var(--text); }
.chat-row.active {
  background: var(--accent-soft);
  color: var(--text);
}
html:not(.light) .chat-row.active { background: rgba(255,255,255,.10); }
.chat-row.active .chat-row-name { font-weight: 700; }
.chat-row-info { gap: 0; }
.chat-row-top { gap: .3rem; }
.chat-row-name { font-weight: 500; font-size: .92rem; }
.chat-row-preview { display: none; }   /* Slack-style: name only, no preview */

/* Channels: hash glyph instead of avatar */
.chat-row.is-channel { padding-inline-start: .35rem; }
.chat-row-hash {
  width: 22px;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  font-weight: 600;
  font-size: 1rem;
  color: var(--text-3);
  flex-shrink: 0;
}
.chat-row.is-channel.active .chat-row-hash { color: var(--text); }

/* DM rows: small avatars (22px) */
.chat-row.is-dm .avatar,
.member-row .avatar { width: 22px; height: 22px; font-size: .65rem; border-radius: 5px; }

/* Header polish */
.chat-header { background: transparent; border-bottom: 1px solid var(--border); }

/* Messages area: flat (no chat-bg image), flat layout */
.chat-messages, .msgs {
  background-image: none !important;
  background: var(--bg);
  padding: .25rem 0 .5rem;
  gap: 0;
}

/* Row layout: avatar column (40px) + content column */
.msg-row {
  display: grid !important;
  grid-template-columns: 44px 1fr;
  gap: 0;
  align-items: flex-start;
  padding: .35rem 1.1rem .25rem;
  position: relative;
  flex-direction: row !important;       /* override .msg-row.mine row-reverse */
}
.msg-row:hover { background: var(--bg-2); }
.msg-row.mine { /* no special alignment in flat mode */ }

.msg-avatar-col {
  display: flex;
  justify-content: center;
  padding-top: 2px;
}
.msg-avatar-col .avatar { width: 36px; height: 36px; font-size: .85rem; border-radius: 6px; }
.msg-avatar-btn,
.msg-avatar-static { display: inline-flex; }

.msg-content-col { min-width: 0; padding-inline-start: .15rem; }

.msg-head {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  margin: 0 0 .1rem;
  line-height: 1.2;
}
.msg-name {
  font-weight: 700;
  font-size: .95rem;
  color: var(--text);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}
.msg-name:hover { text-decoration: underline; }
.msg-time { font-size: .72rem; color: var(--text-3); font-weight: 500; }

/* Grouped: hide head, hide avatar (show timestamp on hover) */
.msg-row.grouped { padding-top: .05rem; padding-bottom: .05rem; }
.msg-row.grouped .msg-avatar-col { padding-top: 4px; }
.msg-grouped-time {
  font-size: .65rem;
  color: var(--text-3);
  opacity: 0;
  transition: opacity .12s;
  font-variant-numeric: tabular-nums;
  /* Stay inside the avatar column so dates never visually collide with
     the message text in the content column. */
  display: inline-block;
  max-width: 44px;
  text-align: center;
  overflow: hidden;
  white-space: nowrap;
  line-height: 1;
}
.msg-row.grouped:hover .msg-grouped-time { opacity: 1; }

/* Flatten the message bubble */
.msg, .msg.mine {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  max-width: 100% !important;
  color: var(--text);
  box-shadow: none;
}
.msg .msg-text {
  font-size: .95rem;
  line-height: 1.45;
  color: var(--text);
}
.msg.mine .msg-text { color: var(--text); }
.msg .sender-name { display: none; }   /* legacy header — replaced by .msg-head */

/* Inline meta (edited tag + read ticks) — flows on the same line as the
   last word of the message text (WhatsApp pattern), drops to next line if
   it doesn't fit. For voice/attachment-only messages, .msg-standalone-meta
   appears on its own thin row underneath. */
.msg-inline-meta {
  display: inline-flex;
  align-items: center;
  gap: .2rem;
  font-size: .7rem;
  color: var(--text-3);
  margin-inline-start: .4rem;
  vertical-align: baseline;
  white-space: nowrap;
}
.msg-inline-meta .ticks { display: inline-flex; }
.msg-inline-meta .ticks svg { width: 13px; height: 13px; color: var(--accent); stroke-width: 2.5; }
.msg-standalone-meta {
  font-size: .7rem;
  color: var(--text-3);
  margin-top: .25rem;
  display: flex;
  align-items: center;
  gap: .25rem;
}
.msg-standalone-meta .ticks svg { width: 13px; height: 13px; color: var(--accent); stroke-width: 2.5; }
/* Legacy .meta — keep harmless in case anything else references it */
.msg .meta { display: inline-flex; font-size: .7rem; color: var(--text-3); }

/* Reactions as soft outlined pills */
.msg .reactions { gap: .3rem; margin-top: .3rem; }
.msg .reaction-chip,
.msg.mine .reaction-chip {
  background: var(--bg-3);
  border: 1px solid var(--border);
  color: var(--text-2);
  border-radius: 12px;
  padding: .12rem .5rem;
  font-size: .78rem;
  display: inline-flex;
  align-items: center;
  gap: .25rem;
}
.msg .reaction-chip:hover { border-color: var(--border-2); }
.msg .reaction-chip.mine,
.msg.mine .reaction-chip.mine {
  background: var(--accent-soft);
  border-color: var(--accent-soft-border);
  color: var(--text);
}

/* Reply quote: flatter look */
.msg .reply-quote,
.msg.mine .reply-quote {
  background: var(--bg-2);
  border-inline-start: 3px solid var(--border-2);
  border-radius: 0 6px 6px 0;
  margin-bottom: .25rem;
}

/* Attachment background tweaks for flat look */
.msg .att-file,
.msg.mine .att-file {
  background: var(--bg-3);
  color: var(--text);
  border: 1px solid var(--border);
}
.msg .att-file:hover { background: var(--card-2); }

/* Voice message: lighter on flat bg */
.voice-msg .voice-play,
.msg:not(.mine) .voice-msg .voice-play,
.msg.mine .voice-msg .voice-play { background: var(--accent); color: var(--accent-fg); }
.voice-msg .voice-wave .vb,
.msg:not(.mine) .voice-msg .voice-wave .vb,
.msg.mine .voice-msg .voice-wave .vb { background: color-mix(in srgb, var(--text-3) 60%, transparent); }

/* Hover dots: position to top-right of content column */
.msg-dots {
  position: absolute;
  top: -14px;
  inset-inline-end: 12px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 26px;
  height: 26px;
  font-size: .9rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  z-index: 4;
  box-shadow: 0 2px 6px rgba(0,0,0,.08);
}
.msg-row:hover .msg-dots { opacity: 1; }
.msg-dots:hover { background: var(--bg-3); opacity: 1 !important; }

/* Composer — soft outlined bar */
.composer.tg-composer {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: none;
  margin: 0;
  padding: .25rem .45rem;
  gap: .25rem;
  transition: border-color .12s, box-shadow .12s;
}
.composer.tg-composer:focus-within {
  border-color: var(--ring);
  box-shadow: 0 0 0 3px var(--ring-glow);
}
.tg-composer textarea {
  font-size: .95rem;
  padding: .55rem .35rem;
  min-height: 36px;
}
.tg-composer textarea::placeholder { color: var(--text-3); }
.comp-btn { width: 32px; height: 32px; }
.comp-primary.is-send { background: var(--accent); color: var(--accent-fg); }
.comp-primary.is-busy { opacity: .55; cursor: progress; pointer-events: none; }
.comp-primary[disabled] { cursor: progress; }

/* Editing mode: accent border + soft tint so the user can't miss it */
.composer.tg-composer.is-editing {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, var(--card));
}
.composer.tg-composer.is-editing:focus-within {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

/* Recording: pulse the send button so the user knows the mic is hot.
   The pulse-rec keyframe was already defined earlier but never applied. */
.comp-primary.recording {
  background: #ef4444 !important;
  color: #fff !important;
  animation: pulse-rec 1.4s infinite;
}

/* Composer wrap groups the reply preview + composer with a single bottom
   margin so they slide together visually, and the reply preview tucks
   into the top edge of the composer instead of floating above it. */
.composer-wrap { margin: .35rem 1rem .85rem; }
.composer-wrap > #reply-preview:not(:empty) {
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: 12px 12px 0 0;
  background: var(--bg-2);
  margin-bottom: -1px;
}
.composer-wrap > #reply-preview:not(:empty) + .composer.tg-composer {
  border-radius: 0 0 12px 12px;
}

/* Empty state when no chat is selected */
.chat-empty-state {
  margin: auto;
  text-align: center;
  padding: 2rem 1rem;
  color: var(--text-3);
}
.chat-empty-state-title {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: .35rem;
}
.chat-empty-state-sub { font-size: .9rem; line-height: 1.5; }

/* Date separator — neutral line + chip */
.date-sep { margin: .9rem .25rem; position: relative; }
.date-sep::before {
  content: '';
  position: absolute;
  inset-inline: 1.1rem;
  top: 50%;
  height: 1px;
  background: var(--border);
}
.date-sep span {
  position: relative;
  background: var(--bg);
  color: var(--text-2);
  border: 1px solid var(--border);
  font-size: .72rem;
  font-weight: 600;
  padding: .15rem .65rem;
  border-radius: 999px;
  backdrop-filter: none;
}
html.light .date-sep span { background: var(--bg); color: var(--text-2); }

/* System message — match the new flat tone */
.msg-system span {
  background: transparent;
  border: 0;
  color: var(--text-3);
  font-size: .78rem;
}

/* Typing indicator — sits under the messages list */
.typing-indicator { padding: .25rem 1.1rem .5rem; color: var(--text-3); }

/* ─────────────────────────────────────────────────────────────────
   Help-tip — small ? icon + side drawer that pulls in a help article
   without leaving the current page. Flat style: no shadows, just a
   gentle border. Drawer slides in from the inset-end (right in LTR,
   left in RTL).
   ───────────────────────────────────────────────────────────────── */

.help-tip-icon {
  appearance: none; cursor: pointer;
  width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--bg-2); border: 1px solid var(--border);
  color: var(--text-3);
  font-size: .72rem; font-weight: 700; line-height: 1;
  padding: 0; margin-inline-start: .35rem;
  vertical-align: middle;
  transition: background .15s, color .15s, border-color .15s;
}
.help-tip-icon:hover {
  background: var(--accent-soft, color-mix(in srgb, var(--accent-2) 14%, transparent));
  color: var(--accent-2);
  border-color: var(--accent-2);
}

.help-drawer-backdrop {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, .35);
  z-index: 200;
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease;
}
.help-drawer-backdrop.open { opacity: 1; pointer-events: auto; }

.help-drawer {
  position: absolute; top: 0; bottom: 0;
  inset-inline-end: 0;
  width: min(480px, calc(100vw - 2.5rem));
  background: var(--bg);
  border-inline-start: 1px solid var(--border);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform .22s ease;
}
html[dir="rtl"] .help-drawer { transform: translateX(-100%); }
.help-drawer-backdrop.open .help-drawer { transform: translateX(0); }

.help-drawer-head {
  display: flex; align-items: center; gap: .55rem;
  padding: .85rem 1rem;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.help-drawer-title {
  margin: 0; flex: 1;
  font-size: 1rem; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.help-drawer-full {
  font-size: .8rem; font-weight: 600;
  color: var(--accent-2); text-decoration: none;
  padding: .3rem .55rem; border-radius: 6px;
}
.help-drawer-full:hover { background: var(--bg-2); }
.help-drawer-close {
  appearance: none; background: transparent; border: 0; cursor: pointer;
  width: 30px; height: 30px; border-radius: 8px;
  font-size: 1.4rem; line-height: 1; color: var(--text-2);
}
.help-drawer-close:hover { background: var(--bg-2); color: var(--text); }

.help-drawer-body {
  flex: 1; overflow-y: auto;
  padding: 1rem 1.2rem 2rem;
  font-size: .92rem; line-height: 1.65;
}
.help-drawer-article h1 { font-size: 1.4rem; margin: 0 0 .4rem; }
.help-drawer-article h2 {
  font-size: 1.1rem; margin: 1.6rem 0 .55rem;
  padding-top: .55rem; border-top: 1px solid var(--border);
}
.help-drawer-article h3 { font-size: 1rem; margin: 1.2rem 0 .4rem; }
.help-drawer-article p, .help-drawer-article li { color: var(--text); }
.help-drawer-article a { color: var(--accent-2); text-decoration: none; }
.help-drawer-article a:hover { text-decoration: underline; }
.help-drawer-article code {
  background: var(--bg-2); color: var(--accent-2);
  padding: .08rem .4rem; border-radius: 4px;
  font-size: .86em;
}
.help-drawer-article pre {
  background: var(--bg-2); color: var(--text);
  padding: .8rem; border-radius: 8px;
  overflow-x: auto; font-size: .82rem; line-height: 1.55;
}
.help-drawer-article pre code { background: transparent; padding: 0; color: inherit; }
.help-drawer-article blockquote {
  background: var(--bg-2);
  border-inline-start: 3px solid var(--accent-2);
  padding: .65rem .9rem; border-radius: 6px;
  margin: .8rem 0;
}
.help-drawer-article blockquote p { margin: 0; }
.help-drawer-article table { width: 100%; border-collapse: collapse; font-size: .88rem; margin: .6rem 0 1rem; }
.help-drawer-article th, .help-drawer-article td {
  text-align: start; padding: .45rem .65rem;
  border-bottom: 1px solid var(--border); vertical-align: top;
}
.help-drawer-article th { background: var(--bg-2); font-weight: 700; }
.help-drawer-article ol, .help-drawer-article ul { padding-inline-start: 1.3rem; }
.help-drawer-article img { max-width: 100%; border-radius: 6px; margin: .5rem 0; }

/* ──────────────────────────────────────────────────────────────────────
   Chat — back-arrow + focus mode + mobile full-screen.
   Hybrid layout: side-by-side on desktop with an opt-in "focus mode"
   that hides the chat sidebar; full-screen swap between conversation
   list and conversation body on phones.
   ────────────────────────────────────────────────────────────────────── */

.chat-back-btn {
  background: transparent; border: 0; cursor: pointer;
  width: 36px; height: 36px; border-radius: 50%;
  color: var(--text); padding: 0;
  display: none; align-items: center; justify-content: center;
  flex-shrink: 0; margin-inline-end: .25rem;
  transition: background .15s ease;
}
.chat-back-btn:hover { background: var(--bg-3); }
.chat-back-btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.chat-back-btn .lucide-ic { width: 22px; height: 22px; }
/* The lucide arrow points left (LTR-natural). Flip in RTL so "back" reads
   as a right-pointing arrow, matching native iOS/Android Arabic UIs. */
html[dir="rtl"] .chat-back-btn .lucide-ic { transform: scaleX(-1); }

.chat-focus-btn.is-active { color: var(--accent); }

/* Desktop focus mode: collapse the chat sidebar so the conversation
   takes the full pane. Back arrow appears so the user can rejoin the
   list. We collapse the grid to a single 1fr track because hiding the
   sidebar with `display:none` removes it from the grid — leaving the
   body to auto-place into column 1 of the original two-column track. */
.chat-shell { transition: grid-template-columns .22s ease; }
.chat-shell.focus-mode { grid-template-columns: 1fr; }
.chat-shell.focus-mode .chat-sidebar { display: none; }
.chat-shell.focus-mode .chat-back-btn { display: inline-flex; }

/* Mobile (≤768px): WhatsApp-style swap. The chat list and the chat body
   live in the same single column; only one is visible at a time, gated
   on the `body.chat-open` flag set by Chat.open() / cleared by closeChat().
   Slide animation gives the screen change a native-feel transition. */
@media (max-width: 768px) {
  .chat-shell { grid-template-columns: 1fr !important; }
  .chat-shell .chat-sidebar { display: flex; width: 100%; border-inline-end: 0; }
  .chat-shell .chat-sidebar-resize { display: none; }
  .chat-shell .chat-body { display: none; }
  body.chat-open .chat-shell .chat-sidebar { display: none; }
  body.chat-open .chat-shell .chat-body { display: flex; animation: chat-slide-in .22s ease; }
  body.chat-open .chat-back-btn { display: inline-flex; }
  /* Focus toggle is meaningless on phones — the layout is already
     full-screen for the active conversation. */
  .chat-focus-btn { display: none; }
  /* Tighten header so the back arrow + name + actions fit on narrow widths. */
  .chat-header { padding: .55rem .6rem; }
  .chat-header-info { gap: .5rem; }
  /* Sidebar search input is redundant on mobile — the topbar ⌘K and the
     bottom-nav already provide global navigation. Removing it reclaims a
     vertical strip that otherwise sits below the topbar in the empty
     state and makes the list feel cramped. */
  .chat-sidebar-search { display: none; }
  /* When a chat is open on mobile, the chat-header already owns its own
     bottom border. Drop the topbar's border-bottom so the two don't
     stack into a thin double-line strip below the icons. */
  body.chat-open .topbar { border-bottom: 0; }
  /* Declutter the chat header — search-messages and call icons are
     surfaced inside the info panel (header tap) instead, so the header
     only shows the back arrow + avatar + name on phones. */
  #chat-search-btn,
  #chat-call-btn { display: none; }
  /* Inside an open conversation: hide the floating bottom-nav so it
     doesn't overlap the composer / emoji button. The chat header's
     back-arrow gives the user their way out, and the composer reclaims
     the full bottom of the screen with safe-area-inset padding so it
     never sits under the Android gesture bar. */
  body.chat-open .bottom-nav { display: none !important; }
  body.chat-open .composer-wrap {
    margin-bottom: max(.85rem, calc(env(safe-area-inset-bottom) + .35rem));
  }
  /* Chat-list view (no conversation open) — last few rows would tuck
     under the floating bottom-nav without breathing room. Pad the
     scrollable list so the final chat is fully reachable. */
  body:not(.chat-open) .chat-list-inner {
    padding-bottom: calc(110px + env(safe-area-inset-bottom));
  }
}

/* ──────────────────────────────────────────────────────────────────────
   Topbar — mobile-specific tweaks.
   Goals:
     • Keep all action icons in a single row (the topbar is flex with no
       wrap, so each item must be small enough to fit on a 360-375px
       viewport).
     • Drop affordances that don't make sense on a phone — focus mode is
       a desktop-only "shrink the chrome" feature; on mobile the layout
       is already full-screen.
     • Surface a dark/light theme toggle here, since the canonical theme
       pill in the sidebar is hidden on phones.
   ────────────────────────────────────────────────────────────────────── */
.topbar-theme { display: none; }

/* ── Topbar user menu (mobile-only) ────────────────────────────────────
   Mirrors the sidebar user card. Visible at ≤720px so phone users can
   still reach Profile / Settings / Sign-out, since the sidebar that
   normally hosts those actions is hidden on phones. */
.topbar-user-slot { display: none; }
.topbar-user-btn { padding: 0; overflow: hidden; }
.topbar-user-btn .avatar { width: 30px; height: 30px; font-size: .72rem; }
.topbar-user-menu {
  display: none;
  position: absolute;
  top: calc(100% + 8px); inset-inline-end: 0;
  min-width: 220px;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 28px rgba(0,0,0,.35);
  padding: .35rem;
  z-index: 60;
}
.topbar-user-menu.open { display: flex; }
.topbar-user-menu > a, .topbar-user-menu > button {
  display: flex; align-items: center; gap: .55rem;
  padding: .55rem .6rem;
  border: 0; background: transparent;
  color: var(--text); text-align: start;
  border-radius: 8px;
  font: inherit; cursor: pointer;
  text-decoration: none;
}
.topbar-user-menu > a:hover, .topbar-user-menu > button:hover { background: var(--bg-3); }
.topbar-user-menu > a .lucide-ic,
.topbar-user-menu > button .lucide-ic { width: 16px; height: 16px; color: var(--text-2); }
.topbar-user-sep { height: 1px; background: var(--border); margin: .25rem .15rem; }
.topbar-user-danger { color: var(--danger); }
.topbar-user-danger:hover { background: color-mix(in srgb, var(--danger) 10%, transparent) !important; }

@media (max-width: 720px) {
  /* ── Premium-mobile topbar (Phase A) ──────────────────────────────────
     Inspired by Linear / Things 3 / Slack mobile — the topbar holds at
     most 2-3 items: a clean left edge, the unread bell, and the avatar
     menu. Everything else (theme, contact, urgent, ticker chips, brand
     mark, ⌘K, focus) collapses behind either the avatar menu or in-page
     surfaces. The page title isn't crammed in the topbar either — it
     renders as a large iOS-style heading below (Phase C). */
  #topbar-focus,
  #topbar-cmdk,
  #topbar-contact,
  #topbar-urgent,
  .topbar-theme,
  .topbar-brand,
  #ticker-mount { display: none !important; }
  /* Avatar menu surfaces Profile / Settings / Theme / Sign-out on phones,
     where the sidebar that normally hosts those actions is hidden. */
  .topbar-user-slot { display: inline-flex; }
  .topbar {
    gap: .35rem;
    padding-inline-start: calc(.6rem + env(safe-area-inset-left));
    padding-inline-end: calc(.6rem + env(safe-area-inset-right));
    flex-wrap: nowrap; min-width: 0;
  }
  .topbar-actions { gap: .35rem; flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
  .topbar-left { flex: 0 0 auto; }
  /* Smaller hit-area on phones — still ≥ 32px Apple HIG minimum. */
  .topbar-bell { width: 36px; height: 36px; }
}
html[dir="rtl"] body.chat-open .chat-shell .chat-body { animation-name: chat-slide-in-rtl; }
@keyframes chat-slide-in {
  from { transform: translateX(8%); opacity: .6; }
  to   { transform: translateX(0);   opacity: 1; }
}
@keyframes chat-slide-in-rtl {
  from { transform: translateX(-8%); opacity: .6; }
  to   { transform: translateX(0);   opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .chat-shell { transition: none; }
  body.chat-open .chat-shell .chat-body { animation: none; }
}

/* ──────────────────────────────────────────────────────────────────────
   Polls — chat استطلاع. The poll lives inside a message bubble; the
   default .msg padding already gives us the outer chrome. The bubble
   below replaces .msg-text with a Slack/Telegram-style stack: question
   header + clickable option rows with fill bars + tally meta + close
   button. Voted options get a brand-tinted fill + check mark; closed
   polls greyscale and become non-interactive.
   ────────────────────────────────────────────────────────────────────── */
.poll-bubble {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  min-width: min(280px, 65vw);
  max-width: 420px;
}
.poll-q {
  display: flex; align-items: flex-start; gap: .5rem;
  font-weight: 700;
  font-size: .98rem;
  color: var(--text);
  line-height: 1.45;
}
.poll-q .lucide-ic {
  width: 18px; height: 18px;
  color: var(--brand);
  margin-top: .15rem;
  flex-shrink: 0;
}
.poll-q-text { flex: 1; word-break: break-word; }

.poll-options-list { display: flex; flex-direction: column; gap: .35rem; }
.poll-opt {
  position: relative;
  display: block;
  width: 100%;
  text-align: start;
  padding: .55rem .75rem;
  background: var(--card-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  cursor: pointer;
  overflow: hidden;
  transition: border-color .15s, background .15s;
}
.poll-opt:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--brand) 35%, var(--border));
}
.poll-opt:disabled { cursor: default; opacity: .85; }
.poll-opt-fill {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  width: 0%;
  transition: width .35s cubic-bezier(.2, .9, .2, 1);
  pointer-events: none;
  z-index: 0;
}
.poll-opt.is-picked {
  border-color: color-mix(in srgb, var(--brand) 60%, var(--border));
  background: color-mix(in srgb, var(--brand) 6%, var(--card-2));
}
.poll-opt.is-picked .poll-opt-fill {
  background: color-mix(in srgb, var(--brand) 18%, transparent);
}
.poll-opt-row {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: .55rem;
  font-size: .92rem;
}
.poll-opt-mark {
  width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--text-3) 50%, transparent);
  font-size: .75rem; font-weight: 800;
  color: var(--brand);
  background: var(--card);
}
.poll-opt.is-picked .poll-opt-mark {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--accent-fg);
}
.poll-opt-text { flex: 1; min-width: 0; word-break: break-word; }
.poll-opt-pct {
  flex-shrink: 0;
  font-size: .82rem;
  font-weight: 700;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.poll-opt.is-picked .poll-opt-pct { color: var(--brand); }
.poll-opt-voters {
  position: relative; z-index: 1;
  display: block;
  font-size: .72rem;
  color: var(--text-3);
  margin-top: .25rem;
  margin-inline-start: 26px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.poll-meta {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem;
  font-size: .78rem;
  color: var(--text-3);
  margin-top: .15rem;
}
.poll-tally { font-weight: 600; }
.poll-close-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: .25rem .65rem;
  font-size: .75rem;
  font-weight: 700;
  color: var(--text-2);
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.poll-close-btn:hover {
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border-color: var(--danger);
  color: var(--danger);
}

.poll-bubble.is-closed .poll-q-text::after {
  content: ' · ' attr(data-closed-suffix);
  color: var(--text-3);
}

/* Create-poll modal */
.poll-create .poll-options { display: flex; flex-direction: column; gap: .4rem; max-height: 36vh; overflow-y: auto; }
.poll-create .poll-opt-row { display: flex; gap: .4rem; align-items: center; }
.poll-create .poll-opt-row .input { flex: 1 1 auto; min-width: 0; }
.poll-create .poll-opt-del {
  width: 36px; height: 36px;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
}
.poll-create .poll-opt-del .lucide-ic { width: 16px; height: 16px; }
.poll-create .poll-add-opt { align-self: flex-start; }
.poll-create .poll-toggle {
  display: flex; align-items: center; gap: .55rem;
  cursor: pointer;
  font-size: .9rem;
  color: var(--text-2);
}
.poll-create .poll-toggle input[type="checkbox"] {
  width: 18px; height: 18px;
  accent-color: var(--brand);
  cursor: pointer;
}

/* ──────────────────────────────────────────────────────────────────────
   Scheduled messages + reminders — modals + popovers + list rows.
   Schedule modal builds on .ctt-modal grid; the "presets" row is a
   3-button quick selector (1h / 3h / tomorrow morning) above the
   manual date+time inputs. Remind-me popover is anchored at the
   click point; same preset list + a "custom" path that opens the
   datetime modal.
   ────────────────────────────────────────────────────────────────────── */
.sched-presets {
  display: flex; gap: .4rem; flex-wrap: wrap;
}
.sched-presets > button {
  flex: 1 1 auto;
  padding: .55rem .8rem;
  background: var(--card-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  font: inherit;
  font-size: .82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.sched-presets > button:hover {
  background: color-mix(in srgb, var(--brand) 12%, var(--card-2));
  border-color: color-mix(in srgb, var(--brand) 35%, var(--border));
}
.sched-quote { background: var(--card-2); border-inline-start-color: color-mix(in srgb, var(--brand) 60%, transparent); }

.remind-pop {
  position: fixed;
  z-index: 70;
  min-width: 200px;
  max-width: 240px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, .35);
  padding: .35rem;
  display: flex;
  flex-direction: column;
  gap: 1px;
  animation: qr-pop-in .18s ease both;
}
html.light .remind-pop { box-shadow: 0 12px 28px rgba(15, 31, 26, .14); }
.remind-pop-title {
  padding: .35rem .55rem .15rem;
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-3);
}
.remind-pop > button {
  display: flex; align-items: center;
  width: 100%;
  padding: .55rem .65rem;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  cursor: pointer;
  text-align: start;
}
.remind-pop > button:hover {
  background: color-mix(in srgb, var(--brand) 10%, var(--card-2));
}

/* Scheduled-list rows reuse .bm-row from bookmarks but add a tiny
   clock-style chip on the time so it reads as "future" not "past". */
.sched-row .bm-row-chat::before {
  content: '';
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--brand);
  margin-inline-end: .35rem;
  vertical-align: middle;
  animation: shift-strip-pulse 1.7s infinite ease-in-out;
}

/* Send button long-press hint — small clock badge that nudges users
   to discover the schedule action. Only shown when textarea has text. */
.comp-primary.is-send::after {
  content: '';
  position: absolute;
  inset-inline-end: -2px; bottom: -2px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--brand);
  border: 2px solid var(--card-2);
  opacity: 0;
  transition: opacity .2s;
}
.comp-primary.is-send { position: relative; }

/* Sidebar "scheduled" trigger — sits next to the bookmark trigger.
   Slightly offset inward so both remain visible without overlap. */
.chat-sidebar-sched-btn {
  inset-inline-end: 3.05rem !important;
}

/* ──────────────────────────────────────────────────────────────────────
   Slash commands — popover that opens above the composer when the user
   types "/" at the start of the textarea. Mirrors the @mention picker
   layout (icon + label + description) but each row is an action, not
   a value to insert. Picking a row consumes the textarea.
   ────────────────────────────────────────────────────────────────────── */
.slash-pop {
  position: absolute;
  bottom: calc(100% + 4px);
  inset-inline-start: 1rem;
  inset-inline-end: 1rem;
  max-width: 360px;
  max-height: 280px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .35);
  padding: .25rem;
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
html.light .slash-pop { box-shadow: 0 10px 28px rgba(15, 31, 26, .14); }
.slash-pop-row {
  display: flex; align-items: center; gap: .65rem;
  padding: .55rem .65rem;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  cursor: pointer;
  text-align: start;
}
.slash-pop-row:hover,
.slash-pop-row.active {
  background: color-mix(in srgb, var(--brand) 12%, var(--card-2));
}
.slash-pop-icon {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  color: var(--brand);
  flex-shrink: 0;
}
.slash-pop-icon .lucide-ic { width: 16px; height: 16px; }
.slash-pop-text {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-width: 0;
}
.slash-pop-cmd {
  font-weight: 700;
  font-size: .92rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--brand);
}
.slash-pop-desc {
  font-size: .78rem;
  color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ──────────────────────────────────────────────────────────────────────
   Quick replies — popover triggered by the lightning button in the
   composer. Hidden by default; opens above the button on tap, closes
   on click outside or after sending. The list is editable by the user
   via a small pencil button in the popover header.
   ────────────────────────────────────────────────────────────────────── */
.qr-pop {
  position: fixed;
  z-index: 70;
  min-width: 240px;
  max-width: min(320px, calc(100vw - 16px));
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, .35);
  padding: .35rem .35rem .55rem;
  display: flex;
  flex-direction: column;
  gap: .35rem;
  animation: qr-pop-in .18s ease both;
}
html.light .qr-pop { box-shadow: 0 12px 28px rgba(15, 31, 26, .14); }
@keyframes qr-pop-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.qr-pop-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: .35rem .55rem .15rem;
}
.qr-pop-title {
  font-size: .78rem; font-weight: 700;
  color: var(--text-3); text-transform: uppercase;
  letter-spacing: .04em;
}
.qr-pop-edit {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; color: var(--text-3);
  border-radius: 6px; cursor: pointer;
}
.qr-pop-edit:hover { color: var(--brand); background: var(--bg-3); }
.qr-pop-edit .lucide-ic { width: 14px; height: 14px; }
.qr-pop-list {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 280px;
  overflow-y: auto;
}
.qr-pop .quick-reply {
  display: block;
  width: 100%;
  text-align: start;
  padding: .55rem .7rem;
  border: 0;
  background: transparent;
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  font-size: .92rem;
  cursor: pointer;
  transition: background .12s ease;
}
.qr-pop .quick-reply:hover {
  background: color-mix(in srgb, var(--brand) 10%, var(--card-2));
}
.qr-pop-empty {
  padding: .85rem .7rem;
  text-align: center;
  font-size: .85rem;
  color: var(--text-3);
}

/* Editor modal — list of input rows + add/reset/save controls. */
.qr-edit { display: flex; flex-direction: column; gap: .8rem; }
.qr-edit-list { display: flex; flex-direction: column; gap: .4rem; max-height: 50vh; overflow-y: auto; }
.qr-edit-row { display: flex; gap: .4rem; align-items: center; }
.qr-edit-row .input { flex: 1 1 auto; min-width: 0; }
.qr-edit-del {
  width: 36px; height: 36px;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
}
.qr-edit-del .lucide-ic { width: 16px; height: 16px; }
.qr-edit-add { align-self: flex-start; }

/* Sidebar "saved messages" trigger inside the chat search row. */
.chat-sidebar-saved-btn {
  position: absolute;
  inset-inline-end: 1.2rem;
  top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  color: var(--text-3);
  cursor: pointer;
  border-radius: 6px;
}
.chat-sidebar-saved-btn:hover { color: var(--brand); background: var(--bg-3); }
.chat-sidebar-saved-btn .lucide-ic { width: 16px; height: 16px; }

/* Saved-messages side panel — list of bookmarked messages with chat
   context, time, and a single-tap unsave control. */
.bm-head { padding: 0 .25rem .85rem; border-bottom: 1px solid var(--border); margin-bottom: .55rem; }
.bm-head h3 { display: flex; align-items: center; margin: 0 0 .25rem; font-size: 1.1rem; font-weight: 800; }
.bm-sub { margin: 0; font-size: .85rem; color: var(--text-3); }
.bm-list { display: flex; flex-direction: column; gap: .35rem; }
.bm-row {
  position: relative;
  display: block;
  width: 100%;
  text-align: start;
  padding: .65rem .8rem;
  background: var(--card-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  font: inherit;
  cursor: pointer;
  color: var(--text);
}
.bm-row:hover { background: var(--card); border-color: color-mix(in srgb, var(--brand) 25%, var(--border)); }
.bm-row-top { display: flex; justify-content: space-between; gap: .5rem; margin-bottom: .25rem; font-size: .75rem; }
.bm-row-chat { font-weight: 700; color: var(--brand); }
.bm-row-time { color: var(--text-3); }
.bm-row-text { color: var(--text-2); font-size: .92rem; line-height: 1.5; word-break: break-word; }
.bm-row-actions { position: absolute; top: 8px; inset-inline-end: 8px; }
.bm-unsave {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; cursor: pointer; border-radius: 6px;
  color: var(--text-3);
}
.bm-unsave:hover { color: var(--danger); background: var(--bg-3); }
.bm-empty { padding: 2rem 1rem; text-align: center; color: var(--text-3); font-size: .9rem; }

/* Tip modal — quick admin → employee bonus, amount chips + manual
   input + reason. Reuses .ctt-actions / .ctt-label from the
   convert-to-task modal so spacing stays consistent. */
.tip-modal { display: flex; flex-direction: column; gap: .8rem; }
.tip-head h3 { display: flex; align-items: center; margin: 0 0 .25rem; font-size: 1.1rem; font-weight: 800; }
.tip-sub { margin: 0; color: var(--text-3); font-size: .85rem; }
.tip-quote {
  padding: .55rem .8rem;
  background: var(--bg-3);
  border-inline-start: 3px solid var(--brand);
  border-radius: 0 8px 8px 0;
  color: var(--text-2);
  font-size: .88rem;
  line-height: 1.5;
}
html[dir="rtl"] .tip-quote { border-radius: 8px 0 0 8px; }
.tip-amounts { display: flex; gap: .35rem; flex-wrap: wrap; }
.tip-amount {
  padding: .4rem .85rem;
  border-radius: 999px;
  background: var(--card-2);
  border: 1px solid var(--border);
  color: var(--text);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.tip-amount:hover { background: color-mix(in srgb, var(--brand) 12%, var(--card-2)); }
.tip-amount.active {
  background: var(--brand);
  color: var(--accent-fg);
  border-color: var(--brand);
}
.tip-field { display: flex; flex-direction: column; gap: .35rem; }

/* ──────────────────────────────────────────────────────────────────────
   Convert-to-task modal — opens from the chat message context menu and
   creates a task pre-filled with the message text. Tight stack of form
   fields with a quoted source preview at the top so the user always
   knows which message they're converting. Two-column row on desktop
   collapses to single column on phones.
   ────────────────────────────────────────────────────────────────────── */
.ctt-modal { display: flex; flex-direction: column; gap: .8rem; }
.ctt-head h3 { margin: 0 0 .25rem; font-size: 1.1rem; font-weight: 800; }
.ctt-sub { margin: 0; color: var(--text-3); font-size: .85rem; }
.ctt-quote {
  display: flex; flex-direction: column; gap: .2rem;
  padding: .65rem .85rem;
  background: var(--bg-3);
  border-inline-start: 3px solid var(--brand);
  border-radius: 0 8px 8px 0;
  font-size: .88rem;
}
html[dir="rtl"] .ctt-quote { border-radius: 8px 0 0 8px; }
.ctt-quote-author { font-weight: 700; color: var(--brand); font-size: .8rem; }
.ctt-quote-text { color: var(--text-2); line-height: 1.5; word-break: break-word; }
.ctt-field { display: flex; flex-direction: column; gap: .35rem; }
.ctt-label { font-size: .82rem; font-weight: 600; color: var(--text-2); }
.ctt-optional { font-weight: 500; color: var(--text-3); font-size: .78rem; }
.ctt-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .75rem;
}
.ctt-actions { display: flex; gap: .5rem; justify-content: flex-end; margin-top: .35rem; }
.ctt-actions .btn { min-width: 88px; }
@media (max-width: 720px) {
  .ctt-row { grid-template-columns: 1fr; }
  .ctt-actions { flex-direction: column-reverse; }
  .ctt-actions .btn { width: 100%; }
}

/* ──────────────────────────────────────────────────────────────────────
   Chat @mentions — popover that opens above the composer when the user
   types `@`, plus the inline pill that highlights resolved mentions in
   message bubbles. Works in both LTR and RTL. The picker anchors to
   #composer-wrap (position: relative) so it floats just above the input.
   ────────────────────────────────────────────────────────────────────── */
.mention-pick {
  position: absolute;
  bottom: calc(100% + 4px);
  inset-inline-start: 1rem;
  inset-inline-end: 1rem;
  max-width: 320px;
  max-height: 240px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .35);
  padding: .25rem;
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
html.light .mention-pick { box-shadow: 0 10px 28px rgba(15, 31, 26, .14); }
.mention-pick-row {
  display: flex; align-items: center; gap: .55rem;
  padding: .45rem .55rem;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  cursor: pointer;
  text-align: start;
}
.mention-pick-row:hover,
.mention-pick-row.active {
  background: color-mix(in srgb, var(--brand) 12%, var(--card-2));
}
.mention-pick-row .avatar { width: 28px; height: 28px; font-size: .72rem; flex-shrink: 0; }
.mention-pick-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 600; font-size: .9rem;
}
/* Position relative on composer-wrap so the picker anchors to it. */
#composer-wrap { position: relative; }

/* Mention pill — inline highlight inside message bubbles. Soft brand
   background + brand text for normal mentions; brighter when YOU are
   the one being mentioned (so a quick scroll spots a mention quickly). */
.msg-text .mention {
  display: inline-block;
  padding: .05rem .35rem;
  margin: 0 .05rem;
  border-radius: 6px;
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  color: var(--brand);
  font-weight: 600;
  font-size: .92em;
  line-height: 1.2;
  vertical-align: baseline;
  white-space: nowrap;
}
.msg-text .mention.is-me {
  background: color-mix(in srgb, var(--brand) 28%, transparent);
  color: var(--accent-fg);
  background: var(--brand);
}

/* ──────────────────────────────────────────────────────────────────────
   Rewards hero card — balance + USD equivalent + redeem CTA. Desktop
   shows it in a single row; mobile stacks vertically with a full-width
   CTA so the button never wraps on top of the points number.
   ────────────────────────────────────────────────────────────────────── */
.rew-hero {
  padding: 1.4rem;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent-2) 12%, var(--bg)),
    var(--bg));
  border: 1px solid color-mix(in srgb, var(--accent-2) 22%, var(--border));
  display: flex;
  align-items: center;
  gap: 1rem;
}
.rew-hero-top {
  display: flex;
  align-items: center;
  gap: .85rem;
  flex: 1 1 auto;
  min-width: 0;
}
.rew-hero-icon {
  width: 48px; height: 48px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent-2) 18%, transparent);
  color: var(--accent-2);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.rew-hero-balance { flex: 1 1 auto; min-width: 0; }
.rew-hero-label {
  font-size: .72rem;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 600;
}
.rew-hero-numbers {
  display: flex; align-items: baseline;
  gap: .5rem;
  font-variant-numeric: tabular-nums;
  flex-wrap: wrap;
}
.rew-hero-points {
  font-size: 2.2rem; font-weight: 800;
  color: var(--accent-2);
  letter-spacing: -0.02em;
  line-height: 1;
}
.rew-hero-unit { font-weight: 600; color: var(--text-2); }
.rew-hero-usd { color: var(--text-3); margin-inline-start: .25rem; }
.rew-hero-cta { text-decoration: none; flex-shrink: 0; }
.rew-hero-cta:hover { text-decoration: none; }

@media (max-width: 720px) {
  .rew-hero {
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
    padding: 1.2rem;
  }
  .rew-hero-top { width: 100%; }
  .rew-hero-points { font-size: 1.95rem; }
  .rew-hero-cta {
    width: 100%;
    justify-content: center;
    padding-block: .7rem;
  }
}

/* ──────────────────────────────────────────────────────────────────────
   Mobile shift strip — live "you're on shift" pill INSIDE the topbar.
   Hidden by default (state="off"); appears inline in topbar-left when
   on-clock with a soft pulsing dot + live duration + live earnings.
   Tappable: opens the shift page. Lives in the chrome rather than as
   a floating overlay so it can't cover page content (channels list,
   rewards card, past-7-days tiles, etc.).
   ────────────────────────────────────────────────────────────────────── */
.mobile-shift-strip { display: none; }
@media (max-width: 720px) {
  .mobile-shift-strip[data-state="on"],
  .mobile-shift-strip[data-state="paused"] {
    display: inline-flex;
    align-items: center;
    gap: .42rem;
    padding: .32rem .7rem .32rem .55rem;
    border-radius: 999px;
    background: linear-gradient(135deg,
      color-mix(in srgb, var(--brand) 18%, var(--card)),
      color-mix(in srgb, var(--brand) 6%, var(--card)));
    border: 1px solid color-mix(in srgb, var(--brand) 32%, var(--border));
    box-shadow: 0 4px 14px -8px color-mix(in srgb, var(--brand) 60%, transparent);
    color: var(--text);
    text-decoration: none;
    font-size: .78rem;
    font-weight: 700;
    min-width: 0;
    max-width: 100%;
    flex: 0 1 auto;
    /* Subtle entrance — fade + grow when state flips on. */
    animation: shift-strip-in .25s ease both;
  }
  .mobile-shift-strip-dot {
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--brand);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 60%, transparent);
    animation: shift-strip-pulse 1.7s infinite ease-in-out;
    flex-shrink: 0;
  }
  .mobile-shift-strip[data-state="paused"] .mobile-shift-strip-dot {
    background: var(--text-3);
    animation: none;
  }
  .mobile-shift-strip-label {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--text-2);
  }
  .mobile-shift-strip-time {
    font-variant-numeric: tabular-nums;
    color: var(--text-2);
    font-weight: 600;
  }
  .mobile-shift-strip-sep { color: var(--text-3); font-weight: 400; }
  .mobile-shift-strip-money {
    color: var(--brand);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
  }
  /* Hide on the dashboard — the hero card there already shows
     earnings + points, no need to duplicate in the topbar. */
  body.page-overview .mobile-shift-strip { display: none !important; }
  /* Inside an open chat conversation: keep the strip visible so the
     employee always knows their shift state, but compact it (just the
     dot + duration, no money figure) so the chat header still has
     room for the back arrow + recipient name on a 360px viewport. */
  body.chat-open .mobile-shift-strip-money,
  body.chat-open .mobile-shift-strip-sep { display: none; }
  body.chat-open .mobile-shift-strip { padding-inline: .55rem .65rem; }
  /* Composer with 5 buttons (mic + attach + emoji + lightning + send)
     plus the textarea is tight on a 360px viewport. Tighten gaps and
     button sizes so the textarea keeps a usable typing area. */
  body.chat-open .tg-composer { gap: .25rem; padding: .3rem .45rem; margin: .4rem .65rem max(.4rem, env(safe-area-inset-bottom) + .1rem); }
  body.chat-open .comp-btn { width: 32px; height: 32px; }
  body.chat-open .comp-btn .lucide-ic { width: 18px; height: 18px; }
}
@keyframes shift-strip-in {
  from { opacity: 0; transform: scale(.92); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes shift-strip-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 60%, transparent); }
  50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--brand) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .mobile-shift-strip-dot { animation: none; }
}

/* ──────────────────────────────────────────────────────────────────────
   Mobile-only large title (Phase C, iOS-style). Hidden on desktop and
   inside the chat shell (chat owns its own back-arrow header). The
   topbar title slot is hidden on mobile via the existing rule, so this
   becomes the primary "where am I" cue and reads as native-iOS premium.
   ────────────────────────────────────────────────────────────────────── */
.page-title-large { display: none; }
@media (max-width: 720px) {
  main:not(:has(.chat-shell)) > .page-title-large {
    display: block;
    padding: .75rem 1.1rem .35rem;
    padding-inline-start: calc(1.1rem + env(safe-area-inset-left));
    padding-inline-end: calc(1.1rem + env(safe-area-inset-right));
    font-size: 1.7rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--text);
    line-height: 1.15;
  }
  /* Empty title (page hasn't called setTitle yet) — collapse the slot
     so we don't leave a stray gap above the content. */
  main:not(:has(.chat-shell)) > .page-title-large:empty { display: none; }
}

/* ──────────────────────────────────────────────────────────────────────
   Mobile-only hero (Phase B) — premium summary card on the dashboard.
   Replaces the topbar earnings ticker on phones so the topbar can stay
   minimal. Two big numbers (this-month earnings + points), tappable to
   open the rewards page. Hidden entirely on desktop.
   ────────────────────────────────────────────────────────────────────── */
.mobile-hero, .mobile-hero-skeleton { display: none; }
@media (max-width: 720px) {
  /* Skeleton placeholder that mirrors the hero card's footprint while
     /api/rewards/ticker is in flight. */
  .mobile-hero-skeleton {
    display: block;
    height: 86px;
    border-radius: 18px;
    margin: 0 0 1rem;
  }
  .mobile-hero {
    display: block;
    text-decoration: none;
    color: var(--text);
    margin: 0 0 1rem;
    padding: 1rem 1.1rem;
    background: linear-gradient(135deg,
      color-mix(in srgb, var(--brand) 14%, var(--card)),
      color-mix(in srgb, var(--brand) 4%, var(--card)));
    border: 1px solid color-mix(in srgb, var(--brand) 25%, var(--border));
    border-radius: 18px;
    box-shadow: 0 6px 18px -10px color-mix(in srgb, var(--brand) 50%, transparent);
    transition: transform .15s ease, box-shadow .15s ease;
  }
  .mobile-hero:active { transform: scale(.99); }
  .mobile-hero-row { display: flex; align-items: stretch; gap: .8rem; }
  .mobile-hero-block { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: .25rem; }
  .mobile-hero-label {
    font-size: .72rem; font-weight: 600;
    color: var(--text-3); letter-spacing: .02em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .mobile-hero-value {
    font-size: 1.6rem; font-weight: 800;
    color: var(--text); line-height: 1.1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
  }
  /* Tiny caption below each big number — explains the value (cash
     equivalent for points, payout schedule for earnings). Keeps the
     hero from feeling like raw numbers without context. */
  .mobile-hero-sub {
    font-size: .68rem;
    color: var(--text-3);
    font-weight: 600;
    margin-top: .15rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .mobile-hero-sub-pts {
    color: color-mix(in srgb, var(--brand) 70%, var(--text-3));
    font-weight: 700;
    font-variant-numeric: tabular-nums;
  }
  .mobile-hero-sep {
    width: 1px;
    background: color-mix(in srgb, var(--brand) 18%, var(--border));
    align-self: stretch;
  }
}

/* ──────────────────────────────────────────────────────────────────────
   Voice message — compact pill with tinted card.
   Replaces the stretched full-width voice player with a fixed-width
   inline pill (WhatsApp/iMessage feel) that visually separates from
   plain text via a subtle accent-tinted background and rounded corners.
   ────────────────────────────────────────────────────────────────────── */
.msg .voice-msg {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  width: fit-content;
  min-width: 0;
  max-width: 320px;
  padding: .4rem .55rem .4rem .45rem;
  background: var(--accent-soft);
  border: 1px solid var(--accent-soft-border);
  border-radius: 18px;
  margin: .15rem 0;
}
.msg .voice-msg .voice-play {
  width: 34px; height: 34px;
  background: var(--accent);
  color: var(--accent-fg);
  box-shadow: 0 1px 3px color-mix(in srgb, var(--accent) 35%, transparent);
}
.msg .voice-msg .voice-play:hover { transform: scale(1.06); transition: transform .12s; }
.msg .voice-msg .voice-play svg { width: 16px; height: 16px; }
.msg .voice-msg .voice-body { gap: .25rem; min-width: 0; flex: 1; }
.msg .voice-msg .voice-wave {
  width: 200px;
  height: 28px;
  gap: 3px;
  display: flex;
  align-items: center;
  cursor: pointer;
  position: relative;
}
.msg .voice-msg .voice-wave .vb,
.msg:not(.mine) .voice-msg .voice-wave .vb,
.msg.mine .voice-msg .voice-wave .vb {
  width: 2.5px;
  min-height: 5px;
  background: color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: 999px;
  transition: background .12s, transform .12s;
  flex-shrink: 0;
}
/* Played bars: solid accent (WhatsApp). No overlay layer needed. */
.msg .voice-msg .voice-wave .vb.played,
.msg:not(.mine) .voice-msg .voice-wave .vb.played,
.msg.mine .voice-msg .voice-wave .vb.played {
  background: var(--accent);
}
/* Hide the legacy progress overlay element if it's still in the DOM */
.msg .voice-msg .voice-progress { display: none; }

.msg .voice-msg .voice-meta {
  font-size: .72rem;
  color: var(--text-2);
  display: flex;
  align-items: center;
  gap: .35rem;
}
.msg .voice-msg .voice-time {
  font-weight: 600;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* Compact variant for very narrow screens */
@media (max-width: 480px) {
  .msg .voice-msg { max-width: 260px; }
  .msg .voice-msg .voice-wave { width: 140px; }
}

/* ──────────────────────────────────────────────────────────────────────
   Liquid Glass — modals, dropdowns, popovers.
   The previous version used `--bg-2` mixed with transparency, which in
   light mode left the modal looking like flat washed-out gray (you blur
   a near-white page through a near-white tint and there's nothing to
   blur). The fix: completely separate light/dark recipes.
     • Light mode  → high-opacity white + strong saturation + crisp top
                     highlight + warm drop shadow → reads as frosted glass
                     sitting above the page (Apple/macOS feel).
     • Dark mode   → smoky translucent surface + subtle inset highlight +
                     deep shadow → reads as polished glass over the room.
   The lighter, brighter modal-backdrop in light mode is the key that
   actually lets the glass "see" colorful content underneath when blurred.
   ────────────────────────────────────────────────────────────────────── */

/* Default (dark) — translucent smoke pane */
.modal-backdrop {
  background: rgba(8, 12, 16, .55);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
}
.modal {
  position: relative;
  background: rgba(22, 26, 32, .60);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .08);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .08),
    inset 0 0 0 1px rgba(255, 255, 255, .015),
    0 32px 64px -20px rgba(0, 0, 0, .65),
    0 12px 24px -8px rgba(0, 0, 0, .35);
}

/* Light — frosted white pane with bright edge highlight */
html.light .modal-backdrop {
  background: rgba(15, 23, 42, .18);
  backdrop-filter: blur(8px) saturate(120%);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
}
html.light .modal {
  background: rgba(255, 255, 255, .72);
  backdrop-filter: blur(40px) saturate(200%);
  -webkit-backdrop-filter: blur(40px) saturate(200%);
  border: 1px solid rgba(255, 255, 255, .85);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -1px 0 rgba(15, 23, 42, .04),
    0 1px 0 rgba(15, 23, 42, .02),
    0 32px 60px -16px rgba(15, 23, 42, .25),
    0 12px 24px -8px rgba(15, 23, 42, .12),
    0 0 0 1px rgba(15, 23, 42, .03);
}

/* Subtle top sheen — gives the surface a light-source highlight that
   reads as a real piece of glass catching light from above. */
.modal::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 50%;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, .06) 0%,
    rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
  z-index: 0;
}
html.light .modal::before {
  background: linear-gradient(180deg,
    rgba(255, 255, 255, .55) 0%,
    rgba(255, 255, 255, 0) 100%);
}
.modal > * { position: relative; z-index: 1; }

@supports not ((backdrop-filter: blur(10px)) or (-webkit-backdrop-filter: blur(10px))) {
  .modal { background: var(--bg-2); }
  html.light .modal { background: #ffffff; }
  .modal-backdrop { background: rgba(0,0,0,.55); }
  html.light .modal-backdrop { background: rgba(15,23,42,.40); }
}

/* Cancel-style ghost buttons inside modals get a soft visible surface so
   they read as buttons rather than plain text. */
.modal .btn-ghost,
.modal-backdrop .btn-ghost {
  background: rgba(255, 255, 255, .04);
  border-color: rgba(255, 255, 255, .12);
  color: var(--text-2);
}
.modal .btn-ghost:hover:not(:disabled),
.modal-backdrop .btn-ghost:hover:not(:disabled) {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .18);
  color: var(--text);
}
html.light .modal .btn-ghost,
html.light .modal-backdrop .btn-ghost {
  background: rgba(15, 23, 42, .045);
  border-color: rgba(15, 23, 42, .10);
  color: var(--text-2);
}
html.light .modal .btn-ghost:hover:not(:disabled),
html.light .modal-backdrop .btn-ghost:hover:not(:disabled) {
  background: rgba(15, 23, 42, .075);
  border-color: rgba(15, 23, 42, .16);
  color: var(--text);
}

/* Same glass treatment for popovers/menus across the chat surface */
.chat-fab-menu,
.attach-menu,
.msg-ctx-menu,
.ctx-reactions,
.emoji-pop,
.reaction-picker,
.sidebar-user-menu {
  background: rgba(22, 26, 32, .72) !important;
  backdrop-filter: blur(28px) saturate(180%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .08);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .06),
    0 16px 36px -10px rgba(0, 0, 0, .55);
}
html.light .chat-fab-menu,
html.light .attach-menu,
html.light .msg-ctx-menu,
html.light .ctx-reactions,
html.light .emoji-pop,
html.light .reaction-picker,
html.light .sidebar-user-menu {
  background: rgba(255, 255, 255, .80) !important;
  border: 1px solid rgba(255, 255, 255, .9);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    0 1px 0 rgba(15, 23, 42, .02),
    0 18px 40px -12px rgba(15, 23, 42, .22),
    0 0 0 1px rgba(15, 23, 42, .035);
}
@supports not ((backdrop-filter: blur(10px)) or (-webkit-backdrop-filter: blur(10px))) {
  .chat-fab-menu, .attach-menu, .msg-ctx-menu, .ctx-reactions,
  .emoji-pop, .reaction-picker, .sidebar-user-menu { background: var(--card) !important; }
  html.light .chat-fab-menu, html.light .attach-menu, html.light .msg-ctx-menu,
  html.light .ctx-reactions, html.light .emoji-pop, html.light .reaction-picker,
  html.light .sidebar-user-menu { background: #ffffff !important; }
}

/* ──────────────────────────────────────────────────────────────────────
   Sidebar tooltip — only when sidebar is collapsed. Branded with the
   accent border so it reads as part of the system, not a generic OS
   tooltip. Uses data-tooltip attribute populated by Shell.mount().
   ────────────────────────────────────────────────────────────────────── */
.shell.sidebar-collapsed .nav a,
.shell.sidebar-collapsed .sidebar-shift,
.shell.sidebar-collapsed .sidebar-user-btn,
.shell.sidebar-collapsed .sidebar-toggle,
.shell.sidebar-collapsed .sidebar-head .brand {
  position: relative;
}
.shell.sidebar-collapsed [data-tooltip]:hover::after,
.shell.sidebar-collapsed [data-tooltip]:focus-visible::after {
  content: attr(data-tooltip);
  position: absolute;
  inset-inline-start: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%);
  /* Dark tooltip in dark mode (default). The light-mode variant below
     flips to a white pill so it doesn't fight the off-white canvas. */
  background: rgba(20, 24, 28, .96);
  color: #F3F4F6;
  padding: .32rem .72rem;
  border-radius: 8px;
  font-size: .8rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  /* Very high z-index so the tooltip wins against any sibling stacking
     context (modals are 10000+, so we stay below them). */
  z-index: 9999;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .42);
  border: 1px solid rgba(255, 255, 255, .06);
  animation: sb-tooltip-in .14s ease both;
}
/* Light-mode tooltip — white pill with dark text, soft shadow tinted to
   match the off-white canvas. Reads as a quiet floating chip, not as a
   loud dark Material toast. */
html.light .shell.sidebar-collapsed [data-tooltip]:hover::after,
html.light .shell.sidebar-collapsed [data-tooltip]:focus-visible::after {
  background: #FFFFFF;
  color: var(--text);
  border-color: rgba(15, 31, 26, .08);
  box-shadow: 0 6px 18px rgba(15, 31, 26, .12);
}
@keyframes sb-tooltip-in {
  from { opacity: 0; transform: translateY(-50%) translateX(-4px); }
  to   { opacity: 1; transform: translateY(-50%) translateX(0); }
}

/* ── Attendance view toggle (Timeline / Table) ────────────────────── */
.att-view-toggle {
  display: inline-flex;
  gap: .15rem;
  padding: .25rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.att-view-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  min-width: 7.25rem;
  padding: .45rem 1rem;
  font: inherit;
  font-weight: 600;
  font-size: .85rem;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: var(--text-3);
  cursor: pointer;
  transition: background .12s, color .12s;
  line-height: 1;
}
.att-view-btn:hover { color: var(--text); background: var(--bg-3); }
.att-view-btn.is-on {
  background: var(--bg-3);
  color: var(--text);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--accent) 35%, transparent);
}
.att-view-btn .lucide-ic { width: 1.05em; height: 1.05em; }
.att-timeline-host { width: 100%; }

#att-daypicker.att-day-locked .dp-field {
  border-color: color-mix(in srgb, var(--warn) 55%, var(--border));
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
}
#att-daypicker.att-day-locked .dp-field .dp-icon { color: var(--warn); }
#att-daypicker.att-day-edit .dp-field {
  border-color: color-mix(in srgb, var(--danger) 55%, var(--border));
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
#att-daypicker.att-day-edit .dp-field .dp-icon { color: var(--danger); }

/* ── Attendance Timeline ──────────────────────────────────────────── */
.att-timeline {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
}
.att-tl-toolbar {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .65rem .85rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  flex-wrap: wrap;
}
.att-tl-modeswitch {
  display: inline-flex;
  gap: .15rem;
  padding: .2rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.att-tl-mode-btn {
  padding: .35rem .8rem;
  font: inherit;
  font-weight: 600;
  font-size: .82rem;
  background: transparent;
  border: 0;
  border-radius: 7px;
  color: var(--text-3);
  cursor: pointer;
  transition: background .12s, color .12s;
}
.att-tl-mode-btn:hover { color: var(--text); background: var(--bg-3); }
.att-tl-mode-btn.is-on {
  background: var(--accent);
  color: var(--accent-contrast, #fff);
}
.att-tl-nav { display: inline-flex; align-items: center; gap: .35rem; }
.att-tl-date {
  min-width: 9rem;
  text-align: center;
  font-weight: 600;
  font-size: .9rem;
  color: var(--text);
}
.att-tl-spacer { flex: 1; }
.att-tl-legend {
  display: inline-flex;
  align-items: center;
  gap: .85rem;
  flex-wrap: wrap;
  font-size: .72rem;
  color: var(--text-3);
}
.att-tl-leg { display: inline-flex; align-items: center; gap: .35rem; }
.att-tl-sw {
  width: .9rem;
  height: .55rem;
  border-radius: 3px;
  display: inline-block;
}
.att-tl-sw.shift    { background: color-mix(in oklab, var(--accent) 18%, var(--bg-3)); border: 1px dashed color-mix(in oklab, var(--accent) 45%, transparent); }
.att-tl-sw.worked   { background: var(--accent); }
.att-tl-sw.overtime { background: var(--warn, #f59e0b); }
.att-tl-sw.live     { background: var(--danger, #ef4444); width: .35rem; height: .9rem; border-radius: 999px; }

/* ── Day mode ─────────────────────────────────────────────────────── */
.att-tl-grid { padding: .5rem .85rem 1rem; }
.att-tl-axis,
.att-tl-row {
  display: grid;
  grid-template-columns: 14rem 1fr;
  align-items: stretch;
  gap: .75rem;
}
.att-tl-axis { padding: .35rem 0 .25rem; }
.att-tl-axis-track {
  position: relative;
  height: 1.25rem;
  border-bottom: 1px solid var(--border);
}
.att-tl-hour {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  font-size: .68rem;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
html[dir="rtl"] .att-tl-hour { transform: translateX(50%); }
.att-tl-rows { display: flex; flex-direction: column; gap: .35rem; }
.att-tl-row { padding: .35rem 0; border-radius: 8px; }
.att-tl-row:hover { background: color-mix(in oklab, var(--bg-3) 50%, transparent); }
.att-tl-name { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.att-tl-name .status-dot {
  width: .55rem; height: .55rem; border-radius: 999px;
  background: var(--bg-3); flex: 0 0 auto;
}
.att-tl-name .status-dot.working { background: var(--success, #10b981); box-shadow: 0 0 0 3px color-mix(in oklab, var(--success, #10b981) 28%, transparent); }
.att-tl-name .status-dot.paused  { background: var(--warn, #f59e0b); }
.att-tl-name .status-dot.ended   { background: var(--text-3); }
.att-tl-name-text { min-width: 0; flex: 1; }
.att-tl-name-main {
  font-weight: 600;
  font-size: .88rem;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.att-tl-name-sub { font-size: .72rem; color: var(--text-3); font-variant-numeric: tabular-nums; }
.att-tl-row-total { font-weight: 600; color: var(--text-2); }
.att-tl-ot-chip {
  display: inline-block;
  margin-inline-start: .25rem;
  padding: 0 .35rem;
  border-radius: 999px;
  background: color-mix(in oklab, var(--warn, #f59e0b) 22%, transparent);
  color: var(--warn, #f59e0b);
  font-size: .68rem;
}
.att-tl-track {
  position: relative;
  height: 2.4rem;
  background: var(--bg-3);
  border-radius: 8px;
  overflow: hidden;
}
.att-tl-shift {
  position: absolute;
  top: 0; bottom: 0;
  background: color-mix(in oklab, var(--accent) 12%, transparent);
  border-inline-start: 1px dashed color-mix(in oklab, var(--accent) 45%, transparent);
  border-inline-end: 1px dashed color-mix(in oklab, var(--accent) 45%, transparent);
}
.att-tl-bar {
  position: absolute;
  top: .35rem; bottom: .35rem;
  border-radius: 5px;
  background: var(--accent);
  box-shadow: 0 1px 0 color-mix(in oklab, var(--accent) 60%, black);
  cursor: default;
  transition: filter .12s;
}
.att-tl-bar:hover { filter: brightness(1.1); }
.att-tl-bar.overtime { background: var(--warn, #f59e0b); }
.att-tl-bar.is-open::after {
  content: "";
  position: absolute;
  inset-inline-end: 0;
  top: 0; bottom: 0;
  width: .35rem;
  border-radius: 0 5px 5px 0;
  background: color-mix(in oklab, var(--accent) 80%, white);
  animation: att-tl-pulse 1.4s ease-in-out infinite;
}
html[dir="rtl"] .att-tl-bar.is-open::after { border-radius: 5px 0 0 5px; }
@keyframes att-tl-pulse {
  0%, 100% { opacity: .55; }
  50%      { opacity: 1; }
}
.att-tl-now {
  position: absolute;
  top: -.15rem; bottom: -.15rem;
  width: 2px;
  background: var(--danger, #ef4444);
  pointer-events: none;
  z-index: 2;
}
.att-tl-now-dot {
  position: absolute;
  top: -.25rem;
  inset-inline-start: -.3rem;
  width: .65rem; height: .65rem;
  border-radius: 999px;
  background: var(--danger, #ef4444);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--danger, #ef4444) 28%, transparent);
}
.att-tl-loading {
  padding: 2.5rem 1rem;
  text-align: center;
  color: var(--text-3);
  font-size: .85rem;
}

/* ── Week mode ────────────────────────────────────────────────────── */
.att-tl-whead {
  display: grid;
  grid-template-columns: 14rem 1fr;
  gap: .75rem;
  padding: .35rem 0 .5rem;
}
.att-tl-whead-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: .35rem;
}
.att-tl-whead-col {
  text-align: center;
  padding: .25rem 0;
  border-bottom: 1px solid var(--border);
}
.att-tl-whead-col.today { border-bottom-color: var(--accent); }
.att-tl-whead-day  { font-size: .7rem;  color: var(--text-3); font-weight: 600; }
.att-tl-whead-date { font-size: .85rem; color: var(--text);   font-weight: 700; font-variant-numeric: tabular-nums; }
.att-tl-wrow {
  display: grid;
  grid-template-columns: 14rem 1fr;
  gap: .75rem;
  padding: .25rem 0;
  border-radius: 8px;
}
.att-tl-wrow:hover { background: color-mix(in oklab, var(--bg-3) 50%, transparent); }
.att-tl-wtrack {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: .35rem;
  align-items: end;
}
.att-tl-wcell {
  position: relative;
  height: 3.4rem;
  background: var(--bg-3);
  border-radius: 6px;
  overflow: hidden;
  cursor: default;
  transition: filter .12s;
}
.att-tl-wcell:hover { filter: brightness(1.1); }
.att-tl-wcell.today  { box-shadow: inset 0 0 0 1px var(--accent); }
.att-tl-wcell.future { opacity: .35; pointer-events: none; }
.att-tl-wcell.absent { background: color-mix(in oklab, var(--danger, #ef4444) 14%, var(--bg-3)); }
.att-tl-wcell.off    { background: var(--bg-2); opacity: .6; }
.att-tl-wcell.live::after {
  content: "";
  position: absolute;
  top: .25rem;
  inset-inline-end: .25rem;
  width: .4rem; height: .4rem;
  border-radius: 999px;
  background: var(--danger, #ef4444);
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--danger, #ef4444) 30%, transparent);
}
.att-tl-wbg {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: color-mix(in oklab, var(--accent) 12%, transparent);
  border-top: 1px dashed color-mix(in oklab, var(--accent) 35%, transparent);
}
.att-tl-wfill { position: absolute; left: 0; right: 0; bottom: 0; }
.att-tl-wfill.regular  { background: var(--accent); }
.att-tl-wfill.overflow { background: color-mix(in oklab, var(--accent) 75%, white); }
.att-tl-wfill.overtime { background: var(--warn, #f59e0b); }

@media (max-width: 720px) {
  .att-tl-axis,
  .att-tl-row,
  .att-tl-whead,
  .att-tl-wrow {
    grid-template-columns: 8rem 1fr;
    gap: .5rem;
  }
  .att-tl-name-main { font-size: .8rem; }
  .att-tl-hour:nth-child(odd) { display: none; }
  .att-tl-legend { display: none; }
}
