:root{
  --surface-1:#fcfcfb;
  --page:#f9f9f7;
  --text-primary:#0b0b0b;
  --text-secondary:#52514e;
  --text-muted:#898781;
  --gridline:#e1e0d9;
  --border:rgba(11,11,11,0.10);
  /* Brand palette (abracket.com): Mountain Meadow green as the primary
     accent, with Cerulean and Flesh as secondary/tertiary touches used
     sparingly on the dashboard and reports so the app reads as branded
     without turning into a rainbow. */
  --accent:#1bae70;
  --accent-wash:rgba(27,174,112,0.08);
  --accent-2:#06b6d4;
  --accent-2-wash:rgba(6,182,212,0.10);
  --accent-3:#fecda5;
  --accent-3-wash:rgba(254,205,165,0.30);
  --good:#1bae70;
  --good-text:#0c7a4f;
  --warning:#fab219;
  --serious:#ec835a;
  --critical:#d03b3b;
  --critical-wash:rgba(208,59,59,0.08);
  --warning-wash:rgba(250,178,25,0.12);
  --good-wash:rgba(27,174,112,0.08);
}
*{box-sizing:border-box;}
html, body{height:100%;}
body{
  margin:0;
  background:var(--page);
  color:var(--text-primary);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing:antialiased;
}

/* ===== Onboarding ===== */
.onboard-screen{min-height:100vh;display:flex;align-items:center;justify-content:center;background:var(--page);padding:24px;}
.onboard-card{width:100%;max-width:420px;background:var(--surface-1);border:1px solid var(--border);border-radius:16px;padding:34px 32px;}
.onboard-logo{width:36px;height:36px;border-radius:10px;display:block;object-fit:contain;margin-bottom:18px;}
.onboard-title{font-size:19px;font-weight:700;margin-bottom:6px;}
.onboard-sub{font-size:14px;color:var(--text-secondary);line-height:1.5;margin-bottom:22px;}
.onboard-field{margin-bottom:14px;}
.onboard-field label{display:block;font-size:13px;font-weight:600;color:var(--text-secondary);margin-bottom:6px;}
.onboard-field input, .onboard-field select{width:100%;border:1px solid var(--gridline);border-radius:8px;padding:10px 12px;font-family:inherit;font-size:15px;background:var(--page);}
.onboard-error{color:var(--critical);font-size:13px;margin:-8px 0 12px;display:none;}
.onboard-role-hint{font-size:12px;color:var(--text-muted);margin-top:10px;line-height:1.5;}
.btn-block{width:100%;text-align:center;padding:11px 15px;}
.onboard-back{background:none;border:none;font-family:inherit;font-size:13px;color:var(--text-muted);cursor:pointer;padding:0;margin-bottom:14px;}
.onboard-back:hover{color:var(--text-primary);}

.auth-tabs{display:flex;gap:4px;background:var(--page);border:1px solid var(--gridline);border-radius:10px;padding:3px;margin-bottom:20px;}
.auth-tab{flex:1;appearance:none;border:none;background:transparent;font-family:inherit;font-size:14px;font-weight:600;color:var(--text-secondary);padding:8px 10px;border-radius:8px;cursor:pointer;}
.auth-tab.active{background:var(--surface-1);color:var(--text-primary);box-shadow:0 1px 2px rgba(11,11,11,0.08);}
.auth-panel{display:none;}
.auth-panel.active{display:block;}
.onboard-loading{opacity:0.65;pointer-events:none;}

/* ===== App shell: top accent + brand bar, left icon+label sidebar, content =====
   The shell itself is pinned to exactly the viewport height with its own
   scroll disabled - only .main-col scrolls internally. That's what keeps
   the header AND the sidebar completely static instead of the sidebar
   drifting off-screen with the page (the header alone being sticky wasn't
   enough, since the sidebar was just a normal flex child of the page's
   own scroll). */
.app-shell{display:flex;flex-direction:column;height:100vh;overflow:hidden;}

.holiday-banner{
  display:flex;align-items:center;gap:10px;padding:10px 28px;flex-shrink:0;
  background:var(--accent-3-wash);color:#7a4a12;border-bottom:1px solid var(--gridline);
  font-size:13px;font-weight:600;
}
.holiday-banner-icon{flex-shrink:0;font-size:16px;line-height:1;}
.holiday-banner-text{flex:1;min-width:0;}
.holiday-banner-close{flex-shrink:0;background:transparent;border:none;color:inherit;opacity:0.6;cursor:pointer;font-size:18px;line-height:1;padding:0 2px;font-family:inherit;}
.holiday-banner-close:hover{opacity:1;}

/* Same layout as .holiday-banner (it shares that class), just re-tinted so
   the two read as distinct occasions when both happen to show at once. */
.birthday-banner{background:var(--accent-2-wash);color:#0e7490;}

.leave-allocation-input{width:70px;border:1px solid var(--gridline);border-radius:8px;padding:6px 8px;font-family:inherit;font-size:13px;background:var(--page);}
.team-birthdate-input{border:1px solid var(--gridline);border-radius:8px;padding:6px 8px;font-family:inherit;font-size:13px;background:var(--page);}

.global-topbar{
  display:flex;align-items:center;justify-content:space-between;padding:14px 28px;
  background:var(--surface-1);border-bottom:1px solid var(--gridline);flex-shrink:0;z-index:30;
  gap:14px;flex-wrap:wrap;
}
.brand-word{font-size:18px;font-weight:700;color:var(--text-primary);letter-spacing:-0.01em;display:flex;align-items:center;gap:8px;}
.brand-logo{width:26px;height:26px;border-radius:7px;flex-shrink:0;display:block;}
.brand-link{appearance:none;border:none;background:transparent;font-family:inherit;padding:0;cursor:pointer;border-radius:6px;}
.brand-link:hover{color:var(--accent);}
.brand-link:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}

.body-row{display:flex;flex:1;min-height:0;}

.sidebar{
  width:68px;flex-shrink:0;background:var(--surface-1);box-shadow:1px 0 0 var(--gridline), 3px 0 10px rgba(11,11,11,0.03);
  display:flex;flex-direction:column;padding:14px 0;overflow-y:auto;
}
.nav-icon-btn{
  position:relative;width:100%;border:none;border-left:3px solid transparent;background:transparent;
  color:var(--text-muted);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0;
  padding:16px 4px;cursor:pointer;font-family:inherit;
}
.nav-icon-btn:hover{background:var(--page);}
.nav-icon-btn.active{border-left-color:var(--accent);color:var(--accent);background:var(--accent-wash);}
.nav-icon-btn svg{width:22px;height:22px;}
.nav-icon-btn .nav-label{display:none;}

.main-col{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--page);overflow-y:auto;height:100%;}

.page-heading{margin-bottom:16px;}
.page-title{font-size:20px;font-weight:700;}
.page-sub{font-size:13px;color:var(--text-muted);margin-top:2px;}

.header-right{display:flex;align-items:center;gap:9px;flex-wrap:wrap;}
.proto-tag{font-size:12px;color:var(--text-muted);border:1px solid var(--border);padding:3px 9px;border-radius:20px;}
.workspace-tag{font-size:12px;color:var(--text-muted);border:1px solid var(--border);padding:3px 9px;border-radius:20px;font-weight:600;}

.day-pill{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;padding:6px 12px;border-radius:20px;cursor:pointer;border:none;font-family:inherit;}
.day-pill .dot{width:7px;height:7px;border-radius:50%;}
.day-pill.locked{background:var(--critical-wash);color:var(--critical);}
.day-pill.locked .dot{background:var(--critical);}
.day-pill.meeting{background:var(--warning-wash);color:#8a5c00;}
.day-pill.meeting .dot{background:var(--warning);}
.day-pill.open{background:var(--good-wash);color:var(--good-text);}
.day-pill.open .dot{background:var(--good);}

.user-chip{position:relative;}
.user-chip-btn{display:flex;align-items:center;gap:8px;background:var(--surface-1);border:1px solid var(--gridline);border-radius:20px;padding:5px 12px 5px 6px;cursor:pointer;font-family:inherit;font-size:13px;font-weight:600;color:var(--text-primary);}
.user-chip-btn .avatar{width:24px;height:24px;font-size:10.5px;}
.user-role-tag{font-size:10.5px;color:var(--text-muted);font-weight:500;margin-left:6px;}
.user-role-tag::before{content:'•';margin-right:6px;font-size:7.5px;vertical-align:middle;color:var(--gridline);}
.user-dropdown{display:none;position:absolute;right:0;top:42px;width:210px;background:var(--surface-1);border:1px solid var(--border);border-radius:12px;box-shadow:0 12px 30px rgba(0,0,0,0.14);z-index:60;padding:8px;}
.user-dropdown.show{display:block;}
.user-dropdown-item{display:block;width:100%;text-align:left;background:transparent;border:none;font-family:inherit;font-size:13px;color:var(--text-secondary);padding:8px 10px;border-radius:8px;cursor:pointer;}
.user-dropdown-item:hover{background:var(--page);color:var(--text-primary);}

.notif-wrap{position:relative;}
.bell-btn{position:relative;width:36px;height:36px;border-radius:10px;border:1px solid var(--gridline);background:var(--surface-1);display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-secondary);}
.bell-btn svg{width:17px;height:17px;}
.notif-badge{position:absolute;top:-5px;right:-5px;background:var(--critical);color:#fff;font-size:10.5px;font-weight:700;min-width:16px;height:16px;border-radius:9px;display:none;align-items:center;justify-content:center;padding:0 4px;}
.notif-dropdown{display:none;position:absolute;right:0;top:44px;width:300px;max-height:360px;overflow-y:auto;background:var(--surface-1);border:1px solid var(--border);border-radius:12px;box-shadow:0 12px 30px rgba(0,0,0,0.14);z-index:60;}
.notif-dropdown.show{display:block;}
.notif-item{padding:11px 14px;border-bottom:1px solid var(--gridline);}
.notif-item:last-child{border-bottom:none;}
.notif-title{font-size:13px;font-weight:600;}
.notif-body{font-size:13px;color:var(--text-secondary);margin-top:2px;}
.notif-time{font-size:11px;color:var(--text-muted);margin-top:3px;}
/* In-app "sweetalert"-style toast stack, top-right - pops up for a new
   delegation while the app is open. Deliberately similar visual language
   to .notif-badge/.notif-dropdown above (same card/shadow/radius) so it
   reads as part of the same notification system, not a bolted-on widget. */
.app-toast-stack{position:fixed;top:70px;right:20px;z-index:200;display:flex;flex-direction:column;gap:10px;width:320px;max-width:calc(100vw - 40px);pointer-events:none;}
.app-toast{pointer-events:auto;background:var(--surface-1);border:1px solid var(--border);border-left:4px solid var(--accent);border-radius:12px;box-shadow:0 14px 34px rgba(0,0,0,0.16);padding:12px 14px;cursor:pointer;animation:app-toast-in .22s ease;}
.app-toast:hover{border-color:var(--border);box-shadow:0 16px 38px rgba(0,0,0,0.20);}
.app-toast-head{display:flex;align-items:flex-start;gap:8px;}
.app-toast-title{font-size:14px;font-weight:700;flex:1;min-width:0;}
.app-toast-close{flex-shrink:0;background:transparent;border:none;color:var(--text-muted);cursor:pointer;font-size:17px;line-height:1;padding:0 0 0 6px;font-family:inherit;}
.app-toast-close:hover{color:var(--text-primary);}
.app-toast-body{font-size:13px;color:var(--text-secondary);margin-top:4px;line-height:1.4;}
.app-toast.leaving{animation:app-toast-out .18s ease forwards;}
@keyframes app-toast-in{from{opacity:0;transform:translateX(16px);}to{opacity:1;transform:translateX(0);}}
@keyframes app-toast-out{from{opacity:1;transform:translateX(0);}to{opacity:0;transform:translateX(16px);}}

/* Sidebar nav badge (e.g. Team Wall's delegated-to-me count) - same shape
   as .notif-badge, positioned relative to the nav-icon-btn's own corner. */
.nav-badge{position:absolute;top:8px;right:10px;background:var(--critical);color:#fff;font-size:10.5px;font-weight:700;min-width:16px;height:16px;border-radius:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;}

.shell{max-width:1200px;margin:0 auto;padding:22px 20px 80px;width:100%;}

.env-banner{
  background:var(--accent-wash);
  border:1px solid rgba(34,134,58,0.20);
  color:var(--text-secondary);
  font-size:14px;
  padding:10px 14px;
  border-radius:10px;
  margin:0 0 22px;
  display:none;
}
.env-banner b{color:var(--text-primary);}
.env-banner.show{display:block;}

.view{display:none;}
.view.active{display:block;}

/* Lock gate */
.lock-gate{display:flex;align-items:center;justify-content:center;min-height:60vh;}
.lock-card{text-align:center;max-width:400px;background:var(--surface-1);border:1px solid var(--border);border-radius:16px;padding:38px 32px;}
.lock-title{font-size:17.5px;font-weight:600;margin-bottom:8px;}
.lock-sub{font-size:14px;color:var(--text-secondary);line-height:1.55;}

/* Cards */
.card{background:var(--surface-1);border:1px solid var(--border);border-radius:14px;padding:20px 22px;margin-bottom:18px;}
.card-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:14px;}
.card-title{font-size:16px;font-weight:600;}
.card-note{font-size:13px;color:var(--text-muted);}

/* Collapsible card header (e.g. "This week's plan", "Delegate a task") */
.card-head-toggle{cursor:pointer;align-items:center;}
.card-head-toggle .daily-chevron{color:var(--text-muted);}
#weeklyPlanCard.collapsed #weeklyPlanChevron{transform:rotate(-90deg);}
#weeklyPlanCard.collapsed #weeklyPlanBody{display:none;}
#wallComposerCard.collapsed #wallComposerChevron{transform:rotate(-90deg);}
#wallComposerCard.collapsed #wallComposerBody{display:none;}

/* Employee view */
.who-strip{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px;}
.who{display:flex;align-items:center;gap:12px;}
.avatar{width:38px;height:38px;border-radius:50%;background:var(--accent-wash);color:var(--accent);display:flex;align-items:center;justify-content:center;font-weight:600;font-size:15px;flex-shrink:0;}
.avatar.sm{width:22px;height:22px;font-size:10.5px;}
.who-name{font-weight:600;font-size:16px;}
.who-role{font-size:13px;color:var(--text-muted);}
.today-date{font-size:13px;color:var(--text-muted);}

.task-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--gridline);font-size:15px;}
.task-row:last-child{border-bottom:none;}
.task-row input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent);flex-shrink:0;}
.task-text{flex:1;}
.task-text.done{color:var(--text-muted);text-decoration:line-through;}

/* Small grey note preview shown under a task's title - used in the Task
   overview table (Today's team tasks) instead of a dedicated Note column,
   and reuses the same look Reports already uses (.hist-note). */
.task-note-preview{font-size:12px;color:var(--text-muted);margin-top:3px;overflow-wrap:anywhere;}

/* Drag-and-drop reordering: only the grip handle is draggable (not the
   whole row), so grabbing a checkbox/icon-button never starts a drag by
   accident. */
.drag-handle{cursor:grab;color:var(--text-muted);display:inline-flex;align-items:center;flex-shrink:0;touch-action:none;}
.drag-handle:active{cursor:grabbing;}
.drag-handle svg{width:14px;height:14px;}
.drag-handle:hover{color:var(--text-secondary);}
.daily-row.dragging, .task-row.dragging{opacity:0.4;}
.daily-row.drag-over-top, .task-row.drag-over-top{box-shadow:inset 0 2px 0 0 var(--accent);}
.daily-row.drag-over-bottom, .task-row.drag-over-bottom{box-shadow:inset 0 -2px 0 0 var(--accent);}

.add-row{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap;}
.add-row input, .add-row select{flex:1;padding:9px 12px;border:1px solid var(--gridline);border-radius:8px;font-family:inherit;font-size:14px;background:var(--page);}
.add-row input[type=date]{flex:0 0 150px;color:var(--text-secondary);}
.add-row select{flex:0 0 200px;color:var(--text-secondary);}
.week-nav{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:16px;}
.week-nav-label{font-size:14px;font-weight:600;color:var(--text-secondary);flex:1;min-width:150px;text-align:center;}
.week-nav input[type=date]{padding:7px 10px;border:1px solid var(--gridline);border-radius:8px;font-family:inherit;font-size:13px;background:var(--page);color:var(--text-secondary);}
.btn{appearance:none;border:none;border-radius:8px;padding:9px 15px;font-family:inherit;font-size:14px;font-weight:600;cursor:pointer;transition:opacity .15s ease;}
.btn:hover{opacity:0.88;}
.btn:disabled{opacity:0.55;cursor:default;}
.btn-primary{background:var(--accent);color:#fff;}
.btn-ghost{background:transparent;color:var(--text-secondary);border:1px solid var(--gridline);}
.btn-sm{padding:6px 11px;font-size:13px;}

/* Busy / loading state for any button (used by the withBusy() JS helper) */
.btn-spinner{display:inline-block;width:12px;height:12px;border:2px solid rgba(255,255,255,0.4);border-top-color:#fff;border-radius:50%;vertical-align:-2px;margin-right:6px;animation:btn-spin .6s linear infinite;}
.btn-ghost .btn-spinner, .chip .btn-spinner, .icon-btn .btn-spinner{border-color:rgba(11,11,11,0.18);border-top-color:var(--text-secondary);}
@keyframes btn-spin{to{transform:rotate(360deg);}}
button.is-busy{cursor:progress;}

/* Small icon-only buttons for row-level edit/delete actions */
.row-actions{display:inline-flex;gap:2px;margin-left:auto;flex-shrink:0;}
.icon-btn{appearance:none;border:none;background:transparent;color:var(--text-muted);cursor:pointer;padding:5px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center;}
.icon-btn svg{width:14px;height:14px;}
.icon-btn:hover{background:var(--accent-wash);color:var(--accent);}
.icon-btn.danger:hover{background:var(--critical-wash);color:var(--critical);}
.icon-btn:disabled{opacity:0.5;cursor:progress;}

.chip{display:inline-flex;align-items:center;gap:6px;font-size:13px;padding:5px 10px;border-radius:20px;border:1px solid var(--gridline);background:var(--page);color:var(--text-secondary);cursor:pointer;font-family:inherit;}
.chip .dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto;}
.chip[data-active="true"]{border-color:transparent;font-weight:600;}
.chip[data-active="true"]:not([data-state]){background:var(--accent-wash);color:var(--accent);}
.chip[data-state="done"][data-active="true"]{background:var(--good-wash);color:var(--good-text);}
.chip[data-state="in_progress"][data-active="true"]{background:var(--warning-wash);color:#8a5c00;}
.chip[data-state="blocked"][data-active="true"]{background:var(--critical-wash);color:var(--critical);}
.chip[data-state="todo"][data-active="true"]{background:var(--accent-wash);color:var(--accent);}
.chip[data-state="open"][data-active="true"]{background:var(--accent-2-wash);color:#0e7490;}
.chip[data-state="overdue"][data-active="true"]{background:var(--critical-wash);color:var(--critical);}
.status-select{display:flex;gap:6px;flex-wrap:wrap;}

.daily-row{padding:10px 0;border-bottom:1px solid var(--gridline);}
.daily-row:last-child{border-bottom:none;}
.daily-top{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;cursor:pointer;}
.daily-top-left{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0;}
.daily-top-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap;flex-shrink:0;}
.daily-chevron{display:inline-flex;color:var(--text-muted);flex-shrink:0;transition:transform .15s ease;}
.daily-chevron svg{width:13px;height:13px;}
.daily-row.expanded .daily-chevron, .daily-chevron.expanded{transform:rotate(180deg);}
.daily-task{font-size:15px;color:var(--text-primary);}
/* Colour the task text by its current status, at a glance, without
   having to read the status badge. */
.daily-task.status-in_progress{color:#8a5c00;}
.daily-task.status-blocked{color:var(--critical);}
.daily-task.status-done{color:var(--text-muted);text-decoration:line-through;}
.daily-body{display:none;padding-top:10px;}
.daily-row.expanded .daily-body{display:block;}
.daily-note{width:100%;border:1px solid var(--gridline);border-radius:8px;padding:7px 10px;font-family:inherit;font-size:13px;background:var(--page);resize:none;margin-top:8px;}

/* This week's plan <-> daily tasks link */
.weekly-progress{cursor:pointer;}
.weekly-progress .daily-chevron{margin-left:2px;}
.weekly-linked-list{margin:2px 0 6px 26px;padding-left:10px;border-left:2px solid var(--gridline);}
.weekly-linked-row{display:flex;align-items:center;gap:10px;padding:5px 0;font-size:13px;}
.weekly-linked-row .task-text{flex:1;color:var(--text-secondary);}
.weekly-linked-row .hist-date{width:auto;}

.toast{display:none;margin-top:12px;background:var(--good-wash);color:var(--good-text);border:1px solid rgba(12,163,12,0.25);padding:9px 12px;border-radius:8px;font-size:14px;}
.toast.err{background:var(--critical-wash);color:var(--critical);border-color:rgba(208,59,59,0.25);}

.hr-summary{display:flex;gap:12px;margin-bottom:18px;}
.mini-stat{flex:1;background:var(--surface-1);border:1px solid var(--border);border-radius:12px;padding:14px 16px;}
.mini-stat .n{font-size:25.5px;font-weight:600;}
.mini-stat .l{font-size:13px;color:var(--text-secondary);margin-top:2px;}
.mini-stat.good .n{color:var(--good-text);}
.mini-stat.warn .n{color:#8a5c00;}
.mini-stat.crit .n{color:var(--critical);}

table{width:100%;border-collapse:collapse;font-size:14px;}
th{text-align:left;font-size:12px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-muted);font-weight:600;padding:0 10px 10px;border-bottom:1px solid var(--gridline);}
td{padding:12px 10px;border-bottom:1px solid var(--gridline);vertical-align:middle;}
tr:last-child td{border-bottom:none;}
.emp-cell{display:flex;align-items:center;gap:10px;}
.emp-name{font-weight:600;}
.emp-role{font-size:13px;color:var(--text-muted);}
.emp-link{cursor:pointer;}
.emp-link:hover{text-decoration:underline;}

.team-role-select{appearance:none;-webkit-appearance:none;border:1px solid var(--gridline);border-radius:8px;padding:7px 26px 7px 10px;font-family:inherit;font-size:14px;font-weight:600;color:var(--text-primary);background:var(--page) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23898781' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 7px center/14px 14px;background-color:var(--page);cursor:pointer;width:124px;flex:0 0 auto;transition:border-color .15s ease;}
.team-role-select:hover{border-color:var(--text-muted);}
.team-role-select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-wash);}

/* No divider line under each Team row - rows separated by padding alone. */
#view-team td{border-bottom:none;}

/* Role + actions share one flex row (instead of separate table columns
   fighting each other for width) so on a narrow window the select and its
   two buttons wrap together as one tidy block, rather than the "Force
   logout" button alone stranding itself on a second line under a select
   that still fits on the first. */
.team-role-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}

.team-group-row{cursor:pointer;background:var(--page);}
.team-group-row:hover{background:var(--accent-wash);}
.team-group-row td{padding:10px;}
/* display:flex belongs on this inner wrapper, not the <td> itself - a
   flex-display table cell stops stretching to the table's auto-layout
   width and shrinks to fit its content instead, which was cutting the
   row short around the Status column. Keeping the <td> a normal
   table-cell (full colspan width) and flexing an inner div fixes it. */
.team-group-head{display:flex;align-items:center;gap:8px;font-weight:600;width:100%;}
.team-group-head .emp-link{font-weight:600;}
.team-group-head .badge{margin-left:auto;}
.team-task-row td:first-child{padding-left:34px;}

.badge{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;padding:4px 10px;border-radius:20px;}
.badge .dot{width:7px;height:7px;border-radius:50%;}
.badge.good{background:var(--good-wash);color:var(--good-text);}
.badge.good .dot{background:var(--good);}
.badge.warn{background:var(--warning-wash);color:#8a5c00;}
.badge.warn .dot{background:var(--warning);}
.badge.crit{background:var(--critical-wash);color:var(--critical);}
.badge.crit .dot{background:var(--critical);}
.badge.info{background:var(--accent-2-wash);color:#0e7490;}
.badge.info .dot{background:var(--accent-2);}
.badge.neutral{background:var(--page);color:var(--text-secondary);border:1px solid var(--gridline);}
.badge.neutral .dot{background:var(--text-muted);}

.legend{display:flex;gap:16px;font-size:13px;color:var(--text-secondary);margin-top:12px;flex-wrap:wrap;}
.legend span{display:inline-flex;align-items:center;gap:6px;}
.legend .dot{width:7px;height:7px;border-radius:50%;}

.stat-row{display:flex;gap:14px;margin-bottom:18px;flex-wrap:wrap;}
.stat-tile{flex:1;min-width:200px;background:var(--surface-1);border:1px solid var(--border);border-top:3px solid var(--accent);border-radius:14px;padding:16px 18px;}
.stat-row .stat-tile:nth-child(2){border-top-color:var(--accent-2);}
.stat-row .stat-tile:nth-child(3){border-top-color:var(--accent-3);}
.stat-row .stat-tile:nth-child(4){border-top-color:var(--warning);}
.stat-tile .label{font-size:13px;color:var(--text-secondary);margin-bottom:6px;}
.stat-tile .value{font-size:30px;font-weight:600;letter-spacing:-0.01em;}
.stat-tile .delta{font-size:13px;margin-top:4px;}
/* A stat tile that opens more detail on click (e.g. the names behind a
   count) - same card, just an affordance so it doesn't look identical to
   the plain read-only tiles next to it. */
.stat-tile-clickable{cursor:pointer;transition:box-shadow .15s ease;}
.stat-tile-clickable:hover{box-shadow:0 4px 14px rgba(11,11,11,0.08);}
.delta.up{color:var(--good-text);}
.delta.down{color:var(--critical);}

.board-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:18px;}
.board h4{font-size:13px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-muted);margin:0 0 10px;display:flex;align-items:center;gap:6px;}
.board h4::before{content:'';display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--accent);}
.board:nth-child(2) h4::before{background:var(--accent-2);}
.board:nth-child(3) h4::before{background:var(--accent-3);}
.board-row{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--gridline);font-size:14px;}
.board-row:last-child{border-bottom:none;}
.rank{width:18px;font-weight:600;color:var(--text-muted);font-size:13px;}
.board-name{flex:1;font-weight:500;}
.board-metric{font-size:13px;color:var(--text-secondary);}

.exc-row{display:flex;align-items:flex-start;gap:10px;padding:10px 0;border-bottom:1px solid var(--gridline);font-size:14px;}
.exc-row:last-child{border-bottom:none;}
.exc-icon{flex-shrink:0;width:20px;height:20px;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;color:#fff;margin-top:1px;}
.exc-icon.crit{background:var(--critical);}
.exc-icon.warn{background:var(--warning);color:#5c3d00;}
.exc-text b{font-weight:600;}
.exc-sub{font-size:13px;color:var(--text-muted);margin-top:1px;}

.report-btn-row{display:flex;justify-content:flex-end;margin-bottom:14px;gap:10px;}

.segmented{display:inline-flex;background:var(--page);border:1px solid var(--gridline);border-radius:10px;padding:3px;margin-bottom:18px;}
.seg-btn{appearance:none;border:none;background:transparent;font-family:inherit;font-size:14px;font-weight:600;color:var(--text-secondary);padding:7px 14px;border-radius:8px;cursor:pointer;}
.seg-btn.active{background:var(--surface-1);color:var(--text-primary);box-shadow:0 1px 2px rgba(11,11,11,0.08);}

.report-builder{display:flex;gap:36px;flex-wrap:wrap;}
.rb-col{flex:1;min-width:220px;}
.rb-label{font-size:13px;font-weight:600;color:var(--text-secondary);margin-bottom:10px;}
.rb-emp-list{display:flex;flex-direction:column;gap:2px;}
.rb-emp-row{display:flex;align-items:center;gap:9px;padding:6px 2px;font-size:14px;}
.rb-emp-row input[type=checkbox]{width:15px;height:15px;accent-color:var(--accent);}
.rb-emp-role{font-size:12px;color:var(--text-muted);}
.rb-emp-actions{display:flex;gap:8px;margin-top:8px;}
.range-chips{display:flex;flex-wrap:wrap;gap:8px;}
.range-chip[data-active="true"]{background:var(--accent-wash);color:var(--accent);border-color:transparent;}
.custom-range{display:none;align-items:center;gap:8px;margin-top:12px;font-size:14px;color:var(--text-secondary);}
.custom-range.show{display:flex;}
.custom-range input[type=date]{padding:6px 8px;border:1px solid var(--gridline);border-radius:8px;font-family:inherit;font-size:14px;background:var(--page);}
.email-field{display:flex;align-items:center;gap:8px;margin-top:14px;}
.email-field input{flex:1;padding:9px 12px;border:1px solid var(--gridline);border-radius:8px;font-family:inherit;font-size:14px;background:var(--page);}

.summary-table td, .summary-table th{padding:10px;}
.bar-track{background:var(--gridline);height:6px;border-radius:4px;overflow:hidden;width:90px;}
.bar-fill{height:100%;background:var(--accent);border-radius:4px;}

/* Task analytics charts (renderTaChart) - hand-built SVG line charts, no
   charting library. */
.ta-legend{display:flex;gap:16px;font-size:13px;color:var(--text-secondary);margin-bottom:10px;flex-wrap:wrap;}
.ta-legend-item{display:inline-flex;align-items:center;gap:7px;}
.ta-legend-line{width:14px;height:2px;border-radius:2px;display:inline-block;}
.ta-chart-wrap{position:relative;}
.ta-svg{width:100%;height:auto;display:block;}
.ta-svg:focus{outline:none;}
.ta-svg .ta-grid{stroke:var(--gridline);stroke-width:1;vector-effect:non-scaling-stroke;}
.ta-svg .ta-axis-label{font-size:10.5px;fill:var(--text-muted);font-family:inherit;}
.ta-svg .ta-crosshair{stroke:var(--gridline);stroke-width:1;vector-effect:non-scaling-stroke;}
.ta-svg .ta-overlay{cursor:crosshair;}
.ta-tooltip{position:absolute;pointer-events:none;background:var(--text-primary);color:#fff;border-radius:8px;padding:8px 10px;font-size:13px;min-width:120px;box-shadow:0 8px 20px rgba(0,0,0,0.18);transition:opacity .1s ease;z-index:5;}
.ta-tooltip-date{font-weight:600;margin-bottom:5px;font-size:12px;color:rgba(255,255,255,0.75);}
.ta-tooltip-row{display:flex;align-items:center;gap:6px;padding:2px 0;}
.ta-tooltip-key{width:8px;height:8px;border-radius:2px;display:inline-block;flex:0 0 auto;}
.ta-tooltip-label{flex:1;color:rgba(255,255,255,0.9);}
.ta-tooltip-val{font-weight:700;}
.ta-table-toggle{appearance:none;border:none;background:transparent;color:var(--accent);font-family:inherit;font-size:13px;font-weight:600;cursor:pointer;padding:10px 0 0;}
.ta-table-wrap{margin-top:10px;max-height:260px;overflow-y:auto;}
.ta-status-row{display:flex;align-items:center;gap:12px;padding:8px 0;border-bottom:1px solid var(--gridline);}
.ta-status-row:last-child{border-bottom:none;}
.ta-status-label{display:flex;align-items:center;gap:7px;font-size:14px;color:var(--text-secondary);width:130px;flex:0 0 auto;}
.ta-status-label .dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;}
.ta-status-row .bar-track{flex:1;width:auto;}
.ta-status-count{width:32px;text-align:right;font-weight:600;font-size:14px;flex:0 0 auto;}

.emp-report-card .card-head{margin-bottom:10px;}
.scroll-box{max-height:230px;overflow-y:auto;padding-right:6px;}
/* Weekly report tab (one person's plan vs. actual for the week) gets a
   taller list so more tasks are visible without scrolling. */
#reportsWeeklyReportMode .scroll-box{max-height:480px;}
.hist-row{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;padding:8px 0;border-bottom:1px solid var(--gridline);font-size:14px;}
.hist-row:last-child{border-bottom:none;}
.hist-left{display:flex;gap:10px;flex:1;min-width:0;}
.hist-date{width:56px;flex-shrink:0;color:var(--text-muted);font-size:12px;padding-top:1px;}
.hist-body .hist-task{overflow-wrap:anywhere;}
.hist-note{font-size:12px;color:var(--text-muted);margin-top:2px;}

.empty-note{font-size:14px;color:var(--text-muted);padding:6px 0;}

.detail-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;}
.detail-who{display:flex;align-items:center;gap:12px;}
.detail-stats{display:flex;gap:10px;margin-bottom:6px;}
.detail-stats .mini-stat{padding:10px 12px;flex:1;}
.detail-stats .n{font-size:20px;}
.detail-section-title{font-size:12px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-muted);margin:16px 0 6px;}
.checkin-row{display:flex;justify-content:space-between;gap:10px;padding:7px 0;border-bottom:1px solid var(--gridline);font-size:13px;}
.checkin-row:last-child{border-bottom:none;}
.checkin-row .cr-mood{color:var(--text-secondary);}

.composer-disabled{color:var(--text-muted);font-size:14px;padding:4px 0;}
.composer-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px;}
.composer-grid .full{grid-column:1/-1;}
.field-inline label{display:block;font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:5px;}
.field-inline select, .field-inline input, .field-inline textarea{width:100%;border:1px solid var(--gridline);border-radius:8px;padding:8px 10px;font-family:inherit;font-size:14px;background:var(--page);}
.field-inline textarea{resize:none;height:44px;}
.field-inline .static-val{padding:8px 10px;background:var(--page);border:1px solid var(--gridline);border-radius:8px;font-size:14px;font-weight:600;}

.filters-bar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:14px;}
.filters-bar .fl{display:flex;flex-direction:column;gap:4px;}
.filters-bar label{font-size:12px;color:var(--text-muted);font-weight:600;}
.filters-bar select, .filters-bar input[type=date]{border:1px solid var(--gridline);border-radius:8px;padding:7px 10px;font-family:inherit;font-size:13px;background:var(--surface-1);min-width:150px;}

.wall-card{border:1px solid var(--border);border-left:4px solid var(--gridline);border-radius:12px;padding:14px 16px;margin-bottom:10px;background:var(--surface-1);transition:background-color .15s ease,border-left-color .15s ease;}
/* Card colour communicates status at a glance instead of archiving closed
   items out of the board - open/in-progress/done match their badge
   colours, and anything past its date (but not done) reads as overdue
   regardless of its underlying open/in_progress status. */
.wall-card.st-open{border-left-color:var(--accent-2);background:var(--accent-2-wash);}
.wall-card.st-in_progress{border-left-color:var(--warning);background:var(--warning-wash);}
.wall-card.st-done{border-left-color:var(--good);background:var(--good-wash);}
.wall-card.st-overdue{border-left-color:var(--critical);background:var(--critical-wash);}
.wall-top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px;flex-wrap:wrap;}
.wall-top-right{display:flex;align-items:center;gap:6px;}
.wall-assign{font-size:13px;color:var(--text-secondary);display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.wall-assign b{color:var(--text-primary);font-weight:600;}
.wall-text{font-size:15px;margin-bottom:6px;}
.wall-meta{font-size:12px;color:var(--text-muted);margin-bottom:6px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
/* white-space:pre-wrap preserves the line breaks/paragraphs someone typed
   into the Note textarea instead of collapsing them into one run-on line -
   the textarea already stored them (clean_str() only trims, never strips
   newlines), this is purely a rendering fix. */
.wall-note{font-size:13px;color:var(--text-secondary);background:var(--page);border-radius:6px;padding:6px 9px;margin-bottom:8px;white-space:pre-wrap;word-break:break-word;}
.wall-note-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--text-muted);margin-bottom:3px;}
/* The note left when a task was marked Done - visually distinct (green
   tint) from the original delegation note so it reads as "how it wrapped
   up" rather than "what was asked for". */
.wall-done-note{background:var(--good-wash);}
.wall-done-note .wall-note-label{color:var(--good-text);}
.wall-actions{display:flex;gap:6px;flex-wrap:wrap;}

/* Composer's "choose file" control + selected-file chip. */
.attachment-input-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.attachment-pick-btn{display:inline-flex;align-items:center;gap:7px;cursor:pointer;}
.attachment-pick-btn svg{width:15px;height:15px;}
.attachment-preview{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--text-secondary);background:var(--page);border:1px solid var(--gridline);border-radius:20px;padding:5px 6px 5px 12px;}
.attachment-preview svg{width:14px;height:14px;flex:0 0 auto;color:var(--text-muted);}
.attachment-preview .icon-btn{padding:3px;color:var(--text-muted);}
.attachment-preview .icon-btn svg{width:13px;height:13px;}

/* A Wall card's attachment - an image thumbnail, or a small downloadable
   file chip for everything else. */
.wall-attachment-img-link{display:inline-block;margin-bottom:8px;}
.wall-attachment-img{display:block;max-width:220px;max-height:160px;border-radius:8px;border:1px solid var(--border);object-fit:cover;}
.wall-attachment-file{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--text-secondary);background:var(--page);border:1px solid var(--gridline);border-radius:8px;padding:6px 10px;margin-bottom:8px;text-decoration:none;}
.wall-attachment-file:hover{border-color:var(--text-muted);}
.wall-attachment-file svg{width:15px;height:15px;flex:0 0 auto;color:var(--text-muted);}
.wall-attachment-name{font-weight:600;color:var(--text-primary);}
.wall-attachment-size{color:var(--text-muted);}

/* Edit-modal fields (SweetAlert2 forms) - every field gets its own small
   bold label above the control, matching the app's own .field/.modal
   pattern, instead of bare stacked inputs with only a placeholder. */
.swal-field{margin:14px 2px 0;text-align:left;}
.swal2-html-container>.swal-field:first-child{margin-top:2px;}
.swal-field-label{display:block;font-size:13px;font-weight:600;color:var(--text-secondary);margin-bottom:6px;}
.swal-current-attachment{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--text-secondary);background:var(--page);border:1px solid var(--gridline);border-radius:8px;padding:7px 10px;text-align:left;}
.swal-current-attachment svg{width:15px;height:15px;flex:0 0 auto;color:var(--text-muted);}
.swal-checkbox-row{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary);margin-top:9px;text-align:left;cursor:pointer;}
.swal-checkbox-row input[type=checkbox]{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;flex:0 0 auto;}
.swal-import-list{max-height:240px;overflow-y:auto;margin-top:6px;border:1px solid var(--gridline);border-radius:8px;padding:4px 10px;}
.import-item-row{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-primary);padding:7px 0;border-bottom:1px solid var(--gridline);text-align:left;cursor:pointer;}
.import-item-row:last-child{border-bottom:none;}
.import-item-row input[type=checkbox]{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;flex:0 0 auto;}
.import-skipped-note{font-size:12px;color:var(--text-muted);padding:7px 0 2px;}
/* The raw OS file-picker control looks out of place against the rest of
   the styled UI, so give it a button that matches the app's own buttons. */
.swal-field input[type=file]{font-family:inherit;font-size:13px;color:var(--text-secondary);width:100%;}
.swal-field input[type=file]::file-selector-button{
  font-family:inherit;font-size:13px;font-weight:600;color:var(--text-secondary);
  background:var(--surface-1);border:1px solid var(--gridline);border-radius:8px;
  padding:7px 13px;margin-right:10px;cursor:pointer;
  transition:background .15s ease,border-color .15s ease,color .15s ease;
}
.swal-field input[type=file]::file-selector-button:hover{background:var(--accent-wash);border-color:var(--accent);color:var(--accent);}

.tl-summary{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px;}

.timeline{display:flex;flex-direction:column;}
.tl-row{display:grid;grid-template-columns:64px 20px 1fr;gap:10px;padding:8px 0;}
.tl-time{font-size:12px;color:var(--text-muted);padding-top:2px;}
.tl-line{display:flex;justify-content:center;position:relative;}
.tl-dot{width:9px;height:9px;border-radius:50%;margin-top:4px;z-index:1;}
.tl-row:not(:last-child) .tl-line::after{content:'';position:absolute;top:14px;bottom:-8px;width:1px;background:var(--gridline);}
.tl-text{font-size:14px;}
.tl-note{font-size:13px;color:var(--text-secondary);margin-top:3px;background:var(--page);border-radius:6px;padding:5px 8px;}

.modal-bg{display:none;position:fixed;inset:0;background:rgba(11,11,11,0.35);align-items:center;justify-content:center;z-index:80;}
.modal-bg.active{display:flex;}
.modal{background:var(--surface-1);border-radius:14px;padding:22px 24px;width:420px;max-width:90vw;box-shadow:0 12px 40px rgba(0,0,0,0.18);max-height:80vh;overflow-y:auto;}
.modal h3{margin:0 0 4px;font-size:17px;}
.modal .sub{font-size:13px;color:var(--text-muted);margin-bottom:16px;}
.field{margin-bottom:14px;}
.field label{display:block;font-size:13px;font-weight:600;color:var(--text-secondary);margin-bottom:6px;}
.field select, .field textarea, .field input{width:100%;border:1px solid var(--gridline);border-radius:8px;padding:8px 10px;font-family:inherit;font-size:14px;background:var(--page);}
.field textarea{resize:none;height:60px;}
.modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:6px;}
.day-note-box{font-size:13px;color:var(--text-secondary);background:var(--page);border:1px solid var(--gridline);border-radius:8px;padding:10px 12px;line-height:1.5;}
.field-error{color:var(--critical);font-size:13px;margin:-8px 0 12px;display:none;}

/* Meetings: attendee picker as horizontal toggle chips instead of a
   vertical checkbox list - reuses the same .chip[data-active] look as the
   range/status chips elsewhere so it reads as one design language. */
.meeting-attendee-chips{display:flex;flex-wrap:wrap;gap:8px;}
.meeting-attendee-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;}
.meeting-attendee-chip .rb-emp-role{color:inherit;opacity:0.6;}

/* Meetings: date-wise history as a collapsed-by-default timeline - each
   row shows date/logged-time/attended-absent counts, and expands on click
   to the attendee names, full notes, and who saved it. Reuses the app's
   existing .daily-chevron rotate + .badge dot components. Extra top margin
   so the timeline reads as visually separate from the range picker above
   it rather than crowding right underneath it. */
#meetingsList, #meetingsEmpty{margin-top:22px;}
.meeting-timeline{display:flex;flex-direction:column;}
.meeting-tl-item{display:flex;gap:12px;}
.meeting-tl-rail{display:flex;flex-direction:column;align-items:center;width:10px;flex-shrink:0;}
.meeting-tl-dot{width:10px;height:10px;border-radius:50%;background:var(--accent);margin-top:14px;flex-shrink:0;}
.meeting-tl-rail-line{flex:1;width:1px;background:var(--gridline);margin-top:4px;}
.meeting-tl-item:last-child .meeting-tl-rail-line{display:none;}
.meeting-tl-content{flex:1;min-width:0;padding-bottom:14px;margin-bottom:14px;border-bottom:1px solid var(--gridline);}
.meeting-tl-item:last-child .meeting-tl-content{padding-bottom:0;margin-bottom:0;border-bottom:none;}
.meeting-tl-head{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;cursor:pointer;padding:6px 0;}
.meeting-tl-head-main{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;}
.meeting-tl-date{font-size:14px;font-weight:600;}
.meeting-tl-time{font-size:12px;color:var(--text-muted);}
.meeting-tl-head-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.meeting-tl-body{display:none;margin-top:10px;font-size:13px;color:var(--text-secondary);line-height:1.5;}
.meeting-tl-item.expanded .meeting-tl-body{display:block;}
.meeting-tl-item.expanded .daily-chevron{transform:rotate(180deg);}
.meeting-tl-body-row{margin-bottom:6px;}
.meeting-tl-body-row b{color:var(--text-primary);}
.meeting-tl-savedby{margin-top:8px;font-size:12px;color:var(--text-muted);}

.report-preview{font-size:14px;line-height:1.55;color:var(--text-secondary);}
.report-preview h4{color:var(--text-primary);font-size:14px;margin:14px 0 6px;}
.report-preview ul{margin:0;padding-left:18px;}
.report-preview .rp-head{font-size:13px;color:var(--text-muted);margin-bottom:10px;}

::-webkit-scrollbar{width:8px;}
::-webkit-scrollbar-thumb{background:var(--gridline);border-radius:8px;}

/* ===== SweetAlert2 dialogs — the library's defaults are oversized/large-
   type for this app's compact UI, so they're pulled down to match the
   size of our own .modal / .btn / .field styling. Every form dialog wraps
   its controls in .swal-field (see above) for a consistent label-above-
   control layout, a proper divider before the action buttons, and select/
   file controls that match the rest of the app instead of looking like
   raw browser defaults. ===== */
/* :not(.swal2-toast) on every rule below is load-bearing, not decoration -
   a toast (Swal.fire({toast:true, ...}), used for "3 tasks imported",
   "Leave request submitted", swalToast(), etc.) is ALSO a .swal2-popup
   under the hood, so an unscoped .swal2-icon/.swal2-title/.swal2-actions
   rule here used to hijack every toast's own compact built-in sizing too -
   most visibly blowing its icon up to a 2.6em dialog-sized icon inside
   what's supposed to be a small corner toast. Scoping these to real
   dialogs only and giving toasts their own small rule below (mirroring
   .app-toast's look) fixes every toast in the app at once, since they all
   share this same CSS. */
.swal2-popup:not(.swal2-toast){
  font-family:inherit !important;
  border-radius:16px !important;
  padding:24px 24px 22px !important;
  box-shadow:0 20px 60px rgba(11,11,11,0.22) !important;
  border:1px solid var(--border) !important;
}
.swal2-popup:not(.swal2-toast) .swal2-title{font-size:18px !important;font-weight:700 !important;padding:2px 0 4px !important;margin:0 0 4px !important;color:var(--text-primary) !important;}
.swal2-popup:not(.swal2-toast) .swal2-html-container{font-size:13px !important;color:var(--text-secondary) !important;margin:8px 2px 2px !important;line-height:1.5 !important;text-align:left !important;}
.swal2-popup:not(.swal2-toast) .swal2-icon{width:2.6em !important;height:2.6em !important;margin:2px auto 10px !important;}
.swal2-popup:not(.swal2-toast) .swal2-icon .swal2-icon-content{font-size:1.5em !important;}
.swal2-popup:not(.swal2-toast) .swal2-actions{margin:20px 0 0 !important;padding-top:16px !important;gap:8px !important;border-top:1px solid var(--gridline) !important;width:100% !important;}

/* Small top-right toasts - left to SweetAlert2's own compact toast layout
   (grid-positioned icon + single-line title, no vertical stacking), just
   re-skinned to match this app's cards (.app-toast uses the same radius/
   shadow/border) instead of the library's plain white-box default. */
.swal2-toast{
  font-family:inherit !important;
  border-radius:12px !important;
  box-shadow:0 14px 34px rgba(11,11,11,0.16) !important;
  border:1px solid var(--border) !important;
}
.swal2-toast .swal2-title{font-size:13px !important;font-weight:600 !important;color:var(--text-primary) !important;}
.swal2-toast .swal2-timer-progress-bar{background:var(--accent) !important;}
.swal2-styled{
  font-size:14px !important;font-weight:600 !important;font-family:inherit !important;
  padding:9px 17px !important;border-radius:9px !important;box-shadow:none !important;border:none !important;
  transition:opacity .15s ease !important;
}
.swal2-styled:hover{opacity:0.88 !important;}
.swal2-styled:focus{box-shadow:0 0 0 2px var(--accent-wash) !important;}
.swal2-confirm{background:var(--accent) !important;}
.swal2-confirm.swal2-default-outline{box-shadow:none !important;}
.swal2-deny{background:var(--critical) !important;}
.swal2-cancel{background:var(--page) !important;color:var(--text-secondary) !important;border:1px solid var(--gridline) !important;}
.swal2-cancel:hover{background:var(--gridline) !important;opacity:1 !important;}
.swal2-input, .swal2-textarea, .swal2-select{
  font-family:inherit !important;font-size:14px !important;border-radius:9px !important;
  border:1px solid var(--gridline) !important;box-shadow:none !important;
  padding:9px 11px !important;margin:0 !important;background:var(--page) !important;height:auto !important;
  color:var(--text-primary) !important;width:100% !important;
}
/* Match the app's own custom-arrow select (see .team-role-select) instead
   of the plain oversized native control SweetAlert2 ships by default. */
.swal2-select{
  appearance:none !important;-webkit-appearance:none !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23898781' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
  background-repeat:no-repeat !important;background-position:right 10px center !important;background-size:14px 14px !important;
  padding-right:30px !important;cursor:pointer !important;
}
.swal2-textarea{min-height:70px !important;resize:vertical !important;}
.swal2-input:hover, .swal2-textarea:hover, .swal2-select:hover{border-color:var(--text-muted) !important;}
.swal2-input:focus, .swal2-textarea:focus, .swal2-select:focus{border-color:var(--accent) !important;box-shadow:0 0 0 3px var(--accent-wash) !important;outline:none !important;}
.swal2-validation-message{font-size:13px !important;border-radius:8px !important;background:var(--critical-wash) !important;color:var(--critical) !important;margin-top:10px !important;}
/* Swal2's built-in `input:'text'` shorthand (used by the simple single-
   field prompts) renders its own label above the input - match it to the
   same .swal-field-label look instead of the library's centered default. */
.swal2-input-label{justify-content:flex-start !important;font-size:13px !important;font-weight:600 !important;color:var(--text-secondary) !important;margin:2px 2px 6px !important;width:100% !important;}

/* New-message toast (see showChatMessageToast()) - a slim notification
   card instead of the blanket .swal2-popup's big-modal padding/icon: an
   accent rail down the left edge, the sender's avatar, name, and a
   2-line-clamped preview. Selector specificity (.swal2-popup.chat-toast-
   popup) wins over the plain .swal2-popup rule above without needing
   !important on every property. */
.swal2-popup.chat-toast-popup{
  padding:14px 16px 14px 14px !important;
  border-radius:12px !important;
  border-left:4px solid var(--accent) !important;
  max-width:360px !important;
}
.chat-toast{display:flex;align-items:flex-start;gap:10px;text-align:left;}
.chat-toast-avatar{flex-shrink:0;}
.chat-toast-body{min-width:0;flex:1;padding-top:1px;}
.chat-toast-name{font-size:14px;font-weight:700;color:var(--text-primary);margin-bottom:2px;}
.chat-toast-text{font-size:13px;color:var(--text-secondary);line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.chat-toast-popup .swal2-timer-progress-bar{background:var(--accent) !important;}
.chat-toast-popup .swal2-close{color:var(--text-muted) !important;font-size:21px !important;top:6px !important;right:6px !important;}
.chat-toast-popup .swal2-close:hover{color:var(--text-primary) !important;}

/* ===== Team chat: two-pane conversation list + message thread. First
   proper two-pane UI in this app, so most of these classes are new; where
   an equivalent already existed (dropdown menu, attachment chip, member
   picker chips) it's reused directly rather than duplicated.

   The Chat view also goes full-bleed: switchView() adds "chat-fullbleed"
   to <body> only while Chat is open, which strips the padded/max-width
   ".shell" card everything else uses so this two-pane layout can fill the
   whole content area edge-to-edge (the top app nav bar stays put). ===== */
.chat-shell{display:flex;flex:1;min-height:0;border:1px solid var(--border);border-radius:14px;background:var(--surface-1);overflow:hidden;}

body.chat-fullbleed .main-col{overflow:hidden;}
body.chat-fullbleed .shell{max-width:none;padding:0;height:100%;display:flex;flex-direction:column;}
body.chat-fullbleed .page-heading,
body.chat-fullbleed .env-banner{display:none;}
body.chat-fullbleed #appViews{flex:1;min-height:0;display:flex;flex-direction:column;}
/* #view-chat needs to actually STRETCH inside #appViews (a flex column),
   not just switch to display:flex - without flex:1 + min-height:0 here it
   only grows to fit its own content, so .chat-shell's two panes fell back
   to their min-height (520px - about half a typical screen) instead of
   filling the real available height. */
#view-chat.active{display:flex;flex-direction:column;flex:1;min-height:0;}
body.chat-fullbleed .chat-shell{flex:1;border-radius:0;border-left:0;border-right:0;border-bottom:0;}

.chat-sidebar{width:300px;flex:0 0 300px;border-right:1px solid var(--border);display:flex;flex-direction:column;min-width:0;}
.chat-sidebar-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:16px 16px 8px;flex-shrink:0;}

.chat-tabs{display:flex;gap:4px;padding:4px 16px 12px;border-bottom:1px solid var(--gridline);flex-shrink:0;}
.chat-tab{position:relative;flex:1;border:none;background:transparent;color:var(--text-secondary);font-size:13px;font-weight:600;padding:7px 8px;border-radius:8px;cursor:pointer;transition:background .15s ease,color .15s ease;}
.chat-tab:hover{background:var(--page);}
.chat-tab.active{background:var(--accent-wash);color:var(--accent);}
.chat-tab-badge{position:absolute;top:1px;right:4px;background:var(--critical);color:#fff;font-size:10px;font-weight:700;min-width:15px;height:15px;line-height:15px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;padding:0 4px;}

.chat-tab-panel{flex:1;min-height:0;display:flex;flex-direction:column;}
.chat-groups-toolbar{padding:10px 12px 0;flex-shrink:0;}

.chat-people-list,
.chat-conv-list{flex:1;overflow-y:auto;padding:8px;}
.chat-conv-item,
.chat-person-item{display:flex;align-items:center;gap:10px;padding:10px 8px;border-radius:10px;cursor:pointer;}
.chat-conv-item:hover,
.chat-person-item:hover{background:var(--page);}
.chat-conv-item.active,
.chat-person-item.active{background:var(--accent-wash);}
.chat-conv-body{min-width:0;flex:1;}
.chat-conv-name{font-size:14px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.chat-conv-preview{font-size:12px;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px;}
.chat-conv-badge{flex-shrink:0;background:var(--accent);color:#fff;font-size:11px;font-weight:700;border-radius:9px;min-width:18px;height:18px;padding:0 5px;display:flex;align-items:center;justify-content:center;}
/* Unread emphasis on a conversation/person row itself (WhatsApp-style bold
   name + darker preview text), on top of the numeric badge above - makes an
   unread group or DM stand out in the list even before you spot the count. */
.chat-conv-item.has-unread .chat-conv-name,
.chat-person-item.has-unread .chat-conv-name{font-weight:800;}
.chat-conv-item.has-unread .chat-conv-preview,
.chat-person-item.has-unread .chat-conv-preview{color:var(--text-primary);font-weight:600;}

/* Presence dot, anchored to the bottom-right of a person's avatar - gray
   (offline) by default, green + a subtle ring when they've made a request
   within CHAT_ONLINE_WINDOW_SECONDS (see isPersonOnline() in app.js). */
.chat-person-avatar-wrap{position:relative;flex-shrink:0;}
.presence-dot{position:absolute;right:-1px;bottom:-1px;width:9px;height:9px;border-radius:50%;background:var(--text-muted);border:2px solid var(--surface-1);}
.presence-dot.online{background:var(--good-text);}
.presence-dot.offline{background:var(--critical);}

.chat-thread{flex:1;display:flex;flex-direction:column;min-width:0;}
.chat-thread-empty{flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-muted);font-size:14px;text-align:center;padding:20px;}
.chat-thread-active{flex:1;display:flex;flex-direction:column;min-height:0;}
.chat-thread-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:14px 18px;border-bottom:1px solid var(--gridline);flex-shrink:0;}
#chatThreadActions{display:flex;align-items:center;gap:4px;flex-shrink:0;}
.chat-thread-title{font-size:15px;font-weight:700;}
.chat-thread-sub{font-size:12px;color:var(--text-muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:420px;}

.chat-messages{flex:1;overflow-y:auto;padding:16px 18px;display:flex;flex-direction:column;}
.chat-msg-row{display:flex;flex-direction:column;max-width:70%;margin-bottom:10px;}
.chat-msg-row.mine{align-self:flex-end;align-items:flex-end;}
.chat-msg-row.theirs{align-self:flex-start;align-items:flex-start;}
.chat-msg-sender{font-size:12px;font-weight:600;color:var(--text-muted);margin-bottom:3px;padding:0 3px;}
.chat-bubble{padding:8px 12px;border-radius:14px;font-size:14px;line-height:1.45;white-space:pre-wrap;word-break:break-word;}
.chat-msg-row.mine .chat-bubble{background:var(--accent);color:#fff;border-bottom-right-radius:4px;}
.chat-msg-row.theirs .chat-bubble{background:var(--page);color:var(--text-primary);border:1px solid var(--gridline);border-bottom-left-radius:4px;}
.chat-msg-row.mine .chat-bubble .wall-attachment-file,
.chat-msg-row.mine .chat-bubble .wall-attachment-img{margin-top:6px;}
.chat-msg-row.deleted .chat-bubble{font-style:italic;color:var(--text-muted);background:transparent;border:1px dashed var(--gridline);}
.chat-msg-meta{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-muted);margin-top:3px;padding:0 3px;}
.chat-ticks{display:inline-flex;align-items:center;color:var(--text-muted);}
.chat-ticks svg{width:14px;height:11px;}
.chat-ticks.read{color:#34b7f1;}
.chat-msg-actions{display:none;gap:1px;}
.chat-msg-row:hover .chat-msg-actions{display:inline-flex;}
.chat-msg-actions .icon-btn{padding:3px;}
.chat-msg-actions svg{width:13px;height:13px;}

/* A shared link inside a message (see linkifyChatText()) - underlined and
   in the accent color so it reads as tappable against either bubble
   color; word-break so a long unbroken URL can't blow out the bubble
   width (.chat-bubble already word-breaks its own plain text the same way). */
.chat-link{color:inherit;text-decoration:underline;word-break:break-all;}
.chat-msg-row.theirs .chat-link{color:var(--accent);}

/* Poll/event messages (see chatPollHtml()/chatEventHtml()) render as a
   neutral card regardless of who sent them or which side of the thread
   they're on - the vote bars/RSVP buttons need to stay legible either way,
   which a solid accent-colored "mine" bubble would fight against. */
.chat-bubble.chat-bubble-rich{background:var(--surface-1) !important;color:var(--text-primary) !important;border:1px solid var(--gridline);border-radius:12px !important;padding:10px 12px;min-width:230px;}

.chat-poll-question,
.chat-event-title{display:flex;align-items:center;gap:6px;font-weight:700;font-size:14px;margin-bottom:8px;}
.chat-poll-question svg,
.chat-event-title svg{width:16px;height:16px;flex:0 0 auto;color:var(--accent);}

.chat-poll-option{position:relative;border:1px solid var(--gridline);border-radius:8px;margin-bottom:6px;cursor:pointer;overflow:hidden;background:var(--page);transition:border-color .15s ease;}
.chat-poll-option:last-child{margin-bottom:0;}
.chat-poll-option:hover{border-color:var(--accent);}
.chat-poll-option.mine{border-color:var(--accent);}
.chat-poll-option-fill{position:absolute;left:0;top:0;bottom:0;background:var(--accent-wash);transition:width .2s ease;}
.chat-poll-option-inner{position:relative;display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 10px;font-size:13px;}
.chat-poll-option-text{font-weight:600;color:var(--text-primary);}
.chat-poll-option-pct{font-size:12px;color:var(--text-muted);flex-shrink:0;white-space:nowrap;}
/* Who voted for this option (see chatPollHtml()) - sits below the
   text/count row, inside the same relatively-positioned inner stack so it
   also renders above the vote-share fill bar instead of under it. */
.chat-poll-option-voters{position:relative;padding:0 10px 7px;margin-top:-3px;font-size:12px;color:var(--text-muted);}
.chat-poll-meta{font-size:12px;color:var(--text-muted);margin-top:6px;}
.chat-poll-results-link{color:var(--accent);cursor:pointer;text-decoration:underline;}

/* "See full results" modal (openChatPollResults()) - plain left-aligned
   rows instead of SweetAlert2's centered default, since this is a list to
   scan, not a short confirmation message. */
.poll-results-list{text-align:left;}
.poll-result-row{padding:8px 0;border-bottom:1px solid var(--gridline);}
.poll-result-row:last-child{border-bottom:none;}
.poll-result-option{display:flex;align-items:center;justify-content:space-between;gap:10px;font-weight:600;font-size:14px;color:var(--text-primary);}
.poll-result-count{font-weight:600;font-size:12px;color:var(--text-muted);flex-shrink:0;}
.poll-result-voters{font-size:13px;color:var(--text-secondary);margin-top:3px;}

.chat-event-when{font-size:13px;color:var(--text-secondary);}
.chat-event-location{font-size:13px;color:var(--text-muted);margin-top:2px;}
.chat-event-rsvps{display:flex;gap:6px;margin-top:10px;flex-wrap:wrap;}
.chat-event-rsvp-btn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--gridline);background:var(--page);border-radius:20px;padding:5px 10px;font-size:13px;font-weight:600;cursor:pointer;color:var(--text-secondary);}
.chat-event-rsvp-btn:hover{border-color:var(--accent);}
.chat-event-rsvp-btn.active{background:var(--accent-wash);border-color:var(--accent);color:var(--accent);}
.chat-event-rsvp-count{font-weight:700;}

/* Poll-creation modal only (see openChatPollModal()) - one row per option,
   an input plus a remove button; .swal2-input already forces margin:0, so
   the row itself carries the vertical gap between options. */
.chat-poll-field-row{display:flex;align-items:center;gap:6px;margin-bottom:6px;}
.chat-poll-field-row .swal2-input{flex:1;}

/* A brief highlight when jumping to a message via its quoted reply. */
@keyframes chatFlash{0%{box-shadow:0 0 0 3px var(--accent-wash);}100%{box-shadow:0 0 0 0 transparent;}}
.chat-msg-row.flash .chat-bubble{animation:chatFlash 1.2s ease;}

/* Quoted "replying to" strip shown inside a bubble - a slightly different
   tint on a mine (accent-colored) bubble vs a theirs (page-colored) one so
   it reads as an inset rather than a mismatched box. */
.chat-msg-reply-quote{display:block;background:rgba(11,11,11,0.06);border-left:3px solid var(--accent);border-radius:6px;padding:4px 8px;margin-bottom:5px;cursor:pointer;}
.chat-msg-row.mine .chat-bubble .chat-msg-reply-quote{background:rgba(255,255,255,0.18);border-left-color:rgba(255,255,255,0.85);}
.chat-msg-reply-quote-name{display:block;font-size:12px;font-weight:700;color:var(--accent);}
.chat-msg-row.mine .chat-bubble .chat-msg-reply-quote-name{color:#fff;}
.chat-msg-reply-quote-text{display:block;font-size:13px;opacity:0.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px;}

/* Reaction pills under a bubble - "mine" (you've reacted with this emoji)
   gets an accent outline so it doubles as a visual toggle state. */
.chat-reactions-row{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px;}
.chat-reaction-pill{display:inline-flex;align-items:center;gap:3px;font-size:13px;line-height:1;background:var(--surface-1);border:1px solid var(--gridline);border-radius:11px;padding:3px 7px;cursor:pointer;color:var(--text-secondary);}
.chat-reaction-pill:hover{border-color:var(--text-muted);}
.chat-reaction-pill.mine{background:var(--accent-wash);border-color:var(--accent);color:var(--accent);font-weight:600;}

/* Quick-reaction and full-emoji popovers for reacting to a message are
   appended straight to <body> (see openChatQuickReactions() /
   openChatFullEmojiReactionPicker() in app.js) so they float above
   everything regardless of which scroll container the message sits in -
   position:fixed with a viewport rect computed at open time. */
.chat-quick-reactions{position:fixed;display:flex;align-items:center;gap:2px;background:var(--surface-1);border:1px solid var(--border);border-radius:22px;padding:4px 6px;box-shadow:0 12px 32px rgba(11,11,11,0.2);z-index:60;}
.chat-quick-reactions button{border:none;background:transparent;font-size:19px;line-height:1;padding:4px 5px;border-radius:50%;cursor:pointer;}
.chat-quick-reactions button:hover{background:var(--page);}
.chat-emoji-picker-floating{position:fixed;z-index:60;box-shadow:0 16px 40px rgba(11,11,11,0.28);}

.chat-composer{position:relative;border-top:1px solid var(--gridline);padding:10px 16px 12px;flex-shrink:0;}
.chat-attach-preview{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary);background:var(--page);border:1px solid var(--gridline);border-radius:8px;padding:6px 10px;margin-bottom:8px;}
/* The leading file icon here (and in Wall's equivalent .attachment-preview
   chip) is a bare <svg> with no width/height attributes - without an
   explicit size it fell back to the browser's intrinsic default for an
   unsized SVG (300x150), which is why an attached file looked huge before
   it was even sent. Direct-child selector so this doesn't also resize the
   "remove" icon-btn's svg nested one level deeper (that one's already
   sized by ".icon-btn svg"). */
.chat-attach-preview > svg,
.attachment-preview > svg{width:15px;height:15px;flex:0 0 auto;color:var(--text-muted);}

/* "Replying to" bar above the composer, WhatsApp-style: accent rail on the
   left, sender + snippet, an X to back out. */
.chat-reply-preview{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;background:var(--page);border-left:3px solid var(--accent);border-radius:8px;padding:7px 10px;margin-bottom:8px;}
.chat-reply-preview-body{min-width:0;flex:1;}
.chat-reply-preview-name{font-size:12px;font-weight:700;color:var(--accent);}
.chat-reply-preview-text{font-size:13px;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px;}
.chat-reply-preview .icon-btn{flex-shrink:0;}

/* The composer itself: a single rounded pill (input field + emoji +
   attach live inside it) with a separate circular accent send button to
   its right - the familiar WhatsApp/most-messengers layout, instead of a
   plain bordered textarea with a text "Send" button. */
.chat-composer-row{display:flex;align-items:flex-end;gap:8px;}
.chat-composer-pill{flex:1;display:flex;align-items:flex-end;gap:2px;background:var(--page);border:1px solid var(--gridline);border-radius:22px;padding:5px 6px 5px 8px;min-width:0;}
.chat-composer-pill:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-wash);}
.chat-composer-pill textarea{flex:1;resize:none;border:none;background:transparent;padding:6px 4px;font-family:inherit;font-size:14px;max-height:120px;color:var(--text-primary);min-width:0;}
.chat-composer-pill textarea:focus{outline:none;}
.chat-emoji-wrap{position:relative;flex:0 0 auto;}
.chat-send-btn{flex:0 0 auto;width:36px;height:36px;border-radius:50%;border:none;background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:opacity .15s ease,transform .1s ease;}
.chat-send-btn:hover{opacity:0.88;}
.chat-send-btn:active{transform:scale(0.94);}
.chat-send-btn svg{width:16px;height:16px;}

/* @mention autocomplete: docked directly above the composer pill (same
   "float above, computed from a rect" family as the emoji/reaction
   popovers, but simpler - it only ever needs to track .chat-composer's own
   position:relative box, not an arbitrary message row's rect). */
.chat-mention-picker{position:absolute;left:16px;right:16px;bottom:100%;margin-bottom:6px;background:var(--surface-1);border:1px solid var(--border);border-radius:10px;box-shadow:0 10px 28px rgba(11,11,11,0.16);max-height:190px;overflow-y:auto;z-index:25;}
.chat-mention-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:14px;color:var(--text-primary);}
.chat-mention-item .avatar{flex-shrink:0;}
.chat-mention-item:hover,
.chat-mention-item.active{background:var(--accent-wash);}
.chat-mention-empty{padding:10px 12px;font-size:13px;color:var(--text-muted);}

/* An "@Name" mention rendered inside a message bubble - a small accent chip,
   same idea as Slack/WhatsApp's mention highlighting. This default (accent
   text on an accent wash) reads fine on "theirs" bubbles (a light/white
   background), but a "mine" bubble's background IS var(--accent) - same
   color as this text - which made a mention I sent unreadable against my
   own bubble. The .mine override below swaps it for a translucent white
   chip with solid white text instead, so it stays legible against either
   bubble color. */
.chat-mention{background:var(--accent-wash);color:var(--accent);font-weight:700;padding:0 3px;border-radius:4px;}
.chat-msg-row.mine .chat-bubble .chat-mention{background:rgba(255,255,255,0.24);color:#fff;}
/* A message that mentions ME (never my own messages) gets a tinted bubble
   so it stands out in the scrollback at a glance, not just inline text. */
.chat-msg-row.mentions-me .chat-bubble{background:var(--accent-wash);border-color:var(--accent);}

/* Emoji picker docked above the composer's smiley button - a plain unicode
   grid (no external picker library/CDN dependency), built once on first
   open and just shown/hidden after that (see toggleChatEmojiPicker()). */
.chat-emoji-picker{position:absolute;bottom:44px;left:0;width:264px;max-height:220px;overflow-y:auto;background:var(--surface-1);border:1px solid var(--border);border-radius:12px;box-shadow:0 14px 34px rgba(11,11,11,0.2);padding:8px;grid-template-columns:repeat(7,1fr);gap:2px;z-index:30;}
.chat-emoji-picker button{border:none;background:transparent;font-size:20px;line-height:1;padding:5px;border-radius:7px;cursor:pointer;}
.chat-emoji-picker button:hover{background:var(--page);}

/* Group-member picker chips (new group / manage group modals) - plain
   .chip[data-active] buttons in a wrapping row. */
.chip-flow{display:flex;flex-wrap:wrap;gap:8px;}

/* ===================== Feed ===================== */
/* Reads like a single centered timeline (Facebook-style), not a full-bleed
   page - constrained to 7 of the shell's 12 "columns" (1200px * 7/12) and
   centered, same proportion a social feed column uses instead of
   stretching edge-to-edge with the rest of the app. The shared page
   title/sub (#headerTitle/#headerSub, same element for every view) is
   otherwise full shell width, so it gets the identical max-width only
   while Feed is the active view (see the "feed-active" body class toggled
   in switchView()) so the heading lines up with the content below it. */
#view-feed{max-width:700px;margin:0 auto;width:100%;}
body.feed-active .page-heading{max-width:700px;margin-left:auto;margin-right:auto;}
.feed-composer-textarea{width:100%;min-height:64px;resize:vertical;border:1px solid var(--gridline);border-radius:10px;padding:10px 12px;font-family:inherit;font-size:14px;background:var(--page);margin-bottom:10px;}
.feed-attach-chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px;}
.feed-attach-chips:empty{margin-bottom:0;}
.feed-composer-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}

.feed-post{padding:18px 20px;}
.feed-post-header{display:flex;align-items:center;gap:10px;margin-bottom:10px;}
.feed-post-headtext{flex:1;min-width:0;}
.feed-post-author{font-size:14px;font-weight:600;}
.feed-post-time{font-size:12px;color:var(--text-muted);}
.feed-post-actions{display:flex;gap:2px;flex-shrink:0;}
.feed-post-text{font-size:14.5px;line-height:1.5;white-space:pre-wrap;word-break:break-word;margin-bottom:10px;}

.feed-attachments-grid{display:grid;gap:4px;margin-bottom:10px;border-radius:10px;overflow:hidden;}
.feed-attachments-grid.feed-attachments-1{grid-template-columns:1fr;}
.feed-attachments-grid.feed-attachments-2,
.feed-attachments-grid.feed-attachments-3,
.feed-attachments-grid.feed-attachments-4{grid-template-columns:1fr 1fr;}
.feed-attachment-img-link{display:block;line-height:0;}
.feed-attachment-img{width:100%;height:100%;max-height:420px;object-fit:cover;display:block;background:var(--page);}
.feed-attachments-grid.feed-attachments-1 .feed-attachment-img{max-height:520px;}
.feed-attachment-video{width:100%;max-height:420px;background:#000;display:block;}

.feed-post-footer{display:flex;gap:6px;border-top:1px solid var(--gridline);border-bottom:1px solid var(--gridline);padding:4px 0;margin-bottom:8px;}
.feed-footer-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:7px;background:transparent;border:none;border-radius:8px;padding:8px;font-family:inherit;font-size:13px;font-weight:600;color:var(--text-secondary);cursor:pointer;}
.feed-footer-btn:hover{background:var(--page);color:var(--text-primary);}
.feed-footer-btn svg{width:16px;height:16px;}

.feed-comments{display:flex;flex-direction:column;gap:8px;margin-bottom:8px;}
.feed-comment-row{display:flex;align-items:flex-start;gap:8px;}
.feed-comment-body{flex:1;min-width:0;}
.feed-comment-bubble{display:inline-block;background:var(--page);border-radius:14px;padding:7px 12px;font-size:13.5px;line-height:1.4;word-break:break-word;}
.feed-comment-author{font-weight:600;margin-right:4px;}
.feed-comment-meta{font-size:11.5px;color:var(--text-muted);margin-top:2px;padding:0 4px;}
.feed-inline-link{background:none;border:none;padding:0;font:inherit;font-size:11.5px;font-weight:600;color:var(--text-muted);cursor:pointer;}
.feed-inline-link:hover{color:var(--accent);text-decoration:underline;}

.feed-comment-composer{display:flex;gap:8px;align-items:center;}
.feed-comment-composer input{flex:1;border:1px solid var(--gridline);border-radius:20px;padding:8px 14px;font-family:inherit;font-size:13.5px;background:var(--page);}
