
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
/* APP-ONLY tokens. Color/type/spacing/motion PRIMITIVES + semantics live in
   /tokens.<hash>.css (loaded BEFORE this file — see index.html) and cascade in via
   compat aliases (--purple, --coral, --surf-*, --text-*, --dur-*, …). Change brand
   colors THERE, not here. Documented at admin.henshu.app → Design rules. */
:root{
  --off-white:#f3f3f4;--light:#f5f4f0;
  --border:rgba(0,0,0,0.07);
  --gold:#e7ce3a;--cream:#e6ded6;--pink:#de3f7f;
  --lavender:#c7abc4;--teal:#3a9ea5;--peach:#df8a83;--orange:#db8648;
  --serif:var(--font-serif);
  --sans:var(--font-sans);
  --mono:var(--font-mono);
  --display:var(--font-display);
  --bg-board:#18181b;
  --bg-inset:var(--surface-inset);/* the INSET role — kept as an alias so its existing users converge on the scale above rather than needing 170 edits */
  --skel-hi:rgba(255,255,255,.13);/* skeleton shimmer highlight; light block flips it */
  --chip-h:22px;/* one height for every @mention / link chip */
  /* ── THE PILL CONTRACT ─────────────────────────────────────────────────────────
     Every pill inside a task reads these and nothing else. They were each carrying
     their own numbers — an @mention chip at 22px/13px/7px radius, a person pill at
     24px/11px/999px, a property pill at 10px — so three things that mean "a small
     labelled token" looked like three different components sitting in one column.
     The @mention chip won because it is the one that appears in the most places.
     Change a value here and every pill in every task follows; a NEW pill only has to
     read the tokens to be correct on the day it ships. --pill-tint is how much of a
     pill's own colour becomes its background, which is the one thing that varies. */
  --pill-h:var(--chip-h,22px);
  --pill-radius:7px;
  --pill-font-size:13px;
  --pill-font-weight:600;
  --pill-pad-x:9px;
  --pill-pad-lead:7px;   /* the side that carries an avatar or glyph sits tighter */
  --pill-gap:6px;
  --pill-ink:var(--cream);
  --pill-tint:18%;
  --pill-remove:14px;
  --sidebar-w:250px;--topbar-h:52px;
  --r-card:14px;--r-card-sm:12px;--r-modal:20px;--r-pill:11px;--r-pill-lg:14px;--r-round:50%;
  --glass-bg:rgba(22,22,27,0.72);--glass-border:rgba(255,255,255,0.12);--glass-blur:blur(26px) saturate(180%);--glass-shadow:0 24px 60px rgba(0,0,0,0.55),inset 0 1px 0 rgba(255,255,255,0.1);
  /* Liquid glass tokens moved to tokens.css — it is the ONE parent that this app,
     the admin console (Design Rules) and the landing page all load, so a tweak
     there restyles every surface. Do not redefine --lg-* here. */
  /* Tab slider — the single source of truth for every sliding pill/thumb in the
     app (project view tabs, task tabs, Home segment, sidebar, mobile bars).
     Documented in Design Rules -> Tabs. Change it here and every bar follows. */
  --tab-slide-dur:300ms;
  --tab-slide-ease:cubic-bezier(.22,1,.36,1);
  --ease-std:cubic-bezier(.22,1,.36,1);--ease-spring:cubic-bezier(.34,1.4,.5,1);--ease-overshoot:cubic-bezier(.34,1.56,.64,1);--ease-exit:cubic-bezier(.4,0,1,1);--ease-enter:cubic-bezier(0,0,.2,1);
  /* Sauce Media signature rainbow color bar (restored from Henshu) */
  --rainbow:linear-gradient(90deg,#e7ce3a 0%,#e7ce3a 12%,#e6ded6 12%,#e6ded6 22%,#de3f7f 22%,#de3f7f 34%,#207baa 34%,#207baa 46%,#73ac83 46%,#73ac83 58%,#c7abc4 58%,#c7abc4 70%,#df8a83 70%,#df8a83 78%,var(--coral) 78%,var(--coral) 90%,#3a9ea5 90%,#3a9ea5 100%);
}
html{scroll-behavior:smooth;touch-action:manipulation;background:var(--bg-board)}
body{background:var(--bg-board);color:var(--off-white);font-family:var(--sans);-webkit-font-smoothing:antialiased;min-height:100vh;overscroll-behavior:none}
::-webkit-scrollbar{width:5px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:999px}::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.22)}

/* RAINBOW STRIPS */
.strip-t,.strip-b{position:fixed;left:0;right:0;height:4px;z-index:10000;transition:background .4s ease}
.strip-t{top:0;background:var(--rainbow)}.strip-b{bottom:0;background:var(--rainbow)}
body:not([data-mobile-mode="app"]) .strip-t,body:not([data-mobile-mode="app"]) .strip-b{display:none}/* #45 — remove top/bottom rainbow color bars on desktop */
/* #9 — remove the top/bottom rainbow frame on mobile entirely (cleaner edge-to-edge). */
body[data-mobile-mode="app"] .strip-t,body[data-mobile-mode="app"] .strip-b{display:none}
.board-bottom-fade{
  position:fixed;left:var(--sidebar-w);right:0;bottom:0;height:210px;
  pointer-events:none;z-index:45;opacity:0;transition:opacity .18s linear;
  background:linear-gradient(to bottom,rgba(10,10,9,0) 0%,rgba(10,10,9,.72) 68%,rgba(10,10,9,1) 100%);
}
.board-bottom-fade.active{opacity:1}

/* ==================== LOGIN GATE ==================== */
.login-gate{
  position:fixed;inset:0;z-index:99999;background:var(--dark);
  display:flex;align-items:center;justify-content:center;flex-direction:column;
  transition:opacity .4s ease,visibility .4s ease;
}
.login-gate.hidden{opacity:0;visibility:hidden;pointer-events:none}
.login-box{text-align:center;max-width:340px;width:100%;padding:0 24px}
.login-title{font-family:var(--sans);font-size:46px;font-weight:800;font-style:italic;letter-spacing:-.035em;color:var(--off-white);margin-bottom:8px}
.login-sub{font-size:13px;color:var(--muted);margin-bottom:32px;letter-spacing:.02em}
.login-input{
  width:100%;padding:14px 20px;border-radius:10px;border:1.5px solid var(--border-d);
  background:var(--bg-inset);color:var(--text-1);font-family:var(--sans);font-size:14px;
  outline:none;transition:border-color .2s;
}
.login-input::placeholder{color:var(--muted)}
.login-input:focus{border-color:var(--coral)}
.login-input.error{border-color:var(--color-error);animation:shake .4s ease}
@keyframes shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}
@keyframes pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.1);opacity:.8}}
.login-btn{
  width:100%;padding:14px;margin-top:12px;border-radius:10px;border:none;
  background:var(--purple);color:#fff;font-family:var(--sans);font-size:14px;font-weight:700;
  cursor:pointer;transition:background .2s,transform .1s;
}
.login-btn:hover{background:#7a61c8;color:#fff}
.login-btn:active{transform:scale(.98)}
.login-error{font-size:12px;color:var(--danger-text);margin-top:12px;min-height:18px}
.login-strip{display:none}
.login-google-wrap{margin-top:24px;display:flex;justify-content:center}
.login-oauth-divider{
  margin:14px 0 10px;display:none;align-items:center;gap:10px;
  font-size:10px;color:var(--muted);letter-spacing:1px;text-transform:uppercase;
}
.login-oauth-divider::before,.login-oauth-divider::after{
  content:'';flex:1;height:1px;background:var(--border-d);
}
.login-oauth-buttons{display:none;flex-direction:column;gap:10px}
.login-oauth-btn{
  width:100%;padding:11px 14px;border-radius:9px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.05);color:var(--off-white);font-family:var(--sans);
  font-size:13px;font-weight:600;cursor:pointer;transition:all .15s ease;
}
.login-oauth-btn:hover{border-color:rgba(255,255,255,.2);background:var(--state-hover)}
.login-oauth-btn.discord:hover{border-color:rgba(88,101,242,.5);color:#cfd5ff}
.login-oauth-btn.slack:hover{border-color:rgba(74,21,75,.6);color:#e7cde7}
.login-oauth-btn:disabled{opacity:.6;cursor:not-allowed}
.login-provider-hint{font-size:11px;color:var(--muted);margin-top:10px;min-height:14px}
.login-not-invited{color:var(--coral);font-size:12px;margin-top:12px;text-align:center}
.login-local-divider{
  margin:18px 0 14px;display:flex;align-items:center;gap:10px;
  font-size:10px;color:var(--muted);letter-spacing:1px;text-transform:uppercase;
}
.login-local-divider::before,.login-local-divider::after{
  content:'';flex:1;height:1px;background:var(--border-d);
}
.login-local-form{display:flex;flex-direction:column;gap:10px}
.login-workspace-choices{display:flex;flex-direction:column;gap:9px;text-align:left}
.login-workspace-choices[hidden]{display:none}
.login-local-form.is-choosing-workspace>input,
.login-local-form.is-choosing-workspace>.login-local-btn,
.login-local-form.is-choosing-workspace>.login-forgot-link{display:none}
.login-workspace-choice-title{font-size:18px;font-weight:700;color:#16171a;text-align:center}
.login-workspace-choice-help{font-size:12px;line-height:1.45;color:#72747a;text-align:center;margin-bottom:3px}
.login-workspace-choice-btn{width:100%;min-height:48px;border:1px solid #d8d9de;border-radius:12px;background:#fff;color:#202126;font:600 14px var(--font-sans);padding:11px 14px;cursor:pointer;text-align:left;transition:border-color .15s ease,background .15s ease}
.login-workspace-choice-btn:hover{border-color:#7c5cff;background:#f7f5ff}
.login-workspace-choice-btn:disabled{opacity:.55;cursor:wait}
.login-workspace-choice-back{border:0;background:transparent;color:#74767e;font:500 12px var(--font-sans);padding:6px;cursor:pointer;text-align:center}
.login-gate.is-choosing-workspace .login-google-wrap,
.login-gate.is-choosing-workspace .login-oauth-divider,
.login-gate.is-choosing-workspace .login-oauth-buttons,
.login-gate.is-choosing-workspace .login-local-divider,
.login-gate.is-choosing-workspace .login-provider-hint{display:none!important}
.login-local-input{
  width:100%;padding:11px 14px;border-radius:9px;border:1px solid var(--border-d);
  background:var(--bg-inset);color:var(--off-white);font-family:var(--sans);
  font-size:13px;outline:none;transition:border-color .15s;
}
.login-local-input::placeholder{color:var(--muted)}
.login-local-input:focus{border-color:var(--coral)}
.login-local-btn{
  width:100%;padding:13px;border-radius:10px;border:none;
  background:var(--purple);color:#fff;font-family:var(--sans);
  font-size:14px;font-weight:700;cursor:pointer;transition:all .15s;
}
.login-local-btn:hover{background:#7a61c8;color:#fff}
.login-local-btn:active{transform:scale(.98)}
.login-local-btn:disabled{opacity:.4;cursor:default}
/* Admin panel */
.admin-section{margin-top:24px}
.admin-table{width:100%;border-collapse:collapse;font-size:12px}
.admin-table th{text-align:left;padding:8px 12px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);border-bottom:1px solid var(--border-d)}
.admin-table td{padding:8px 12px;border-bottom:1px solid rgba(255,255,255,.03);color:var(--cream)}
.admin-table tr:hover td{background:rgba(255,255,255,.02)}
.admin-user-row{display:flex;align-items:center;gap:8px}
.admin-user-avatar{width:24px;height:24px;border-radius:50%;background:var(--coral);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:var(--white);overflow:hidden}
.admin-user-avatar img{width:100%;height:100%;object-fit:cover;object-position:center;border-radius:50%;display:block;aspect-ratio:1 / 1}
.admin-invite-form{display:flex;gap:8px;margin-top:12px}
.admin-input{padding:8px 12px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--cream);font-family:var(--sans);font-size:12px;outline:none;flex:1}
.admin-input:focus{border-color:var(--coral)}
.admin-btn{padding:8px 16px;border-radius:6px;border:none;background:var(--coral);color:var(--white);font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer;transition:opacity .15s}
.admin-btn:hover{opacity:.85}
.admin-btn-sm{padding:4px 10px;font-size:10px}
.admin-btn-danger{background:transparent;border:1px solid rgba(239,68,68,.4);color:var(--danger-text)}
.admin-btn-danger:hover{background:rgba(239,68,68,.08)}
.admin-role-badge{font-size:9px;padding:2px 8px;border-radius:3px;font-weight:600;text-transform:uppercase}
.admin-role-badge.admin{background:rgba(231,206,58,.12);color:var(--gold)}
.admin-role-badge.member{background:rgba(255,255,255,.06);color:var(--muted)}
.admin-role-badge.editor{background:rgba(115,172,131,.12);color:var(--green)}
.admin-role-badge.viewer{background:rgba(255,255,255,.06);color:var(--muted)}
.admin-role-badge.user{background:rgba(255,255,255,.06);color:var(--muted)}
.admin-role-badge.super-admin{background:rgba(180,40,40,.18);color:#e04040}

/* Markdown chat formatting */
.chat-msg.bot{white-space:normal}
.chat-msg.bot p{margin:4px 0}.chat-msg.bot ul,.chat-msg.bot ol{margin:4px 0 4px 16px}.chat-msg.bot li{margin:2px 0}
.chat-msg.bot code{background:var(--surface-inset);padding:1px 5px;border-radius:3px;font-family:var(--sans);font-size:11px}
.chat-msg.bot pre{background:rgba(255,255,255,.06);padding:8px 10px;border-radius:5px;overflow-x:auto;overflow-y:auto;max-height:280px;margin:6px 0}
.chat-msg.bot pre code{background:none;padding:0}
.chat-msg.bot strong{color:var(--cream);font-weight:600}
.chat-msg.bot h1,.chat-msg.bot h2,.chat-msg.bot h3{font-size:13px;font-weight:700;color:var(--cream);margin:8px 0 4px}
.chat-msg.bot a{color:var(--blue);text-decoration:underline}

/* ==================== APP SHELL ==================== */
.app{display:flex;min-height:100vh;opacity:0;transition:opacity .4s ease;user-select:none;-webkit-user-select:none}
.app.visible{opacity:1}
input,textarea,[contenteditable]{user-select:text;-webkit-user-select:text}
.chat-msg,.card-comment-text,.kanban-card-text,.chat-message-row{user-select:text;-webkit-user-select:text}

/* The app shell surface. The sidebar and the page canvas beside it are ONE surface, but
   they were written as two literals — #0c0c0e and #0a0a0b — which put a faint seam down
   the middle of every page. Both read this token now, so they cannot drift apart again.
   Light theme keeps its own light canvas (its sidebar is deliberately dark), so only the
   dark value is shared. */
/* Two surfaces, not five. --bg-shell/--bg-canvas is the GROUND (sidebar, page, board
   columns); --surface-raised is the one thing that sits ON it (view tabs, task cards).
   Cards and tabs were #161618 and rgba(255,255,255,.05) over different grounds, which
   is why they never quite matched. Same token over the same ground = identical. */
/* ── THE SURFACE SCALE ─────────────────────────────────────────────────────────────
   FOUR surfaces, four jobs. Every container in the app should read one of these and
   nothing else. An audit of a single chat page found 23 distinct painted backgrounds,
   eight of them neutral greys — several separated by 1-3% alpha, which is invisible
   on its own and is exactly why nothing quite lines up.

     --bg-shell / --bg-canvas   THE GROUND. Sidebar, page, board columns. One plane;
                                nothing is "behind" anything else.
     --surface-raised           SITS ON the ground: view tabs, task cards.
     --surface-inset            RECESSED INTO it: search fields, the composer, wells.
     --surface-overlay          FLOATS ABOVE it: menus, popovers, hover toolbars.

   Adding a fifth value is how this drifted the first time. If something needs a new
   shade, it almost certainly wants one of these four in a different role. */
:root{
  --bg-shell:#0c0c0e;
  --bg-canvas:var(--bg-shell);
  --surface-raised:rgba(255,255,255,.05);
  --surface-inset:rgba(255,255,255,.07);
  --surface-overlay:#141416;
  /* A STATE, not a fifth surface. Hover is a tint applied ON TOP of whatever surface an
     element already has, which is why it cannot be one of the four — and why folding the
     77 hover rules into --surface-inset would have made hover indistinguishable from rest
     on every inset element. Same value it always had; it just has a name now, so the next
     hover style is right without anyone having to go looking for the number. */
  --state-hover:rgba(255,255,255,.08);
  /* A CONTAINER holds a set of items: a board column, the list/trash panel, a Home widget,
     a link-preview card. It sits between the ground and a raised card — a board is
     genuinely three levels deep — and it is OPAQUE on purpose: several of these surfaces
     are position:sticky, and a translucent fill lets rows scroll through underneath.
     Mixed from the ground rather than typed as a hex, so it moves when the ground does. */
  --surface-container:color-mix(in srgb,#ffffff 2.25%,var(--bg-shell));
}
html[data-theme="light"]{--bg-canvas:var(--bg-app);--surface-raised:#fff;--surface-inset:rgba(0,0,0,.05);--surface-overlay:#fff}

/* SIDEBAR */
.sidebar{
  width:var(--sidebar-w);background:var(--bg-shell);color:var(--white);
  display:flex;flex-direction:column;position:fixed;top:0;left:0;bottom:0;z-index:100;
  transition:transform .3s cubic-bezier(.22,1,.36,1);overflow:hidden;
}
.sidebar-nav-sections{flex:1;display:flex;flex-direction:column;overflow:hidden;min-height:0}
/* DM sidebar takeover (#2) — a full-sidebar overlay conversation list */
.sidebar-dm-dot{margin-left:auto;flex-shrink:0}
.sidebar-dm-dot.has-notif{min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--color-error);color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1}
.dm-sidebar-panel{position:absolute;inset:0;z-index:60;display:none;flex-direction:column;background:var(--dark)}
.dm-sidebar-panel.open{display:flex}
.dm-sb-head{display:flex;align-items:center;gap:10px;padding:18px 14px 12px;border-bottom:1px solid rgba(255,255,255,.07);flex-shrink:0}
.dm-sb-back{width:30px;height:30px;border-radius:8px;border:none;background:transparent;color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .14s,color .14s}
.dm-sb-back:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.dm-sb-title{font-family:var(--sans);font-size:15px;font-weight:700;color:var(--off-white)}
.dm-sb-list{flex:1;overflow-y:auto;padding:8px}
.dm-sb-empty{padding:30px 16px;text-align:center;color:var(--muted);font-size:13px;line-height:1.7}
.dm-sb-item{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:none;background:transparent;border-radius:10px;cursor:pointer;text-align:left;transition:background .12s;margin-bottom:1px}
.dm-sb-item:hover{background:rgba(255,255,255,.05)}
.dm-sb-item.active{background:rgba(124,92,255,.16)}
.dm-sb-av{width:32px;height:32px;border-radius:50%;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,.1);color:var(--cream);font-size:13px;font-weight:700;overflow:hidden}
.dm-sb-av img{width:100%;height:100%;object-fit:cover}
.dm-sb-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.dm-sb-name{font-size:14px;color:var(--off-white);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dm-sb-item.unread .dm-sb-name{color:#fff;font-weight:700}
.dm-sb-prev{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dm-sb-badge{flex-shrink:0;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--color-error);color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}
.dm-sb-foot{padding:12px;border-top:1px solid rgba(255,255,255,.07);flex-shrink:0}
.dm-sb-new{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px;border-radius:10px;border:none;background:var(--coral);color:#fff;font-family:var(--sans);font-size:14px;font-weight:600;cursor:pointer;transition:background .14s}
.dm-sb-new:hover{background:var(--color-primary-hover)}
.sidebar-nav-scroll{flex:1;overflow-y:auto;overflow-x:hidden;min-height:0}
.sidebar-header{padding:24px 20px 20px;border-bottom:1px solid var(--border-d);display:flex;align-items:center;gap:10px}
.sidebar-title{font-family:var(--serif);font-size:20px;font-weight:400;letter-spacing:-.5px}
.sidebar-label{font-size:11px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;color:var(--muted);padding:20px 16px 8px}
.sidebar-nav{padding:0}
.sidebar-nav a{
  display:flex;align-items:center;gap:10px;padding:10px 16px;
  font-size:14px;font-weight:500;color:rgba(255,255,255,.5);text-decoration:none;
  transition:color .15s ease,background .15s ease;position:relative;cursor:pointer;
}
.sidebar-nav a:hover{color:rgba(255,255,255,.85);background:rgba(255,255,255,.04)}
.sidebar-nav a.active{color:var(--white);background:var(--state-hover)}
.sidebar-nav a.active::before{content:'';position:absolute;left:0;top:4px;bottom:4px;width:3px;background:var(--coral);border-radius:0 3px 3px 0}
.sidebar-nav a svg{width:18px;height:18px;opacity:.6;flex-shrink:0}
.sidebar-nav a.active svg{opacity:1}

/* Sidebar Banner + Server Header */
.sidebar-banner{position:relative;width:100%;height:108px;overflow:hidden;flex-shrink:0;background:var(--banner-tint,linear-gradient(120deg,#1b1b21,#26262e));opacity:1;transition:background .5s ease}
/* Workspace banner entrance: slide in from the RIGHT (matches the toast motion), fired once per
   workspace switch by _playBannerEnter — never on every re-render. */
@keyframes bannerSlideIn{from{opacity:0;transform:translateX(calc(100% + 30px))}to{opacity:1;transform:translateX(0)}}
.sidebar-banner.banner-enter,.ws-banner.banner-enter,.m-drawer-banner.banner-enter{animation:bannerSlideIn .34s cubic-bezier(.22,1,.36,1) both}
@media(prefers-reduced-motion:reduce){.sidebar-banner.banner-enter,.ws-banner.banner-enter,.m-drawer-banner.banner-enter{animation:none}}
.sidebar-banner-img{width:100%;height:100%;object-fit:cover}
.sidebar-banner-glow{position:absolute;inset:0;background:radial-gradient(120% 90% at 18% 0%,rgba(255,255,255,0.22),transparent 58%);pointer-events:none}
.sidebar-banner-fade{position:absolute;left:0;right:0;bottom:0;height:74px;background:linear-gradient(to bottom,transparent 0%,color-mix(in srgb, var(--banner-tint, #0c0c0e) 26%, #0c0c0e) 58%,#0c0c0e 100%);pointer-events:none;transition:background .5s ease}
.sidebar-banner-gradient{position:absolute;bottom:0;left:0;right:0;height:50px;background:linear-gradient(to bottom,transparent,#0c0c0e);pointer-events:none}

/* ── Glass workspace card (overlaps the gradient banner): identity + Home + switcher ── */
.sidebar-ws-card{position:relative;z-index:2;display:flex;align-items:center;gap:4px;margin:-24px 12px 0;padding:6px 8px 6px 10px;border-radius:14px;flex-shrink:0;
  background:rgba(255,255,255,0.08);backdrop-filter:blur(18px) saturate(180%);-webkit-backdrop-filter:blur(18px) saturate(180%);
  border:1px solid rgba(255,255,255,0.2);box-shadow:inset 0 1px 0 rgba(255,255,255,0.28),0 10px 28px rgba(0,0,0,0.3);transition:background .16s ease}
.sidebar-ws-card:hover{background:rgba(255,255,255,0.14)}
.sidebar-ws-nav{flex:1;min-width:0;padding:0;margin:0;overflow:visible}
.sidebar-ws-card .sidebar-ws-main{display:flex;align-items:center;flex:1;min-width:0;padding:0;background:none;color:var(--white)}
.sidebar-ws-card .sidebar-ws-main:hover,.sidebar-ws-card .sidebar-ws-main.active{background:none}
.sidebar-ws-card .sidebar-ws-main.active::before{content:none}
/* ── Morph Island: workspace ⇄ home. Stacked layers; the active layer's children
      lift from below with a per-child cascade (badge → text). ── */
.sidebar-ws-morph{position:relative;flex:1;min-width:0;height:42px;overflow:hidden}
.ws-layer{position:absolute;inset:0;display:flex;align-items:center;gap:11px;min-width:0}
.ws-layer > *{transition:transform .55s cubic-bezier(.22,1,.36,1),opacity .4s ease;will-change:transform,opacity}
.ws-layer > *:nth-child(1){transition-delay:0s}
.ws-layer > *:nth-child(2){transition-delay:.08s}
/* default: workspace layer up, home layer parked below */
.ws-layer-space > *{transform:translateY(0);opacity:1}
.ws-layer-home > *{transform:translateY(135%);opacity:0}
.ws-layer-settings > *{transform:translateY(135%);opacity:0}
/* hover OR on the home page: morph to the home layer */
.sidebar-ws-card:hover .ws-layer-space > *,
body.is-home .sidebar-ws-card .ws-layer-space > *{transform:translateY(135%);opacity:0}
.sidebar-ws-card:hover .ws-layer-home > *,
body.is-home .sidebar-ws-card .ws-layer-home > *{transform:translateY(0);opacity:1}
/* On the settings page the card IS the settings identity: gear + "Settings", riding the
   exact same lift-from-below cascade as home. It outranks the home layer (a settings page
   is not the dashboard) and, unlike home, survives hover -- hovering the card while you
   are in settings should not pretend you are somewhere else. */
body.is-settings .sidebar-ws-card .ws-layer-space > *,
body.is-settings .sidebar-ws-card:hover .ws-layer-space > *,
body.is-settings .sidebar-ws-card .ws-layer-home > *,
body.is-settings .sidebar-ws-card:hover .ws-layer-home > *{transform:translateY(135%);opacity:0}
body.is-settings .sidebar-ws-card .ws-layer-settings > *,
body.is-settings .sidebar-ws-card:hover .ws-layer-settings > *{transform:translateY(0);opacity:1}
@media(prefers-reduced-motion:reduce){.ws-layer > *{transition:opacity .2s ease}.ws-layer-home > *{transform:none}.ws-layer-space > *{transform:none}.sidebar-ws-card:hover .ws-layer-space > *,body.is-home .sidebar-ws-card .ws-layer-space > *{transform:none}.sidebar-ws-card:hover .ws-layer-home > *,body.is-home .sidebar-ws-card .ws-layer-home > *{transform:none}.ws-layer-settings > *{transform:none}body.is-settings .sidebar-ws-card .ws-layer-settings > *{transform:none}.sidebar-ws-card.ws-open .ws-layer-settings > *{transform:none !important}}
/* ── Workspace icon: no border, no container (transparent-GIF friendly).
      The gradient placeholder shows ONLY when the icon is empty (initials, no <img>). ── */
.sidebar-ws-badge{width:42px;height:42px;flex:none}
.sidebar-ws-badge-default{width:42px;height:42px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:none;border:none;color:#fff;font:700 13px var(--sans)}
.sidebar-ws-badge-default:not(:has(img)){background:linear-gradient(140deg,#8b5cf6,#6366f1)}
.sidebar-ws-badge-default img{width:100%;height:100%;object-fit:cover;border-radius:inherit;display:block}
/* Home and Settings share this badge, and both take the BANNER's colour first — that is
   the thing they sit under, so matching the logo (or the house purple) while the banner
   was something else read as a mismatch. Falls back to the logo accent, then the
   workspace accent, for a workspace whose banner yields no usable colour. */
.sidebar-ws-badge-home{width:42px;height:42px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb, var(--banner-tint,var(--ws-logo-accent,var(--ws-accent,#7c5cff))) 26%, transparent);
  color:color-mix(in srgb, var(--banner-tint,var(--ws-accent,#7c5cff)) 45%, #fff);
  transition:background .25s ease,color .25s ease}
.sidebar-ws-badge-home svg{width:20px;height:20px}
.sidebar-ws-id{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center}
.sidebar-ws-id strong{font:700 15px var(--sans);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidebar-ws-sub{font:500 11px var(--sans);color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidebar-ws-caret{width:28px;height:28px;flex:none;border:none;background:none;border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-2);transition:background .14s ease}
.sidebar-ws-caret:hover{background:rgba(255,255,255,0.1);color:#fff}
/* Dual-glyph caret (owner spec 2026-08-13). The chevron points RIGHT at rest and
   rotates smoothly to DOWN while the menu is open. Off Home the button rests as
   a HOUSE and cross-fades to the chevron only while the button itself is hovered
   (or the menu is open). Click always toggles the menu. */
.sidebar-ws-caret{position:relative}
.sidebar-ws-caret svg{width:14px;height:14px;position:absolute;top:50%;left:50%;margin:-7px 0 0 -7px;transition:opacity .18s ease,transform .26s cubic-bezier(.22,.61,.36,1)}
.sidebar-ws-caret .swc-chev{transform:rotate(-90deg)}
.sidebar-ws-caret.open .swc-chev{transform:rotate(0deg)}
body.is-home .sidebar-ws-caret .swc-house{opacity:0}
body.is-home .sidebar-ws-caret .swc-chev{opacity:1}
body:not(.is-home) .sidebar-ws-caret .swc-house{opacity:1}
body:not(.is-home) .sidebar-ws-caret .swc-chev{opacity:0}
body:not(.is-home) .sidebar-ws-caret:hover .swc-house,body:not(.is-home) .sidebar-ws-caret.open .swc-house{opacity:0}
body:not(.is-home) .sidebar-ws-caret:hover .swc-chev,body:not(.is-home) .sidebar-ws-caret.open .swc-chev{opacity:1}

/* ── Sidebar nav: active = purple tint (no coral stripe), to match the mockup ── */
/* Colour only — the pill draws the selection. */
.sidebar-nav a.active,.sidebar-fav-nav a.active,.sidebar-section-nav a.active,.sidebar-cat-item.active{color:#fff}
.sidebar-nav a.active::before,.sidebar-fav-nav a.active::before,.sidebar-section-nav a.active::before{content:none}
.sidebar-nav a.active svg{opacity:1}
/* Folder/category labels: sentence-case 13px (not tiny uppercase eyebrows) per mockup */
.sidebar-section-name{font-size:13px;font-weight:600;letter-spacing:.2px;text-transform:none;color:var(--text-2)}
/* The same grey the folder's own NAME already wears (.sidebar-section-name) and that every
   uncoloured project and channel icon resolves to. It was a step darker than both, which is
   what made one folder in a list of boards look disabled. Not currentColor: the folder LABEL
   row is white, so inheriting made the icon brighter than everything around it instead. */
.sidebar-section-folder{stroke:rgba(235,235,245,.82)}

/* ── Footer icon button (relocated notifications bell) ── */
.sidebar-icon-btn{position:relative;background:none;border:none;padding:6px;cursor:pointer;border-radius:8px;color:var(--muted);transition:color .15s ease,background .15s ease;flex-shrink:0;display:flex;align-items:center;justify-content:center}
.sidebar-icon-btn svg{width:18px;height:18px}
.sidebar-icon-btn:hover{color:var(--off-white);background:var(--state-hover)}
.sidebar-icon-btn .notif-badge{top:0;right:0}
.sidebar-server-bar{display:flex;align-items:center;height:48px;box-sizing:border-box;padding:0 14px;border-bottom:none;position:relative;flex-shrink:0}
.sidebar-server-trigger{display:flex;align-items:center;gap:8px;flex:1;min-width:0;cursor:pointer;border:none;background:none;padding:0;font-family:var(--sans);color:var(--cream)}
.sidebar-server-trigger:hover .sidebar-server-name{color:var(--off-white)}
.sidebar-server-trigger:hover .sidebar-server-caret{opacity:1}
.sidebar-server-icon{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,var(--coral),var(--coral-shade));display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:#fff;flex-shrink:0;overflow:hidden}
.sidebar-server-icon img{width:100%;height:100%;object-fit:cover}
.sidebar-server-name{font-size:15px;font-weight:700;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .12s}
.sidebar-server-caret{width:12px;height:12px;opacity:.5;flex-shrink:0;transition:opacity .12s,transform .15s;fill:none;stroke:currentColor;stroke-width:2.5}
.sidebar-server-caret.open{transform:rotate(180deg)}
.sidebar-invite-btn{width:28px;height:28px;border:none;background:rgba(255,255,255,.06);color:var(--muted);border-radius:6px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .15s;flex-shrink:0;margin-left:auto}
.sidebar-invite-btn:hover{background:rgba(255,255,255,.12);color:var(--cream)}
.sidebar-invite-btn svg{width:16px;height:16px}

/* Server Dropdown Menu */
.server-dropdown{display:none;position:absolute;top:100%;left:8px;right:8px;background:var(--glass-bg);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:1px solid var(--glass-border);border-radius:14px;padding:6px;z-index:200;box-shadow:var(--glass-shadow)}
.server-dropdown.open{display:block}
.server-dropdown-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:6px;border:none;background:none;color:var(--cream);font-size:12px;font-weight:500;cursor:pointer;width:100%;text-align:left;font-family:var(--sans);transition:background .1s}
.server-dropdown-item:hover{background:rgba(255,255,255,.06)}
.server-dropdown-item svg{width:16px;height:16px;opacity:.5;flex-shrink:0}
.server-dropdown-item .sdi-label{flex:1}
/* Switcher motion (owner ask 2026-08-12): a subtle cascade as the menu opens, and a
   mac-dock hop on the workspace you choose. Both re-trigger naturally because the
   dropdown and the workspace sublist show via display:none -> block, which restarts
   child animations. The sublist rows carry --sd-i from the renderer; the top-level
   items stagger by nth-child (the sublist div is child 1, buttons start at 2). */
/* The menu card itself opens smoothly in BOTH contexts (plain dropdown and the
   ws-open sidebar card — the latter's own rule below re-points sdFlow's slot). */
.server-dropdown.open{animation:sdMenuOpen .22s cubic-bezier(.21,.61,.35,1)}
@keyframes sdMenuOpen{from{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:none}}
/* fill:backwards, NOT both — a forwards fill would pin transform:none forever and
   silently swallow the hover magnification below. */
/* The cascade must FINISH INSIDE the panel's own opening motion (max-height morph,
   280ms in _sdExpand). At the old 24ms step × .24s the last two items — Create
   Project and Create Folder — didn't start until 96/120ms and were still fading in
   at 360ms, long after the panel had visibly finished: the menu appeared to open
   "up to Manage Workspaces", then the last rows popped in (owner report, Aug 13).
   A 12ms step over .2s puts the final row's finish at 272ms — one motion. */
.server-dropdown.open>.server-dropdown-item{animation:sdCascadeIn .2s cubic-bezier(.21,.61,.35,1) backwards}
.server-dropdown.open>.server-dropdown-item:nth-child(3){animation-delay:12ms}
.server-dropdown.open>.server-dropdown-item:nth-child(4){animation-delay:24ms}
.server-dropdown.open>.server-dropdown-item:nth-child(5){animation-delay:36ms}
.server-dropdown.open>.server-dropdown-item:nth-child(6){animation-delay:48ms}
.server-dropdown.open>.server-dropdown-item:nth-child(7){animation-delay:60ms}
.server-dropdown.open>.server-dropdown-item:nth-child(8){animation-delay:72ms}
.server-dropdown.open>.server-dropdown-item:nth-child(n+9){animation-delay:84ms}
#sdWorkspaceList .server-dropdown-item{animation:sdCascadeIn .26s cubic-bezier(.21,.61,.35,1) backwards;animation-delay:calc(var(--sd-i,0)*26ms)}
@keyframes sdCascadeIn{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
/* Workspace icons: the real uploaded logo, or the name's first letter — never an
   emoji (owner refinement 2026-08-13). */
.sd-ws-ic{width:20px;height:20px;border-radius:50%;overflow:hidden;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,.07)}
.sd-ws-ic img{width:100%;height:100%;object-fit:cover;display:block}
.sd-ws-ic-letter{font-size:11px;font-weight:700;color:var(--off-white);border:1px solid var(--border-d);text-transform:uppercase;line-height:1}
/* Dock-style hover magnification, CONTENT-ONLY (owner refinement 2026-08-13):
   the icon+name wrapper (.sd-ws-row) scales — the hovered row biggest, its
   immediate neighbours slightly — while the → arrow on the right never moves.
   Scaling the inner wrapper also can't clip the list's overflow container.
   :has() covers the row ABOVE the hovered one; without support, hovered+below
   still magnify (graceful). */
.sd-ws-row{flex:1;min-width:0;display:inline-flex;align-items:center;gap:10px;transition:transform .16s cubic-bezier(.2,.6,.3,1);transform-origin:left center}
.sd-ws-row .sdi-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Agency folders: a sub-workspace sits under the agency that owns it. Emitted as
   flat siblings (see renderWorkspaceSwitcher) so the cascade and the neighbour
   magnification survive; the indent and rail are what read as nesting. */
#sdWorkspaceList .server-dropdown-item{padding-left:18px;position:relative}
.sd-ws-caret{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;
  margin-left:-6px;margin-right:-2px;flex-shrink:0;border-radius:4px;color:var(--muted);cursor:pointer;
  transition:color .12s,background .12s}
.sd-ws-caret:hover{color:var(--off-white);background:rgba(255,255,255,.09)}
.sd-ws-caret-ic{width:12px !important;height:12px !important;opacity:1 !important;
  transition:transform .16s cubic-bezier(.2,.6,.3,1)}
.sd-ws-parent.collapsed .sd-ws-caret-ic{transform:rotate(-90deg)}
#sdWorkspaceList .sd-ws-parent-label{cursor:default;color:var(--muted)}
#sdWorkspaceList .sd-ws-parent-label:hover{background:none}
#sdWorkspaceList .sd-ws-parent-label:hover .sd-ws-row{transform:none}
#sdWorkspaceList .sd-ws-child{padding-left:38px}
/* The sidebar's own tree connector, same construction: a trunk down the left with a tick
   running out of it, and the last child in the run curving into its row instead of the
   line carrying on past it. The trunk sits at 19px because that is the centre of the
   caret on the agency row above — it was at 22, which read as drifting right of the
   arrow it hangs from — and the tick ends at 38px, exactly where the child's own icon
   box begins. */
#sdWorkspaceList .sd-ws-child::after{
  content:'';position:absolute;left:19px;top:0;height:100%;width:19px;
  border-left:1px solid var(--border-d);opacity:.55;pointer-events:none;
  background:linear-gradient(var(--border-d),var(--border-d)) no-repeat 0 50% / 100% 1px}
/* :last-child cannot find it — a group's children are flat siblings followed by another
   agency's row or the Create Workspace action. "The last one in this run" is the child
   with no child after it. */
#sdWorkspaceList .sd-ws-child:not(:has(+ .sd-ws-child))::after{
  height:50%;border-bottom:1px solid var(--border-d);border-radius:0 0 0 6px;background:none}
#sdWorkspaceList .sd-ws-child .sd-ws-ic{width:18px;height:18px}
#sdWorkspaceList .sd-ws-child .sd-ws-ic-letter{font-size:10px}
/* Create rows: the same row shape as a workspace so the list stays one column, but
   muted and marked with a dashed tile — they make a workspace rather than being one. */
#sdWorkspaceList .sd-ws-action{color:var(--muted)}
#sdWorkspaceList .sd-ws-action:hover{color:var(--off-white)}
#sdWorkspaceList .sd-ws-action-new{margin-top:2px;padding-left:18px}
.sd-ws-ic-add{background:none;border:1px dashed var(--border-d)}
.sd-ws-action:hover .sd-ws-ic-add{border-color:var(--coral);color:var(--coral)}
.sd-ws-ic-add svg{width:11px !important;height:11px !important;opacity:1 !important}
/* The list scrolls vertically for a long workspace list, but the hover magnification grows
   a row rightwards from its left edge — which the shared overflow:auto answered with a
   horizontal scrollbar appearing under the cursor. Only the vertical axis may scroll; the
   few pixels the scaled row gains are clipped, which is what the effect wants anyway. */
#sdWorkspaceList{overflow-x:hidden}
#sdWorkspaceList .server-dropdown-item:hover .sd-ws-row{transform:scale(1.08)}
#sdWorkspaceList .server-dropdown-item:hover+.server-dropdown-item .sd-ws-row{transform:scale(1.03)}
#sdWorkspaceList .server-dropdown-item:has(+ .server-dropdown-item:hover) .sd-ws-row{transform:scale(1.03)}
.server-dropdown-item.sd-bounce,#sdWorkspaceList .server-dropdown-item.sd-bounce{animation:sdDockHop .42s cubic-bezier(.28,.84,.42,1) both}
@keyframes sdDockHop{0%{transform:none}28%{transform:translateY(-7px) scaleY(1.04)}55%{transform:translateY(0) scaleY(.97)}74%{transform:translateY(-2px)}100%{transform:none}}
@media (prefers-reduced-motion:reduce){
.server-dropdown.open,.server-dropdown.open>.server-dropdown-item,#sdWorkspaceList .server-dropdown-item,.server-dropdown-item.sd-bounce{animation:none}
.sd-ws-row,#sdWorkspaceList .server-dropdown-item:hover .sd-ws-row,#sdWorkspaceList .server-dropdown-item:hover+.server-dropdown-item .sd-ws-row{transition:none;transform:none}
.sidebar-ws-caret svg{transition:none}
}
.server-dropdown-item.danger{color:var(--danger-text)}
.server-dropdown-item.danger svg{opacity:.7}
.server-dropdown-sep{height:1px;background:var(--border-d);margin:4px 0}
.server-dropdown-item{border-radius:9px}
.server-dropdown-item.sdi-create{align-items:flex-start;gap:11px;padding:9px 10px}
.server-dropdown-item.sdi-create .scm-ic{flex-shrink:0;width:22px;height:22px;display:flex;align-items:center;justify-content:center;color:var(--cream);margin-top:1px;opacity:1}
.server-dropdown-item.sdi-create .scm-ic svg{width:20px;height:20px;opacity:1}
.server-dropdown-item.sdi-create .scm-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.server-dropdown-item.sdi-create .scm-title{font-size:14px;font-weight:600;color:var(--off-white)}
.server-dropdown-item.sdi-create .scm-desc{font-size:12px;color:var(--muted);font-weight:400}

/* MAIN */
.main{margin-left:var(--sidebar-w);flex:1;height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-canvas)}

/* TOP BAR */
.topbar{
  position:sticky;top:0;z-index:50;
  height:var(--topbar-h);box-sizing:border-box;
  /* L/R padding matches the board content column (icon-left 24px, Settings/toolbar-right 16px) so
     the breadcrumb lines up with the project icon below it and the search lines up with Settings. */
  padding:0 16px 0 24px;display:flex;align-items:center;gap:16px;
  /* THE GROUND, opaque. This was rgba(10,10,9,.85) over a blur — frosted glass, from when
     the bar floated over a differently-coloured page. Composited over today's #0c0c0e it
     lands at about rgb(10,10,10): darker and less blue than the canvas, which is why the
     top of every page read as its own strip. The bar is still position:sticky, and an
     opaque sticky bar is what you want anyway — content scrolling under it should be
     hidden, not smeared. The saturate() was also tinting whatever passed beneath. */
  background:var(--bg-canvas);
  
  /* NEVER shrink. The topbar has a definite height (--topbar-h), but as a flex item in
     .main it was still shrinkable — so on some pages the layout negotiation squeezed it
     to 48.16px while others got the full 52px. Every page below inherits that as a
     4px jump in the title, the tabs and the first divider, which is the "layout shifts
     when I switch pages" symptom. A fixed-height bar has no business flexing. */
  flex-shrink:0;
  /* No rule under the topbar. It and the tab-row rule below were the two horizontal
     lines cutting across every page; the surfaces already read as separate through
     spacing and fill, so the strokes were only adding noise. */
  border-bottom:none}
.topbar-left{display:flex;align-items:center;gap:14px;min-width:0}
/* ── Top-bar breadcrumb (mockup: italic "Workspace › Page") ── */
.topbar-crumb{display:flex;align-items:center;gap:9px;min-width:0;font-family:var(--sans)}
.topbar-crumb .tc-ws{font:600 14px var(--sans);font-style:italic;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:.14em;margin-right:-.14em}
.topbar-crumb .tc-sep{width:13px;height:13px;flex:none;color:var(--text-3)}
.topbar-crumb .tc-page{font:700 14px var(--sans);font-style:italic;color:var(--text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:min(46vw,520px);padding-right:.14em;margin-right:-.14em}
/* ── Top-bar search field (opens spotlight) ── */
.topbar-search{margin-left:auto;display:flex;align-items:center;gap:10px;height:36px;width:340px;flex:none;padding:0 13px;border-radius:10px;
  /* Same surface as the cards on Home and the panes in a project. Three different greys
     for the search field, the view tabs and the cards beside them read as three unrelated
     apps stacked in one window. */
  background:var(--surface-container);border:none;cursor:text;color:var(--text-3);font:400 13px var(--sans);transition:background .14s ease,color .14s ease}
.topbar-search:hover{background:color-mix(in srgb,var(--surface-container) 100%,#fff 4%);color:var(--text-2)}
.topbar-search svg{width:15px;height:15px;flex:none}
.topbar-search span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:760px){.topbar-search{width:auto;flex:1}.topbar-search span{display:none}}
/* Desktop top bar is hidden in the mobile app shell (mobile uses its own floating nav). */
body[data-mobile-mode="app"] .topbar{display:none}
/* Workshop pages provide their own header (tabs + view toolbar), so
   the global topbar's left title block is redundant — hide it. The
   right-side actions (notifications, members, search) stay visible. */
/* Breadcrumb lives in the TOPBAR on every page (consistent with Home) — show it on boards too
   and hide the board-header's own breadcrumb so it's not duplicated / in a different spot. */
#wsHeaderCw .ws-breadcrumb,#wsHeaderMain .ws-breadcrumb{display:none}
.topbar-title{font-family:var(--sans);font-size:18px;font-weight:600;letter-spacing:-.01em;color:var(--off-white)}
/* Breadcrumb rename removed — the .topbar-inline-edit input, its emoji grid and
   the .topbar-title.editable hover affordance all went with it. */
.ws-empty-hologram{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none}
.ws-empty-hologram-inner{display:flex;flex-direction:column;align-items:center;gap:14px;padding:48px 56px;border:2px dashed rgba(255,255,255,.12);border-radius:16px;cursor:pointer;pointer-events:auto;transition:border-color .3s,background .3s;background:transparent;user-select:none}
.ws-empty-hologram-inner:hover{border-color:rgba(124,92,255,.35);background:rgba(124,92,255,.04)}
.ws-empty-hologram-icon{font-size:32px;opacity:.25;transition:opacity .3s}
.ws-empty-hologram-inner:hover .ws-empty-hologram-icon{opacity:.5}
.ws-empty-hologram-text{font-family:var(--serif);font-size:16px;color:var(--muted);opacity:.5;transition:opacity .3s}
.ws-empty-hologram-inner:hover .ws-empty-hologram-text{opacity:.8;color:var(--off-white)}
.topbar-badge{font-family:var(--sans);font-size:10px;font-weight:500;padding:4px 10px;border-radius:20px;letter-spacing:.5px;display:inline-flex;align-items:center;gap:5px}
.topbar-right{display:flex;align-items:center;gap:2px;margin-left:auto}
.topbar-action-btn{width:32px;height:32px;border:none;background:none;color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:6px;transition:all .15s;position:relative}
.topbar-action-btn:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.topbar-action-btn.active{color:var(--coral)}
.topbar-action-btn svg{width:18px;height:18px}
.topbar-btn{
  padding:8px 18px;border-radius:60px;border:1.5px solid var(--border-d);background:rgba(255,255,255,.06);
  font-family:var(--sans);font-size:12px;font-weight:600;color:var(--off-white);cursor:pointer;
  transition:all .2s ease;display:flex;align-items:center;gap:6px;text-decoration:none;
}
.topbar-btn:hover{border-color:var(--coral);background:var(--coral);color:var(--white)}
.app-close-btn{
  width:28px;height:28px;min-width:28px;padding:0;border-radius:8px;
  border:none;background:rgba(255,255,255,.03);
  color:rgba(255,255,255,.45);display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;line-height:1;transition:color .15s,border-color .15s,background .15s;
}
.app-close-btn:hover{color:var(--off-white);background:var(--state-hover)}
.app-close-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}
.app-close-btn svg{width:12px;height:12px;display:block}
.sidebar-profile{display:flex;align-items:center;gap:11px;padding:0 10px;height:54px;border-radius:11px;cursor:pointer;transition:background .14s ease}
.sidebar-profile:hover{background:rgba(255,255,255,0.05)}
.sidebar-profile-avatar{width:36px;height:36px;min-width:36px;border-radius:50%;background:linear-gradient(140deg,#a855f7,#ec4899 55%,#f59e0b);color:var(--white);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;overflow:hidden;flex-shrink:0}
.sidebar-profile-avatar img{width:100%;height:100%;display:block;border-radius:inherit;object-fit:cover}
.sidebar-profile-info{flex:1;min-width:0;display:flex;flex-direction:column}
.sidebar-profile-info strong{font-size:14px;line-height:1.3;font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidebar-profile-status{font-size:12px;line-height:1.3;color:var(--muted);display:flex;align-items:center;gap:5px;margin-top:2px}
.sidebar-settings-btn{background:none;border:none;padding:6px;cursor:pointer;border-radius:8px;color:var(--muted);transition:color .15s ease,background .15s ease;flex-shrink:0;display:flex;align-items:center;justify-content:center}
.sidebar-settings-btn svg{width:18px;height:18px;transition:transform .4s cubic-bezier(.22,1,.36,1)}
.sidebar-settings-btn:hover{color:var(--off-white);background:var(--state-hover)}
.sidebar-settings-btn:hover svg{transform:rotate(90deg)}

/* ═══════ USER SETTINGS OVERLAY ═══════ */
.user-settings-overlay{position:fixed;inset:0;z-index:99998;background:rgba(0,0,0,.65);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);display:none;align-items:center;justify-content:center;padding:40px}
.user-settings-overlay.open{display:flex}
/* Floating container */
.user-settings-wrap{display:flex;width:100%;max-width:960px;height:min(85vh,720px);background:var(--dark);border:1px solid var(--border-d);border-radius:14px;overflow:hidden;box-shadow:0 24px 80px rgba(0,0,0,.6);position:relative}
/* Left nav */
.user-settings-nav{width:220px;min-width:220px;background:rgba(255,255,255,.025);padding:20px 12px 24px;overflow-y:auto;display:flex;flex-direction:column;border-right:1px solid var(--border-d)}
.user-settings-nav-label{font-size:10px;text-transform:uppercase;letter-spacing:1px;color:var(--muted);padding:8px 12px 4px;font-weight:700}
.user-settings-nav-item{display:flex;align-items:center;gap:10px;padding:7px 12px;border-radius:6px;cursor:pointer;font-size:14px;color:var(--cream);transition:background .12s,color .12s;white-space:nowrap}
.user-settings-nav-item:hover{background:rgba(255,255,255,.06);color:var(--off-white)}
.user-settings-nav-item.active{background:rgba(255,255,255,.1);color:var(--off-white);font-weight:600}
.user-settings-nav-item svg{width:18px;height:18px;flex-shrink:0;opacity:.6}
.user-settings-nav-item.active svg{opacity:1}
.user-settings-nav-sep{height:1px;background:var(--border-d);margin:8px 12px}
/* Right content */
.user-settings-content{flex:1;overflow-y:auto;padding:28px 36px 36px}
.user-settings-content-inner{max-width:640px}
.user-settings-section{display:none}
.user-settings-section.active{display:block}
.user-settings-section h2{font-family:var(--serif);font-size:22px;font-weight:400;color:var(--off-white);margin-bottom:20px}
/* Close button — inside floating panel, top-right */
.user-settings-close{position:absolute;top:14px;right:14px;z-index:2;width:36px;height:36px;border-radius:50%;border:1.5px solid var(--border-d);background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--muted);transition:color .15s,border-color .15s,background .15s}
.user-settings-close:hover{color:var(--off-white);border-color:rgba(255,255,255,.25);background:rgba(255,255,255,.06)}
.user-settings-close svg{width:16px;height:16px}
/* Content cards & rows */
.us-card{background:rgba(255,255,255,.03);border:0;border-radius:10px;padding:16px 20px;margin-bottom:16px}
.us-card-header{display:flex;align-items:center;gap:16px;margin-bottom:14px}
.us-card-avatar{width:72px;height:72px;min-width:72px;border-radius:50%;background:var(--coral);color:var(--white);display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;overflow:hidden}
.us-card-avatar img{width:100%;height:100%;object-fit:cover;border-radius:inherit}
.us-card-meta{flex:1;min-width:0}
.us-card-name{font-size:18px;font-weight:600;color:var(--off-white);line-height:1.2}
.us-card-email{font-size:13px;color:var(--muted);margin-top:2px}
.us-row{display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--border-d)}
.us-row:last-child{border-bottom:none}
.us-row-left{flex:1;min-width:0}
.us-row-label{font-size:12px;text-transform:uppercase;letter-spacing:.3px;color:var(--muted);margin-bottom:2px}
.us-row-value{font-size:14px;color:var(--off-white)}
.us-row-btn{padding:6px 16px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--cream);cursor:pointer;font-size:12px;font-weight:500;transition:background .12s,color .12s}
.us-row-btn:hover{background:rgba(255,255,255,.1);color:var(--off-white)}
.us-row-btn.danger{border-color:rgba(239,68,68,.35);color:var(--danger-text)}
.us-row-btn.danger:hover{background:rgba(239,68,68,.12);border-color:var(--color-error)}
/* Toggle switch */
.us-toggle{position:relative;width:40px;height:22px;border-radius:11px;background:rgba(255,255,255,.12);cursor:pointer;transition:background .2s;flex-shrink:0}
.us-toggle.on{background:var(--green)}
.us-toggle::after{content:'';position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:var(--white);transition:transform .2s}
.us-toggle.on::after{transform:translateX(18px)}
/* Section description */
.us-section-desc{font-size:13px;color:var(--muted);margin-bottom:16px;line-height:1.5}
@media(max-width:700px){
.user-settings-overlay{padding:16px}
.user-settings-wrap{height:min(92vh,800px)}
.user-settings-nav{width:56px;min-width:56px;padding:16px 6px 20px}
.user-settings-nav-item span{display:none}
.user-settings-nav-label{display:none}
.user-settings-content{padding:24px 16px 28px}
}

.profile-avatar{
  width:34px;height:34px;min-width:34px;min-height:34px;flex:0 0 34px;border-radius:50%;
  background:var(--coral);color:var(--white);display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;overflow:hidden;aspect-ratio:1 / 1;line-height:1;position:relative;
}
.profile-avatar img{
  width:100%;height:100%;min-width:100%;min-height:100%;
  display:block;border-radius:inherit;object-fit:cover;object-position:center;
}
.sidebar-footer{padding:10px 12px;border-top:1px solid rgba(255,255,255,0.07);flex-shrink:0}

/* wave-5: sidebar STORAGE meter — sits above the user profile card. Themed via tokens
   so it reads correctly in dark + light. Hidden until bootstrap usage is known. */

/* Notification bell */
.notif-wrap{position:relative}
.notif-bell{
  width:36px;height:36px;border-radius:50%;border:1px solid var(--border-d);background:rgba(255,255,255,.05);
  display:flex;align-items:center;justify-content:center;cursor:pointer;position:relative;transition:all .15s;
}
.notif-bell:hover{border-color:rgba(255,255,255,.18);background:rgba(255,255,255,.09)}
.notif-bell svg{width:17px;height:17px;color:var(--muted);transition:color .15s}
.notif-bell:hover svg{color:var(--off-white)}
.notif-badge{
  position:absolute;top:-3px;right:-3px;min-width:17px;height:17px;border-radius:9px;
  background:var(--coral);color:var(--white);font-size:10px;font-weight:700;
  display:none;align-items:center;justify-content:center;padding:0 4px;
  font-family:var(--sans);line-height:1;
}
.notif-badge.visible{display:flex}
/* Right-side slide-out panel (notifications + members) */
/* Global right sidebar — matches chatroom cr-members-sidebar style */
.main-body{display:flex;flex:1;min-height:0;overflow:hidden;position:relative}/* positioning context for the overlaying right panel */
/* Notifications / members panel: OVERLAYS the page instead of shrinking it — animating
   `width` reflowed the whole board on every open. It now slides in on `transform`
   (compositor-only, 300ms) at a wider size so more of each notification is readable. */
:root{--right-panel-w:340px}
.global-right-sidebar{position:absolute;top:0;right:0;bottom:0;width:var(--right-panel-w);flex-shrink:0;background:var(--dark);display:flex;flex-direction:column;border-left:1px solid var(--border-d);box-shadow:-18px 0 40px rgba(0,0,0,.32);transition:transform var(--dur-modal,300ms) var(--ease-std),opacity var(--dur-modal,300ms) var(--ease-std);overflow:hidden;z-index:30;transform:translateX(0)}
.global-right-sidebar.hidden{transform:translateX(100%);opacity:0;pointer-events:none;border-left:none}
/* Pin panel content to its FINAL width so text never re-wraps mid-slide. */
.global-right-sidebar>div{width:var(--right-panel-w);flex-shrink:0;box-sizing:border-box}
.global-right-sidebar-header{padding:16px 16px 10px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.7px;color:var(--muted);display:flex;align-items:center;justify-content:space-between;flex-shrink:0}
.global-right-sidebar-header button{background:none;border:none;color:var(--muted);font-size:12px;cursor:pointer;font-family:var(--sans);padding:3px 8px;border-radius:4px;transition:all .15s}
.global-right-sidebar-header button:hover{color:var(--cream);background:rgba(255,255,255,.06)}
@media(max-width:768px){.global-right-sidebar{display:none!important}}
.sidebar-nav-scroll::-webkit-scrollbar,.global-right-sidebar ::-webkit-scrollbar,.cr-members-sidebar::-webkit-scrollbar{width:4px}
.sidebar-nav-scroll::-webkit-scrollbar-track,.global-right-sidebar ::-webkit-scrollbar-track,.cr-members-sidebar::-webkit-scrollbar-track{background:transparent}
.sidebar-nav-scroll::-webkit-scrollbar-thumb,.global-right-sidebar ::-webkit-scrollbar-thumb,.cr-members-sidebar::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:4px}
.sidebar-nav-scroll::-webkit-scrollbar-thumb:hover,.global-right-sidebar ::-webkit-scrollbar-thumb:hover,.cr-members-sidebar::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.22)}
.notif-list{overflow-y:auto;padding:4px 0}
.notif-item{
  display:flex;align-items:flex-start;gap:10px;padding:10px 14px;cursor:pointer;
  transition:background .12s;border-left:3px solid transparent;
}
.notif-item:hover{background:rgba(255,255,255,.04)}
.notif-item.unread{border-left-color:var(--coral);background:rgba(124,92,255,.04)}
.notif-icon{font-size:15px;line-height:1;margin-top:1px;flex-shrink:0;color:var(--coral,#8c72db);display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px}
.notif-icon svg{width:16px;height:16px;display:block}
.notif-body{flex:1;min-width:0}
.notif-title{font-size:13px;font-weight:600;color:var(--off-white);line-height:1.3}
.notif-text{font-size:12px;color:var(--muted);line-height:1.4;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.notif-time{font-size:11px;color:var(--muted);margin-top:3px;opacity:.7;display:flex;align-items:center;gap:7px}
/* Workspace chip — shows which workspace an aggregated notification came from. */
.notif-ws{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.2px;color:var(--lilac,#a99bff);background:rgba(124,92,255,.14);border-radius:5px;padding:1px 6px;opacity:1;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.notif-empty{padding:30px 14px;text-align:center;font-size:12px;color:var(--muted)}
.profile-modal{max-width:500px}
.profile-modal h3{font-family:var(--serif);font-size:24px;font-weight:400;margin-bottom:4px;color:var(--off-white)}
.profile-modal-sub{font-size:12px;color:var(--muted);margin-bottom:18px}
.profile-form-grid{display:grid;gap:10px}
.profile-form-row{display:grid;gap:6px}
.profile-form-row label{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.4px}
.profile-input,.profile-textarea{
  width:100%;padding:10px 12px;border-radius:8px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.04);color:var(--cream);font-family:var(--sans);font-size:13px;outline:none;
}
.profile-input:focus,.profile-textarea:focus{border-color:var(--coral)}
.profile-textarea{min-height:90px;resize:vertical;line-height:1.5}
.profile-modal-avatar{display:flex;align-items:center;gap:12px;padding:10px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.02)}
.profile-modal-avatar .profile-avatar{width:52px;height:52px;min-width:52px;min-height:52px;flex:0 0 52px;font-size:18px}
.profile-modal-avatar-note{font-size:11px;color:var(--muted);line-height:1.4}
.profile-upload-controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.profile-upload-controls .topbar-btn{padding:7px 12px;border-radius:6px;font-size:11px}
.profile-upload-status{font-size:11px;color:var(--muted);line-height:1.4;word-break:break-word}
.profile-modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}
.profile-cancel-btn{padding:8px 14px;border-radius:8px;background:none;border:1px solid var(--border-d);color:var(--muted);font-family:var(--sans);font-size:12px;cursor:pointer}
.profile-cancel-btn:hover{color:var(--cream);border-color:rgba(255,255,255,.2)}
.profile-save-btn{padding:8px 16px;border-radius:8px;background:var(--coral);border:none;color:#fff;font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer}
.profile-save-btn:hover{opacity:.88}
.profile-save-btn:disabled{opacity:.6;cursor:default}

/* CONTENT & PAGES */
.content{padding:28px 36px 60px;flex:1;min-width:0;overflow-y:auto;overflow-x:hidden}
.page{display:none;opacity:0}
/* Page-load / data / card / column entrance animations removed per request — pages and items
   appear instantly, no fade/pop-in. (Click-pulse + popups keep their interaction animations.)
   NOTE: .page.active MUST restore opacity:1 — the removed pageFadeIn animation (with `forwards`)
   used to be the only thing that did so; without it every active page rendered fully transparent
   (the blank-screen regression from bbe330f). */
.page.active{display:block;opacity:1}
.data-loaded{animation:none}
.kanban-card.card-pop-in{animation:none}
.kanban-col.col-pop-in{animation:none}
/* Click pulse on card open */
@keyframes cardClickPulse{0%{transform:scale(1)}40%{transform:scale(.96)}100%{transform:scale(1)}}
.kanban-card.card-click-pulse{animation:cardClickPulse .25s cubic-bezier(.22,1,.36,1)}
/* Project content entrance — a blur+fade the JS applies (renderWorkshopCurrentView) to the ACTIVE
   view container on the FIRST content paint of a board-open, so the async-loaded board eases in
   instead of hard-popping. Deliberately NOT on the .page container (page-level fade reintroduced
   the empty-page flash from bbe330f) and NOT on view-tab switches / internal re-renders (the JS
   flag only fires once per navigateToChildWorkshop). */
@keyframes cwContentEnter{from{opacity:0;filter:blur(10px)}to{opacity:1;filter:blur(0)}}
.cw-content-enter{animation:cwContentEnter .34s cubic-bezier(.22,.61,.36,1) both;will-change:opacity,filter}
@media(prefers-reduced-motion:reduce){.cw-content-enter{animation:none}}

/* STAT CARDS */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:28px}
.stat-card{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:12px;padding:22px;transition:box-shadow .2s,transform .2s}
.stat-card:hover{box-shadow:0 4px 24px rgba(0,0,0,.3);transform:translateY(-1px)}
.stat-label{font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;color:var(--muted);margin-bottom:6px;display:flex;align-items:center;gap:6px}
.stat-label .dot{width:7px;height:7px;border-radius:50%}
.stat-value{font-family:var(--serif);font-size:32px;font-weight:600;line-height:1.1;margin-bottom:3px;color:var(--off-white)}
.stat-change{font-size:11px;font-weight:600}
.stat-change.up{color:var(--green)}.stat-change.down{color:var(--danger-text)}.stat-change.neutral{color:var(--muted)}

/* PANELS */
.panels{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:28px}
.panel{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:12px;padding:24px}
.panel-wide{grid-column:1/-1}
.panel-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}
.panel-title{font-size:13px;font-weight:700;display:flex;align-items:center;gap:8px;color:var(--off-white)}
.panel-action{font-size:11px;font-weight:600;color:var(--coral);text-decoration:none;cursor:pointer;transition:color .15s}
.panel-action:hover{color:var(--pink)}

/* TOOLS HUB */
.tools-hub-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.tools-hub-card{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:14px;padding:28px 24px;cursor:pointer;transition:all .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px}
.tools-hub-card:hover{background:var(--state-hover);transform:translateY(-3px);box-shadow:0 8px 32px rgba(0,0,0,.3);border-color:var(--coral)}
.tools-hub-icon{font-size:36px;line-height:1}
.tools-hub-name{font-size:15px;font-weight:700;color:var(--off-white)}
.tools-hub-desc{font-size:11px;color:var(--muted);line-height:1.4}
.tools-hub-ext{font-size:9px;color:var(--muted);opacity:.5;display:flex;align-items:center;gap:3px;margin-top:2px}
.tools-hub-card{position:relative}
.tools-hub-fav{position:absolute;top:10px;right:10px;background:none;border:none;cursor:pointer;font-size:18px;color:var(--muted);opacity:.4;transition:all .2s;padding:4px;line-height:1;z-index:2}
.tools-hub-fav:hover{opacity:1;color:var(--gold);transform:scale(1.2)}
.tools-hub-fav.active{opacity:1;color:var(--gold)}
.tools-hub-fav.active:hover{color:var(--coral)}
.tools-hub-create{border-style:dashed!important;opacity:.65}
.tools-hub-create:hover{opacity:1}
.tools-hub-shared-badge{font-size:9px;color:var(--muted);opacity:.6;display:flex;align-items:center;gap:3px;margin-top:2px}
.tools-hub-menu-wrap{position:absolute;top:10px;left:10px;z-index:3}
.tools-hub-menu-btn{
  width:24px;height:24px;border-radius:6px;border:1px solid var(--border-d);
  background:rgba(0,0,0,.22);color:var(--muted);font-size:14px;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;opacity:.7;transition:all .15s;
}
.tools-hub-menu-btn:hover{opacity:1;color:var(--off-white);border-color:rgba(255,255,255,.2)}
.tools-hub-menu{
  display:none;position:absolute;top:28px;left:0;min-width:140px;background:var(--dark);
  border:1px solid var(--border-d);border-radius:8px;padding:4px 0;box-shadow:0 8px 24px rgba(0,0,0,.5)
}
.tools-hub-menu.open{display:block}
.tools-hub-menu button{
  display:block;width:100%;text-align:left;padding:7px 12px;background:none;border:none;
  color:var(--cream);font-family:var(--sans);font-size:12px;cursor:pointer
}
.tools-hub-menu button:hover{background:rgba(255,255,255,.06)}
.tools-hub-menu button.danger{color:var(--danger-text)}
.tools-hub-menu button.danger:hover{background:rgba(239,68,68,.1)}
/* Read-only card modal — hide comment delete buttons */
.card-modal-readonly button[onclick*="deleteCardComment"]{display:none}
.card-modal-readonly .inline-field-form{display:none}
.card-modal-readonly button[onclick*="removeCardCustomField"]{display:none}
.card-modal-readonly button[onclick*="openFieldModalFromCard"]{display:none}
.card-modal-readonly .property-preset-picker{display:none}
.card-modal-readonly button[onclick*="removeFieldTag"]{display:none}
.card-modal-readonly #cardCommentAttachBtn,.card-modal-readonly #cardCommentMicBtn{display:none!important}
.property-preset-item:hover{background:rgba(255,255,255,.06)}
.property-preset-item:active{background:rgba(255,255,255,.1)}
.card-modal-readonly #cardModalTagEditor,.card-modal-readonly #cardDescToolbar{display:none!important}
/* Sidebar Divider — "my apps" hover */
.sidebar-divider{display:flex;align-items:center;gap:0;margin:8px 16px;height:16px;cursor:default;position:relative}
.sidebar-divider-line{flex:1;height:1px;background:var(--border-d);transition:all .35s ease}
.sidebar-divider-label{font-size:9px;font-weight:600;letter-spacing:1.2px;text-transform:uppercase;color:var(--muted);opacity:0;max-width:0;overflow:hidden;white-space:nowrap;transition:all .35s ease;padding:0}
.sidebar-divider:hover .sidebar-divider-label{opacity:.7;max-width:80px;padding:0 8px}
.sidebar-divider:hover .sidebar-divider-line{flex:1}
.sidebar-divider-label-always{opacity:.5!important;max-width:80px!important;padding:0 8px!important}
.sidebar-divider:hover .sidebar-divider-label-always{opacity:.7!important}
.sidebar-divider-clickable{cursor:pointer}
.sidebar-divider-clickable:hover{background:rgba(255,255,255,.02);border-radius:4px}
.sidebar-divider-actions{display:flex;gap:2px;opacity:0;transition:opacity .15s;margin-left:2px;flex-shrink:0}
.sidebar-divider:hover .sidebar-divider-actions{opacity:1}
.sidebar-divider.collapsed .sidebar-divider-label-always{opacity:.3!important}
.sidebar-add-category-btn{opacity:0;transition:opacity .2s;cursor:pointer}
.sidebar-add-category-btn:hover{opacity:.7!important}
.sidebar:hover .sidebar-add-category-btn{opacity:.25}
.sidebar-cat-item{display:flex;align-items:center;gap:8px;padding:7px 12px 7px 30px;font-size:12px;color:var(--muted);text-decoration:none;border-radius:6px;transition:color .15s ease,background .15s ease;cursor:default;user-select:none;-webkit-user-select:none}
.sidebar-cat-item:hover{background:rgba(255,255,255,.035);color:var(--off-white)}
.sidebar-cat-item.active{color:var(--off-white)}
/* A folder's colour has to reach the projects inside it.
   --muted is declared under html[data-brand="saucemedia"], NOT at the root, so on any
   other brand it resolves to nothing — which makes color-mix() invalid at computed-value
   time, and an invalid value drops the whole declaration. The rows then inherited plain
   white and folder colours vanished entirely. The literal fallback is the same value that
   block defines, so nothing changes on saucemedia and every other brand starts working. */
.sidebar-cat-colored .sidebar-cat-item{color:color-mix(in srgb,var(--cat-color) 55%,var(--muted,#999990))}
.sidebar-cat-colored .sidebar-cat-item:hover{color:var(--cat-color)}
.sidebar-cat-colored .sidebar-cat-item.active{color:var(--cat-color)}
/* The icon carries the folder's colour at FULL strength — matching the folder header —
   while the label stays softened, so the row reads as "inside that folder" at a glance.
   A project with its own icon tint sets an inline colour on the glyph and still wins. */
.sidebar-cat-colored .sidebar-cat-item .fav-icon{color:var(--cat-color)}
/* ...and so does the LABEL. Owner: "the text color for stuff inside folders does not match
   the folder color — make the text the same as the icon". Replaces the 55% mix toward
   --muted that made a child read a shade off its own folder. */
.sidebar-cat-colored .sidebar-cat-item,
.sidebar-cat-colored .sidebar-cat-child .sidebar-channel-name{color:var(--cat-color)}
.sidebar-cat-colored .sidebar-cat-child .sidebar-channel-name{color:color-mix(in srgb,var(--cat-color) 55%,var(--muted,#999990))}
.sidebar-cat-colored .sidebar-cat-child:hover .sidebar-channel-name{color:var(--cat-color)}
.sidebar-cat-colored .sidebar-cat-child .sidebar-channel-icon svg{stroke:color-mix(in srgb,var(--cat-color) 45%,var(--muted,#999990))}
.sidebar-cat-colored .sidebar-cat-child:hover .sidebar-channel-icon svg{stroke:var(--cat-color)}
.sidebar-cat-colored .sidebar-section-label:hover .sidebar-section-name{color:var(--cat-color)}
.sidebar-section-nav .sidebar-cat-item{padding-left:30px}
.sidebar-cat-item .fav-icon{font-size:14px;line-height:1;width:18px;text-align:center;flex-shrink:0}
.sidebar-cat-item .fav-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Sidebar Favorites */
.sidebar-fav-nav a{display:flex;align-items:center;gap:10px;padding:8px 12px 8px 16px;font-size:14px;color:var(--muted);text-decoration:none;border-radius:6px;transition:color .15s ease,background .15s ease;cursor:default;position:relative;user-select:none;-webkit-user-select:none}
.sidebar-fav-nav a.active{color:var(--off-white);background:var(--bg-inset)}
.sidebar-fav-nav a.active::before{content:'';position:absolute;left:0;top:4px;bottom:4px;width:3px;background:var(--coral);border-radius:0 3px 3px 0}
.sidebar-fav-nav a:hover{background:rgba(255,255,255,.035);color:var(--off-white)}
.sidebar-fav-nav a .fav-icon{font-size:16px;line-height:1;width:20px;text-align:center;flex-shrink:0}
.sidebar-fav-nav a .fav-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sidebar-fav-nav a .fav-remove{opacity:0;font-size:11px;color:var(--muted);cursor:pointer;padding:2px 4px;border-radius:4px;transition:all .15s;flex-shrink:0}
.sidebar-fav-nav a:hover .fav-remove{opacity:.6}
.sidebar-fav-nav a .fav-remove:hover{opacity:1;color:var(--danger-text);background:rgba(239,68,68,.1)}
/* Sidebar context menu */
.sidebar-ctx-menu{position:fixed;z-index:9010;min-width:160px;background:var(--glass-bg);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);opacity:1;border:1px solid var(--glass-border);border-radius:14px;box-shadow:var(--glass-shadow);padding:4px;font-size:12px}
.sidebar-ctx-menu button{display:flex;align-items:center;gap:8px;width:100%;background:none;border:none;color:var(--cream);padding:8px 14px;cursor:pointer;font-size:12px;font-family:inherit;text-align:left;border-radius:6px;transition:background .12s}
.sidebar-ctx-menu button:hover{background:var(--state-hover)}
.sidebar-ctx-menu button.ctx-danger{color:var(--danger-text)}
.sidebar-ctx-menu button.ctx-danger:hover{background:rgba(239,68,68,.1)}
.sidebar-ctx-menu .ctx-sep{height:1px;background:var(--border-d);margin:4px 0}
/* Richer "+" create menu (Folder / Project) with icon + title + description. */
.sidebar-create-menu{min-width:252px;padding:6px}
.sidebar-create-menu button{align-items:flex-start;gap:12px;padding:10px 12px}
.sidebar-create-menu .scm-ic{flex-shrink:0;width:22px;height:22px;display:flex;align-items:center;justify-content:center;color:var(--cream);margin-top:1px}
.sidebar-create-menu .scm-ic svg{width:20px;height:20px}
.sidebar-create-menu .scm-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.sidebar-create-menu .scm-title{font-size:14px;font-weight:600;color:var(--off-white)}
.sidebar-create-menu .scm-desc{font-size:12px;color:var(--muted);font-weight:400}
.sidebar-create-menu .scm-section{font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);padding:8px 12px 3px}
/* "+" button on the Sauce Media home row that opens the create menu. */
/* "+" create button next to the agency name. Visible by default (so the
   owner/admin always sees it); only hidden for explicit client-mode users. */
.sidebar-home-add{position:absolute;top:0;bottom:0;right:8px;display:flex;align-items:center;padding:0 6px;background:none;border:none;cursor:pointer;color:var(--muted);z-index:4;opacity:0;transition:opacity .15s;pointer-events:auto}
.sidebar-home-add svg{width:17px;height:17px}
.sidebar-home-add:hover{color:var(--off-white)}
.sidebar-clients-wrap:hover .sidebar-home-add,.sidebar-home-add:hover{opacity:1}
body[data-shuttle-mode="client"] .sidebar-home-add{opacity:0;pointer-events:none}
/* Automations is an agency feature — hide it from client-facing users. */
body[data-shuttle-mode="client"] [data-footer-tab="automations"]{display:none}
/* Footer nav (Automations + Trash) — use a compact item scale, NOT the oversized 15px/700/24px-icon
   top-level .sidebar-nav style, so they match the rest of the sidebar items. */
#sidebarFooterNav a{display:flex;align-items:center;gap:12px;height:40px;padding:0 12px;min-height:0;border-radius:10px;font-size:14px;font-weight:600;color:rgba(235,235,245,0.62)}
#sidebarFooterNav a svg{width:18px;height:18px;opacity:.85}
#sidebarFooterNav a:hover{color:var(--white)}
.sidebar-ctx-menu .ctx-submenu-wrap{position:relative}
.sidebar-ctx-menu .ctx-submenu{display:none;position:absolute;left:100%;top:-4px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:4px;min-width:160px;z-index:9011;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.sidebar-ctx-menu .ctx-submenu-wrap:hover .ctx-submenu{display:block}
.sidebar-ctx-menu .ctx-submenu button{padding:6px 12px;font-size:12px}
.sidebar-ctx-menu .ctx-arrow{margin-left:auto;opacity:.4;font-size:10px}
.sidebar-ctx-menu .ctx-check{width:16px;text-align:center;flex-shrink:0;font-size:14px;opacity:.7}
.sidebar-ctx-menu .ctx-subtitle{margin-left:auto;font-size:10px;color:var(--muted)}
.edit-ctx-menu{position:fixed;z-index:9999;min-width:180px;background:var(--glass-bg);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:1px solid var(--glass-border);border-radius:14px;box-shadow:var(--glass-shadow);padding:4px;font-size:12px}
.edit-ctx-menu button{display:flex;align-items:center;gap:10px;width:100%;background:none;border:none;color:var(--cream);padding:7px 14px;cursor:pointer;font-size:12px;font-family:inherit;text-align:left;border-radius:6px;transition:background .12s}
.edit-ctx-menu button:hover{background:var(--state-hover)}
.edit-ctx-menu button:disabled{opacity:.3;cursor:default;pointer-events:none}
.edit-ctx-menu button .ctx-shortcut{margin-left:auto;font-size:10px;color:var(--muted);font-family:var(--sans);letter-spacing:.3px}
.edit-ctx-menu .ctx-sep{height:1px;background:var(--border-d);margin:3px 0}
.sidebar-fav-nav a.fav-dragging{opacity:.22;cursor:grabbing;transform:scale(.985)}
.sidebar-fav-nav a.fav-drop-target{background:rgba(255,255,255,.1);color:var(--off-white)}
.sidebar-fav-drop-marker{height:2px;border-radius:2px;margin:2px 12px 2px 18px;background:var(--coral);box-shadow:0 0 0 1px rgba(124,92,255,.32)}
.sidebar-fav-ghost{
  position:fixed;z-index:9005;pointer-events:none;opacity:.9;
  box-shadow:0 12px 40px rgba(0,0,0,.5);transform:rotate(2deg);
}

.sidebar-fav-label {
  display: flex; align-items: center; padding: 20px 10px 6px 10px;
  cursor: pointer; user-select: none; -webkit-user-select: none; gap: 4px;
}
.sidebar-fav-label:hover { background: rgba(255,255,255,.02); }
.sidebar-fav-caret {
  width: 10px; height: 10px; flex-shrink: 0;
  fill: none; stroke: var(--muted); stroke-width: 2.5;
  transition: transform .15s ease; transform: rotate(0deg);
}
.sidebar-fav-label.collapsed .sidebar-fav-caret { transform: rotate(-90deg); }
.sidebar-fav-label > span:first-of-type {
  font-size: 9px; font-weight: 700; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--muted); flex: 1;
}
.sidebar-fav-label:hover > span:first-of-type { color: rgba(255,255,255,.65); }
.sidebar-fav-actions { display: flex; gap: 2px; opacity: 0; transition: opacity .15s; margin-left: auto; }
.sidebar-fav-label:hover .sidebar-fav-actions { opacity: 1; }
.sidebar-fav-add {
  display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 3px;
  background: none; border: none; color: var(--muted);
  font-size: 14px; cursor: pointer; transition: all .1s; padding: 0;
}
.sidebar-fav-add:hover { color: var(--off-white); background: rgba(255,255,255,0.08); }
.sidebar-fav-nav { overflow: hidden; transition: max-height .2s ease; }
.sidebar-fav-nav.collapsed { max-height: 0 !important; }

/* ── Sidebar Channels & DMs ── */
.sidebar-section-label {
  display: flex; align-items: center; padding: 12px 12px 6px 12px;
  cursor: pointer; user-select: none; -webkit-user-select: none; gap: 5px;
}
.sidebar-section-label:hover { background: rgba(255,255,255,.02); }
.sidebar-section-caret {
  width: 12px; height: 12px; flex-shrink: 0;
  fill: none; stroke: var(--muted); stroke-width: 2.5;
  transition: transform .15s ease; transform: rotate(0deg);
}
.sidebar-section-label.collapsed .sidebar-section-caret { transform: rotate(-90deg); }
/* Folder icon replacing the caret on category headers — closed when collapsed,
   open when expanded (no rotation; the path itself conveys open/closed state). */
.sidebar-section-folder { width: 18px; height: 18px; flex-shrink: 0; fill: none; stroke: rgba(235,235,245,.82); }
/* The folder label lines its icon and its text up with every other sidebar row: the
   glyph sits in the same 20px .fav-icon box, and the 10px gap puts the name on the
   same x as the project and channel names below it (a 5px gap put it 10px left). */
.sidebar-cat-label { gap: 10px; }
.sidebar-cat-label > .fav-icon { display: flex; align-items: center; justify-content: center; width: 20px; flex-shrink: 0; }
.sidebar-section-name {
  font-size: 11px; font-weight: 700; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--muted); flex: 1;
}
.sidebar-section-label:hover .sidebar-section-name { color: rgba(255,255,255,.65); }
.sidebar-section-actions { display: flex; gap: 2px; opacity: 0; transition: opacity .15s; margin-left: auto; }
.sidebar-section-label:hover .sidebar-section-actions { opacity: 1; }
.sidebar-section-add {
  display: flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 3px;
  background: none; border: none; color: var(--muted);
  font-size: 16px; cursor: pointer; transition: all .1s; padding: 0;
}
.sidebar-section-add:hover { color: var(--off-white); background: var(--state-hover); }
.sidebar-section-nav { padding: 0; overflow: hidden; transition: max-height .2s ease; }
.sidebar-section-nav.collapsed { max-height: 0 !important; }
.sidebar-section-nav a {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px 8px 16px;
  font-size: 14px; color: var(--muted); text-decoration: none;
  border-radius: 6px; transition: all .15s; cursor: default;
  position: relative; user-select: none; -webkit-user-select: none;
}
.sidebar-section-nav a.active { color: var(--text-1); }
.sidebar-section-nav a.active::before {
  content: ''; position: absolute; left: 0; top: 4px; bottom: 4px;
  width: 3px; background: var(--coral); border-radius: 0 3px 3px 0;
}
.sidebar-section-nav a:hover { background: rgba(255,255,255,.06); color: var(--off-white); }
.sidebar-channel-icon { font-size: 16px; line-height: 1; width: 20px; text-align: center; flex-shrink: 0; opacity: .7; display: flex; align-items: center; justify-content: center; }
.sidebar-channel-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-channel-voice-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex-shrink: 0; box-shadow: 0 0 4px rgba(115,172,131,.5); }
.sidebar-dragging { opacity:.4 }
.sidebar-drag-over { background:var(--state-hover); box-shadow:inset 0 -2px 0 var(--coral); }
/* Unified sidebar drag */
#sidebarUnifiedItems > [data-sidebar-idx] { cursor: pointer; }
.sidebar-unified-dragging { opacity: .22; cursor: grabbing !important; }
.sidebar-unified-drop-marker { height: 2px; margin: 2px 12px; background: var(--coral); border-radius: 2px; box-shadow: 0 0 0 1px rgba(124,92,255,.32); pointer-events: none; }
.sidebar-unified-ghost { position: fixed; z-index: 9005; pointer-events: none; opacity: .9; box-shadow: 0 12px 40px rgba(0,0,0,.5); transform: scale(.95) rotate(2deg); transition: transform .1s; background: var(--bg-dark); border-radius: 6px; }
.sidebar-cat-drop-target { outline: 2px solid var(--coral); outline-offset: -2px; border-radius: 6px; background: rgba(124,92,255,.06); }
.sidebar-cat-child { cursor: pointer; }
.sidebar-cat-child .sidebar-section-nav a { padding-left: 30px; }
/* Category tree connector lines.
   These used to be written as .sidebar-cat-wrapper > .sidebar-section-nav > …, but the
   folder-collapse animation added a grid shell (.sidebar-cat-body) between the wrapper and
   the nav. That extra level broke every one of these direct-child selectors at once and the
   tree silently disappeared. Both shapes are matched now so neither can drop it again.
   The trunk drops from the folder glyph's centre (its 20px box starts at the row's 16px
   padding, so centre = 26px) and the tick runs out to 36px, exactly where a nested row's
   own icon box begins. */
.sidebar-cat-wrapper > .sidebar-section-nav > .sidebar-cat-item,
.sidebar-cat-wrapper > .sidebar-section-nav > .sidebar-cat-child,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > .sidebar-cat-item,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > .sidebar-cat-child { position: relative; }
.sidebar-cat-wrapper > .sidebar-section-nav > .sidebar-cat-item::after,
.sidebar-cat-wrapper > .sidebar-section-nav > .sidebar-cat-child::after,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > .sidebar-cat-item::after,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > .sidebar-cat-child::after {
  content: ''; position: absolute; left: 25px; top: 0; height: 100%; width: 11px;
  /* The folder's own colour at full strength — the glyph's colour, not a tint of it. An
     uncoloured folder falls back to whatever its glyph is drawn in (see --sb-tree). */
  border-left: 1px solid var(--cat-color, var(--sb-tree)); opacity: 1; pointer-events: none;
  background: linear-gradient(var(--cat-color, var(--sb-tree)), var(--cat-color, var(--sb-tree))) no-repeat 0 50% / 100% 1px;
}
.sidebar-cat-wrapper > .sidebar-section-nav > .sidebar-cat-item:last-child::after,
.sidebar-cat-wrapper > .sidebar-section-nav > .sidebar-cat-child:last-child::after,
.sidebar-cat-wrapper > .sidebar-section-nav > a.sidebar-cat-item:last-of-type::after,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > .sidebar-cat-item:last-child::after,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > .sidebar-cat-child:last-child::after,
.sidebar-cat-wrapper > .sidebar-cat-body > .sidebar-section-nav > a.sidebar-cat-item:last-of-type::after {
  height: 50%; border-bottom: 1px solid var(--cat-color, var(--sb-tree));
  border-radius: 0 0 0 6px; background: none;
}
.sidebar-drop-highlight { outline: 2px dashed var(--coral); outline-offset: -2px; border-radius: 6px; background: rgba(124,92,255,.06); }
.group-table-row[draggable] { cursor: grab; }
.sidebar-cat-label { cursor: pointer; }
/* #2 — folders should read like normal sidebar items, not retro VCRMono section headers */
.sidebar-section-label.sidebar-cat-label,
.sidebar-section-label.sidebar-cat-label .sidebar-section-name { font-family: var(--sans); letter-spacing: normal; text-transform: none; font-size: 14px; font-weight: 500; }
.sidebar-notif-dot { width:8px; height:8px; border-radius:50%; background:var(--coral); flex-shrink:0; margin-left:auto; animation:notifPulse 2s ease infinite; }
@keyframes notifPulse { 0%,100%{opacity:1} 50%{opacity:.5} }
.sidebar-section-label .sidebar-section-notif { width:6px; height:6px; border-radius:50%; background:var(--coral); display:none; margin-left:6px; flex-shrink:0; }
.sidebar-section-label .sidebar-section-notif.has-notif { display:inline-block; }
.sidebar-dm-avatar { width: 18px; height: 18px; border-radius: 50%; background: rgba(255,255,255,.08); color: var(--muted); font-size: 8px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; overflow: hidden; }
.sidebar-dm-avatar img { width: 100%; height: 100%; object-fit: cover; }
.sidebar-section-empty { padding: 6px 18px; font-size: 11px; color: var(--muted); opacity: .4; font-style: italic; display: block; }
/* User picker rows (used by forward-message picker) */
.dm-user-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px; cursor: pointer; transition: background .15s; }
.dm-user-row:hover { background: rgba(255,255,255,.06); }
.dm-user-row.selected { background: rgba(115,172,131,.1); }
.mv-mention-dot{width:8px;height:8px;border-radius:50%;background:var(--coral);margin-left:auto;flex-shrink:0;animation:dmBadgePop .25s ease}
@keyframes dmBadgePop{0%{transform:scale(0)}70%{transform:scale(1.15)}100%{transform:scale(1)}}
/* Link embeds */
.msg-link { color:var(--blue); text-decoration:none; word-break:break-all; }
.msg-link:hover { text-decoration:underline; }
.msg-embed { margin-top:6px; border-left:3px solid var(--lp-accent,var(--coral)); background:var(--surface-container); border-radius:0 8px 8px 0; padding:10px 14px; max-width:480px; position:relative; }
/* The site's own brand colour paints the bar once the preview lands (--lp-accent),
   which is what makes an unfurl recognisable at a glance. Until then it is the
   product accent, so a card is never unstyled. */
.msg-embed-site { font-size:11px; color:var(--muted); margin-bottom:3px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.msg-embed-author { font-size:12px; font-weight:700; color:var(--cream); margin-bottom:2px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.msg-embed-link .msg-embed-title { white-space:normal; }
.msg-embed-link .msg-embed-desc:empty { display:none; }
.msg-embed-link .msg-embed-img { display:block; width:100%; max-height:260px; object-fit:cover; }
/* Play-in-place: the thumbnail IS the poster, so the button is a bare wrapper with a
   glyph over it rather than a second surface. */
.msg-embed-play{display:block;position:relative;width:100%;padding:0;border:none;background:none;cursor:pointer;border-radius:6px;overflow:hidden;margin-top:8px}
.msg-embed-play .msg-embed-img{margin-top:0}
.msg-embed-play-btn{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:54px;height:54px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.62);color:#fff;transition:background .15s ease,transform .15s ease;pointer-events:none}
.msg-embed-play:hover .msg-embed-play-btn{background:var(--lp-accent,rgba(0,0,0,.82));transform:translate(-50%,-50%) scale(1.06)}
.msg-embed-play:focus-visible{outline:2px solid var(--lp-accent,var(--purple));outline-offset:2px}
.msg-embed-frame{display:block;width:100%;aspect-ratio:16/9;border:0;border-radius:6px;margin-top:8px;background:#000}
.msg-embed-title { font-size:13px; font-weight:600; color:var(--blue); margin-bottom:3px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.msg-embed-title a { color:var(--blue); text-decoration:none; }
.msg-embed-title a:hover { text-decoration:underline; }
.msg-embed-desc { font-size:12px; color:var(--muted); line-height:1.4; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.msg-embed-domain { font-size:10px; color:var(--muted); opacity:.6; margin-top:4px; }
.msg-embed-close { position:absolute; top:6px; right:8px; width:18px; height:18px; border-radius:4px; border:none; background:rgba(255,255,255,.06); color:var(--muted); font-size:11px; cursor:pointer; display:flex; align-items:center; justify-content:center; opacity:0; transition:all .15s; }
.msg-embed:hover .msg-embed-close { opacity:1; }
.msg-embed-close:hover { background:rgba(255,255,255,.12); color:var(--cream); }
.msg-embed-img { margin-top:8px; max-width:100%; max-height:200px; border-radius:6px; object-fit:cover; }
/* Chat message grouping — main styles now in CHAT ROOMS section */

/* Shuttle favorites: always show section area so hover target exists */
.shuttle-fav-section { display: flex !important; }
.shuttle-fav-hover-btn { opacity: 0; transition: opacity .2s ease; }
.shuttle-fav-section:hover .shuttle-fav-hover-btn { opacity: 1; }
.shuttle-fav-empty { display: block; padding: 6px 18px; font-size: 11px; color: var(--muted); opacity: .5; font-style: italic; }

/* Feature Request page */
.feature-req-form { max-width: 560px; }
.feature-req-form label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-bottom: 4px; margin-top: 16px; }
.feature-req-form input, .feature-req-form textarea, .feature-req-form select {
  width: 100%; background: #111110; border: 1px solid var(--border-d); border-radius: 8px;
  color: var(--cream); font-family: var(--sans); font-size: 13px; padding: 10px 12px; resize: vertical;
}
.feature-req-form textarea { min-height: 100px; line-height: 1.5; }
.feature-req-list { margin-top: 32px; border-top: 1px solid var(--border-d); padding-top: 24px; }
.feature-req-card { border: 1px solid var(--border-d); border-radius: 10px; padding: 14px 16px; margin-bottom: 10px; background: rgba(255,255,255,.02); }
.feature-req-card-title { font-size: 14px; font-weight: 600; color: var(--cream); }
.feature-req-card-meta { font-size: 11px; color: var(--muted); margin-top: 4px; }
.feature-req-card-desc { font-size: 12px; color: var(--off-white); margin-top: 8px; line-height: 1.5; }
.feature-req-priority { display: inline-block; font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 4px; text-transform: uppercase; letter-spacing: .5px; }
.feature-req-priority.low { background: rgba(115,172,131,.15); color: var(--green); }
.feature-req-priority.medium { background: rgba(201,180,106,.15); color: var(--gold); }
.feature-req-priority.high { background: rgba(255,107,107,.15); color: var(--prio-high); }

/* Shuttle settings: allowed domains section */
.shuttle-domains-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.shuttle-domain-tag { display: inline-flex; align-items: center; gap: 4px; background: rgba(255,255,255,.06); border: 1px solid var(--border-d); border-radius: 6px; padding: 4px 10px; font-size: 12px; color: var(--cream); }
.shuttle-domain-tag .remove-domain { cursor: pointer; color: var(--muted); font-size: 14px; line-height: 1; }
.shuttle-domain-tag .remove-domain:hover { color: var(--coral); }

/* Shuttle branding: logo drop zone */
.shuttle-logo-drop{display:flex;align-items:center;gap:16px;border:2px dashed var(--border-d);border-radius:10px;padding:20px;cursor:pointer;transition:border-color .2s,background .2s;background:rgba(255,255,255,.02)}
.shuttle-logo-drop:hover,.shuttle-logo-drop.dragover{border-color:var(--coral);background:rgba(124,92,255,.04)}
.shuttle-logo-preview{width:56px;height:56px;border-radius:10px;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--muted);overflow:hidden;flex-shrink:0}
.shuttle-logo-preview img{width:100%;height:100%;object-fit:contain}
.shuttle-logo-drop-text{display:flex;flex-direction:column;gap:2px}

/* Shuttle admin page (Henshu) */
.app-internal-badge{display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:600;color:rgba(180,170,200,.8);background:rgba(140,120,180,.1);padding:2px 8px;border-radius:10px;border:1px solid rgba(140,120,180,.15);letter-spacing:.3px;user-select:none}

/* ═══════ CANVAS DASHBOARD ═══════ */
#page-dashboard{position:fixed;top:var(--topbar-h);left:var(--sidebar-w);right:0;bottom:0;margin:0;padding:0;z-index:1;background:var(--bg-canvas)}
#page-dashboard::after{display:none}




/* Recently Visited Widget */
.rv-grid{display:flex;gap:10px;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin}
.rv-grid::-webkit-scrollbar{height:3px}
.rv-grid::-webkit-scrollbar-track{background:transparent}
.rv-grid::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:999px}
.rv-card{flex:0 0 auto;width:108px;border:1px solid var(--border-d);border-radius:10px;padding:14px 10px 12px;background:rgba(255,255,255,.03);cursor:pointer;transition:all .15s;display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center}
.rv-card:hover{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.18);transform:translateY(-1px);box-shadow:0 4px 16px rgba(0,0,0,.3)}
.rv-icon{font-size:22px;width:42px;height:42px;border-radius:10px;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.rv-name{font-size:12px;font-weight:600;color:var(--cream);line-height:1.3;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.rv-date{font-size:10px;color:var(--muted)}
/* My Tasks Widget */
.my-tasks-board{display:flex;flex-direction:column;gap:14px}
.my-tasks-group{border:1px solid var(--border-d);border-radius:16px;overflow:hidden;background:rgba(255,255,255,.02)}
.my-tasks-group-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;background:rgba(255,255,255,.03);cursor:pointer;transition:background .15s}
.my-tasks-group-head:hover{background:rgba(255,255,255,.05)}
.my-tasks-group-main{display:flex;align-items:center;gap:12px;min-width:0}
.my-tasks-group-accent{width:4px;height:30px;border-radius:999px;flex-shrink:0}
.my-tasks-group-name{font-size:13px;font-weight:800;color:var(--cream);letter-spacing:.08em;text-transform:uppercase}
.my-tasks-group-count{font-size:11px;font-weight:700;color:var(--muted);padding:4px 10px;border-radius:999px;background:rgba(255,255,255,.08)}
.my-tasks-group-caret{font-size:11px;color:var(--muted);transition:transform .15s ease}
.my-tasks-group.collapsed .my-tasks-group-caret{transform:rotate(-90deg)}
.my-tasks-group.collapsed .my-tasks-table-wrap{display:none}
.my-tasks-table-head,.my-tasks-row{display:grid;grid-template-columns:minmax(0,1.8fr) 140px 150px 120px;gap:16px;align-items:center;padding:0 18px}
.my-tasks-table-head{min-height:40px;background:rgba(0,0,0,.12);font-size:10px;font-weight:800;color:var(--muted);letter-spacing:.08em;text-transform:uppercase}
.my-tasks-row{min-height:64px;border-top:1px solid rgba(255,255,255,.05);cursor:pointer;transition:background .15s}
.my-tasks-row:hover{background:rgba(255,255,255,.035)}
.my-tasks-row.is-complete{opacity:.7}
.my-tasks-row.is-complete .my-tasks-task-name{text-decoration:line-through;color:var(--muted)}
.my-tasks-taskcell{min-width:0;display:flex;flex-direction:column;gap:4px}
.my-tasks-task-name{font-size:14px;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.my-tasks-task-sub{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.my-tasks-statuscell,.my-tasks-boardcell,.my-tasks-actioncell{display:flex;align-items:center}
.my-tasks-statuspill{display:inline-flex;align-items:center;justify-content:center;padding:4px 10px;border-radius:7px;font-size:11px;font-weight:700;background:rgba(255,255,255,.08);color:var(--muted);white-space:nowrap}
.my-tasks-boardpill{display:inline-flex;align-items:center;max-width:100%;padding:4px 10px;border-radius:999px;font-size:11px;font-weight:700;background:rgba(255,255,255,.08);color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.my-tasks-actioncell{justify-content:flex-end}
.my-tasks-completebtn{border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.05);color:var(--muted);border-radius:10px;padding:7px 11px;font-size:11px;font-weight:700;cursor:pointer;transition:all .15s;white-space:nowrap}
.my-tasks-completebtn:hover{border-color:rgba(255,255,255,.24);color:var(--cream);background:rgba(255,255,255,.09)}
.my-tasks-completebtn.is-done{border-color:rgba(129,199,132,.28);background:rgba(129,199,132,.14);color:var(--green)}
.my-tasks-completebtn.is-done:hover{border-color:rgba(129,199,132,.4);background:rgba(129,199,132,.2)}
@media (max-width: 900px){
  .my-tasks-table-head,.my-tasks-row{grid-template-columns:minmax(0,1.5fr) 120px 120px 110px}
}
@media (max-width: 720px){
  .my-tasks-table-head{display:none}
  .my-tasks-row{grid-template-columns:minmax(0,1fr) auto;gap:10px;padding-top:14px;padding-bottom:14px}
  .my-tasks-statuscell,.my-tasks-boardcell{grid-column:1 / 2}
  .my-tasks-actioncell{grid-column:2 / 3;grid-row:1 / span 3;align-self:center}
  .my-tasks-taskcell{padding-right:8px}
}

/* Overview (Recap + Calendar) — uses the same layout as a kanban workshop page.
   #page-master-view sits inside .content (which has 28px 36px padding); the
   sticky .workshop-views tab strip and the panes below it inherit that frame.
   The Calendar pane mirrors #workshopCalendarView exactly so the calendar grid
   ends up edge-to-edge with the sidebar (via .calendar-container negative-margin). */
/* Scope to .active so the master-view page doesn't render as a 139px-tall
   ghost above other pages. ID-level specificity was overriding the base
   .page{display:none} rule for non-active pages.
   IDENTICAL layout pattern to #page-workshop.active: escape .content's
   28px top + 60px bottom padding via negative margins, then extend height
   by 88px to reclaim that space. Net effect: the calendar grid grows by
   88px vertically and the Unscheduled bar sits flush against the viewport
   bottom — matching the Studio calendar exactly. */
#page-master-view.active{margin:-28px -36px -60px;height:calc(100% + 88px);display:flex!important;flex-direction:column;overflow:hidden;padding:0!important;min-height:0}
#page-master-view.active>:first-child{margin-top:0!important}
/* Overview header — two centered rows.
     Row 1: filter (left)   ·   Prev / Month / Next (center)   ·   + Add (right)
     Row 2: Day / Week / Month toggle (center)
   The tab-nav wrapper injected by _renderCalendarTabNav has display:contents
   so its children participate directly in this grid. */
#page-master-view.active .workshop-views{
  display:grid !important;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas:
    "filter month-nav add"
    "view-tg view-tg view-tg";
  align-items:center;gap:8px 12px;
  position:relative!important;top:auto!important;flex-shrink:0;
  padding:12px 36px!important;margin:0 0 8px!important;
  border-bottom:1px solid var(--border-d);
  min-height:0!important;height:auto!important
}
#page-master-view.active .workshop-views > [data-cal-tab-nav]{display:contents}
#page-master-view.active .workshop-views .mv-filter-wrap{grid-area:filter;justify-self:start}
#page-master-view.active .workshop-views .cal-month-nav{grid-area:month-nav;justify-self:center}
#page-master-view.active .workshop-views .mv-add-btn{grid-area:add;justify-self:end;margin:0 !important}
#page-master-view.active .workshop-views .cal-view-toggle{grid-area:view-tg;justify-self:center}
#page-master-view.active .workshop-views .cal-month-nav .workshop-view-btn[data-cal-tab-nav-label]{
  font-size:15px;font-weight:700;min-width:160px
}
/* Calendar pane — IDENTICAL inset to #workshopCalendarView (padding:14px 36px 28px).
   No negative margins (the page itself escapes .content's padding). */
#mvCalendarPane{flex:1;min-height:0;overflow-y:auto;padding:14px 36px 28px;display:flex;flex-direction:column}
#mvCalendarPane .calendar-toolbar{margin-bottom:6px;margin-top:6px;padding:0 12px}
/* Responsive padding match — mirrors the workshop calendar's responsive rules. */
@media(max-width:900px){
  #page-master-view.active .workshop-views{padding:12px 16px 10px!important}
  #mvCalendarPane{padding:10px 16px 20px}
}
@media(max-width:768px){
  #page-master-view.active .workshop-views{padding:10px 12px 8px!important}
  #mvCalendarPane{padding:8px 12px 20px}
}
/* "Go to item" button (injected by mvDecorateModal) — color tracks the card's
   column status color via the kanban modal's existing --modal-col-color var. */
/* Overview calendar chip — custom layout:
     [workspace avatar] CLIENT NAME: TITLE         (one line if it fits)
                       [STATUS PILL]
   When the title is too long it wraps after the colon's trailing space:
     [workspace avatar] CLIENT NAME:
                        TITLE
                       [STATUS PILL]
   Applies only to master-view chips (data-workshop-id="__master__"). */
.calendar-day-card[data-workshop-id="__master__"] .cdc-line{align-items:flex-start;gap:6px}
.calendar-day-card[data-workshop-id="__master__"] img.mv-chip-avatar,
.calendar-day-card[data-workshop-id="__master__"] span.mv-chip-avatar{width:14px !important;height:14px !important;min-width:14px;max-width:14px;border-radius:50%;overflow:hidden;flex-shrink:0;display:inline-block;background:rgba(255,255,255,.10);object-fit:cover;padding:0;margin:0;border:0;margin-top:1px}
.calendar-day-card[data-workshop-id="__master__"] .mv-chip-avatar-blank{background:rgba(255,255,255,.10)}
.calendar-day-card[data-workshop-id="__master__"] .cdc-text.mv-chip-text{
  flex:1;min-width:0;
  white-space:normal;          /* override engine's nowrap */
  word-break:break-word;
  overflow:visible;            /* let it grow vertically */
  text-overflow:clip;
  line-height:1.25;
  font-weight:500
}
.calendar-day-card[data-workshop-id="__master__"] .mv-chip-client{
  font-weight:800;letter-spacing:.04em;text-transform:uppercase;font-size:11px;
  color:var(--off-white)
}
.calendar-day-card[data-workshop-id="__master__"] .mv-chip-sep{
  font-weight:700;color:var(--muted);margin-right:1px
}
.calendar-day-card[data-workshop-id="__master__"] .mv-chip-title{
  font-weight:600;letter-spacing:.02em;text-transform:uppercase;font-size:11px;
  color:var(--cream)
}
/* "Go to item" arrow — bare icon sitting right after the title text. No
   container/background; hover just shifts the icon color to the column accent. */
.mv-title-goto{display:inline-flex;align-items:center;justify-content:center;
  background:none;border:0;padding:0;margin:0;color:var(--muted);cursor:pointer;
  vertical-align:middle;flex-shrink:0;line-height:0;
  transition:color .15s,transform .12s ease}
.mv-title-goto:hover{color:var(--modal-col-color, var(--coral));transform:translate(2px,-2px)}
.mv-title-goto:focus-visible{outline:2px solid var(--modal-col-color, var(--coral));outline-offset:2px;border-radius:4px}
.mv-title-goto svg{display:block;pointer-events:none}
/* Lock indicator next to the "Board" property label — signals non-removable. */
.mv-lock-icon{display:inline-flex;align-items:center;margin-left:4px;color:var(--muted);opacity:.55}
.mv-lock-icon svg{display:block}
/* "Board" value pill — sizing, padding, background, radius all match
   .prop-person-pill so it sits flush alongside Producer/Editor/VO Artist. */
.mv-board-pill{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--cream);
  padding:2px 8px 2px 2px;background:rgba(255,255,255,.08);border-radius:999px;
  border:0;font-family:inherit;line-height:1.2;cursor:pointer;transition:background .15s}
.mv-board-pill:hover{background:rgba(255,255,255,.13)}
/* Direct <img> child mirrors prop-person-pill > img. */
.mv-board-pill > img{width:20px;height:20px;border-radius:50%;object-fit:cover;display:block;flex-shrink:0}
/* Initials fallback — mirrors prop-person-initials. */
.mv-board-pill-blank{width:20px;height:20px;border-radius:50%;background:rgba(255,255,255,.12);display:inline-flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:var(--cream);flex-shrink:0}
.mv-board-pill svg{flex-shrink:0;color:var(--muted);opacity:.6}
.mv-board-pill:hover svg{opacity:1}
/* Overview tabs visually match the kanban .workshop-view-btn pattern — both
   Recap and Calendar buttons carry that class. Only the unread-count badge
   needs a small dedicated style. */
.workshop-view-btn.mv-tab{display:inline-flex;align-items:center;gap:6px}
.mv-tab-count{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 6px;border-radius:999px;background:var(--coral);color:#fff;font-size:10px;font-weight:800;line-height:1}
/* Filter button — uses .workshop-view-btn as its base; this section is just
   the funnel/caret icon sizing and the active-state coral accents. */
.workshop-view-btn.mv-filter-btn{display:inline-flex;align-items:center;gap:7px}
.workshop-view-btn.mv-filter-btn svg{width:13px;height:13px;flex-shrink:0;opacity:.88}
.workshop-view-btn.mv-filter-btn .mv-filter-caret{width:11px;height:11px;opacity:.65;transition:transform .15s}
.workshop-view-btn.mv-filter-btn.open .mv-filter-caret{transform:rotate(180deg)}
.workshop-view-btn.mv-filter-btn .mv-filter-count{display:none;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 6px;border-radius:999px;background:var(--coral);color:#fff;font-size:10px;font-weight:800;letter-spacing:0;text-transform:none;line-height:1}
.workshop-view-btn.mv-filter-btn.has-filters{border-color:rgba(124,92,255,.45);color:var(--coral);background:rgba(124,92,255,.09)}
.workshop-view-btn.mv-filter-btn.has-filters .mv-filter-count{display:inline-flex}
/* Filter panel — drops below the button. */
.mv-filter-panel{position:absolute;top:calc(100% + 6px);right:0;min-width:260px;max-width:340px;background:#15151a;border:1px solid var(--border-d);border-radius:10px;box-shadow:0 18px 48px rgba(0,0,0,.55);padding:8px 4px;z-index:9050;animation:mvFilterPop .15s ease-out}
@keyframes mvFilterPop{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.mv-filter-section-title{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:6px 12px 4px}
.mv-filter-row{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:7px;cursor:pointer;transition:background .12s}
.mv-filter-row:hover{background:rgba(255,255,255,.05)}
.mv-filter-row input[type=checkbox]{margin-top:2px;cursor:pointer;accent-color:var(--coral)}
.mv-filter-row-text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.mv-filter-row-label{font-size:12px;font-weight:600;color:var(--cream)}
.mv-filter-row-help{font-size:11px;color:var(--muted);line-height:1.35}
.mv-filter-foot{display:flex;justify-content:flex-end;padding:6px 8px 4px;border-top:1px solid var(--border-d);margin-top:6px}
.mv-filter-clear{background:none;border:0;color:var(--muted);font-size:11px;cursor:pointer;padding:4px 8px;border-radius:5px;font-family:inherit;transition:background .12s,color .12s}
.mv-filter-clear:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.mv-add-btn{background:var(--coral);border:0;color:#fff;padding:6px 14px;border-radius:6px;cursor:pointer;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.mv-add-btn:hover{filter:brightness(1.1)}
.mv-pane{padding:14px 18px 18px}
/* Recap — stat cards row */
.mv-stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:18px}
.mv-stat-card{padding:14px 16px;border-radius:10px;background:var(--bg-inset);border:1px solid var(--border-d);display:flex;flex-direction:column;gap:4px;min-height:84px;position:relative;overflow:hidden}
.mv-stat-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--mv-stat-accent,var(--coral));border-radius:3px 0 0 3px}
.mv-stat-card.is-zero{opacity:.55}
.mv-stat-card.is-zero::before{opacity:.35}
.mv-stat-overdue{--mv-stat-accent:var(--coral)}
.mv-stat-today{--mv-stat-accent:#e7ce3a}
.mv-stat-week{--mv-stat-accent:#73ac83}
.mv-stat-mentions{--mv-stat-accent:#c7abc4}
.mv-stat-label{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.mv-stat-value{font-size:30px;font-weight:800;color:var(--cream);line-height:1;letter-spacing:-.5px;font-variant-numeric:tabular-nums;margin-top:4px}
.mv-stat-sub{font-size:11px;color:var(--muted);margin-top:auto}
@media (max-width:900px){.mv-stats-grid{grid-template-columns:repeat(2,1fr)}}
/* Recap — sections + task rows */
.mv-recap-section{margin-bottom:16px}
.mv-recap-empty{padding:60px 20px;text-align:center;color:var(--muted);font-size:13px}
.mv-recap-empty strong{display:block;color:var(--cream);font-size:14px;margin-bottom:6px}
.mv-recap-empty-thin{padding:18px 14px;text-align:left;font-size:12px}
.mv-recap-more{font-size:11px;color:var(--muted);padding:8px 4px 0;text-align:center}
.mv-task-list{display:flex;flex-direction:column;gap:4px}
.mv-task-row{display:grid;grid-template-columns:minmax(80px,140px) minmax(0,1fr) 70px 22px minmax(60px,140px);gap:12px;align-items:center;padding:10px 12px;background:var(--bg-inset);border:1px solid var(--border-d);border-radius:8px;cursor:pointer;text-decoration:none;color:var(--cream);outline:none;transition:background .12s,border-color .12s,box-shadow .12s,transform .12s}
.mv-task-row:hover{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.18);transform:translateY(-1px)}
.mv-task-row:focus-visible{box-shadow:0 0 0 2px var(--color-brand-tint-strong);border-color:var(--color-primary)}
.mv-task-row.is-overdue{border-color:rgba(239,68,68,.32);background:rgba(239,68,68,.05)}
.mv-task-row.is-today{border-color:rgba(231,206,58,.32);background:rgba(231,206,58,.05)}
.mv-task-status{font-size:10px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;padding:3px 8px;border-radius:4px;background:rgba(255,255,255,.08);color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center}
.mv-task-text{font-size:13px;color:var(--cream);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
.mv-task-due{font-size:11px;color:var(--muted);font-weight:600;text-align:right;white-space:nowrap}
.mv-task-due.is-overdue{color:var(--coral)}
.mv-task-due.is-today{color:#e7ce3a}
/* Workspace icon — circular, matching the avatar treatment used elsewhere in
   the app. overflow:hidden clips any whitespace/halo baked into the source
   image so the icon reads as a proper pfp regardless of how the logo was cropped. */
.mv-task-ws-icon{width:22px;height:22px;border-radius:50%;overflow:hidden;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,.06)}
.mv-task-ws-icon img{width:100%;height:100%;object-fit:cover;display:block}
.mv-task-ws-icon-blank{background:rgba(255,255,255,.04)}
.mv-task-ws-name{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600}
@media (max-width:760px){
  .mv-task-row{grid-template-columns:1fr auto;gap:6px;padding:10px}
  .mv-task-status{grid-column:1 / 2;justify-self:start}
  .mv-task-text{grid-column:1 / -1}
  .mv-task-due{grid-column:1 / 2;justify-self:start;text-align:left}
  .mv-task-ws-icon{grid-column:2 / 3;grid-row:1 / 2}
  .mv-task-ws-name{display:none}
}
/* Recap — per-production pills */
.mv-workspace-pills{display:flex;flex-wrap:wrap;gap:8px;padding-top:4px}
.mv-workspace-pill{display:inline-flex;align-items:center;gap:8px;padding:7px 12px 7px 7px;background:var(--bg-inset);border:1px solid var(--border-d);border-radius:999px;color:var(--cream);text-decoration:none;font-size:12px;transition:background .12s,border-color .12s}
.mv-workspace-pill:hover{background:var(--state-hover);border-color:rgba(255,255,255,.18)}
.mv-workspace-pill-name{font-weight:600}
.mv-workspace-pill-count{font-size:11px;color:var(--muted);background:rgba(255,255,255,.06);padding:1px 7px;border-radius:999px;font-variant-numeric:tabular-nums}
.mv-workspace-pill .mv-task-ws-icon{width:24px;height:24px;border-radius:50%}
.mv-recap-list{display:flex;flex-direction:column;gap:6px}
.mv-recap-section-head{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);padding:14px 4px 6px;display:flex;align-items:center;justify-content:space-between;gap:10px}
.mv-recap-section-head:first-child{padding-top:4px}
.mv-recap-section-head .mv-recap-clear{background:none;border:0;color:var(--muted);font-size:11px;cursor:pointer;text-transform:none;letter-spacing:0;font-weight:600;text-decoration:underline}
.mv-recap-section-head .mv-recap-clear:hover{color:var(--cream)}
/* ── @Mentions recap card (Slack-style one-at-a-time dismissal) ─────────
   Pinned to the top of Overview. Shows the latest unread mention with the
   card title + comment preview, plus Keep Unread / Mark as Read CTAs.
   Hidden entirely when there are no unread mentions. */
.mv-mention-recap{
  margin:0 0 18px;
  background:linear-gradient(180deg,rgba(255,255,255,.04) 0%,rgba(255,255,255,.02) 100%);
  border:1px solid var(--border-d);border-radius:16px;
  overflow:hidden;display:flex;flex-direction:column;
  box-shadow:0 4px 14px rgba(0,0,0,.18)
}
.mv-mention-recap.is-hidden{display:none}
.mv-mention-recap-head{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 18px;border-bottom:1px solid var(--border-d);flex-shrink:0
}
.mv-mention-recap-head .mr-title-wrap{display:flex;align-items:center;gap:10px;min-width:0}
.mv-mention-recap-head .mr-icon{
  width:32px;height:32px;border-radius:9px;
  background:rgba(124,58,237,.16);color:#a78bfa;
  display:inline-flex;align-items:center;justify-content:center;flex-shrink:0
}
.mv-mention-recap-head .mr-icon svg{width:16px;height:16px}
.mv-mention-recap-head .mr-title{
  font-size:13px;font-weight:700;color:var(--cream);
  display:flex;align-items:center;gap:8px;min-width:0
}
.mv-mention-recap-head .mr-count{
  font-size:11px;font-weight:700;color:var(--muted);
  padding:3px 9px;border-radius:999px;background:rgba(255,255,255,.06);
  white-space:nowrap
}
.mv-mention-recap-head .mr-undo{
  background:none;border:0;color:var(--muted);cursor:pointer;
  font-size:13px;font-weight:600;padding:5px 10px;border-radius:8px;
  transition:background .12s,color .12s
}
.mv-mention-recap-head .mr-undo:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.mv-mention-recap-head .mr-undo[disabled]{opacity:.4;pointer-events:none}
.mv-mention-recap-body{
  padding:16px 18px 14px;display:flex;flex-direction:column;gap:10px;cursor:pointer;
  transition:background .12s;-webkit-tap-highlight-color:transparent
}
.mv-mention-recap-body:hover{background:rgba(255,255,255,.025)}
.mv-mention-recap-context{
  display:flex;align-items:center;gap:8px;
  font-size:12px;color:var(--muted);font-weight:500
}
.mv-mention-recap-context .mr-context-icon{
  width:18px;height:18px;border-radius:5px;
  display:inline-flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.06);overflow:hidden;flex-shrink:0
}
.mv-mention-recap-context .mr-context-icon img{width:100%;height:100%;object-fit:cover}
.mv-mention-recap-context .mr-card-title{
  color:var(--cream);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%
}
.mv-mention-recap-context .mr-sep{opacity:.5}
.mv-mention-recap-author{
  display:flex;align-items:center;gap:10px;margin-top:2px
}
.mv-mention-recap-author .mr-author-avatar{width:28px;height:28px;border-radius:50%;flex-shrink:0;overflow:hidden;display:inline-flex;align-items:center;justify-content:center}
.mv-mention-recap-author .mr-author-avatar img{width:100%;height:100%;object-fit:cover}
.mv-mention-recap-author .mr-author-meta{display:flex;flex-direction:column;gap:0;min-width:0}
.mv-mention-recap-author .mr-author-name{font-size:14px;font-weight:600;color:var(--cream);line-height:1.2}
.mv-mention-recap-author .mr-author-time{font-size:11px;color:var(--muted);line-height:1.2}
.mv-mention-recap-text{
  font-size:14px;color:var(--off-white);line-height:1.45;
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;
  overflow:hidden;word-break:break-word
}
.mv-mention-recap-text .mr-at{
  color:#a78bfa;font-weight:600;background:rgba(124,58,237,.12);
  padding:0 4px;border-radius:4px
}
.mv-mention-recap-actions{
  display:flex;align-items:stretch;gap:10px;
  padding:12px 18px 16px;border-top:1px solid var(--border-d);
  background:rgba(255,255,255,.015)
}
.mv-mention-recap-actions .mr-btn{
  flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:13px 14px;border-radius:11px;font-size:14px;font-weight:600;
  cursor:pointer;border:0;transition:background .12s,transform .08s;
  -webkit-tap-highlight-color:transparent
}
.mv-mention-recap-actions .mr-btn:active{transform:scale(.98)}
.mv-mention-recap-actions .mr-btn-keep{
  background:rgba(255,255,255,.05);color:var(--off-white);
  border:1px solid var(--border-d)
}
.mv-mention-recap-actions .mr-btn-keep:hover{background:var(--state-hover)}
.mv-mention-recap-actions .mr-btn-read{
  background:#16a34a;color:#fff;box-shadow:0 1px 0 rgba(255,255,255,.1) inset
}
.mv-mention-recap-actions .mr-btn-read:hover{background:#15803d}
/* Exit animation when a card is dismissed (Mark as Read or Keep Unread →
   advance). The next card crossfades in via the JS handler. */
.mv-mention-recap.is-leaving{animation:mvRecapLeave var(--dur-press) var(--ease-exit) forwards}
.mv-mention-recap.is-entering{animation:mvRecapEnter .26s cubic-bezier(.22,1,.36,1) both}
@keyframes mvRecapLeave{
  from{opacity:1;transform:scale(1)}
  to{opacity:0;transform:scale(.97) translateY(-4px)}
}
@keyframes mvRecapEnter{
  from{opacity:0;transform:scale(.98) translateY(4px)}
  to{opacity:1;transform:none}
}/* Mobile compact tweaks */
body[data-mobile-mode="app"] .mv-mention-recap{margin:0 12px 14px;border-radius:14px}
body[data-mobile-mode="app"] .mv-mention-recap-head{padding:12px 14px}
body[data-mobile-mode="app"] .mv-mention-recap-body{padding:14px 14px 12px}
body[data-mobile-mode="app"] .mv-mention-recap-actions{padding:10px 14px 14px}

/* Recap — Mentions (top-of-page, redesigned) */
.mv-mentions-block{margin-bottom:24px}
.mv-mention-row{position:relative;display:grid;grid-template-columns:40px minmax(0,1fr) auto;gap:14px;align-items:flex-start;padding:14px 16px;background:rgba(255,255,255,.025);border:1px solid var(--border-d);border-radius:14px;cursor:pointer;outline:none;transition:background .15s,border-color .15s,transform .12s ease,box-shadow .15s;overflow:hidden}
.mv-mention-row + .mv-mention-row{margin-top:6px}
.mv-mention-row:hover{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.18);transform:translateY(-1px);box-shadow:0 8px 24px rgba(0,0,0,.22)}
.mv-mention-row:focus-visible{box-shadow:0 0 0 2px var(--color-brand-tint-strong)}
.mv-mention-row.unread{background:linear-gradient(120deg,rgba(140,114,219,.12) 0%,rgba(140,114,219,.04) 50%,rgba(140,114,219,0) 100%);border-color:rgba(140,114,219,.32)}
.mv-mention-row.unread::before{content:"";position:absolute;left:0;top:10px;bottom:10px;width:3px;background:var(--coral);border-radius:0 3px 3px 0;box-shadow:0 0 12px rgba(140,114,219,.5)}
.mv-mention-row.unread:hover{background:linear-gradient(120deg,rgba(140,114,219,.18) 0%,rgba(140,114,219,.06) 50%,rgba(140,114,219,.01) 100%)}
.mv-mention-avatar{width:40px;height:40px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff;font-size:18px;font-weight:700;overflow:hidden;background:rgba(255,255,255,.08);line-height:1}
.mv-mention-avatar.is-fallback{background:rgba(255,255,255,.08)}
.mv-mention-avatar img{width:100%;height:100%;object-fit:cover;display:block}
.mv-mention-body{min-width:0;display:flex;flex-direction:column;gap:8px}
.mv-mention-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px;font-size:13px;color:var(--cream);line-height:1.35}
.mv-mention-actor{font-weight:700;color:var(--off-white)}
.mv-mention-verb{color:var(--muted)}
.mv-mention-card-title{font-weight:600;color:var(--cream);max-width:480px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mv-mention-when{margin-left:auto;color:var(--muted);font-size:11px;font-weight:500;letter-spacing:.02em;white-space:nowrap;padding-left:8px}
.mv-mention-quote{font-size:13px;color:var(--off-white);line-height:1.5;padding:8px 12px;background:rgba(0,0,0,.18);border-left:2px solid rgba(255,255,255,.18);border-radius:4px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}
.mv-mention-row.unread .mv-mention-quote{border-left-color:var(--coral)}
.mv-mention-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--muted)}
.mv-mention-ws-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 10px 3px 4px;background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:999px;color:var(--cream);font-weight:600;font-size:11px}
.mv-mention-ws-icon{width:18px;height:18px;border-radius:50%;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,.06);flex-shrink:0}
.mv-mention-ws-icon img{width:100%;height:100%;object-fit:cover;display:block}
.mv-mention-ws-icon-blank{background:rgba(255,255,255,.04)}
.mv-mention-actions{display:flex;align-items:center;gap:6px;flex-shrink:0;align-self:center}
.mv-mention-btn{background:rgba(255,255,255,.05);border:1px solid var(--border-d);color:var(--cream);padding:6px 12px;border-radius:8px;cursor:pointer;font-size:11px;font-weight:600;text-decoration:none;display:inline-flex;align-items:center;gap:5px;transition:background .15s,border-color .15s,color .15s}
.mv-mention-btn:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.22);color:var(--cream)}
.mv-mention-btn.icon{padding:7px 9px}
.mv-mention-row.unread .mv-mention-btn.icon{background:rgba(140,114,219,.14);border-color:rgba(140,114,219,.34);color:var(--coral)}
.mv-mention-row.unread .mv-mention-btn.icon:hover{background:rgba(140,114,219,.24);color:#fff}
@media (max-width:680px){
  .mv-mention-row{grid-template-columns:32px minmax(0,1fr);gap:10px;padding:12px}
  .mv-mention-avatar{width:32px;height:32px;font-size:14px}
  .mv-mention-actions{grid-column:1 / -1;justify-self:flex-end;margin-top:4px}
  .mv-mention-when{margin-left:0}
}
/* Dismiss animation when a mention is marked read. Slide+fade first, then
   collapse the row's height/padding/margin/border so the rows below shift up
   smoothly. Pointer events disabled during the animation so re-clicks no-op. */
.mv-mention-row.is-dismissing{
  pointer-events:none;
  overflow:hidden;
  animation:
    mvMentionDismissSlide 320ms cubic-bezier(.4,0,.2,1) forwards,
    mvMentionDismissCollapse 280ms cubic-bezier(.4,0,.2,1) 280ms forwards;
}
@keyframes mvMentionDismissSlide{
  to{opacity:0;transform:translateX(64px);filter:blur(2px)}
}
@keyframes mvMentionDismissCollapse{
  from{
    max-height:320px;
    padding-top:14px;padding-bottom:14px;
    margin-top:6px;margin-bottom:0;
    border-top-width:1px;border-bottom-width:1px;
  }
  to{
    max-height:0;
    padding-top:0;padding-bottom:0;
    margin-top:0;margin-bottom:0;
    border-top-width:0;border-bottom-width:0;
  }
}
.mv-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:9999;display:flex;align-items:flex-start;justify-content:center;padding:80px 20px 20px;overflow-y:auto}
.mv-modal{background:var(--dark,#1a1a1a);border:1px solid var(--border-d);border-radius:14px;width:100%;max-width:520px;color:var(--cream);box-shadow:0 30px 80px rgba(0,0,0,.6)}
.mv-modal-head{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--border-d)}
.mv-modal-title{font-size:14px;font-weight:800;letter-spacing:.04em}
.mv-modal-x{background:none;border:0;color:var(--muted);font-size:22px;cursor:pointer;line-height:1;padding:0 4px}
.mv-modal-x:hover{color:var(--cream)}
.mv-modal-body{padding:18px 20px;display:flex;flex-direction:column;gap:14px}
.mv-modal-foot{padding:14px 20px;border-top:1px solid var(--border-d);display:flex;justify-content:flex-end;gap:8px}
.mv-field{display:flex;flex-direction:column;gap:5px}
.mv-field>span{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.mv-field input,.mv-field select,.mv-field textarea{background:rgba(0,0,0,.3);border:1px solid var(--border-d);color:var(--cream);font-family:inherit;font-size:13px;padding:8px 10px;border-radius:6px;outline:none}
.mv-field input:focus,.mv-field select:focus,.mv-field textarea:focus{border-color:rgba(140,114,219,.5)}
.mv-field textarea{resize:vertical;min-height:60px}
.mv-btn-primary{background:var(--coral);border:0;color:#fff;padding:8px 18px;border-radius:7px;cursor:pointer;font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.mv-btn-primary:hover{filter:brightness(1.1)}
.mv-btn-primary:disabled{opacity:.5;cursor:not-allowed}
.mv-btn-secondary{background:rgba(255,255,255,.05);border:1px solid var(--border-d);color:var(--cream);padding:8px 18px;border-radius:7px;cursor:pointer;font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.mv-btn-secondary:hover{background:rgba(255,255,255,.1)}
.mv-owner-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:999px;font-size:11px;font-weight:700;color:var(--cream);align-self:flex-start}
.mv-assignees{font-size:11px;color:var(--muted)}
.mv-assignees .mv-asg-pill{display:inline-block;padding:2px 8px;background:rgba(255,255,255,.06);border-radius:999px;margin:2px 4px 0 0;color:var(--cream)}

.am-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10100;display:flex;align-items:center;justify-content:center;padding:20px;backdrop-filter:blur(4px)}
.am-modal{background:var(--dark);border:1px solid var(--border-d);border-radius:14px;width:100%;max-width:500px;max-height:85vh;overflow-y:auto;padding:28px;position:relative}
.am-modal h3{font-family:var(--serif);font-size:20px;color:var(--cream);margin:0 0 18px;font-weight:400}
.am-modal-close{position:absolute;top:16px;right:16px;background:none;border:none;color:var(--muted);cursor:pointer;font-size:18px;padding:4px}
.am-modal-close:hover{color:var(--cream)}

/* Brand Bible */
.bb-section{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:12px;padding:20px 22px;margin-bottom:16px}
.bb-section-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:14px}
.bb-color-grid{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:12px}
.bb-color-swatch{position:relative;width:72px;cursor:pointer;text-align:center}
.bb-color-swatch-dot{width:72px;height:48px;border-radius:8px;border:1px solid var(--border-d);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .15s}
.bb-color-swatch-dot:hover{transform:scale(1.04)}
.bb-color-swatch-name{font-size:10px;color:var(--muted);margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bb-color-swatch-hex{font-size:9px;color:var(--sec);font-family:var(--sans);margin-top:1px}
.bb-color-remove{position:absolute;top:-5px;right:-5px;width:16px;height:16px;border-radius:50%;background:rgba(0,0,0,.7);border:1px solid var(--border-d);color:var(--coral);font-size:10px;cursor:pointer;display:none;align-items:center;justify-content:center;line-height:1;padding:0}
.bb-color-swatch:hover .bb-color-remove{display:flex}
.bb-add-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:6px;border:1px dashed rgba(255,255,255,.15);background:none;color:var(--muted);font-size:11px;font-family:var(--sans);cursor:pointer;transition:all .15s}
.bb-add-btn:hover{border-color:var(--coral);color:var(--coral);background:rgba(124,92,255,.06)}
.bb-font-row{display:flex;align-items:center;gap:12px;padding:10px 12px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:8px;margin-bottom:8px}
.bb-font-name{font-size:13px;color:var(--cream);font-weight:600;flex:1;min-width:0}
.bb-font-usage{font-size:11px;color:var(--muted);flex:2;min-width:0}
.bb-font-remove{background:none;border:none;color:var(--sec);cursor:pointer;padding:4px;border-radius:4px;display:flex;align-items:center;transition:color .15s;flex-shrink:0}
.bb-font-remove:hover{color:var(--coral)}
.bb-logo-area{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.bb-logo-preview{width:120px;height:80px;border-radius:8px;border:1px solid var(--border-d);background:rgba(255,255,255,.03);display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}
.bb-logo-preview img{max-width:100%;max-height:100%;object-fit:contain}
.bb-logo-placeholder{color:var(--sec);font-size:11px;text-align:center}
.bb-input{width:100%;padding:8px 12px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none;box-sizing:border-box}
.bb-input:focus{border-color:var(--coral)}
.bb-input::placeholder{color:var(--muted)}
.bb-textarea{width:100%;padding:10px 12px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none;resize:vertical;min-height:80px;box-sizing:border-box;line-height:1.5}
.bb-textarea:focus{border-color:var(--coral)}
.bb-textarea::placeholder{color:var(--muted)}
.bb-save-indicator{font-size:10px;color:var(--green);opacity:0;transition:opacity .3s}
.bb-save-indicator.visible{opacity:1}
.bb-color-modal-overlay{position:fixed;inset:0;z-index:10200;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.6)}
.bb-color-modal{background:var(--dark);border:1px solid var(--border-d);border-radius:12px;padding:24px;width:280px;box-shadow:0 8px 32px rgba(0,0,0,.5)}
.bb-color-modal-title{font-size:14px;font-weight:600;color:var(--off-white);margin-bottom:16px}
.bb-color-picker-wrap{width:100%;height:36px;border-radius:6px;border:1px solid var(--border-d);overflow:hidden;margin-bottom:10px;cursor:pointer}
.bb-color-picker-wrap input[type=color]{width:100%;height:100%;border:none;padding:0;cursor:pointer;background:none}

/* Favorite Tool Selector */
.fav-tool-selector {
  position: fixed; z-index: 10000; display: none; width: 220px;
  background: var(--dark); border: 1px solid var(--border-d); border-radius: 10px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5); padding: 6px;
}
.fav-tool-selector.visible { display: block; }
.fav-tool-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  border-radius: 6px; cursor: pointer; transition: all .1s;
  color: var(--cream); font-size: 13px;
}
.fav-tool-item:hover { background: rgba(255,255,255,0.08); }
.fav-tool-item.active { background: rgba(124,92,255,0.12); color: var(--coral); }

@media(max-width:900px){.tools-hub-grid{grid-template-columns:1fr 1fr}}
@media(max-width:500px){.tools-hub-grid{grid-template-columns:1fr}}

/* RISING STARS */
.rising-star-card{display:block;text-decoration:none;color:inherit;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:10px;padding:12px;transition:all .18s ease}
.rising-star-card:hover{border-color:rgba(255,255,255,.2);background:rgba(255,255,255,.06);transform:translateY(-1px)}
.rising-star-head{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}
.rising-star-name{font-size:13px;font-weight:700;color:var(--off-white);line-height:1.3}
.rising-star-platform{font-size:9px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;padding:3px 7px;border-radius:999px;background:rgba(255,255,255,.08);color:var(--muted);white-space:nowrap}
.rising-star-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:10px;color:var(--muted);margin-top:6px}
.rising-star-score{font-family:var(--sans);font-size:10px;padding:2px 6px;border-radius:6px;background:rgba(231,206,58,.12);color:var(--gold)}
.rising-star-headline{font-size:12px;color:var(--cream);line-height:1.45;margin-top:8px}
.rising-star-signal{font-size:11px;color:var(--muted);line-height:1.4;margin-top:6px}


/* CONTENT OUTLIERS */
/* === CONTENT OUTLIERS (1of10 style) === */
.co-layout{display:flex;flex:1;min-height:0}
.co-sidebar{width:220px;flex-shrink:0;background:rgba(255,255,255,.02);border-right:1px solid var(--border-d);display:flex;flex-direction:column;overflow-y:auto}
.co-sidebar-header{padding:16px 14px 10px;border-bottom:1px solid var(--border-d)}
.co-sidebar-header h3{font-size:11px;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);margin:0;font-weight:600}
.co-sidebar-nav{padding:8px 0}
.co-nav-item{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;font-size:12px;font-weight:600;color:var(--muted);transition:all .12s;border:none;background:none;width:100%;text-align:left;font-family:var(--sans)}
.co-nav-item:hover{background:rgba(255,255,255,.04);color:var(--cream)}
.co-nav-item.active{background:rgba(124,92,255,.08);color:var(--coral)}
.co-nav-item svg{width:15px;height:15px;opacity:.65;flex-shrink:0}
.co-nav-item.active svg{opacity:1}
.co-nav-count{margin-left:auto;font-size:10px;font-weight:700;color:var(--muted);background:rgba(255,255,255,.06);padding:2px 7px;border-radius:10px}
.co-nav-item.active .co-nav-count{color:var(--coral);background:rgba(124,92,255,.12)}
.co-sidebar-channels{padding:8px 0;border-top:1px solid var(--border-d);margin-top:auto}
.co-sidebar-channels-header{display:flex;align-items:center;justify-content:space-between;padding:0 14px 8px}
.co-sidebar-channels-header span{font-size:10px;text-transform:uppercase;letter-spacing:.7px;color:var(--muted);font-weight:600}
.co-channel-item{display:flex;align-items:center;gap:8px;padding:6px 14px;cursor:pointer;font-size:11px;color:var(--cream);transition:background .12s;border:none;background:none;width:100%;text-align:left;font-family:var(--sans)}
.co-channel-item:hover{background:rgba(255,255,255,.04)}
.co-channel-item.active{color:var(--coral)}
.co-channel-avatar{width:24px;height:24px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;flex-shrink:0;color:var(--cream)}
.co-main{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden}
.co-topbar{display:flex;align-items:center;gap:12px;padding:12px 20px;border-bottom:1px solid var(--border-d);flex-shrink:0;flex-wrap:wrap}
.co-search{flex:1;min-width:180px;max-width:320px;position:relative}
.co-search input{width:100%;padding:7px 12px 7px 32px;border-radius:8px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none;transition:border-color .15s;box-sizing:border-box}
.co-search input:focus{border-color:var(--coral)}
.co-search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:14px;height:14px;color:var(--muted);pointer-events:none}
.co-topbar-right{display:flex;align-items:center;gap:8px;margin-left:auto}
.co-filter-btn{display:flex;align-items:center;gap:5px;padding:6px 12px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--muted);font-size:11px;font-weight:600;cursor:pointer;font-family:var(--sans);transition:all .15s}
.co-filter-btn:hover{border-color:rgba(255,255,255,.15);color:var(--cream)}
.co-filter-btn.active{border-color:var(--coral);color:var(--coral);background:rgba(124,92,255,.06)}
.co-filter-btn svg{width:13px;height:13px}
.co-filters{display:none;padding:10px 20px;border-bottom:1px solid var(--border-d);background:rgba(255,255,255,.015)}
.co-filters.open{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.co-filter-group{display:flex;align-items:center;gap:6px}
.co-filter-group label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.co-filter-pill{padding:4px 10px;border-radius:6px;border:1px solid var(--border-d);background:none;color:var(--muted);font-size:11px;font-weight:600;cursor:pointer;font-family:var(--sans);transition:all .12s}
.co-filter-pill:hover{border-color:rgba(255,255,255,.15);color:var(--cream)}
.co-filter-pill.active{border-color:var(--coral);color:var(--coral);background:rgba(124,92,255,.08)}
.co-stats-bar{display:flex;gap:16px;padding:10px 20px;border-bottom:1px solid var(--border-d);flex-shrink:0;flex-wrap:wrap}
.co-stat{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--muted)}
.co-stat .num{font-weight:700;color:var(--cream);font-family:var(--sans);font-size:13px}
.co-stat .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.co-grid-wrap{flex:1;padding:16px 20px;overflow-y:auto}
.co-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}
.co-card{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:10px;overflow:hidden;cursor:pointer;transition:all .18s ease;text-decoration:none;color:inherit;display:block}
.co-card:hover{border-color:rgba(255,255,255,.2);background:rgba(255,255,255,.06);transform:translateY(-2px);box-shadow:0 6px 20px rgba(0,0,0,.25)}
.co-card-thumb{position:relative;width:100%;aspect-ratio:16/9;overflow:hidden}
.co-card-thumb-img{width:100%;height:100%;object-fit:cover}
.co-card-thumb-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:28px;color:rgba(255,255,255,.15)}
.co-card-duration{position:absolute;bottom:6px;right:6px;padding:2px 6px;border-radius:4px;background:rgba(0,0,0,.8);color:#fff;font-size:10px;font-weight:600;font-family:var(--sans)}
.co-card-tier{position:absolute;top:8px;left:8px;font-size:9px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;padding:3px 8px;border-radius:6px}
.co-card-score{position:absolute;bottom:6px;left:6px;font-size:11px;font-weight:700;padding:3px 8px;border-radius:6px;background:rgba(0,0,0,.7);color:var(--gold);font-family:var(--sans)}
.co-card-body{padding:10px 12px 12px}
.co-card-title{font-size:13px;font-weight:700;color:var(--off-white);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-bottom:6px}
.co-card-channel{display:flex;align-items:center;gap:6px;margin-bottom:8px}
.co-card-channel-avatar{width:20px;height:20px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:700;flex-shrink:0;color:var(--cream)}
.co-card-channel-name{font-size:11px;color:var(--muted);font-weight:600}
.co-card-stats{display:flex;gap:10px;flex-wrap:wrap}
.co-card-stat{font-size:10px;color:var(--muted);display:flex;align-items:center;gap:3px}
.co-card-stat .val{font-weight:700;color:var(--cream)}
.co-card-velocity{font-size:10px;font-weight:700;padding:2px 6px;border-radius:4px}
.co-table-wrap{flex:1;padding:16px 20px;overflow-y:auto}
.co-skeleton-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}
.co-skeleton-card{border-radius:10px;overflow:hidden;border:1px solid var(--border-d);background:rgba(255,255,255,.03)}
.co-skeleton-thumb{aspect-ratio:16/9;background:rgba(255,255,255,.04);animation:co-shimmer 1.5s infinite}
.co-skeleton-body{padding:12px}
.co-skeleton-line{height:10px;border-radius:4px;background:rgba(255,255,255,.06);animation:co-shimmer 1.5s infinite;margin-bottom:8px}
.co-skeleton-line.short{width:60%}
.co-skeleton-line.medium{width:80%}
@keyframes co-shimmer{0%{opacity:.4}50%{opacity:.8}100%{opacity:.4}}
.co-empty{text-align:center;padding:60px 20px;color:var(--muted)}
.co-empty svg{width:48px;height:48px;opacity:.3;margin-bottom:12px}
.co-empty-title{font-size:14px;font-weight:600;color:var(--cream);margin-bottom:4px}
.co-empty-sub{font-size:12px}
.co-track-btn{position:absolute;top:8px;right:8px;background:rgba(0,0,0,.6);border:none;padding:4px;border-radius:50%;cursor:pointer;color:var(--muted);transition:all .15s;line-height:0;z-index:2}
.co-track-btn:hover{color:var(--gold)}
.co-track-btn.tracked{color:var(--gold)}
/* UPCOMING MEETINGS */
.meetings-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.meeting-card{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:10px;padding:12px}
.meeting-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.meeting-card-title{font-size:14px;font-weight:700;color:var(--off-white);line-height:1.35}
.meeting-card-meta{font-size:11px;color:var(--muted);line-height:1.45;margin-top:7px}
.meeting-card-assets{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.meeting-asset-pill{display:inline-flex;align-items:center;gap:4px;text-decoration:none;font-size:10px;font-weight:600;padding:4px 7px;border-radius:999px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream)}
.meeting-asset-pill:hover{border-color:rgba(255,255,255,.2);background:var(--state-hover)}
.meeting-asset-pill.muted{color:var(--muted);border-style:dashed}
.meeting-account-list{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px}
.meeting-account-chip{font-size:10px;border-radius:999px;padding:4px 8px;border:1px solid var(--border-d);background:rgba(255,255,255,.03);color:var(--muted)}
@media(max-width:900px){.co-sidebar{display:none}.co-grid{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}}
@media(max-width:600px){.co-grid{grid-template-columns:1fr}.co-topbar{flex-direction:column;align-items:stretch}.co-search{max-width:none}}

/* TOGGLE TABS */
.toggle-tabs{display:flex;gap:4px;background:rgba(255,255,255,.06);border-radius:8px;padding:3px}
.toggle-tab{padding:6px 16px;border-radius:6px;border:none;background:none;font-family:var(--sans);font-size:11px;font-weight:600;color:var(--muted);cursor:pointer;transition:all .15s}
.toggle-tab.active{background:rgba(255,255,255,.1);color:var(--off-white);box-shadow:0 1px 3px rgba(0,0,0,.2)}

/* CONSOLE */
.console{
  background:var(--dark);border-radius:10px;padding:20px;font-family:var(--sans);
  font-size:12px;color:var(--green);min-height:200px;line-height:1.8;overflow-y:auto;
}
.console-line{opacity:.6}
.console-line.active{opacity:1}
.console-prompt{color:var(--coral)}
.console-cursor{display:inline-block;width:7px;height:14px;background:var(--green);animation:blink 1s step-end infinite;vertical-align:middle;margin-left:2px}
@keyframes blink{50%{opacity:0}}
@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}

/* KANBAN */
.kanban{display:flex;gap:10px;overflow-x:auto;padding-bottom:8px;align-items:flex-start}
.kanban-col{background:var(--dark);border:1px solid color-mix(in srgb, var(--col-color, var(--border-d)) 18%, transparent);border-radius:8px;min-width:220px;max-width:300px;flex:1;min-height:200px;display:flex;flex-direction:column;transition:box-shadow .15s ease,background .2s ease,border-color .2s ease}
.kanban-col-header-bar{min-height:22px;border-radius:8px 8px 0 0;flex-shrink:0;cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none;position:relative;z-index:5;transition:filter .15s;display:flex;align-items:center;justify-content:flex-end;padding-right:4px;overflow:visible}
.kanban-col-header-bar:hover{filter:brightness(1.15)}
.kanban-col-header-bar:active{cursor:grab}
.kanban-col-header{display:flex;align-items:center;justify-content:space-between;padding:10px 14px 8px;position:relative}
.kanban-col-title{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;display:flex;align-items:center;gap:8px;color:var(--off-white)}
.kanban-col-name{outline:none;cursor:text;padding:1px 4px;border-radius:4px;transition:background .15s}
.kanban-col-name:hover{background:var(--state-hover)}
.kanban-col-name:focus{background:rgba(255,255,255,.12);box-shadow:0 0 0 1px var(--gold)}
.kanban-col-count{font-family:var(--sans);font-size:10px;color:var(--muted);background:rgba(255,255,255,.08);padding:1px 7px;border-radius:10px}
.kanban-col-body{padding:4px 10px 10px;flex:1;display:flex;flex-direction:column}
.kanban-card{background:var(--surface-raised);border:1px solid var(--hairline-2);border-radius:var(--r-card);padding:14px 16px;margin-bottom:12px;min-height:auto;font-size:13px;transition:background var(--dur-short),box-shadow var(--dur-short) var(--ease-std),border-color var(--dur-short) ease,opacity .16s linear,transform var(--dur-short) var(--ease-std);color:var(--cream);position:relative}
/* No lift on hover. Three rules each translated the tile up (-2px, -2px, -1px, last
   one winning), so sweeping down a column made every tile jump in turn and the column
   read as sliding. Hover still changes colour and shadow — it just does not move. */
.kanban-card:hover{box-shadow:0 12px 28px rgba(0,0,0,.4);border-color:var(--hairline-3)}
/* Column-color left accent bar on EVERY kanban card. Completed cards override to
   green (rule below, later in source). Color-by-field cards keep their own stripe
   via the higher-specificity [data-card-color]::before rule. */
.kanban-card::before{display:none}
/* Completed cards (kanban + calendar). Toggled via right-click → Mark complete;
   in these views right-click is the only completion path. Dim + green accent
   + struck title so done work stays visible but recedes. */
.kanban-card.card-completed{opacity:.7}
.kanban-card.card-completed:hover{opacity:.9}
.kanban-card.card-completed .kanban-card-text{text-decoration:line-through;text-decoration-color:rgba(134,192,108,.85);text-decoration-thickness:2.5px;color:var(--muted)}
/* Kanban complete toggle (top-right) — mirrors the List view's checkmark: hidden
   until card hover, stays green when complete. */
.kanban-card{position:relative}
/* top:13px, not 7px, so the 22px toggle's centre lands on the task icon's — the icon
   sits 24px below the tile's top (14px padding plus its offset in the title row) and
   this centred at 18px, leaving the check floating 6px above the icon it sits opposite. */
.kc-complete-toggle{position:absolute;top:13px;right:7px;z-index:4;width:22px;height:22px;padding:0;border:none;background:none;color:var(--text-3);cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%;opacity:0;transition:opacity .14s ease,color .14s ease,background .14s ease}
.kanban-card:hover .kc-complete-toggle{opacity:1}
.kc-complete-toggle:hover{color:#86c06c;background:rgba(134,192,108,.14)}
.kc-complete-toggle.is-done{opacity:1;color:#86c06c}
/* The top-right toggle replaces the old separate bottom-right completed check. */
.kanban-card .kanban-card-check{display:none}
.calendar-day-card.card-completed,.cal-unscheduled-chip.card-completed,.cal-upcoming-item.card-completed{opacity:.55;text-decoration:line-through;text-decoration-color:rgba(134,192,108,.7)}
/* Completed KANBAN card: the SAME outline-circle + check used in list view
   (green stroke, no fill) replaces the bottom-right cluster (comments etc.). */
.kanban-card-check{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--green,#86c06c);flex-shrink:0}
.kanban-card-check svg{display:block}
/* Completed CALENDAR chips: swap the leading status dot for a green check.
   The two sidebar dots carry an inline background, so !important + a ::before
   glyph (pseudo-elements ignore the host's inline style) is required. */
.card-completed > .cdc-line > .cdc-dot,
.card-completed > .cal-upcoming-dot,
.card-completed > .cu-dot{position:relative;background:transparent !important;overflow:visible}
.card-completed > .cdc-line > .cdc-dot::before,
.card-completed > .cal-upcoming-dot::before,
.card-completed > .cu-dot::before{content:"\2713";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:var(--green,#86c06c);font-size:12px;font-weight:800;line-height:1}
.kanban-card:hover{background:color-mix(in srgb, var(--col-color, var(--state-hover)) 22%, var(--dark));border-color:color-mix(in srgb, var(--col-color, var(--border-d)) 36%, transparent);box-shadow:0 2px 8px rgba(0,0,0,.25)}
.kanban-card.card-active{border-color:var(--col-color,var(--coral));box-shadow:0 0 0 1px var(--col-color,var(--coral)),0 4px 24px rgba(0,0,0,.5)}
.kanban-card-text{line-height:1.35;font-weight:700;font-size:15px;color:var(--text-1);white-space:normal;word-wrap:break-word;max-width:100%}
.kc-stage{display:flex;align-items:center;gap:7px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;line-height:1;margin-bottom:11px}
.kc-stage-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
/* The same row, now carrying the task's NAME instead of its status: it has to wear the
   title's type, not the 11px uppercase eyebrow's. align-items:flex-start keeps the icon
   on the FIRST line of a title that wraps to two; the padding-right reserves the space
   the hover complete-toggle occupies, so a long name never runs underneath it (reserved
   always, not on hover, or the text would reflow every time the pointer entered). */
.kc-stage.kc-stage-title{align-items:flex-start;gap:9px;font-size:inherit;font-weight:inherit;
  text-transform:none;letter-spacing:normal;line-height:inherit;margin-bottom:0;padding-right:20px}
.kc-stage.kc-stage-title > :not(.kanban-card-text){flex:none;margin-top:4px}
.kc-stage.kc-stage-title .kanban-card-text{flex:1;min-width:0}
.kanban-card-meta{display:flex;align-items:center;gap:8px;margin-top:6px;font-size:11px;color:var(--muted)}
.kanban-card-meta svg{width:12px;height:12px;opacity:.5}
.kanban-card-tag{font-size:10px;padding:1px 6px;border-radius:3px;font-weight:600;display:inline-flex;align-items:center;gap:3px}
.kanban-card-del{background:none;border:none;color:var(--muted);cursor:pointer;font-size:14px;padding:0 2px;transition:color .15s;flex-shrink:0;position:absolute;top:6px;right:6px;opacity:0;transition:opacity .15s}
.kanban-card:hover .kanban-card-del{opacity:1}
.kanban-card-del:hover{color:var(--coral)}
.ctx-disabled{opacity:.35;pointer-events:none;cursor:default}
.kanban-card-lock{position:absolute;bottom:5px;right:6px;font-size:10px;color:var(--muted);opacity:.5;line-height:1}
.kanban-card-source{position:absolute;bottom:5px;right:6px;font-size:9px;color:var(--muted);opacity:.45;line-height:1;font-style:italic}
.kanban-card-routed-icon{color:var(--coral);opacity:.7;line-height:1;display:inline-flex;align-items:center}
.kanban-card.card-selected{background:color-mix(in srgb,var(--col-color,#64b4ff) 12%,var(--dark));border-color:var(--col-color,#64b4ff);box-shadow:0 0 0 1px color-mix(in srgb,var(--col-color,#64b4ff) 90%,transparent)}.kanban-card.card-selected:hover{background:color-mix(in srgb,var(--col-color,#64b4ff) 20%,var(--dark))}
.multi-select-bar{position:fixed;bottom:28px;left:50%;transform:translateX(-50%);z-index:9100;display:flex;align-items:center;gap:8px;padding:9px 15px;background:var(--glass-bg);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:1px solid var(--glass-border);border-radius:16px;box-shadow:var(--glass-shadow);font-size:12px;color:var(--cream);white-space:nowrap;transition:opacity .18s,transform .18s}
.multi-select-bar.hidden{opacity:0;pointer-events:none;transform:translateX(-50%) translateY(14px)}
.multi-select-bar-count{font-weight:600;color:var(--off-white);padding-right:10px;border-right:1px solid var(--border-d);margin-right:2px}
.multi-select-bar-btn{background:rgba(255,255,255,.07);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);cursor:pointer;font-size:12px;padding:5px 11px;font-family:var(--sans);transition:background .12s,color .12s,border-color .12s}
.multi-select-bar-btn:hover{background:rgba(255,255,255,.13);color:var(--off-white)}
.multi-select-bar-btn.danger:hover{background:rgba(239,68,68,.18);border-color:rgba(239,68,68,.4);color:var(--danger-text)}
.multi-select-bar-btn.complete:hover{background:rgba(91,207,142,.18);border-color:rgba(91,207,142,.42);color:#5bcf8e}
.multi-select-bar-dismiss{background:none;border:none;color:var(--muted);cursor:pointer;font-size:18px;padding:1px 4px;line-height:1;transition:color .12s;margin-left:2px}
.multi-select-bar-dismiss:hover{color:var(--off-white)}
.multi-select-move-wrap{position:relative}
.multi-select-move-dropdown{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);border:1px solid var(--lg-border);border-radius:12px;box-shadow:var(--lg-shadow);min-width:170px;overflow:hidden;display:none}
.multi-select-move-dropdown.open{display:block}
.multi-select-move-dropdown button{display:flex;width:100%;background:none;border:none;padding:8px 14px;font-size:12px;color:var(--cream);cursor:pointer;text-align:left;font-family:var(--sans);align-items:center;gap:8px}
.multi-select-move-dropdown button:hover{background:rgba(255,255,255,.06);color:var(--off-white)}
.multi-select-prop-wrap{position:relative}
.multi-select-prop-dropdown{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);border:1px solid var(--lg-border);border-radius:12px;box-shadow:var(--lg-shadow);min-width:200px;max-height:320px;overflow-y:auto;display:none}
.multi-select-prop-dropdown.open{display:block}
.multi-select-prop-dropdown button{display:flex;width:100%;background:none;border:none;padding:8px 14px;font-size:12px;color:var(--cream);cursor:pointer;text-align:left;font-family:var(--sans);align-items:center;gap:8px}
.multi-select-prop-dropdown button:hover{background:rgba(255,255,255,.06);color:var(--off-white)}
.multi-select-prop-dropdown .bulk-prop-editor{padding:10px 12px;border-top:1px solid var(--border-d)}
.multi-select-prop-dropdown .bulk-prop-editor input{width:100%;padding:6px 8px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);font-size:12px;font-family:var(--sans);box-sizing:border-box}
.multi-select-prop-dropdown .bulk-prop-editor input:focus{border-color:var(--coral);outline:none}
.multi-select-prop-dropdown .bulk-prop-editor-row{display:flex;gap:6px;margin-top:6px}
.multi-select-prop-dropdown .bulk-prop-apply{padding:4px 12px;border:none;border-radius:5px;background:var(--coral);color:#fff;font-size:11px;font-weight:600;cursor:pointer;font-family:var(--sans)}
.multi-select-prop-dropdown .bulk-prop-clear{padding:4px 10px;border:1px solid var(--border-d);border-radius:5px;background:none;color:var(--muted);font-size:11px;cursor:pointer;font-family:var(--sans)}
.multi-select-prop-dropdown .bulk-person-item{display:flex;align-items:center;gap:8px;padding:7px 12px;cursor:pointer;font-size:12px;color:var(--cream);transition:background .1s}
.multi-select-prop-dropdown .bulk-person-item:hover{background:rgba(255,255,255,.06)}
.multi-select-prop-dropdown .bulk-prop-section-title{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);padding:8px 12px 4px}
.kanban-add{width:100%;padding:10px 14px;border:none;border-radius:0;background:color-mix(in srgb, var(--col-color, rgba(255,255,255,.04)) 4%, transparent);font-family:var(--sans);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);cursor:pointer;transition:all .15s;text-align:center;flex-shrink:0;border-bottom:1px solid color-mix(in srgb, var(--col-color, var(--border-d)) 18%, transparent)}
.kanban-add:hover{color:color-mix(in srgb, var(--col-color, var(--cream)) 70%, var(--cream));background:color-mix(in srgb, var(--col-color, var(--state-hover)) 10%, transparent)}
.kanban-input{width:100%;padding:8px 10px;border:1.5px solid var(--border-d);border-radius:6px;font-family:var(--sans);font-size:13px;outline:none;background:rgba(255,255,255,.06);color:var(--off-white);margin-bottom:6px}
.kanban-input:focus{border-color:var(--col-color,var(--coral))}
/* The add-a-task input stands in the + button's own slot, so it copies the + button's
   box exactly — same padding, same radius, same margins, no border — and its height is
   set inline from the button it replaced. Its focus tint is the + button's HOVER tint,
   not the column's colour: the highlight has to look like the thing it grew out of,
   which is why a purple square offset from the + read as broken. */
.kanban-input-inplace{box-sizing:border-box;width:100%;flex-shrink:0;
  margin:2px 0 !important;padding:9px 8px !important;border:none !important;border-radius:8px;
  background:transparent !important;text-align:center;
  font-size:13px;font-weight:600;color:var(--off-white)}
.kanban-input-inplace:focus{border:none !important;outline:none;
  background:rgba(255,255,255,.05) !important}
.kanban-input-inplace::placeholder{color:var(--muted);font-weight:600;text-transform:none;letter-spacing:0}
html[data-theme="light"] .kanban-input-inplace:focus{background:rgba(0,0,0,.04) !important}
/* Priority badges */
.kanban-priority-badge{display:inline-flex;align-items:center;font-size:9px;font-weight:700;padding:2px 7px;border-radius:20px;letter-spacing:.4px;text-transform:uppercase;flex-shrink:0}
.kanban-priority-badge.high{background:rgba(255,107,107,.15);color:var(--prio-high)}
.kanban-priority-badge.med{background:rgba(231,206,58,.15);color:var(--gold)}
.kanban-priority-badge.low{background:rgba(115,172,131,.15);color:var(--green)}
.kanban-card.priority-high{border-left:2px solid rgba(255,107,107,.6)}
.kanban-card.priority-med{border-left:2px solid rgba(231,206,58,.4)}
/* Priority selector in card modal */
.priority-selector{display:flex;gap:4px}
.priority-btn{font-size:10px;font-weight:600;padding:3px 10px;border-radius:20px;border:1.5px solid var(--border-d);background:none;color:var(--muted);cursor:pointer;font-family:var(--sans);transition:all .12s;letter-spacing:.3px;text-transform:uppercase}
.priority-btn:hover{opacity:.85}
.priority-btn.active-high,.priority-btn:hover.pv-high{background:rgba(255,107,107,.15);border-color:rgba(255,107,107,.5);color:var(--prio-high)}
.priority-btn.active-med,.priority-btn:hover.pv-med{background:rgba(231,206,58,.15);border-color:rgba(231,206,58,.4);color:var(--gold)}
.priority-btn.active-low,.priority-btn:hover.pv-low{background:rgba(115,172,131,.15);border-color:rgba(115,172,131,.4);color:var(--green)}
.priority-btn.active-none{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.2);color:var(--off-white)}

/* TABLE SHELL */
.table-shell{width:100%;border-collapse:collapse}
.table-shell th{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);text-align:left;padding:10px 14px;border-bottom:2px solid var(--border-d)}
.table-shell td{font-size:13px;padding:12px 14px;border-bottom:1px solid var(--border-d);color:var(--cream)}
.table-shell tr:hover td{background:rgba(255,255,255,.03)}
.table-shell .empty-row td{text-align:center;padding:48px;color:var(--muted);font-style:italic}

/* TASK LIST */
.task-list{list-style:none}
.task-item{display:flex;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid var(--border-d)}
.task-item:last-child{border-bottom:none}
.task-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.task-dot.active{background:var(--green)}.task-dot.inactive{background:var(--mid-gray)}.task-dot.error{background:var(--color-error)}
.task-name{font-size:13px;font-weight:500;flex:1;color:var(--cream)}
.task-meta{font-family:var(--sans);font-size:11px;color:var(--muted)}

/* QUICK LINKS */
.quick-links{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}
.quick-link{
  display:flex;align-items:center;gap:12px;padding:18px 20px;border-radius:10px;
  border:1px solid var(--border-d);background:rgba(255,255,255,.04);text-decoration:none;color:var(--off-white);
  transition:all .15s ease;
}
.quick-link:hover{border-color:rgba(255,255,255,.15);transform:translateY(-1px);box-shadow:0 4px 16px rgba(0,0,0,.3)}
.quick-link-icon{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
.quick-link-name{font-size:14px;font-weight:600}
.quick-link-url{font-family:var(--sans);font-size:10px;color:var(--muted)}

/* EMPTY STATE */
.empty-state{text-align:center;padding:40px 20px;color:var(--muted)}
.empty-state svg{width:40px;height:40px;margin-bottom:12px;opacity:.25}
.empty-state h3{font-family:var(--serif);font-size:18px;font-weight:400;color:var(--cream);margin-bottom:4px}
.empty-state p{font-size:12px;max-width:300px;margin:0 auto;line-height:1.6}

/* STATUS DOT */
.status-dot{width:7px;height:7px;border-radius:50%;display:inline-block}
.status-dot.online{background:var(--green)}.status-dot.offline{background:var(--mid-gray)}.status-dot.warning{background:var(--gold)}

/* CHAT WIDGET */
.chat-box{display:flex;flex-direction:column;height:320px}
.chat-messages{flex:1;overflow-y:auto;padding:4px 0;display:flex;flex-direction:column;gap:10px}
.chat-msg{max-width:85%;padding:10px 14px;border-radius:12px;font-size:13px;line-height:1.5;word-break:break-word}
.chat-msg.user{align-self:flex-end;background:var(--coral);color:var(--white);border-bottom-right-radius:4px}
.chat-msg.bot{align-self:flex-start;background:rgba(255,255,255,.08);color:var(--cream);border-bottom-left-radius:4px}
.chat-msg.system{align-self:flex-start;background:rgba(255,255,255,.04);border:1px dashed rgba(255,255,255,.12);color:var(--muted);border-radius:8px;font-size:11px;padding:7px 10px}
.chat-msg.bot .typing{display:inline-flex;gap:4px}.chat-msg.bot .typing span{width:5px;height:5px;border-radius:50%;background:var(--muted);animation:chatDot 1.2s infinite}
.chat-msg.bot .typing span:nth-child(2){animation-delay:.2s}.chat-msg.bot .typing span:nth-child(3){animation-delay:.4s}
@keyframes chatDot{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.chat-input-row{display:flex;gap:8px;margin-top:12px}
.chat-input{flex:1;padding:10px 14px;border-radius:10px;border:1px solid var(--border-d);background:var(--bg-inset);color:var(--off-white);font-family:var(--sans);font-size:13px;outline:none;transition:border-color .2s}
.chat-input:focus{border-color:var(--modal-col-color,var(--coral))}
.chat-input::placeholder{color:var(--muted)}
/* Card-modal comment box: borderless/box-less (scoped so other .chat-input uses keep their border) */
#cardModalCommentInput .chat-input,#cardModalCommentInput .chat-input:focus{border:none !important;box-shadow:none !important;outline:none !important;background:transparent}
.chat-send{padding:10px 18px;border-radius:10px;border:none;background:var(--coral);color:var(--white);font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer;transition:opacity .15s}
.chat-send:hover{opacity:.85}
.chat-send:disabled{opacity:.4;cursor:default}
.chat-message-row{display:flex;flex-direction:column;gap:6px;max-width:85%}
.chat-message-row.user{align-self:flex-end;align-items:flex-end}
.chat-message-row.bot{align-self:flex-start;align-items:flex-start}
.chat-reactions{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.chat-reaction{
  display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:8px;
  border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.05);color:var(--cream);
  font-size:13px;line-height:1;cursor:pointer;transition:all .15s;
}
.chat-reaction:hover{border-color:rgba(255,255,255,.22);background:rgba(255,255,255,.10)}
.chat-reaction.active{border-color:rgba(124,92,255,.45);background:rgba(124,92,255,.14);color:var(--off-white)}
.chat-reaction-count{font-family:var(--sans);font-size:11px;color:var(--muted)}
.chat-reaction.active .chat-reaction-count{color:var(--off-white)}
.chat-reactions.approval-reaction-strip{gap:8px}
.chat-reaction.approval-pill{
  border-color:rgba(231,206,58,.48);
  background:rgba(231,206,58,.14);
  box-shadow:0 0 0 1px rgba(231,206,58,.2),0 0 14px rgba(231,206,58,.24);
}
.chat-reaction.approval-pill:hover{
  border-color:rgba(124,92,255,.68);
  background:rgba(124,92,255,.2);
  box-shadow:0 0 0 1px rgba(124,92,255,.3),0 0 14px rgba(124,92,255,.3);
}
.chat-reaction.approval-pill.active{
  border-color:rgba(124,92,255,.75);
  background:rgba(124,92,255,.24);
  box-shadow:0 0 0 1px rgba(124,92,255,.35),0 0 16px rgba(124,92,255,.35);
}
.chat-reaction-add{
  display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:8px;
  border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);color:var(--muted);font-size:14px;cursor:pointer;
  transition:all .15s;
}
.chat-reaction-add:hover{border-color:rgba(124,92,255,.45);color:var(--coral);background:rgba(124,92,255,.10)}
.chat-reaction-emoji-img{width:16px;height:16px;object-fit:contain;vertical-align:middle}
.reactable{position:relative}
.reaction-hover-tools{
  position:absolute;top:-44px;right:0;display:flex;align-items:center;gap:1px;
  /* NO backdrop-filter. --dark is opaque, so the blur was filtering a backdrop nobody can
     see — while forcing the panel onto its own composited layer that re-rasterises every
     time anything behind it repaints (a hovered row, an avatar, an unfurl image arriving).
     That is a well-known Chrome flicker source and it bought nothing here. */
  padding:5px 6px;background:var(--dark);
  border:1px solid rgba(255,255,255,.1);border-radius:10px;box-shadow:0 4px 20px rgba(0,0,0,.6);z-index:40;
  /* The hide is DELAYED; the show is not. A hover panel that vanishes the instant the
     pointer clips its edge — crossing a gap, passing over a child, a repaint moving the
     hit target by a pixel — flickers on and off as you sweep. Holding it for 160ms costs
     nothing when you are genuinely leaving and removes every one-frame dropout. */
  /* 70ms of grace, then gone in 90. The old 160+120 was built to survive a one-frame
     dropout and overshot: leaving a message left its toolbar hanging there for a third of
     a second, which reads as the panel being slow to notice you have gone. */
  opacity:0;visibility:hidden;transform:translateY(4px);pointer-events:none;
  transition:opacity .09s .07s,transform .09s .07s,visibility 0s .16s;
}
.reaction-hover-tools::after{content:'';position:absolute;bottom:-10px;left:0;right:0;height:14px}
.reactable:hover>.reaction-hover-tools,.reactable:focus-within>.reaction-hover-tools,.reaction-hover-tools:hover{
  opacity:1;visibility:visible;transform:translateY(0);pointer-events:auto;
  transition:opacity .12s 0s,transform .12s 0s,visibility 0s 0s;   /* appears immediately */
}
.reaction-hover-btn{
  width:30px;height:30px;padding:0;border-radius:7px;border:none;
  background:transparent;color:var(--cream);font-size:16px;display:inline-flex;
  align-items:center;justify-content:center;cursor:pointer;line-height:1;transition:color .15s,background .15s;
}
.reaction-hover-btn:hover{background:rgba(255,255,255,.1);color:var(--off-white)}
.reaction-hover-btn.more{font-size:16px;color:var(--muted)}
.reaction-hover-btn.more:hover{background:rgba(255,255,255,.1);color:var(--cream)}
.reaction-hover-btn.approval-only{
  width:34px;
  border-color:rgba(231,206,58,.48);
  background:rgba(231,206,58,.15);
  box-shadow:0 0 0 1px rgba(231,206,58,.2),0 0 16px rgba(231,206,58,.25);
}
.reaction-hover-btn.approval-only:hover{
  border-color:rgba(124,92,255,.7);
  background:rgba(124,92,255,.2);
  box-shadow:0 0 0 1px rgba(124,92,255,.3),0 0 16px rgba(124,92,255,.32);
}
.hover-edit-btn{color:var(--muted)!important}
.hover-edit-btn:hover{background:rgba(255,255,255,.1)!important;color:var(--cream)!important}
/* Same grey as the icons beside it. Without this it inherited the row's own brighter
   colour and read as the one lit button in a row of dim ones. */
.hover-reply-btn{color:var(--muted)!important}
.hover-reply-btn:hover{background:rgba(255,255,255,.1)!important;color:var(--cream)!important}
.hover-thread-btn{color:var(--muted)!important}
.hover-thread-btn:hover{background:rgba(255,255,255,.1)!important;color:var(--cream)!important}
/* Forward is grey like Reply beside it. It was the one blue control in a row of greys,
   which read as a state rather than an action. */
.hover-forward-btn{color:var(--muted)!important}
.hover-forward-btn:hover{background:rgba(255,255,255,.1)!important;color:var(--cream)!important}
.hover-delete-btn{display:none!important}
body.shift-held .hover-delete-btn{display:inline-flex!important;color:white!important}
body.shift-held .hover-delete-btn:hover{background:rgba(255,255,255,.1)!important;color:white!important}
.reaction-hover-btn .chat-reaction-emoji-img{width:18px;height:18px;opacity:1;filter:none}
.chat-message-row.user .reaction-hover-tools{left:0;right:auto}
.card-comment.approval-request{
  border:1px solid rgba(231,206,58,.2);
  border-radius:8px;
  padding:8px;
  box-shadow:inset 0 0 0 1px rgba(231,206,58,.08);
}
@media (hover:none) {
  .reaction-hover-tools{opacity:1;visibility:visible;transform:none;pointer-events:auto}
}
@media (hover:none) and (max-width:900px) {
  .reaction-hover-tools{padding:3px 4px;gap:0;right:4px}
  .reaction-hover-btn{width:26px;height:26px;font-size:14px}
  .reaction-hover-btn .chat-reaction-emoji-img{width:15px;height:15px}
  .hover-edit-btn,.hover-forward-btn{display:none !important}
  .cr-msg-row.reactable>.reaction-hover-tools{right:4px}
}

/* EMOJI PICKER */
.emoji-picker{
  position:fixed;z-index:10220;display:none;max-width:min(300px,calc(100vw - 16px));
  background:rgba(10,10,9,.94);backdrop-filter:blur(14px);
  border:1px solid rgba(255,255,255,.10);border-radius:12px;
  box-shadow:0 8px 28px rgba(0,0,0,.45);padding:6px;
}
.emoji-picker.visible{display:block}
/* Hover-row reaction picker: same shell as the composer's emoji picker above, so
   the two ways into "react with an emoji" look like one control. Fill/blur/border
   come from the shared liquid-glass rule at the end of this file. */
.reaction-quick-picker{
  position:fixed;z-index:10300;display:none;max-width:min(300px,calc(100vw - 16px));
  border-radius:12px;padding:6px;
}
.emoji-picker-grid{display:flex;flex-wrap:wrap;gap:3px}
.emoji-picker-divider{height:1px;background:rgba(255,255,255,.08);margin:5px 3px}
.emoji-picker-btn,.emoji-picker-custom-btn{
  width:36px;height:34px;padding:0;border-radius:8px;border:1px solid transparent;
  background:transparent;color:var(--off-white);font-size:18px;display:inline-flex;
  align-items:center;justify-content:center;cursor:pointer;line-height:1;transition:background .12s,border-color .12s;
}
.emoji-picker-btn:hover,.emoji-picker-custom-btn:hover{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.14)}
.emoji-picker-custom-btn img{width:20px;height:20px;object-fit:contain}

/* ===== INLINE EMOTE (shortcode expansion) ===== */
/* 1.35em read fine in chat (15-16px text) but card comments and descriptions run at
   12-13px, where it collapsed to ~17px — small enough that an animated emote was
   unreadable. The floor is what actually fixes it: em alone means the emote keeps
   shrinking with whatever type it happens to sit in. */
/* An emote is a CHARACTER, not an image. 1.7em with a 22px floor made it taller than
   the line box, which is what inflated the caret next to one and pushed the lines apart.
   1.5em sits inside a normal 13px line (19.5px vs a ~19px line box) so text around it
   keeps its rhythm, and the baseline offset lands it where an emoji would sit rather
   than floating on the middle of the line. */
.inline-emote{display:inline-block;width:1.5em;height:1.5em;min-width:18px;min-height:18px;
  vertical-align:-0.35em;object-fit:contain;margin:0 1px;border-radius:2px}

/* ===== EMOTE MANAGER (settings panel) ===== */
.emote-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:8px;margin-top:12px}
.emote-card{border:1px solid var(--border-d);border-radius:8px;padding:10px 8px;background:rgba(255,255,255,.03);display:flex;flex-direction:column;align-items:center;gap:6px;position:relative;transition:background .15s}
.emote-card:hover{background:rgba(255,255,255,.06)}
.emote-card img{width:36px;height:36px;object-fit:contain}
.emote-card-name{font-size:11px;color:var(--muted);text-align:center;word-break:break-all;font-family:var(--sans);max-width:100%}
.emote-card-actions{display:flex;gap:4px;margin-top:2px}
.emote-card-actions button{width:22px;height:22px;border-radius:4px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:rgba(255,255,255,.4);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:10px;transition:all .15s}
.emote-card-actions button:hover{background:rgba(255,255,255,.1);color:var(--off-white)}
.emote-card-actions button.del:hover{background:rgba(239,68,68,.1);color:var(--danger-text)}

/* ===== BULK EMOTE UPLOAD MODAL ===== */
.emote-upload-drop{border:2px dashed var(--border-d);border-radius:10px;padding:28px;text-align:center;cursor:pointer;transition:border-color .15s,background .15s;margin-bottom:16px}
.emote-upload-drop:hover,.emote-upload-drop.drag-over{border-color:var(--coral);background:rgba(124,92,255,.05)}
.emote-upload-drop-icon{opacity:.4;margin-bottom:8px}
.emote-upload-drop p{font-size:12px;color:var(--muted);margin:4px 0}
.emote-upload-drop p strong{color:var(--coral)}
.emote-preview-grid{display:grid;grid-template-columns:1fr;gap:6px;margin-bottom:16px;max-height:300px;overflow-y:auto}
.emote-preview-item{border:1px solid var(--border-d);border-radius:8px;padding:10px 8px;background:rgba(255,255,255,.03);display:flex;flex-direction:column;align-items:center;gap:6px;position:relative}
.emote-preview-item img{width:40px;height:40px;object-fit:contain}
.emote-preview-item input{width:100%;box-sizing:border-box;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:4px;padding:4px 6px;color:var(--cream);font-size:11px;font-family:var(--sans);text-align:center;outline:none}
.emote-preview-item input:focus{border-color:var(--coral)}
.emote-remove-preview{position:absolute;top:4px;right:4px;background:none;border:none;color:rgba(255,255,255,.3);cursor:pointer;font-size:14px;line-height:1;padding:0;transition:color .15s}
.emote-remove-preview:hover{color:var(--coral)}
.emote-preview-item.emote-status-ok{border-color:rgba(115,172,131,.4)}
.emote-preview-item.emote-status-err{border-color:rgba(239,68,68,.4)}
.emote-preview-status{font-size:10px;color:var(--muted);text-align:center}

/* ===== EMOTE INPUT PICKER (insert :name: into text fields) ===== */
.emote-input-picker{display:none;position:fixed;z-index:10025;background:rgba(14,14,13,.96);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.12);border-radius:10px;box-shadow:0 6px 20px rgba(0,0,0,.45);padding:8px;width:240px}
.emote-input-picker.open{display:flex;flex-direction:column;gap:6px}
.emote-input-picker-search{padding:6px 8px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);font-size:12px;font-family:var(--sans);outline:none;width:100%;box-sizing:border-box}
.emote-input-picker-search:focus{border-color:var(--coral)}
.emote-input-picker-grid{display:flex;flex-wrap:wrap;gap:4px;overflow-y:auto;max-height:150px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.1) transparent}
.emote-input-picker-btn{width:32px;height:32px;border-radius:6px;border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.04);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;transition:background .15s;flex-shrink:0}
.emote-input-picker-btn:hover{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.25)}
.emote-input-picker-btn img{width:20px;height:20px;object-fit:contain}
.emote-input-picker-empty{font-size:12px;color:var(--muted);padding:8px;text-align:center;width:100%}
.emote-btn{width:32px;height:32px;border-radius:8px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:rgba(255,255,255,.5);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px;transition:all .15s;flex-shrink:0}
.emote-btn:hover{background:rgba(255,255,255,.1);color:var(--off-white)}


/* COMMAND POPUP */
.cmd-popup{position:absolute;bottom:100%;left:0;right:80px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:6px;margin-bottom:6px;display:none;max-height:240px;overflow-y:auto;z-index:10;box-shadow:0 -4px 20px rgba(0,0,0,.4)}
.cmd-popup.visible{display:block}
.cmd-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:6px;cursor:pointer;transition:background .1s}
.cmd-item:hover,.cmd-item.active{background:var(--state-hover)}
.cmd-item .cmd-name{font-family:var(--sans);font-size:12px;color:var(--coral);font-weight:600;min-width:90px}
.cmd-item .cmd-desc{font-size:11px;color:var(--muted)}
/* Liquid glass (Design Rules -> Liquid glass). Safe here because the popup is
   re-parented to <body> before it opens — a blurred ancestor would become a
   backdrop root and the blur would sample nothing. */
.mention-popup{position:fixed;background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);border:1px solid var(--lg-border);border-radius:12px;max-height:200px;overflow-y:auto;z-index:10100;display:none;box-shadow:var(--lg-shadow);width:300px}
.mention-popup.visible{display:block;animation:mentionPopIn 150ms cubic-bezier(.22,1,.36,1) both}
@keyframes mentionPopIn{from{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.mention-popup.visible{animation:none}}
.mention-item{padding:10px 14px;cursor:pointer;font-size:13px;display:flex;align-items:center;gap:10px;transition:background .1s}
.mention-item:hover,.mention-item.selected{background:var(--bg-inset)}
.mention-item .mention-avatar{width:22px;height:22px;border-radius:50%;background:var(--coral);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;color:white;overflow:hidden}
.mention-item .mention-avatar img{width:100%;height:100%;object-fit:cover}
.mention-item .mention-bot-badge{font-size:10px;margin-left:auto;opacity:.5}
.mention-section-header{font-size:9px;text-transform:uppercase;color:var(--muted);padding:4px 10px 2px;letter-spacing:.5px;opacity:.7}
.pb-task-card{background:var(--card);border-radius:8px;padding:12px;margin-bottom:8px;cursor:pointer;transition:background .15s}
.pb-task-card:hover{background:rgba(255,255,255,.06)}
.pb-task-card .pb-card-title{font-size:13px;font-weight:500;margin-bottom:4px}
.pb-task-card .pb-card-meta{font-size:11px;color:var(--muted)}
.pb-task-card .pb-card-source{font-size:10px;padding:2px 6px;border-radius:4px;background:rgba(255,255,255,.06);color:var(--muted);display:inline-block;margin-top:4px}

/* CARD DETAIL MODAL */
.card-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px}
/* Card modal: shrink to content. The previous min-height:80vh forced an
   80% viewport-height modal even when the card had a short description and
   no comments — left a giant empty void at the bottom. Now the modal sizes
   to fit, capped at 85vh. */
/* A1: constant modal height across tabs. Was max-height:90vh (content-driven), so switching
   Main↔Files↔Review↔Schedule↔History jumped the card's size. Pin a stable height so the outer
   card stays put and the body scrolls internally (A2 sticky tabs handle the pinned tab bar).
   Fullscreen + mobile override this below. */
/* height was a flat 90vh, so the card was always 90% of the window whether it held two
   properties or twenty — on a large monitor that is a screenful of empty space under the
   comment box. It fits its content now and only grows to 90vh when the content needs it. */
/* ONE height, whatever the task holds. height:auto meant a card with four properties and
   no comments opened short and the next one opened full-screen-tall, so every task you
   clicked resized the window you were reading. Capped in px as well as vh so a large
   monitor does not stretch it into a column of empty space. The body scrolls inside. */
.card-modal{position:relative;background:var(--dark);border:1px solid var(--modal-col-color,var(--border-d));border-radius:14px;width:100%;max-width:820px;height:min(86vh,880px);max-height:90vh;overflow-y:auto;padding:32px;transition:max-width .25s ease;display:flex;flex-direction:column}
/* .review-active is retired — a second, content-dependent review width made the modal
   resize while you were looking at it. cm-review-active is the single review width. */
.card-modal.cm-review-active .rev-side,.card-modal.cm-schedule-active .rev-side{width:392px;max-height:none}
.card-modal.cm-review-active .rev-list{max-height:60vh}
.card-modal-share:hover,.card-modal-fs:hover{color:var(--off-white);border-color:rgba(255,255,255,.25)}
.card-modal:fullscreen{max-width:none;width:100vw;height:100vh;max-height:100vh;border-radius:0;padding:24px 32px}
.card-modal:fullscreen .rev-side{max-height:none}
.card-modal:fullscreen .rev-list{max-height:none}
.card-modal:-webkit-full-screen{max-width:none;width:100vw;height:100vh;max-height:100vh;border-radius:0;padding:24px 32px}
body[data-mobile-mode="app"] .card-modal-share,body[data-mobile-mode="app"] .card-modal-fs{display:none !important}
@keyframes modalPopIn{0%{opacity:0;transform:scale(.92) translateY(16px);filter:blur(4px)}50%{opacity:1;transform:scale(1.012) translateY(-2px);filter:blur(0)}100%{opacity:1;transform:scale(1) translateY(0);filter:none}}
@keyframes modalOverlayFade{from{opacity:0}to{opacity:1}}
@keyframes modalContentReveal{0%{opacity:0;transform:translateY(14px) scale(.97);filter:blur(3px)}60%{opacity:1;transform:translateY(-1px) scale(1.005);filter:blur(0)}100%{opacity:1;transform:translateY(0) scale(1);filter:none}}
.card-modal-overlay.modal-pop-in{animation:modalOverlayFade .2s ease both}
.card-modal-overlay.modal-pop-in .card-modal{animation:modalPopIn .35s cubic-bezier(.22,1,.36,1) both}
.card-modal-overlay.modal-pop-in .card-modal-title{animation:modalContentReveal .4s cubic-bezier(.22,1,.36,1) both;animation-delay:80ms}
.card-modal-overlay.modal-pop-in .card-modal-meta{animation:modalContentReveal .4s cubic-bezier(.22,1,.36,1) both;animation-delay:120ms}
.card-modal-overlay.modal-pop-in .card-modal-tabs{animation:modalContentReveal .4s cubic-bezier(.22,1,.36,1) both;animation-delay:160ms}
.card-modal-overlay.modal-pop-in .card-modal-section{animation:modalContentReveal .4s cubic-bezier(.22,1,.36,1) both}
.card-modal-overlay.modal-pop-in .card-modal-section:nth-child(1){animation-delay:200ms}
.card-modal-overlay.modal-pop-in .card-modal-section:nth-child(2){animation-delay:260ms}
.card-modal-overlay.modal-pop-in .card-modal-section:nth-child(3){animation-delay:320ms}
.card-modal-overlay.modal-pop-in .card-modal-section:nth-child(4){animation-delay:380ms}
.card-modal-overlay.modal-pop-in .card-modal-section:nth-child(n+5){animation-delay:420ms}
.card-modal-overlay.modal-pop-in .card-modal-close{animation:modalContentReveal .35s cubic-bezier(.22,1,.36,1) both;animation-delay:60ms}
.card-modal-overlay.modal-pop-in #cardModalCommentInput{animation:modalContentReveal .4s cubic-bezier(.22,1,.36,1) both;animation-delay:380ms}

/* Files task inspector: keep #cardModal as the one canonical modal in body and
   dock its overlay over the disposable third Files column. The Files renderer
   can freely replace #hdTaskEditorDock; JS only remeasures this fixed singleton. */
#hdTaskEditorDock{display:none}
#cardModal.card-modal-files-dock{
  position:fixed;right:auto;bottom:auto;padding:0;background:transparent;
  align-items:stretch;justify-content:stretch;overflow:hidden;
  backdrop-filter:none;-webkit-backdrop-filter:none;
}
#cardModal.card-modal-files-dock>.card-modal{
  width:100%!important;height:100%;max-width:none!important;max-height:none;margin:0;padding:22px;
  box-sizing:border-box;border-radius:0;box-shadow:none;
}
#cardModal.card-modal-files-dock .card-modal-tabs{
  flex:0 0 auto;min-width:0;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;
}
#cardModal.card-modal-files-dock #cardModalTabMain,
#cardModal.card-modal-files-dock #cardModalTabReview,
#cardModal.card-modal-files-dock #cardModalTabSchedule,
#cardModal.card-modal-files-dock #cardModalTabSocial{min-width:0;max-width:100%}
/* Review and Social widen the normal popup based on viewport width. Inside the
   narrow inspector they instead become vertical, container-sized layouts. */
#cardModal.card-modal-files-dock .rev-wrap.rev2{flex-direction:column;height:auto;overflow:visible}
#cardModal.card-modal-files-dock .rev2 .rev-main{width:100%;min-height:320px;flex:none}
#cardModal.card-modal-files-dock .rev2 .rev-side{
  width:100%;height:auto;max-height:none;border-left:0;border-top:1px solid var(--hairline-2)
}
#cardModal.card-modal-files-dock .rev2 .rev-player{width:min(100%,calc(52vh * var(--rev-ar,1.77778)));height:auto;max-height:none;aspect-ratio:var(--rev-ar,16/9)}
#cardModal.card-modal-files-dock .rev2 .rev-stage{padding:0}
#cardModal.card-modal-readonly .rev-reply-composer,
#cardModal.card-modal-readonly .rev-upload-overlay,
#cardModal.card-modal-readonly .rev-replace{display:none!important}
#cardModal.card-modal-readonly #cardModalTabSchedule textarea,
#cardModal.card-modal-readonly #cardModalTabSchedule input,
#cardModal.card-modal-readonly #cardModalTabSchedule .sch-accounts,
#cardModal.card-modal-readonly #cardModalTabSchedule .sch-drop,
#cardModal.card-modal-readonly #cardModalTabSchedule .sch-media-x{pointer-events:none;opacity:.55}
#cardModal.card-modal-files-dock.modal-pop-in,
#cardModal.card-modal-files-dock.modal-pop-in>.card-modal,
#cardModal.card-modal-files-dock.modal-pop-in .card-modal-title,
#cardModal.card-modal-files-dock.modal-pop-in .card-modal-meta,
#cardModal.card-modal-files-dock.modal-pop-in .card-modal-tabs,
#cardModal.card-modal-files-dock.modal-pop-in .card-modal-section,
#cardModal.card-modal-files-dock.modal-pop-in .card-modal-close,
#cardModal.card-modal-files-dock.modal-pop-in #cardModalCommentInput{animation:none!important}
#cardModal.card-modal-files-fullscreen{inset:0;width:auto;height:auto;padding:0}
#cardModal.card-modal-files-fullscreen>.card-modal{
  width:100%!important;height:100%;max-width:none!important;max-height:none!important;margin:0;border-radius:0;
}
.card-modal-close{position:absolute;top:16px;right:16px;outline:none}
/* Task title. The subtle filled container is the affordance that it's editable.
   The "…" is presentation ONLY — the full string is always in textContent, and
   focusing drops the ellipsis and lets the field scroll, so a long title stays
   fully reachable (hover also shows it via data-tip). */
.card-modal-title{font-family:var(--serif);font-size:22px;margin-bottom:10px;outline:none;color:var(--off-white);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  /* NO negative margin — it made the title's container overhang the status row,
     tabs and description by 14px. Same call .ws-page-title.is-editable made. */
  padding:6px 14px;cursor:text;
  /* Same container as the project board's own editable title
     (.ws-page-title.is-editable) — one "this is editable" affordance across
     the app instead of a recessed well here and a soft fill there. */
  border-radius:12px;
  background:transparent;
  border:1px solid transparent;
  transition:background var(--dur-short,.15s) var(--ease-std,ease),border-color var(--dur-short,.15s) var(--ease-std,ease)}
.card-modal-title[contenteditable="false"]{background:transparent;cursor:default}
.card-modal-title:hover{background:var(--bg-inset);border-color:var(--hairline-2)}
.card-modal-title:focus,.card-modal-title.is-editing{text-overflow:clip;overflow-x:auto;overflow-y:hidden;border-color:var(--hairline)}
.card-modal-title::-webkit-scrollbar{height:6px}
.card-modal-title::-webkit-scrollbar-thumb{background:var(--hairline-2);border-radius:3px}
.card-modal-meta{font-size:11px;color:var(--muted);margin-bottom:16px;display:flex;gap:12px;align-items:center;position:relative;z-index:10}
.card-modal-section{margin-bottom:20px}
.card-modal-section-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:8px}
/* Inline Subtasks section (card modal, above Properties) */
.subtask-inline-count{font-size:11px;font-weight:600;color:var(--muted);background:rgba(255,255,255,.06);padding:1px 7px;border-radius:10px;text-transform:none;letter-spacing:0}
.subtask-inline-progress{flex:0 0 90px;height:6px;background:var(--surface-inset);border-radius:999px;overflow:hidden;text-transform:none;letter-spacing:0}
.subtask-inline-progress-fill{display:block;height:100%;background:var(--green,#86c06c);border-radius:999px;transition:width .3s ease}
/* ---- Subtask columns -------------------------------------------------------
   The strip is a fixed-width block of fixed-width cells, NOT a wrapping flex row.
   Wrapping + justify-content:flex-end was what made every row land differently:
   values packed to the right edge, so their x depended on how many were filled in.
   The header (.subtask-col-heads) is the same total width, laid out with the same
   per-cell widths, which is what keeps a label over its own column. */
.subtask-inline-vals{display:flex;align-items:center;margin-left:auto;
  flex:none;width:70%;min-width:0;flex-wrap:nowrap;justify-content:flex-start}
/* Description preview — one line, truncated at the next column. Muted and 11px so it
   reads as secondary to the subtask name it sits beside rather than competing with it. */
.subtask-inline-desc{display:block;width:100%;font-size:11px;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.subtask-inline-cell{display:flex;align-items:center;min-width:0;height:20px;
  padding-right:12px;overflow:hidden;white-space:nowrap}
/* A cell must never wrap: a two-line "Aug 24, 2026" grew the whole row and broke the
   single row height every other row keeps. Truncate instead — the full value is on
   the cell's title attribute. */
.subtask-inline-cell > *{min-width:0;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.subtask-inline-head{display:flex;align-items:center;gap:10px;padding:0 8px}
.subtask-col-heads{display:flex;align-items:center;flex:none;width:70%;min-width:0;margin-left:auto;
  font-size:10px;font-weight:600;letter-spacing:.4px;color:var(--muted);opacity:.7;
  text-transform:uppercase}
/* A person chip rendered 24px against every other value's 19.5 — its wrapper's 2px
   padding plus the inline baseline gap under the avatar — so a row with someone
   assigned stood 38px while its neighbours stood 34, and the list read as ragged for
   a reason that had nothing to do with the columns. Pin the chip box rather than
   chasing each contributor: inline-flex kills the baseline gap, and a fixed 20px
   height + the row's 7px padding is the 34px every row now holds. */
.subtask-inline-cell .subtask-inline-val,
.subtask-inline-cell .subtask-inline-due{display:inline-flex;align-items:center;
  height:20px;padding:0 7px;max-width:100%}
.subtask-inline-cell .subtask-inline-val > *{max-height:18px}
/* personAvatarHtml() writes width/height as an INLINE style, so a class rule loses to
   it and the 18px avatar pushed person rows to 36px against everyone else's 34.
   !important is the only lever a stylesheet has against an inline style. */
.subtask-inline-cell .card-avatar{width:16px!important;height:16px!important;border-width:1px}
.subtask-inline-cell .prop-person-pill{padding:2px 8px 2px 2px}
.subtask-inline-row{min-height:34px}
.subtask-col-head{min-width:0;padding-right:12px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
/* The row's own 8px of side padding has to match the header's, or every column sits
   8px off from the label above it. */
.subtask-inline-row{overflow:hidden}
.subtask-inline-val{font-size:11px;color:var(--cream);background:rgba(255,255,255,.06);padding:2px 7px;border-radius:6px;white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis;flex-shrink:0}
/* Automations page */
.auto-page-empty{text-align:center;padding:48px 24px}
.auto-card{display:flex;align-items:flex-start;gap:12px;padding:14px 16px;border:1px solid var(--border-d);border-radius:12px;background:rgba(255,255,255,.02);margin-bottom:10px;transition:border-color .15s,background .15s}
.auto-card:hover{border-color:rgba(255,255,255,.16)}
.auto-card-off{opacity:.6}
.auto-card-main{flex:1;min-width:0;cursor:pointer}
.auto-card-name{font-size:14px;font-weight:600;color:var(--cream);margin-bottom:3px}
.auto-card-sentence{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:8px}
.auto-card-meta{display:flex;align-items:center;gap:12px;font-size:11px;color:var(--muted)}
.auto-card-actions{display:flex;gap:4px;flex-shrink:0}
.auto-icon-btn{width:30px;height:30px;border-radius:7px;background:none;border:1px solid transparent;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s,color .12s}
.auto-icon-btn:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.auto-icon-danger:hover{color:var(--danger-text)}
.auto-switch{position:relative;display:inline-block;width:34px;height:20px;flex-shrink:0;margin-top:2px;cursor:pointer}
.auto-switch input{opacity:0;width:0;height:0}
.auto-switch-slider{position:absolute;inset:0;background:rgba(255,255,255,.12);border-radius:999px;transition:background .15s}
.auto-switch-slider:before{content:"";position:absolute;width:14px;height:14px;left:3px;top:3px;background:#fff;border-radius:50%;transition:transform .15s}
.auto-switch input:checked+.auto-switch-slider{background:var(--green,#86c06c)}
.auto-switch input:checked+.auto-switch-slider:before{transform:translateX(14px)}
.auto-tmpl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
.auto-tmpl-card{border:1px solid var(--border-d);border-radius:12px;padding:16px;background:rgba(255,255,255,.02)}
.auto-tmpl-name{font-size:14px;font-weight:600;color:var(--cream);margin-bottom:6px}
.auto-tmpl-note{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:12px}
.auto-history{display:flex;flex-direction:column;gap:1px}
.auto-history-row{display:flex;align-items:center;gap:14px;padding:9px 12px;border-radius:8px;font-size:13px}
.auto-history-row:hover{background:rgba(255,255,255,.03)}
.auto-history-when{color:var(--muted);width:96px;flex-shrink:0}
.auto-history-rule{color:var(--cream);font-weight:500;width:180px;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.auto-history-card{flex:1;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.auto-history-ev{color:var(--muted);font-size:11px}
.auto-builder{max-width:640px}
.auto-name-input{width:100%;padding:11px 13px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.04);color:var(--cream);font-size:14px;box-sizing:border-box;margin-bottom:16px}
.auto-flow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.auto-flow-row{padding:8px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.02)}
.auto-flow-tag{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:4px 9px;border-radius:6px;flex-shrink:0}
.auto-flow-when{background:rgba(140,114,219,.18);color:var(--purple,#8c72db)}
.auto-flow-if{background:rgba(223,179,0,.16);color:#e8c34d}
.auto-flow-do{background:rgba(134,192,108,.16);color:var(--green,#86c06c)}
.auto-flow-word{font-size:13px;color:var(--muted)}
.auto-flow-muted{opacity:.7;font-style:italic}
.auto-flow-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:18px 0 8px}
.auto-flow-sub{font-weight:400;text-transform:none;letter-spacing:0;opacity:.7}
.auto-sel,.auto-val-input{padding:7px 10px;border:1px solid var(--border-d);border-radius:8px;background:rgba(255,255,255,.05);color:var(--cream);font-family:var(--sans);font-size:13px;color-scheme:dark;max-width:210px}
.auto-val-input{min-width:120px}
.auto-row-x{margin-left:auto;width:24px;height:24px;border-radius:6px;background:none;border:none;color:var(--muted);cursor:pointer;font-size:16px;line-height:1;flex-shrink:0}
.auto-row-x:hover{color:var(--coral);background:rgba(255,255,255,.06)}
.auto-add-row{background:none;border:1px dashed var(--border-d);color:var(--muted);font-family:var(--sans);font-size:12px;padding:7px 12px;border-radius:8px;cursor:pointer;transition:border-color .15s,color .15s;margin-top:2px}
.auto-add-row:hover{border-color:var(--coral);color:var(--coral)}
.auto-builder-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:22px;padding-top:16px;border-top:1px solid var(--border-d);flex-wrap:wrap}
.auto-builder-preview{font-size:12px;color:var(--muted);font-style:italic;flex:1;min-width:200px;line-height:1.5}
/* Trash page — unified palette: purple accent + peach (soft-red) destructive, no theme-variable coral/blue */
/* The page header is the shared .hi-top / .ws-page-title pair Home uses, so Trash reads as
   a page in this app rather than a settings card. Its controls sit on the title's baseline
   rather than at the top of a tall two-line header. */
.trash-top{align-items:flex-end}
/* .hi-sub is a near-white alpha built for the dark Home header; a theme token instead, so
   the subtitle is legible in light mode too. */
.trash-top .hi-sub{color:var(--text-2)}
.trash-controls{margin-left:auto;display:flex;align-items:center;gap:10px}
.trash-purge-label{font-size:12px;color:var(--muted)}
.trash-purge-select{background:rgba(255,255,255,.04);border:1px solid var(--border-d);color:var(--cream);font-size:12px;padding:6px 10px;border-radius:8px;cursor:pointer;font-family:var(--sans);color-scheme:dark}
.trash-empty-btn{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;padding:7px 13px;border-radius:8px;cursor:pointer;border:1px solid rgba(239,68,68,.4);background:var(--color-error-tint);color:var(--danger-text);font-family:var(--sans);transition:background .15s,border-color .15s}
.trash-empty-btn:hover{background:rgba(223,138,131,.16);border-color:rgba(223,138,131,.6)}
/* Trash rows styled exactly like a kanban card: var(--dark) container, left color stripe,
   subtle border (no harsh outline), dropshadow. */
/* Flat HDrive-file-row look (matches .fm-crow) instead of the old boxed card. */
/* Match the project List (group) view — a flat table of hairline-divided rows inside a bordered
   shell, ~44px tall, subtle hover — instead of a stack of standalone cards. */
/* No well around the list. When there are rows, .gv-flat-table draws its own frame — the
   same one a project's List tab draws — so a wrapper here only ever nested one box inside
   another; when there are none, the empty state should sit on the page, not in a panel. */
#trashList{min-width:0}
/* An empty page needs air above the mark, or it reads as a stray icon under the header. */
.trash-empty{padding:96px 20px 40px}
.trash-row{display:flex;align-items:center;gap:12px;position:relative;border:0;border-bottom:1px solid var(--border-d);border-radius:0;background:transparent;box-shadow:none;margin:0;min-height:44px;padding:6px 14px;transition:background .1s ease}
.trash-row::before{display:none}
.trash-row:hover{background:rgba(255,255,255,.04);box-shadow:none;transform:none;border-color:var(--border-d)}
.trash-row:last-child{border-bottom:none}
#hdTrashSec .trash-row:last-child{border-bottom:1px solid var(--border-d)}
.trash-icon{flex-shrink:0;width:30px;height:30px;border-radius:7px;background:rgba(140,114,219,.12);display:flex;align-items:center;justify-content:center;color:var(--purple,#8c72db);overflow:hidden}
.trash-icon svg{width:16px;height:16px}
.trash-icon img,.trash-icon video{width:100%;height:100%;object-fit:cover;display:block}
.trash-row-main{flex:1;min-width:0}
.trash-row-title{font-size:14px;font-weight:600;color:var(--cream);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trash-origin{font-size:12px;color:var(--muted);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trash-row-meta{font-size:12px;color:var(--muted);margin-top:3px}
.trash-days-low{color:var(--danger-text)}
.trash-row-actions{display:flex;gap:7px;flex-shrink:0;align-items:center}
.trash-btn{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;font-family:var(--sans);padding:7px 12px;border-radius:8px;cursor:pointer;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);transition:background .15s,border-color .15s,color .15s}
.trash-btn-restore:hover{background:rgba(140,114,219,.14);border-color:var(--purple,#8c72db);color:var(--purple,#8c72db)}
.trash-btn-delete{color:var(--muted)}
.trash-btn-delete:hover{background:var(--color-error-tint);border-color:rgba(239,68,68,.5);color:var(--danger-text)}
/* Automation board-assignment chips */
.auto-boards{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:6px}
.auto-board-chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--cream);background:rgba(140,114,219,.14);border:1px solid rgba(140,114,219,.3);padding:4px 6px 4px 9px;border-radius:8px}
.auto-board-chip svg{color:var(--purple,#8c72db);opacity:.9}
.auto-board-x{background:none;border:none;color:var(--muted);cursor:pointer;font-size:15px;line-height:1;padding:0 2px;border-radius:4px}
.auto-board-x:hover{color:var(--peach,#df8a83)}
.auto-board-add{background:none;border:1px dashed var(--border-d);color:var(--muted);font-family:var(--sans);font-size:12px;padding:5px 11px;border-radius:8px;cursor:pointer;transition:border-color .15s,color .15s}
.auto-board-add:hover{border-color:var(--purple,#8c72db);color:var(--purple,#8c72db)}
.auto-board-warn{font-size:12px;color:var(--peach,#df8a83);font-style:italic}
.auto-board-gate{margin-top:14px;padding:22px 16px;text-align:center;border:1px dashed var(--border-d);border-radius:10px;color:var(--muted);font-size:13px;background:rgba(255,255,255,.02)}
.subtask-inline-list{display:flex;flex-direction:column;gap:2px;margin-bottom:8px}
.subtask-inline-row{display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:8px;transition:background .12s}
.subtask-inline-row:hover{background:rgba(255,255,255,.04)}
.subtask-inline-check{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:20px;height:20px;border-radius:50%;cursor:pointer;color:var(--muted);opacity:.5;transition:color .15s,opacity .15s,transform .12s}
.subtask-inline-row:hover .subtask-inline-check{opacity:.85}
.subtask-inline-check:hover{color:var(--green,#86c06c);opacity:1;transform:scale(1.1)}
.subtask-inline-check.is-done{color:var(--green,#86c06c);opacity:1}
.subtask-inline-title{flex:1;min-width:0;font-size:13px;color:var(--cream);cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.subtask-inline-title:hover{text-decoration:underline;text-decoration-color:rgba(255,255,255,.3)}
.subtask-inline-row.is-done .subtask-inline-title{text-decoration:line-through;text-decoration-color:rgba(134,192,108,.85);text-decoration-thickness:2px;color:var(--muted)}
.subtask-inline-due{font-size:11px;color:var(--muted);background:rgba(255,255,255,.05);padding:2px 7px;border-radius:6px;flex-shrink:0}
/* Subtask status — dot + label, the same shape the List view's status cell uses,
   sized to sit in the row's value strip rather than its own column. */
.subtask-inline-status{display:inline-flex;align-items:center;gap:5px;font-size:11px;
  color:var(--st-color,var(--muted));white-space:nowrap;flex-shrink:0}
.subtask-inline-status::before{content:"";width:6px;height:6px;border-radius:50%;
  background:var(--st-color,var(--muted));flex:none}
/* Subtask row ⋮ — hover-only, exactly like .card-prop-menu-btn on a property row. */
.subtask-inline-menu-btn{
  display:inline-flex;visibility:hidden;background:none;border:none;color:var(--muted);
  font-size:14px;cursor:pointer;padding:0 2px;line-height:1;flex-shrink:0;opacity:.5;
  transition:opacity .1s}
/* The subtask name occupies the same 110px column a property label does, so its ⋮
   lands at the same x. Reserved even when hidden, so the row does not shift on hover. */
/* Fixed 62px so the ⋮ after it lands at x=108 — the same column a property's ⋮ sits
   in (its 110px label's right edge). A property label is a fixed column, so matching
   its ⋮ position means the subtask name has to become one too.

   SUPERSEDED: that 62px pin is what left a 111px dead zone between the name and the
   first column once the values became a real table — and it ellipsised any name over
   ~62px, which is most of them. The name now fills the space the value strip does not
   take. Because every row has identical structure, flex:1 still resolves to the SAME
   width on every row, so the ⋮ keeps a consistent x down the list; it just no longer
   shares that x with the 110px property label's ⋮. Widening .card-prop-label to
   ~210px would realign the two, at the cost of a much wider label column. */
.subtask-inline-row .subtask-inline-title{
  flex:1 1 0;width:auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.subtask-inline-row .subtask-inline-menu-btn{display:inline-flex;visibility:hidden;margin-right:0}
.subtask-inline-row:hover .subtask-inline-menu-btn{visibility:visible}
.subtask-inline-menu-btn:hover{opacity:1;color:var(--cream)}
/* Inline rename on the row, matching the property rename affordance. */
.subtask-rename-input{
  flex:1;min-width:0;background:rgba(255,255,255,.05);
  border:1px solid var(--hairline,rgba(255,255,255,.18));border-radius:6px;outline:none;
  color:var(--cream);font-family:var(--sans);font-size:13px;padding:3px 6px}
/* Status swatch in the subtask menu, where a checkmark marks the current one. */
.ctx-status-dot{display:inline-block;width:10px;height:10px;border-radius:50%;flex:none}
.subtask-inline-add{margin-top:2px;background:none;border:1px dashed var(--border-d);color:var(--muted);font-family:var(--sans);font-size:12px;padding:7px 12px;border-radius:8px;cursor:pointer;transition:border-color .15s,color .15s}
/* ── Subtask detail, expanded in place ────────────────────────────────────────
   Replaces the old stacked overlay. The panel is rendered fresh each time it
   opens, so the reveal is an ANIMATION (a transition would have no start state
   to move from). 0fr→1fr grows to the content's own height without a magic
   max-height; the inner wrapper needs overflow:hidden + min-height:0 for the
   grid track to actually clip during the animation. */
.subtask-expand{
  position:relative;
  display:grid;grid-template-rows:1fr;
  /* Eased out rather than in-out: the panel arrives quickly then settles, which
     reads smoother when switching straight from one open subtask to another. */
  animation:subtaskExpandIn .15s cubic-bezier(.22,1,.36,1)}
@keyframes subtaskExpandIn{
  from{grid-template-rows:0fr;opacity:0}
  to{grid-template-rows:1fr;opacity:1}}
/* Already open and merely re-rendering — adding a property, saving a field. Replaying
   the open animation there makes the panel look like it collapsed and reopened. */
.subtask-expand.is-static{animation:none}
/* Closing. Duration comes from JS because it differs by intent: ~300ms when you
   closed the panel yourself, ~100ms when it is only clearing out for another
   subtask. Eased OUT, same family as the opening curve: it drops away immediately
   and decelerates into the close, so the long tail does the settling rather than the
   start feeling sticky. `forwards` holds the closed frame until the re-render
   removes the node, otherwise it snaps back to full height for a frame at the end. */
.subtask-expand.is-collapsing{
  animation:subtaskExpandOut var(--subtask-collapse-ms,300ms) cubic-bezier(.22,1,.36,1) forwards}
@keyframes subtaskExpandOut{
  from{grid-template-rows:1fr;opacity:1}
  to{grid-template-rows:0fr;opacity:0}}
/* No card of its own — no fill, no outline. The panel is an indented continuation
   of its row, so the left inset matches the row's title (past the check circle)
   and nothing is inset on the right. */
/* Clipping layer only — it must carry NO vertical padding or margin. overflow:hidden
   clips content but not the box's own spacing, so anything here survives the collapse
   and leaves the panel stuck partly open. 37px = the row's 8px padding + 20px check
   circle + 9px gap, so content starts exactly under the subtask's name. */
.subtask-expand > .subtask-expand-inner{
  overflow:hidden;min-height:0;margin-left:37px}
/* Everything vertical lives here, inside the clipped region, so it collapses to 0. */
.subtask-expand-body{
  /* Symmetric 8px, matching the card's own row padding, instead of the 6/2 it had.
     Its children then share one left edge: the description box, the property rows and
     the + Add Property button all start together rather than at three offsets. */
  display:flex;flex-direction:column;gap:8px;padding:8px 0;margin-bottom:8px}
/* The property rows inside a panel carry the card's 8px row padding, which pushed
   their labels 8px right of the description box above them. Pull that back so every
   line in the panel starts on the same x. */
.subtask-expand-props .card-prop-row{margin-left:-8px;margin-right:-8px}
.subtask-expand-props .card-prop-add{margin-left:0}
/* Connector rail — shows the panel is hanging off the row above rather than
   floating as its own item. It lives on the OUTER element, not .subtask-expand-inner:
   the inner needs overflow:hidden for the 0fr→1fr animation to clip, which also
   clipped a rail positioned outside its padding box (it never painted at all).
   position:absolute keeps it from becoming a grid item and claiming a row.
   left:17px centres the 2px rail on the check circle (x=18 from the row's left:
   8px row padding + half the 20px circle), so it reads as a thread hanging from
   that subtask's own checkbox. --border-d (8% white) vanished against the modal's
   near-black fill, so the rail sits a step above a plain hairline. */
.subtask-expand::before{
  content:"";position:absolute;left:17.5px;top:0;bottom:0;width:1px;
  /* A hairline, faded out at both ends so it reads as a connector rather than a
     hard rule. `left` keeps it centred on the check circle (x=18: 8px row padding
     + half the 20px circle). No border-radius — the gradient's soft ends do that
     job. Width drops to half a pixel on retina below, which is a single device
     pixel; 1px here is the floor for 1x displays, where .5px would round away. */
  /* Runs the full height of the expanded panel — top:0/bottom:0 — so it reaches past
     the last property to the panel's bottom edge. Only the outermost 10px at each end
     fade, so the rail reads as spanning the whole subtask rather than stopping short. */
  background:linear-gradient(to bottom,
    transparent 0,
    rgba(255,255,255,.20) 34px,
    rgba(255,255,255,.20) calc(100% - 34px),
    transparent 100%);
  pointer-events:none}
/* True hairline where the display can draw one: .5px = 1 device pixel at 2x.
   left shifts to 17.75px so the thinner line stays centred on x=18. */
@media (min-resolution:2dppx){
  .subtask-expand::before{width:.5px;left:17.75px}
}
/* The open row reads as the panel's header rather than a separate item. */
.subtask-inline-row.is-expanded{background:rgba(255,255,255,.04)}
.subtask-inline-row.is-expanded .subtask-inline-title{text-decoration:none}
/* The description is a contenteditable .mention-input, not a textarea — a textarea
   can't hold @mention chips. Its empty-state text comes from .mention-input:empty
   ::before reading data-placeholder, so no ::placeholder rule applies. The wrapper
   is the positioning context for the mention popup. */
.subtask-expand-descwrap{position:relative}
.subtask-expand-desc{
  /* No outline, matching the task description — the fill already reads as a field. */
  background:rgba(255,255,255,.03);border:1px solid transparent;border-radius:7px;outline:none;
  color:var(--cream);font-family:var(--sans);font-size:12px;line-height:1.5;
  padding:8px;min-height:114px;max-height:294px;overflow-y:auto;width:100%;box-sizing:border-box}
.subtask-expand-desc:focus{border-color:var(--hairline,rgba(255,255,255,.18))}

/* Subtask properties are the SAME component as a task's properties — same
   .card-prop-row / -label / -value, same 32px row, same 110px label column, same
   hover-only ⋮. Nothing here restyles them; an earlier version laid them out on
   their own grid and the two stopped matching. Only the container is scoped. */
.subtask-expand-props{padding-top:4px;border-top:1px solid rgba(255,255,255,.05)}
.subtask-inline-add:hover{border-color:var(--coral);color:var(--coral)}
/* Per-subtask popup (reuses .card-modal / .card-modal-overlay shell) */
.subtask-popup-x{position:absolute;top:16px;right:16px;width:28px;height:28px;border-radius:6px;background:none;border:1px solid var(--border-d);color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;z-index:2}
.subtask-popup-x:hover{color:var(--cream);border-color:var(--muted)}
.subtask-popup-head{display:flex;align-items:flex-start;gap:12px;margin-bottom:20px;padding-right:36px}
.subtask-popup-check{flex-shrink:0;margin-top:2px;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;cursor:pointer;color:var(--muted);opacity:.6;transition:color .15s,opacity .15s,transform .12s}
.subtask-popup-check:hover{color:var(--green,#86c06c);opacity:1;transform:scale(1.08)}
.subtask-popup-check.is-done{color:var(--green,#86c06c);opacity:1}
.subtask-popup-titlewrap{flex:1;min-width:0}
.subtask-popup-title-row{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.subtask-popup-parent{font-family:var(--serif);font-size:20px;color:var(--muted);white-space:nowrap}
.subtask-popup-dash{opacity:.6}
.subtask-popup-title{flex:1;min-width:120px;font-family:var(--serif);font-size:22px;background:none;border:none;border-bottom:1px solid transparent;color:var(--off-white);outline:none;padding:0 0 2px}
.subtask-popup-title:focus{border-bottom-color:var(--border-d)}
.subtask-popup-tag{font-style:italic;font-size:12px;color:var(--muted);opacity:.55;margin-top:3px}
.subtask-popup-desc{width:100%;min-height:90px;padding:11px 12px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.04);color:var(--cream);font-family:var(--sans);font-size:13px;box-sizing:border-box;resize:vertical}
.subtask-popup .card-prop-value input,.subtask-popup .card-prop-value select{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;color:var(--cream);font-family:var(--sans);font-size:13px;padding:7px 10px;color-scheme:dark}
.card-desc-editor-wrap{
  border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.04);
  transition:border-color .15s,background .15s;overflow:hidden;
}
.card-desc-editor-wrap:focus-within{border-color:var(--modal-col-color,var(--color-primary));background:rgba(255,255,255,.06)}
.card-desc-toolbar-bar{
  display:flex;align-items:center;gap:1px;padding:4px 8px;border-bottom:1px solid var(--border-d);
  background:rgba(255,255,255,.03);flex-wrap:wrap;
}
.card-desc-toolbar-bar .desc-tb-btn{
  background:none;border:none;color:rgba(255,255,255,.4);cursor:pointer;padding:4px 6px;border-radius:4px;
  display:flex;align-items:center;justify-content:center;transition:color .12s,background .12s;font-size:11px;
  font-weight:600;font-family:var(--sans);line-height:1;
}
.card-desc-toolbar-bar .desc-tb-btn:hover{color:var(--cream);background:var(--state-hover)}
.card-desc-toolbar-bar .desc-tb-btn.active{color:var(--cream);background:rgba(255,255,255,.12)}
.card-desc-toolbar-bar .desc-tb-sep{width:1px;height:18px;background:rgba(255,255,255,.1);margin:0 3px;flex-shrink:0}
.desc-tb-color-popup,.desc-tb-fontsize-popup{
  position:absolute;top:100%;left:0;z-index:250;background:var(--bg-dark,#1a1a2e);border:1px solid var(--border-d);
  border-radius:8px;padding:8px;box-shadow:0 4px 16px rgba(0,0,0,.4);display:none;
}
.desc-tb-color-popup.open,.desc-tb-fontsize-popup.open{display:block}
.desc-tb-color-grid{display:flex;flex-wrap:wrap;gap:4px;max-width:160px}
.desc-tb-color-swatch{width:20px;height:20px;border-radius:4px;cursor:pointer;border:2px solid transparent;transition:border-color .12s}
.desc-tb-color-swatch:hover{border-color:rgba(255,255,255,.5)}
.desc-tb-color-swatch.active{border-color:var(--cream)}
.desc-tb-fontsize-popup button{
  display:block;width:100%;text-align:left;background:none;border:none;color:var(--cream);
  padding:4px 12px;border-radius:4px;cursor:pointer;font-size:12px;white-space:nowrap;
}
.desc-tb-fontsize-popup button:hover{background:var(--state-hover)}
.card-modal-description{
  width:100%;min-height:220px;max-height:400px;overflow-y:auto;
  color:var(--cream);
  font-family:var(--sans);font-size:13px;line-height:1.6;
  padding:10px 14px;outline:none;
  white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word;
  background:transparent;border:none;border-radius:0;
}
.card-modal-description:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}
.card-modal-description h1,.card-modal-description h2,.card-modal-description h3{
  margin:8px 0 4px;font-family:var(--sans);line-height:1.3;
}
.card-modal-description h1{font-size:20px}
.card-modal-description h2{font-size:16px}
.card-modal-description h3{font-size:14px}
.card-modal-description ul,.card-modal-description ol{margin:6px 0 6px 18px;padding:0}
.card-modal-description li{margin:2px 0}
.card-modal-description ul.desc-checklist{list-style:none;margin:6px 0;padding:0}
.card-modal-description ul.desc-checklist li{display:flex;align-items:flex-start;gap:6px;margin:2px 0;padding:2px 0}
.card-modal-description ul.desc-checklist li label{display:flex;align-items:flex-start;gap:6px;flex:1;cursor:text;min-height:20px}
.card-modal-description ul.desc-checklist li input[type="checkbox"]{appearance:none;-webkit-appearance:none;width:16px;height:16px;min-width:16px;border:2px solid rgba(255,255,255,.3);border-radius:4px;background:transparent;cursor:pointer;margin-top:2px;position:relative;transition:background .15s,border-color .15s}
.card-modal-description ul.desc-checklist li input[type="checkbox"]:checked{background:var(--green);border-color:var(--green)}
.card-modal-description ul.desc-checklist li input[type="checkbox"]:checked::after{content:'';position:absolute;left:4px;top:1px;width:5px;height:9px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
.card-modal-description ul.desc-checklist li input[type="checkbox"]:hover{border-color:rgba(255,255,255,.5)}
.card-modal-description ul.desc-checklist li.checked .checklist-text{text-decoration:line-through;color:rgba(255,255,255,.35)}
.card-modal-description a{color:var(--blue);text-decoration:none}
.card-modal-description a:hover{text-decoration:underline}
.card-modal-description code{
  background:var(--surface-inset);border:1px solid rgba(255,255,255,.12);border-radius:4px;padding:1px 4px;
}
.card-modal-description pre{
  background:rgba(0,0,0,.25);border:1px solid rgba(255,255,255,.12);border-radius:8px;padding:8px;overflow:auto;margin:8px 0;
}
.card-modal-description s,.card-modal-description strike{text-decoration:line-through;color:rgba(255,255,255,.45)}
.card-modal-description-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}
.card-modal-description-preview{display:none!important}
/* Upload-in-progress warning banner */
.card-upload-warning{display:none;align-items:center;gap:10px;padding:10px 16px;margin:-8px -28px 12px;background:rgba(231,206,58,.12);border-bottom:1px solid rgba(231,206,58,.25);animation:uploadWarnPulse 2s ease-in-out infinite}
.card-upload-warning.active{display:flex}
.card-upload-warning-icon{font-size:18px;line-height:1;flex-shrink:0}
.card-upload-warning-text{font-size:12px;font-weight:600;color:var(--gold);letter-spacing:.3px;text-transform:uppercase}
@keyframes uploadWarnPulse{0%,100%{opacity:1}50%{opacity:.7}}
/* Template mode banner */
.card-template-banner{display:flex;align-items:center;gap:10px;padding:10px 16px;margin:-8px -28px 12px;background:rgba(231,206,58,.08);border-bottom:1px solid rgba(231,206,58,.2)}
.desc-link-popup{
  position:absolute;z-index:260;background:var(--bg-dark,#1a1a2e);border:1px solid var(--border-d);
  border-radius:8px;padding:10px;box-shadow:0 4px 16px rgba(0,0,0,.4);display:none;min-width:260px;
}
.desc-link-popup.open{display:block}
.desc-link-popup label{display:block;font-size:11px;color:var(--muted);margin-bottom:3px}
.desc-link-popup input{
  width:100%;padding:5px 8px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.06);
  color:var(--cream);font-size:12px;outline:none;margin-bottom:8px;
}
.desc-link-popup input:focus{border-color:var(--coral)}
.desc-link-popup .desc-link-btns{display:flex;gap:6px;justify-content:flex-end}
.desc-link-popup .desc-link-btns button{
  padding:4px 12px;border-radius:6px;font-size:11px;cursor:pointer;border:none;font-weight:600;
}
.desc-link-popup .desc-link-ok{background:var(--coral);color:#fff}
.desc-link-popup .desc-link-cancel{background:rgba(255,255,255,.08);color:var(--cream)}
.card-desc-preview-link{color:var(--blue);text-decoration:none}
.card-desc-preview-link:hover{text-decoration:underline}
.card-desc-preview-hash{
  display:inline-block;padding:1px 6px;border-radius:10px;background:rgba(124,92,255,.14);color:var(--coral);font-size:11px;font-weight:600;
}
.card-desc-preview-img-wrap{margin:8px 0}
.card-desc-preview-img{
  display:block;max-width:100%;max-height:280px;border-radius:8px;border:1px solid rgba(255,255,255,.12);
}
.card-desc-img-resize-wrap{position:relative;display:inline-block;margin:8px 0}
.card-desc-img-resize-wrap.selected .card-desc-img-resize-handle{display:block}
.card-desc-img-resize-handle{position:absolute;width:10px;height:10px;background:var(--coral);border:2px solid #fff;border-radius:2px;cursor:se-resize;display:none;z-index:10}
.card-desc-img-resize-handle.tl{top:-5px;left:-5px;cursor:nw-resize}
.card-desc-img-resize-handle.tr{top:-5px;right:-5px;cursor:ne-resize}
.card-desc-img-resize-handle.bl{bottom:-5px;left:-5px;cursor:sw-resize}
.card-desc-img-resize-handle.br{bottom:-5px;right:-5px;cursor:se-resize}
.card-comment{padding:10px 0;border-bottom:1px solid var(--border-d);font-size:13px;line-height:1.5;border-radius:6px;transition:background .25s,box-shadow .25s,padding-left .25s,padding-right .25s}
/* Highlight a comment the user just navigated to from a mention. Stronger
   visual treatment than before:
     - 5px coral inset stripe (was 3px)
     - Pronounced pulsing background tint
     - A "MENTIONED" pill anchored to the top-right of the comment so the user
       can spot exactly where they were tagged on long threads
   Fades away after 12 seconds or on first mouseenter. */
/* Minimal: just a left-edge accent strip in the card's status color.
   No full-row background, no "MENTIONED HERE" pill — keeps the
   comment readable and unobtrusive while still drawing the eye to the
   exact row. Pulses gently so it's noticeable on long threads. */
.card-comment.mv-comment-highlight,
.mv-comment-highlight{
  position:relative;
  scroll-margin-top:100px;
  animation:mvCommentHighlightPulse 1.6s ease-in-out infinite;
}
@keyframes mvCommentHighlightPulse{
  0%,100%{box-shadow:inset 4px 0 0 var(--modal-col-color, var(--coral))}
  50%    {box-shadow:inset 4px 0 0 var(--modal-col-color, var(--coral)), 0 0 0 4px color-mix(in srgb, var(--modal-col-color, var(--coral)) 18%, transparent)}
}
.card-comment:last-child{border-bottom:none}
/* Comment author name is neutral white at rest, then tints to the card
   modal's status color (--modal-col-color) on hover — signals clickability
   while staying readable as part of the comment header. */
.card-comment-author{font-weight:600;color:var(--cr-au,var(--off-white));font-size:12px;transition:color .15s}
.card-comment-author:hover{color:var(--modal-col-color,var(--coral))}
.card-comment-avatar{display:inline-flex;align-items:center;transition:transform .15s}
.card-comment-avatar:hover{transform:scale(1.08)}
.card-comment-time{font-size:10px;color:var(--muted);margin-left:8px}
.card-comment-text{margin-top:4px;color:var(--cream)}
.coding-block{margin-top:6px;border:1px solid rgba(255,255,255,.1);border-radius:6px;background:rgba(0,0,0,.25);font-size:12px}
.coding-block summary{cursor:pointer;padding:6px 10px;color:var(--cream);font-weight:600;font-size:11px;user-select:none}
.coding-block summary:hover{color:var(--coral)}
.coding-block pre{margin:0;padding:8px 10px;white-space:pre-wrap;word-break:break-word;color:var(--cream);font-family:var(--font-mono,'SF Mono',monospace);font-size:11px;line-height:1.5;max-height:300px;overflow-y:auto;border-top:1px solid var(--border-d)}
.card-comment-text .mention,.mention{font-weight:600;padding:1px 6px;border-radius:4px;font-size:inherit;line-height:inherit}
/* Chips that point at something are <a> now (see renderMentionSpan). They must read as
   pills, not as links: no underline, no visited colour, and the same inline box a span
   had. A missing target keeps the pill shape and says so instead of being clickable. */
a.mention,a.mention:visited,a.mention:hover{text-decoration:none;color:inherit}

.mention-hash{color:var(--text-1);background:var(--bg-inset)}
/* Person @mentions: tint matches the surrounding card modal's status color
   (via --modal-col-color set on .card-modal). Outside a card context the
   coral fallback keeps mentions readable. color-mix gives us the same
   subtle 14%/24% opacity treatment regardless of the column's actual hex. */
.mention-person{color:var(--modal-col-color,var(--coral));background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 14%,transparent);transition:background .15s,color .15s}
.mention-person:hover{background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 26%,transparent)}
.mention-task{color:var(--blue);background:rgba(74,144,217,.12);cursor:pointer}
.mention-task:hover{background:rgba(74,144,217,.22)}
.mention-journal{color:var(--lavender);background:rgba(183,148,214,.12);cursor:pointer}
.mention-journal:hover{background:rgba(183,148,214,.22)}
/* Kept only for content rendered before bots became ordinary members; new bot mentions
   render through the person path. Matched to it so old and new read the same. */
.mention-bot{color:#cbbdff;background:rgba(124,92,255,.24)}
.mention-special{color:#f5c542;background:rgba(245,197,66,.15);font-weight:700}
.mention-page{color:var(--gold);background:rgba(229,195,104,.12);cursor:pointer}
a.auto-link{color:var(--blue);text-decoration:none;word-break:break-all}
a.auto-link:hover{text-decoration:underline}
.mention-page:hover{background:rgba(229,195,104,.22)}
.kanban-card-subtask-progress{display:inline-flex;align-items:center;gap:4px;font-size:10px;color:var(--muted);padding:3px 8px;background:rgba(255,255,255,.04);border-radius:6px}
.kanban-card-subtask-progress .subtask-bar{width:40px;height:4px;background:var(--surface-inset);border-radius:2px;overflow:hidden}
.kanban-card-subtask-progress .subtask-bar-fill{height:100%;background:var(--green);border-radius:2px;transition:width .3s ease}
.kanban-card-subtask-progress.all-done{color:var(--green)}
.progress-tab-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 0}
.progress-activity-feed{padding:12px 14px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.02)}
.progress-activity-title{font-size:10px;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);font-weight:700;margin-bottom:8px}
.progress-activity-live{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--blue)}
.progress-activity-idle{font-size:12px;color:var(--muted);font-style:italic}
.progress-bar-section{padding:0 2px}
.progress-bar-label{font-size:11px;color:var(--cream);margin-bottom:6px}
.progress-bar-track{height:6px;background:var(--surface-inset);border-radius:3px;overflow:hidden}
.progress-bar-fill{height:100%;background:var(--green);border-radius:3px;transition:width .4s ease}
.progress-checklist{display:flex;flex-direction:column;gap:4px}
.progress-checklist-item{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;font-size:12px;color:var(--cream);border:1px solid transparent}
.progress-checklist-item.done{color:var(--muted);text-decoration:line-through}
.progress-checklist-item.done .progress-check-icon{color:var(--green)}
.progress-checklist-item.working{border-color:rgba(32,123,170,.3);background:rgba(32,123,170,.06)}
.progress-checklist-item.working .progress-check-icon{color:var(--blue)}
.progress-checklist-item.stuck{border-color:rgba(239,68,68,.3);background:rgba(239,68,68,.06)}
.progress-checklist-item.stuck .progress-check-icon{color:var(--coral)}
.progress-checklist-item.active{border-color:rgba(32,123,170,.5);background:rgba(32,123,170,.1)}
.progress-check-icon{width:16px;text-align:center;flex-shrink:0}
.progress-check-result{font-size:10px;color:var(--muted);margin-left:auto;cursor:help;text-decoration:underline dotted}
.mention-input{cursor:text;white-space:pre-wrap;word-wrap:break-word;overflow-y:auto}
.mention-input:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}
.mention-input:focus:empty::before{opacity:.6}
/* No display:inline here — it overrode the generic .mention-chip inline-flex rule and
   left the pfp sitting off-center inside the chip. */
/* A chip in the COMPOSER carries an avatar, so its box is taller than a line of text. Left
   on the baseline it hangs below the words around it — the same problem the rendered message
   chips already solve with vertical-align:middle, which this rule was overriding by not
   setting one. inline-flex centres the avatar against the name inside the pill at the same
   time, so both alignments come from one rule instead of fighting each other. */
.mention-input .mention-chip{display:inline-flex;align-items:center;gap:4px;vertical-align:middle;
  font-weight:600;padding:1px 6px;border-radius:4px;white-space:nowrap;line-height:1.35;font-size:inherit}
.mention-input .mention-chip > *{flex:none}
.mention-input .mention-chip[data-type="bot"],
.mention-input .mention-chip[data-type="person"]{color:var(--coral);background:rgba(124,92,255,.12)}
.mention-input .mention-chip[data-type="task"]{color:var(--blue);background:rgba(74,144,217,.12)}
.mention-input .mention-chip[data-type="journal"]{color:var(--lavender);background:rgba(183,148,214,.12)}
.mention-input .mention-chip[data-type="page"]{color:var(--gold);background:rgba(229,195,104,.12)}
.mention-input .mention-chip[data-type="special"]{color:#f5c542;background:rgba(245,197,66,.15);font-weight:700}
.mention-input .mention-chip[data-type="drive"]{color:#4285f4;background:rgba(66,133,244,.12)}
.drive-link-pill{display:inline-flex;align-items:center;gap:3px;height:var(--chip-h,22px);padding:0 7px;border-radius:6px;box-sizing:border-box;background:rgba(66,133,244,.12);color:#4285f4;font-size:inherit;font-weight:600;text-decoration:none;white-space:nowrap;cursor:pointer;line-height:1.1;vertical-align:middle;max-width:min(280px,100%);min-width:0}
/* Branded URL chips — bare links render as compact mention-style pills (color set inline per brand) */
.link-chip{display:inline-flex;align-items:center;gap:5px;height:var(--chip-h,22px);padding:0 8px;border-radius:6px;box-sizing:border-box;background:color-mix(in srgb,currentColor 14%,transparent);font-size:inherit;font-weight:600;text-decoration:none !important;white-space:nowrap;cursor:pointer;line-height:1.1;vertical-align:middle;max-width:min(280px,100%);min-width:0}
.link-chip:hover{background:color-mix(in srgb,currentColor 22%,transparent)}
.link-chip svg{flex:none}
.link-chip span{overflow:hidden;text-overflow:ellipsis}
.drive-link-pill:hover{background:rgba(66,133,244,.2);text-decoration:none}
.drive-link-pill svg{flex-shrink:0}
[data-hold-delete]{position:relative;overflow:hidden;isolation:isolate;touch-action:none;--hold-delete-ms:2000ms;--hold-delete-color:#dc2626}
[data-hold-delete]::after{content:'';position:absolute;inset:0;background:var(--hold-delete-color);opacity:0;transform:scaleX(0);transform-origin:left center;transition:transform var(--hold-delete-ms) linear,opacity .12s linear;pointer-events:none;border-radius:inherit}
[data-hold-delete].hold-active{color:var(--hold-delete-color)!important;border-color:var(--hold-delete-color)!important;transition:color var(--hold-delete-ms) linear,border-color var(--hold-delete-ms) linear,background-color var(--hold-delete-ms) linear!important}
[data-hold-delete].hold-active::after{opacity:.38;transform:scaleX(1)}
.card-tags{display:flex;flex-wrap:wrap;gap:6px}
.card-tag{font-size:10px;font-weight:600;padding:3px 10px;border-radius:20px;background:rgba(255,255,255,.08);color:var(--muted);cursor:pointer}
.card-tag:hover{background:rgba(124,92,255,.15);color:var(--coral)}
.card-prop-tags{display:flex;flex-wrap:wrap;gap:6px;min-height:22px;padding:4px;border:1px solid rgba(255,255,255,.07);border-radius:8px;background:rgba(255,255,255,.02)}
.card-prop-tag{display:inline-flex;align-items:center;gap:6px;font-size:10px;font-weight:600;padding:3px 8px;border-radius:999px;background:rgba(255,255,255,.08);color:rgba(255,255,255,.9)}
.card-prop-tag-remove{width:14px;height:14px;border-radius:50%;border:none;background:rgba(255,255,255,.14);color:rgba(255,255,255,.8);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1;font-size:10px;padding:0}
.card-prop-tag-remove:hover{background:rgba(255,255,255,.28);color:#fff}
.card-col-select{
  padding:6px 12px;border-radius:8px;border:1px solid var(--col-select-color,var(--border-d));
  background:rgba(255,255,255,.06);color:var(--col-select-color,var(--off-white));
  font-family:var(--sans);font-size:12px;outline:none;color-scheme:dark;
  -webkit-appearance:none;appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 8px center;padding-right:28px;
}
.card-col-select option{background:var(--dark);color:var(--cream);padding:6px 12px}
.card-col-select:focus{border-color:var(--col-select-color,var(--coral))}
/* Standardized Dropdown (ms-dropdown) */
.ms-dropdown{position:relative;display:inline-block}
.ms-dropdown-trigger{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:7px 12px;background:rgba(255,255,255,.05);border:1px solid var(--col-select-color,var(--border-d));border-radius:8px;color:var(--col-select-color,var(--cream));font-size:12px;font-weight:600;font-family:var(--sans);cursor:pointer;transition:border-color .15s,box-shadow .15s;outline:none;text-align:left}
.ms-dropdown-trigger:hover{border-color:rgba(124,92,255,.4)}
.ms-dropdown-trigger:focus,.ms-dropdown.open .ms-dropdown-trigger{border-color:var(--coral);box-shadow:0 0 0 3px rgba(124,92,255,.12)}
.ms-dropdown-trigger-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms-dropdown-trigger-chevron{flex-shrink:0;color:var(--muted);display:flex;align-items:center;transition:transform .15s}
.ms-dropdown.open .ms-dropdown-trigger-chevron{transform:rotate(180deg)}
.ms-dropdown-menu{display:none;position:absolute;top:calc(100% + 4px);left:0;min-width:100%;width:max-content;z-index:200;background:#111110;border:1px solid var(--border-d);border-radius:10px;box-shadow:0 8px 32px rgba(0,0,0,.7);max-height:240px;overflow-y:auto;overflow-x:hidden}
.ms-dropdown.open .ms-dropdown-menu{display:block}
.ms-dropdown-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:12px;font-weight:500;color:var(--cream);transition:background .1s}
.ms-dropdown-item:hover{background:var(--state-hover)}
.ms-dropdown-item-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms-dropdown-item-check{flex-shrink:0;margin-left:8px;color:var(--green);display:flex;align-items:center;opacity:0}
.ms-dropdown-item.selected{background:rgba(255,255,255,.05)}
.ms-dropdown-item.selected .ms-dropdown-item-check{opacity:1}
.ms-dropdown-item.selected:hover{background:var(--state-hover)}
/* Card Modal Tabs */
/* A2: keep the tab bar pinned to the top of the modal while the body scrolls. The scroll
   container (.card-modal) has 32px padding-top, so top:-32px pins the bar flush at the very top
   as content scrolls beneath it. Solid background + z-index so scrolled content passes under. */
/* Tightened: the rule under the tabs sat in a 14px/12px well that read as a gap rather than a
   divider. Both were also off the 4px grid the design rules require (14px was a one-off). */
.card-modal-tabs{display:flex;gap:2px;align-items:center;margin-bottom:var(--sp-2);border-bottom:1px solid var(--hairline-2);position:sticky;top:-32px;z-index:6;background:var(--modal-bg,#0c0c0e);padding-top:var(--sp-3);padding-bottom:2px;margin-top:2px}
html[data-theme="light"] .card-modal-tabs{background:var(--card,#fff)}
/* Full-screen padding is 24px top → adjust the sticky offset to match. */
.card-modal:fullscreen .card-modal-tabs,.card-modal:-webkit-full-screen .card-modal-tabs{top:-24px}
/* Mobile card modal manages its own scroll/tabs — don't pin there. */
body[data-mobile-mode="app"] .card-modal-tabs{position:static;top:auto}
.card-modal-tab{padding:9px 14px;background:none;border:none;color:var(--muted);font-size:var(--text-base);font-weight:600;letter-spacing:.1px;cursor:pointer;display:inline-flex;align-items:center;gap:8px;transition:color var(--dur-toggle) var(--ease-std);font-family:var(--sans);user-select:none;position:relative;z-index:1;border-radius:10px;white-space:nowrap}
.card-modal-tab svg{width:18px;height:18px;opacity:.65;flex-shrink:0;transition:opacity var(--dur-toggle) var(--ease-std)}
.card-modal-tab:hover svg{opacity:.9}
.card-modal-tab.active svg{opacity:1}
.card-modal-tab:hover{color:var(--cream)}
/* The active tab is tinted toward the card's column colour, so the selector reads
   as the same accent as the status chip instead of a white label on a coloured
   thumb. Only 45% of the way there, blended into --text-1: the raw column colour
   fails contrast badly on the 20%-tinted thumb — the DEFAULT swatch #e7ce3a lands
   at 1.45:1 in light theme, and #333333 at 1.46:1 in dark. 45% is the most colour
   that still clears 4.5:1 across every COL_COLOR_PALETTE entry in both themes
   (worst case 4.67:1). Blending into --text-1 is what makes it self-correcting:
   pale swatches darken in light theme, dark swatches lighten in dark theme. */
.card-modal-tab.active{color:color-mix(in srgb,var(--modal-col-color,var(--text-1)) 45%,var(--text-1))}
/* Sliding pill thumb for the card-modal tabs — same engine + timing as the view tabs. */
/* Task tabs follow the card's own column colour (--modal-col-color), so the tab
   highlight matches the task rather than being purple everywhere. No border: the
   fill IS the selector, and an outline on a moving thumb reads as a second edge. */
.card-modal-tabs .m-pill-thumb{background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 20%,transparent);border:0;border-radius:10px;transition:transform var(--tab-slide-dur) var(--tab-slide-ease),width var(--tab-slide-dur) var(--tab-slide-ease),height var(--tab-slide-dur) var(--tab-slide-ease),opacity .15s ease}
@media(prefers-reduced-motion:reduce){.card-modal-tabs .m-pill-thumb{transition:opacity .18s ease}}
/* Tab drag-to-reorder removed with its feature — .draggable/.dragging/.drag-over-* went
   with the listeners that set them. */
/* + Tab button & dropdown */
.card-tab-add-btn{padding:6px 10px;background:none;border:none;border-bottom:2px solid transparent;color:var(--muted);font-size:14px;font-weight:600;cursor:pointer;transition:all .15s;font-family:var(--sans);display:flex;align-items:center;position:relative}
.card-tab-add-btn:hover{color:var(--cream);background:rgba(255,255,255,.04)}
.card-tab-add-dropdown{position:absolute;top:calc(100% + 6px);left:0;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:6px;min-width:180px;box-shadow:0 8px 24px rgba(0,0,0,.5);z-index:300;display:none}
.card-tab-add-dropdown.open{display:block}
.card-tab-add-dropdown button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;background:none;border:none;color:var(--cream);font-size:12px;cursor:pointer;border-radius:6px;font-family:var(--sans);transition:background .12s}
.card-tab-add-dropdown button:hover{background:var(--state-hover)}
.card-tab-add-dropdown button svg{flex-shrink:0}
/* Checklist tab */
.custom-checklist{list-style:none;padding:0;margin:0}
.custom-checklist li{display:flex;align-items:flex-start;gap:8px;padding:6px 0;border-bottom:1px solid rgba(255,255,255,.04)}
.custom-checklist li:last-child{border-bottom:none}
.custom-checklist li input[type="checkbox"]{appearance:none;-webkit-appearance:none;width:18px;height:18px;min-width:18px;border:2px solid rgba(255,255,255,.3);border-radius:4px;cursor:pointer;position:relative;top:1px;transition:all .15s}
.custom-checklist li input[type="checkbox"]:checked{background:var(--green);border-color:var(--green)}
.custom-checklist li input[type="checkbox"]:checked::after{content:'';position:absolute;left:5px;top:1px;width:4px;height:9px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
.custom-checklist li input[type="checkbox"]:hover{border-color:rgba(255,255,255,.5)}
.custom-checklist li .cl-text{flex:1;background:none;border:none;color:var(--cream);font-size:13px;font-family:var(--sans);outline:none;padding:2px 0;line-height:1.4}
.custom-checklist li .cl-text:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}
.custom-checklist li.checked .cl-text{text-decoration:line-through;opacity:.4}
.custom-checklist li .cl-delete{opacity:0;background:none;border:none;color:var(--muted);cursor:pointer;padding:2px 4px;font-size:14px;transition:opacity .12s}
.custom-checklist li:hover .cl-delete{opacity:.6}
.custom-checklist li .cl-delete:hover{color:var(--coral);opacity:1}
.cl-progress-bar{height:4px;background:var(--surface-inset);border-radius:2px;margin-bottom:12px;overflow:hidden}
.cl-progress-fill{height:100%;background:var(--modal-col-color,var(--green));border-radius:2px;transition:width .25s ease}
.cl-add-item{display:flex;align-items:center;gap:6px;padding:8px 0;cursor:pointer;color:var(--muted);font-size:12px;transition:color .15s}
.cl-add-item:hover{color:var(--cream)}
/* Checklist percentage header */
.cl-pct-header{display:flex;align-items:center;gap:14px;padding:2px 0 14px}
.cl-pct-num{font-size:34px;font-weight:800;color:var(--modal-col-color,var(--green));letter-spacing:-1.5px;line-height:1;font-variant-numeric:tabular-nums}
.cl-pct-done .cl-pct-num{color:var(--modal-col-color,var(--green))}
.cl-pct-meta{display:flex;flex-direction:column;gap:2px}
.cl-pct-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.cl-pct-count{font-size:12px;color:var(--muted)}
/* Checklist item expand button & properties */
.custom-checklist li{flex-wrap:wrap}
.cl-expand-btn{opacity:0;background:none;border:none;color:var(--muted);cursor:pointer;padding:2px 4px;transition:opacity .12s,color .12s;border-radius:3px;flex-shrink:0;display:flex;align-items:center;margin-top:1px}
.custom-checklist li:hover .cl-expand-btn{opacity:.5}
.cl-expand-btn:hover{opacity:1!important;background:rgba(255,255,255,.06);color:var(--cream)}
.cl-expand-btn.open{opacity:.8!important;color:var(--cream)}
.cl-expand-btn svg{transition:transform .15s}
.cl-expand-btn.open svg{transform:rotate(90deg)}
.cl-inline-props{display:flex;align-items:center;gap:3px;flex-shrink:0;margin-left:auto;overflow:hidden;max-width:260px}
.cl-inline-chip{display:inline-flex;align-items:center;gap:3px;font-size:10px;padding:2px 7px;border-radius:4px;background:rgba(255,255,255,.06);color:var(--muted);white-space:nowrap;cursor:pointer;border:1px solid transparent;transition:background .12s,border-color .12s,color .12s,opacity .12s;max-width:100px;overflow:hidden;text-overflow:ellipsis;font-family:var(--sans);line-height:1.5;flex-shrink:0}
.cl-inline-chip:hover{background:rgba(255,255,255,.11);border-color:var(--border-d);color:var(--cream)}
.cl-inline-chip-empty{opacity:0}
.custom-checklist li:hover .cl-inline-chip-empty{opacity:.35}
.cl-inline-chip-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.cl-item-props-wrap{display:none;width:100%;padding:4px 0 8px 26px;border-bottom:1px solid rgba(255,255,255,.04)}
.cl-item-props-wrap.open{display:block}
.cl-prop-row{display:flex;align-items:center;gap:8px;padding:3px 0;font-size:12px}
.cl-prop-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);min-width:76px;flex-shrink:0;display:flex;align-items:center;gap:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cl-prop-value{flex:1;min-width:0;display:flex;align-items:center}
.cl-prop-value .group-inline-edit{padding:3px 6px;font-size:12px;height:auto}
.cl-prop-value .due-date-input{font-size:12px;padding:2px 6px}
.cl-prop-value .ms-dropdown-trigger{padding:4px 8px;font-size:11px}
/* Board card checklist progress */
.kanban-card-cl{margin-top:6px}
.kanban-card-cl-bar{height:3px;background:rgba(255,255,255,.08);border-radius:2px;overflow:hidden;margin-bottom:4px}
.kanban-card-cl-fill{height:100%;background:var(--col-color,var(--green));border-radius:2px;transition:width .3s}
.kanban-card-cl-footer{display:flex;align-items:center;justify-content:space-between;gap:6px}
.kanban-card-cl-pct{font-size:10px;font-weight:700;color:var(--col-color,var(--green));flex-shrink:0}
.kanban-card-cl-next{font-size:10px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
/* Custom tab close button */
.card-modal-tab .tab-close{opacity:0;margin-left:4px;font-size:10px;color:var(--muted);cursor:pointer;padding:2px;border-radius:3px;transition:all .12s}
.card-modal-tab:hover .tab-close{opacity:.6}
.card-modal-tab .tab-close:hover{opacity:1;color:var(--danger-text);background:rgba(239,68,68,.12)}
.card-history{padding:4px 0}
.history-created-banner{background:rgba(115,172,131,.08);border:1px solid rgba(115,172,131,.18);border-radius:8px;padding:10px 14px;margin-bottom:16px;display:flex;align-items:center;gap:10px}
.history-created-banner-text{font-size:12px;color:var(--cream)}
.history-created-banner-text b{color:var(--green);font-weight:600}
.history-entry{display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--border-d)}
.history-entry:last-child{border-bottom:none}
.history-entry-icon{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px}
.history-entry-icon.hist-created{background:rgba(115,172,131,.15);color:var(--green)}
.history-entry-icon.hist-title{background:rgba(124,92,255,.12);color:var(--coral)}
.history-entry-icon.hist-field{background:rgba(32,123,170,.12);color:var(--blue)}
.history-entry-icon.hist-desc{background:rgba(199,171,196,.12);color:var(--lavender)}
.history-entry-icon.hist-move{background:rgba(231,206,58,.1);color:var(--gold)}
.history-entry-icon.hist-status{background:rgba(115,172,131,.15);color:var(--green)}
.history-entry-icon.hist-assignee{background:rgba(32,123,170,.12);color:var(--blue)}
.history-entry-icon.hist-priority{background:rgba(231,206,58,.12);color:var(--gold)}
.history-entry-icon.hist-due{background:rgba(199,171,196,.14);color:var(--lavender)}
.history-entry-icon.hist-attachment{background:rgba(32,123,170,.12);color:var(--blue)}
/* History entries inherit the card's status color so they match the modal accent (not a clashing green). */
.card-modal .history-entry-icon.hist-created,
.card-modal .history-entry-icon.hist-title,
.card-modal .history-entry-icon.hist-field,
.card-modal .history-entry-icon.hist-desc,
.card-modal .history-entry-icon.hist-move,
.card-modal .history-entry-icon.hist-status,
.card-modal .history-entry-icon.hist-assignee,
.card-modal .history-entry-icon.hist-priority,
.card-modal .history-entry-icon.hist-due,
.card-modal .history-entry-icon.hist-attachment{
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 15%,transparent) !important;
  color:var(--modal-col-color,var(--coral)) !important;
}
.card-modal .history-created-banner-text b{color:var(--modal-col-color,var(--coral)) !important}
.card-modal .history-diff-to{background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 12%,transparent) !important;color:var(--modal-col-color,var(--coral)) !important}
.history-entry-body{flex:1;min-width:0}
.history-entry-meta{display:flex;align-items:baseline;gap:5px;flex-wrap:wrap;margin-bottom:3px}
.history-entry-actor{font-size:12px;font-weight:600;color:var(--cream)}
.history-entry-action{font-size:12px;color:var(--muted)}
.history-entry-action b{color:var(--off-white);font-weight:600}
.history-entry-ts{font-size:11px;color:var(--sec);margin-left:auto;white-space:nowrap;padding-left:8px}
.history-diff{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:4px}
.history-diff-from{font-size:11px;background:rgba(239,68,68,.1);color:var(--danger-text);padding:2px 7px;border-radius:4px;text-decoration:line-through;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.history-diff-to{font-size:11px;background:rgba(115,172,131,.1);color:var(--green);padding:2px 7px;border-radius:4px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.history-diff-arrow{color:var(--sec);font-size:11px;flex-shrink:0}
.history-empty{padding:32px 0;text-align:center;color:var(--muted);font-size:13px}
.subtasks-wrap{display:flex;flex-direction:column;gap:10px}
.subtasks-summary{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--border-d);border-radius:8px;background:rgba(255,255,255,.02)}
.subtasks-summary-title{font-size:12px;color:var(--cream);font-weight:600}
.subtasks-summary-meta{font-size:11px;color:var(--muted)}
.subtasks-list{display:flex;flex-direction:column;gap:8px}
.subtask-row{display:flex;align-items:center;gap:8px;padding:8px;border:1px solid var(--border-d);border-radius:8px;background:rgba(255,255,255,.02)}
.subtask-row.done{border-color:rgba(115,172,131,.35);background:rgba(115,172,131,.08)}
.subtask-row.stuck{border-color:rgba(239,68,68,.35);background:rgba(239,68,68,.08)}
.subtask-row.working{border-color:rgba(32,123,170,.35);background:rgba(32,123,170,.08)}
.subtask-order{width:24px;flex-shrink:0;font-size:11px;color:var(--muted);text-align:right}
.subtask-status{width:96px;flex-shrink:0;padding:5px 8px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);font-size:11px;font-family:var(--sans)}
.subtask-text-input{flex:1;min-width:0;padding:6px 8px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.03);color:var(--cream);font-size:12px;font-family:var(--sans)}
.subtask-text-input:disabled,.subtask-status:disabled{opacity:.7;cursor:not-allowed}
.subtask-text-view{flex:1;min-width:0;font-size:12px;color:var(--cream);line-height:1.4;word-break:break-word}
.subtask-row.done .subtask-text-view{text-decoration:line-through;color:var(--muted)}
.subtask-delete-btn{width:24px;height:24px;border-radius:6px;border:1px solid rgba(239,68,68,.25);background:rgba(239,68,68,.08);color:var(--danger-text);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.subtask-delete-btn:hover{background:rgba(239,68,68,.16)}
.subtasks-actions{display:flex;justify-content:flex-end}
.subtasks-add-btn{padding:7px 12px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);font-size:11px;font-weight:600;font-family:var(--sans);cursor:pointer}
.subtasks-add-btn:hover{background:var(--state-hover)}
.subtasks-empty{padding:28px 0;text-align:center;color:var(--muted);font-size:12px}
.subtasks-legacy-note{font-size:11px;color:var(--muted)}
/* Description edit/preview toggle */
.card-desc-edit-container{position:relative}
.card-desc-toolbar{position:absolute;bottom:6px;right:6px;display:flex;gap:2px;z-index:2}
.card-desc-toolbar button{background:none;border:none;color:rgba(255,255,255,.18);cursor:pointer;padding:4px;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:color .12s}
.card-desc-toolbar button:hover{color:rgba(255,255,255,.5)}
/* Delete trash icon */
.card-modal-delete-btn{background:none!important;border:none!important;cursor:pointer;color:rgba(255,255,255,.25);padding:8px;border-radius:8px;display:flex;align-items:center;transition:color .15s}
.card-modal-delete-btn:hover{color:rgba(255,255,255,.45)}
/* Shake animation for hold-delete trash */
[data-hold-delete].hold-delete-shake::after{display:none!important}
[data-hold-delete].hold-delete-shake.hold-active{animation:trash-shake var(--hold-delete-ms) linear forwards!important}
@keyframes trash-shake{0%{transform:rotate(0)}5%{transform:rotate(-2deg)}10%{transform:rotate(2deg)}15%{transform:rotate(0)}25%{transform:rotate(-4deg)}30%{transform:rotate(4deg)}35%{transform:rotate(-4deg)}40%{transform:rotate(4deg)}50%{transform:rotate(-7deg)}55%{transform:rotate(7deg)}60%{transform:rotate(-9deg)}65%{transform:rotate(9deg)}70%{transform:rotate(-11deg)}75%{transform:rotate(11deg)}80%{transform:rotate(-13deg)}85%{transform:rotate(13deg)}90%{transform:rotate(-15deg)}95%{transform:rotate(15deg)}100%{transform:rotate(16deg)}}
/* Hold-delete rapid-click hint */
/* Comment attachment icon */
.comment-attach-btn{background:none;border:none;color:var(--text-3);cursor:pointer;padding:4px;display:flex;align-items:center;transition:color .12s;position:absolute;right:8px;top:50%;transform:translateY(-50%)}.comment-attach-btn:hover{color:var(--text-2)}
/* ── Comment composer: one rounded bar, actions grouped on the right ────────
   The field and the buttons are flex siblings, so the icon row can grow or
   shrink without ever overlapping the text (the old absolutely-positioned
   buttons sat on top of a hand-padded input). */
.cmt-bar{display:flex !important;flex-direction:row !important;flex-wrap:nowrap;align-items:flex-end;gap:6px;
  background:var(--bg-inset);border:1px solid var(--hairline-2);border-radius:12px;
  padding:6px 8px 6px 12px;
  transition:border-color var(--dur-short,.15s) var(--ease-std,ease)}
.cmt-bar:focus-within{border-color:var(--hairline)}
/* font-family / color / resize are explicit because .cmt-field is used by BOTH a
   contenteditable div and a <textarea>. A div inherits the page font; a textarea does
   not — it falls back to the UA default, which is monospace in Chrome, and it also
   ships a drag-resize handle unless told otherwise. */
.cmt-field{flex:1 1 auto !important;min-width:0 !important;width:auto !important;background:none !important;border:0 !important;padding:6px 0 !important;
  min-height:24px;max-height:140px;overflow-y:auto;line-height:1.5;
  font-family:var(--sans);font-size:14px;color:var(--off-white);resize:none;
  word-break:break-word;overflow-wrap:break-word;outline:none}
.cmt-field::placeholder{color:var(--text-3)}
.cmt-actions{display:flex !important;align-items:center;gap:2px;flex:0 0 auto !important;padding-bottom:2px;white-space:nowrap}
.cmt-btn{width:30px;height:30px;flex:none;padding:0;border:0;background:none;border-radius:8px;
  color:var(--text-3);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
  transition:background var(--dur-toggle,.12s) var(--ease-std,ease),color var(--dur-toggle,.12s) var(--ease-std,ease)}
.cmt-btn:hover{background:var(--bg-inset);color:var(--text-1)}
.cmt-btn:active{transform:scale(.94)}
.cmt-btn.recording{color:var(--danger-text);animation:vmPulse 1s ease-in-out infinite}
/* Composer icon size lives in ONE place. An <svg> with a viewBox but no width/height and
   no CSS size does not draw at its viewBox size — viewBox only supplies an aspect ratio,
   so width/height fall back to the SVG default of 100% and the glyph swells to fill its
   30px button. That is how the Review composer's annotate + attach icons ended up roughly
   double their neighbours.
   :not([width]) is load-bearing, not decoration: surfaces that opt into a larger glyph by
   writing the size on the svg (the DM composer's 19px icons) must keep theirs, and a
   blanket .cmt-btn svg{width:17px} would silently shrink them because an author rule beats
   a presentation attribute. */
.cmt-btn svg{flex:none}
.cmt-btn svg:not([width]){width:17px;height:17px}
/* The mic was mobile-only; it belongs on every surface. */
.cmt-bar .cmt-mic{display:inline-flex}
/* Emoji grid buttons for the (previously unbuilt) #emojiPicker. */
.emoji-pick-btn{width:32px;height:32px;border:0;background:none;border-radius:7px;cursor:pointer;
  font-size:19px;line-height:1;display:inline-flex;align-items:center;justify-content:center;
  transition:background var(--dur-toggle,.12s) var(--ease-std,ease),transform var(--dur-press,.1s) var(--ease-std,ease)}
.emoji-pick-btn:hover{background:var(--bg-inset)}
.emoji-pick-btn:active{transform:scale(.88)}
/* #14a — Voice memo: mic button (mobile only), recording state, bubble, indicator */
.comment-mic-btn{display:none;background:none;border:none;color:var(--text-3);cursor:pointer;padding:4px;align-items:center;transition:color .12s;position:absolute;right:34px;top:50%;transform:translateY(-50%)}
.comment-mic-btn:hover{color:var(--text-2)}
.comment-mic-btn.recording{color:var(--coral);animation:vmPulse 1s ease-in-out infinite}
@keyframes vmPulse{0%,100%{opacity:1}50%{opacity:.35}}
body[data-mobile-mode="app"] .comment-mic-btn{display:flex}
body[data-mobile-mode="app"] #cardCommentInput{padding-right:64px !important}
.voice-memo{margin-top:4px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.04);overflow:hidden}
.voice-memo-summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;padding:10px 12px;font-size:13px;color:var(--cream);user-select:none}
.voice-memo-summary::-webkit-details-marker{display:none}
.voice-memo-ico{font-size:15px}
.voice-memo-label{font-weight:600}
.voice-memo-dur{color:var(--muted);font-size:12px}
.voice-memo-hint{margin-left:auto;color:var(--muted);font-size:11px}
.voice-memo[open] .voice-memo-hint{display:none}
.voice-memo-body{padding:0 12px 12px}
.voice-memo-transcript{font-size:14px;line-height:1.5;color:var(--cream);margin-top:8px;white-space:pre-wrap}
.voice-rec-indicator{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(84px + env(safe-area-inset-bottom,0px));z-index:10200;background:#1a1a19;border:1px solid var(--border-d);border-radius:999px;padding:8px 14px;display:flex;align-items:center;gap:8px;font-size:13px;color:var(--cream);box-shadow:0 8px 24px rgba(0,0,0,.5)}
.voice-rec-indicator .vri-dot{width:10px;height:10px;border-radius:50%;background:var(--coral);animation:vmPulse 1s ease-in-out infinite}
.voice-rec-indicator button{background:var(--coral);color:#fff;border:none;border-radius:999px;padding:4px 12px;font-size:12px;font-weight:600;cursor:pointer}
/* #9 — Automations page mobile polish (full-width header/search, scrollable pill
   tabs) + board picker as a full-page sheet. The builder overlay is already
   full-screen via the .card-modal mobile rules; trigger/action <select>s use the
   native iOS picker (not a custom dropdown). */
body[data-mobile-mode="app"] #page-automations .panel-header{flex-direction:column;align-items:stretch;gap:8px}
body[data-mobile-mode="app"] #page-automations #autoSearch{margin-left:0 !important;width:100% !important}
body[data-mobile-mode="app"] #page-automations .page-tabs{display:flex;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;gap:8px}
body[data-mobile-mode="app"] #page-automations .page-tabs::-webkit-scrollbar{height:0}
body[data-mobile-mode="app"] #page-automations .page-tab{flex:0 0 auto;white-space:nowrap}
body[data-mobile-mode="app"] #autoBoardMenu.auto-board-sheet{
  position:fixed !important;inset:0 !important;left:0 !important;top:0 !important;
  width:100% !important;max-width:100% !important;min-width:0 !important;
  height:100dvh !important;max-height:100dvh !important;
  border:0 !important;border-radius:0 !important;box-shadow:none !important;
  z-index:10095 !important;padding:0 0 calc(24px + env(safe-area-inset-bottom,0px)) !important
}
body[data-mobile-mode="app"] #autoBoardMenu.auto-board-sheet button:not(.csw-msheet-done){padding:14px 16px !important;font-size:15px !important}
/* Comment images full width */
/* max-width:100% alone meant a screenshot rendered at the full width of the comment
   column — in a widened modal that is enormous, and nothing about a comment wants to be
   read at that size. Capped to a reading size; click still opens the original. */
.card-comment-img{max-width:min(100%,420px);max-height:320px;width:auto;height:auto;object-fit:contain;
  border-radius:8px;border:1px solid rgba(255,255,255,.1);cursor:pointer;display:block;margin-top:8px}

/* KANBAN ENHANCEMENTS */
.kanban-col-menu{position:relative}
.kanban-col-menu-btn{background:none;border:none;color:var(--muted);cursor:pointer;font-size:16px;padding:0 4px;transition:color .15s;line-height:1;letter-spacing:2px;opacity:0;transition:opacity .15s}
.kanban-col-header-bar:hover .kanban-col-menu-btn{opacity:1}
.kanban-col-menu-btn:hover{color:var(--off-white)}
.kanban-col.kanban-col-shrunk{min-width:34px;max-width:34px;flex:0 0 34px;min-height:22px;position:relative}
.kanban-col.kanban-col-shrunk .kanban-col-header{display:none}
.kanban-col.kanban-col-shrunk .kanban-col-body{display:none}
.kanban-col.kanban-col-shrunk .kanban-col-header-bar{padding-right:0;justify-content:center;border-radius:8px;flex:1;writing-mode:vertical-rl;align-items:center;gap:6px;padding:8px 0;font-size:10px;font-weight:700;letter-spacing:.5px;color:rgba(0,0,0,.7);text-transform:uppercase;overflow:hidden}
.kanban-col.kanban-col-shrunk .kanban-col-header-bar:hover{filter:brightness(1.2)}
.kanban-col.kanban-col-shrunk .kanban-col-menu{display:none}
.kanban-col.kanban-col-shrunk .kanban-col-shrunk-label{pointer-events:none;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;max-height:100%}
.kanban-col-dropdown{display:none;position:absolute;top:100%;right:0;background:var(--dark);border:1px solid var(--border-d);border-radius:8px;padding:6px;min-width:auto;z-index:200;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.kanban-col-dropdown.open{display:block}
.kanban-col-dropdown-actions{display:flex;gap:4px;justify-content:flex-end}
.kanban-col-dropdown-actions button{width:28px;height:28px;border-radius:6px;background:none;border:1px solid var(--border-d);color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;transition:all .15s}
.kanban-col-dropdown-actions button:hover{background:var(--state-hover);color:var(--cream);border-color:rgba(255,255,255,.2)}
.kanban-col-dropdown-actions button.danger:hover{background:rgba(239,68,68,.12);color:var(--danger-text);border-color:rgba(239,68,68,.3)}
.kanban-col-sort{margin-top:6px;padding-top:6px;border-top:1px solid var(--border-d)}
.kanban-col-sort-option{padding:5px 8px;font-size:11px;color:var(--muted);cursor:pointer;border-radius:4px;transition:background .1s,color .1s;white-space:nowrap}
.kanban-col-sort-option:hover{background:var(--state-hover);color:var(--cream)}
.kanban-col-sort-option.active{color:var(--gold)}
.color-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:5px;padding:8px 10px}
.color-grid-swatch{width:26px;height:26px;border-radius:6px;cursor:pointer;border:2px solid transparent;transition:border-color .15s,transform .1s}
.color-grid-swatch:hover{transform:scale(1.15);border-color:rgba(255,255,255,.4)}
.color-grid-swatch.active{border-color:var(--white);box-shadow:0 0 0 1px var(--white)}
.kanban-add-col-btn{min-width:40px;height:40px;background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .15s;color:var(--muted);font-size:18px;flex-shrink:0;align-self:flex-start;margin-top:16px}
.kanban-add-col-btn:hover{border-color:var(--coral);color:var(--coral);background:rgba(255,255,255,.06)}
/* Idle add-column affordance — reuse the empty column body, but do not invent a
   colour bar/title for a status that does not exist yet. Tapping it swaps in the
   real blank inline header editor. */
.kanban-col-ghost{opacity:0;cursor:pointer;transition:opacity .25s ease;box-shadow:none}
.kanban-col-ghost:hover{opacity:.6}
.kanban-col-ghost.kanban-col-ghost-empty{opacity:.42}
.kanban-col-ghost.kanban-col-ghost-empty:hover{opacity:.62}
.kanban-col-ghost .kanban-col-name{color:var(--muted)}
.kanban-col-ghost-body{display:flex;align-items:center;justify-content:center;min-height:130px}
/* Pointer-event drag & drop */
.kanban-card{cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none}
.kanban-card.card-hold{box-shadow:0 0 0 1px var(--col-color,var(--coral)),0 4px 24px rgba(0,0,0,.5),0 0 16px color-mix(in srgb,var(--col-color,var(--coral)) 20%,transparent);border-color:var(--col-color,var(--coral))}
.kanban-card.dragging{opacity:.2;cursor:grabbing}
.kanban-card-ghost{position:fixed;z-index:9000;pointer-events:none;opacity:.92;transition:background .25s ease,box-shadow .25s ease,border-color .25s ease;transform-origin:center center}
.kanban-card-ghost.card-active{box-shadow:0 0 0 1px var(--col-color,var(--coral)),0 8px 32px rgba(0,0,0,.6),0 0 20px color-mix(in srgb,var(--col-color,var(--coral)) 25%,transparent)}
/* Clip the left colour-accent bar (::before) to the card's rounded bounds while lifted /
   dragged, so it can't poke past the corners. Multi-drag ghosts keep overflow visible for
   their count badge + peeking stack-shadow. */
.kanban-card.card-hold,
.kanban-card-ghost:not(.kanban-card-ghost-multi){overflow:hidden}
/* #5 — overflow:hidden alone leaks the rounded corners while the ghost is transformed
   (a WebKit bug: border-radius clipping bleeds during transform/scale), so the 3px accent
   bar pokes past the corners on the lifted card. clip-path: inset(... round) survives the
   transform and re-clips to the card's actual radius (12px mobile, 6px desktop). The 3px bar
   is too narrow to round to the corner itself, so clipping is the only correct fix. */
.kanban-card.card-hold,
.kanban-card-ghost:not(.kanban-card-ghost-multi){clip-path:inset(0 round 6px)}
body[data-mobile-mode="app"] .kanban-card.card-hold,
body[data-mobile-mode="app"] .kanban-card-ghost:not(.kanban-card-ghost-multi){clip-path:inset(0 round 12px)}
/* Multi-card drag: count badge + a peeking stacked-card shadow behind the ghost. */
.kanban-drag-count{position:absolute;top:-9px;right:-9px;min-width:21px;height:21px;padding:0 6px;border-radius:11px;background:var(--purple,#8c72db);color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.45);z-index:3}
.kanban-drag-stack{position:absolute;inset:0;border-radius:6px;background:var(--dark);border:1px solid var(--col-color,var(--border-d));transform:translate(6px,7px);z-index:-1}
/* Drop target: coloured glow ring in the destination column's own colour. Drawn
   as a box-shadow, not a border — .kanban-col.drop-target keeps `border:none`
   so the ring can't change the column's size mid-drag. (The JS used to set
   style.borderColor here, which `border:none !important` silently swallowed —
   that is why the coloured glow disappeared.) */
/* "Mark complete" — a header icon button like Files/Share/Close, so it inherits
   their size, radius and hover. Only the done state differs: green tick. */
.card-modal-iconbtn.cm-complete-btn.is-done{color:var(--success)}
.card-modal-iconbtn.cm-complete-btn.is-done:hover{color:var(--success);
  background:color-mix(in srgb,var(--success) 15%,transparent)}
.card-modal-iconbtn.cm-complete-btn.is-done svg circle{fill:color-mix(in srgb,var(--success) 18%,transparent)}
/* A crisp 2px ring in the destination column's colour and nothing else. This used to
   add `0 0 26px -6px` of the same colour on top — a halo bleeding well past the column,
   which stacked with the placeholder's own glow and the edge gradients so a single drag
   lit up three separate effects at once. The ring alone says "it lands here"; the glow
   only said "something is happening", which you already knew. */
.kanban-col.drop-target{background:#1d1d22 !important;border:none !important;
  box-shadow:0 0 0 2px var(--drop-color,var(--coral));
  transition:box-shadow .14s var(--ease-std,ease),background .14s var(--ease-std,ease)}
/* Ghost of the dragged task, sitting in the slot it will land in. Matches the
   real card's box so the column doesn't reflow when the drop lands. */
/* Dashed outline + a faint fill, no glow. The slot only has to read as "the card lands
   in this gap" — it is already inside a ringed column, so a second light source on the
   same colour just doubled up. Border thinned to 1.5px and the fill dropped 12% -> 7%. */
.kanban-drop-placeholder{display:flex;align-items:center;box-sizing:border-box;
  padding:14px 16px;margin-bottom:12px;border-radius:var(--r-card);
  border:1.5px dashed color-mix(in srgb,var(--drop-color,var(--coral)) 70%,transparent);
  background:color-mix(in srgb,var(--drop-color,var(--coral)) 7%,transparent);
  color:var(--text-2);font:600 13px var(--sans);overflow:hidden;
  }
.kanban-drop-placeholder.is-new{animation:wsDropPhIn 120ms var(--ease-std,ease) both}
.kanban-drop-placeholder span{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
@keyframes wsDropPhIn{from{opacity:0;transform:scale(.98)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.kanban-drop-placeholder{animation:none}}
/* The source card leaves the flow while dragging; the placeholder stands in for
   it, so the column height stays put and the drop slot can't oscillate. */
.kanban-card.drag-collapsed{display:none !important}
.kanban-card.card-remote-ghost{opacity:.5;box-shadow:0 0 0 2px rgba(245,158,11,.5),0 4px 16px rgba(245,158,11,.15);border-radius:8px;transition:opacity .18s ease,box-shadow .3s ease,transform .18s ease;pointer-events:none;position:relative}
.kanban-card-remote-floating{position:fixed;z-index:9000;pointer-events:none;opacity:.85;box-shadow:0 12px 40px rgba(0,0,0,.45);border-radius:6px;transition:left .18s cubic-bezier(.4,0,.2,1),top .18s cubic-bezier(.4,0,.2,1),opacity .3s ease,transform .12s ease;will-change:left,top,transform;background:var(--dark);border:1px solid var(--border-d);cursor:default;min-height:0;margin:0;transform-origin:center center}
.kanban-col.col-remote-drop-target>.kanban-col-header{box-shadow:0 2px 0 rgba(245,158,11,.4)}
.kanban-card.card-remote-typing{box-shadow:0 0 0 2px rgba(99,179,237,.5),0 4px 16px rgba(99,179,237,.15);transition:box-shadow .15s ease}
.kanban-card.drop-above,.kanban-card.drop-below{transition:box-shadow .12s ease}
.kanban-cards{min-height:20px}
/* Auto-scroll affordance at the viewport edges. Kept, because it tells you the board is
   about to scroll — but narrowed 72px -> 52px and the tint taken from 40% to 18%, so it
   reads as a hint at the edge of vision instead of a third light source competing with
   the drop ring. */
.kanban-drag-edge-glow{
  position:fixed;top:0;bottom:0;width:52px;pointer-events:none;opacity:0;z-index:9055;
  transition:opacity .12s ease-out,transform .12s ease-out;
  --glow-color:#e8c547;   /* default (desktop); mobile sets it to the destination column colour */
}
.kanban-drag-edge-glow.left{left:0;transform:translateX(-20px);
  background:linear-gradient(90deg,color-mix(in srgb,var(--glow-color) 18%,transparent),transparent)}
.kanban-drag-edge-glow.right{right:0;transform:translateX(20px);
  background:linear-gradient(270deg,color-mix(in srgb,var(--glow-color) 18%,transparent),transparent)}
.kanban-drag-edge-glow.active{opacity:1;transform:translateX(0)}
/* View switcher */
/* Transparent, not --bg-main. This row sits ON the canvas; painting #0a0a0b over a
   #0c0c0e ground drew a subtly different rectangle behind the tabs — the visible
   band across the top of a chat page. Project pages already forced it transparent
   further down, so chat was the only place still showing it. */
.workshop-views{display:flex;align-items:center;gap:4px;margin-bottom:14px;position:relative;z-index:40;background:transparent;padding:10px 0;border-bottom:none}

/* ── Workshop tabs (Airtable-style) ─────────────────────────────────
   Top tab strip that lets the user keep multiple independent kanban
   boards under one workshop. Active tab gets a coral underline + solid
   text; inactive tabs are muted and fade in on hover. The "+" button
   creates a new board (a new entry in data.tabs). */
.workshop-tabs{display:flex;align-items:center;gap:2px;padding:0;margin-bottom:0;border-bottom:1px solid var(--border-d);min-height:36px;position:relative;z-index:41;overflow-x:auto;overflow-y:hidden}
.workshop-tabs::-webkit-scrollbar{height:0}
.workshop-tab{display:inline-flex;align-items:center;gap:7px;padding:9px 10px 10px;font-size:13px;color:var(--muted);cursor:pointer;position:relative;font-weight:500;transition:color .15s,background .15s;border-radius:6px 6px 0 0;flex-shrink:0;user-select:none;-webkit-user-select:none}
.workshop-tab:hover{color:var(--cream);background:rgba(255,255,255,.04)}
.workshop-tab.active{color:var(--off-white);font-weight:600;background:rgba(255,255,255,.05)}
.workshop-tab.active::after{content:'';position:absolute;left:6px;right:6px;bottom:-1px;height:2px;background:var(--coral);border-radius:1px}
.workshop-tab-name{outline:none;line-height:1}
.workshop-tab-name[contenteditable="true"]{background:rgba(255,255,255,.08);padding:1px 5px;border-radius:3px;box-shadow:0 0 0 1px var(--coral)}
.workshop-tab-caret{width:10px;height:10px;opacity:.55;flex-shrink:0;margin-top:1px}
.workshop-tab.active .workshop-tab-caret{opacity:.85}
/* Icon slot to the left of the tab name. Hidden 'set icon' SVG only
   shows on hover when no icon is set yet; once an emoji is picked,
   it shows always. */
.workshop-tab-icon{width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--muted);padding:0;cursor:pointer;border-radius:4px;flex-shrink:0;line-height:1;transition:background .12s,color .12s}
.workshop-tab-icon svg{width:14px;height:14px}
.workshop-tab-icon:hover{background:var(--state-hover);color:var(--cream)}
.workshop-tab.active .workshop-tab-icon{color:var(--off-white)}
.workshop-tab-icon-picker{background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.55);padding:8px;width:260px;animation:wsViewMenuIn .14s ease-out}
.workshop-tab-icon-picker .wti-row{display:flex;align-items:center;gap:8px;padding-bottom:6px;border-bottom:1px solid var(--border-d);margin-bottom:6px}
.workshop-tab-icon-picker .wti-row-label{font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);font-weight:600}
.workshop-tab-icon-picker .wti-clear{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid var(--border-d);background:transparent;border-radius:6px;color:var(--muted);cursor:pointer;transition:background .12s,color .12s,border-color .12s}
.workshop-tab-icon-picker .wti-clear:hover{background:rgba(239,68,68,.12);color:var(--danger-text);border-color:color-mix(in srgb,var(--color-error) 35%,transparent)}
.workshop-tab-icon-picker .wti-clear svg{width:13px;height:13px}
.workshop-tab-icon-picker .wti-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.workshop-tab-icon-picker .wti-grid button{width:30px;height:30px;border:0;background:transparent;border-radius:5px;cursor:pointer;line-height:1;padding:0;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;transition:background .1s,color .1s}
.workshop-tab-icon-picker .wti-grid button:hover{background:var(--state-hover);color:var(--cream)}
.workshop-tab-icon-picker .wti-grid button svg{width:15px;height:15px}
/* Custom workspace emoji section — divider + label + image-only
   buttons that match the SVG-button grid. */
.workshop-tab-icon-picker .wti-divider{height:1px;background:var(--border-d);margin:8px 0 6px}
.workshop-tab-icon-picker .wti-section-label{font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);font-weight:600;padding:0 4px 6px}
.workshop-tab-icon-picker .wti-custom-btn img{width:18px;height:18px;object-fit:contain;display:block;pointer-events:none}
/* When a tab's icon is a custom emoji <img>, scale it down to the
   same visual weight as the SVG icons. */
.workshop-tab-icon-emoji{width:15px;height:15px;object-fit:contain;display:block;pointer-events:none}
.workshop-tab-add{border:none;background:none;color:var(--muted);cursor:pointer;padding:7px 10px;font-size:15px;font-weight:400;border-radius:6px;transition:background .15s,color .15s;line-height:1;margin-left:2px;flex-shrink:0}
.workshop-tab-add:hover{background:rgba(255,255,255,.06);color:var(--cream)}
/* Drop target highlight while a tab is being dragged. Applies to
   another tab (reorder target) OR a sidebar workshop link (move). */
.ws-tab-drop-target{outline:2px solid var(--coral);outline-offset:1px;border-radius:6px;background:color-mix(in srgb,var(--coral) 14%,transparent)!important;transition:background .12s,outline .12s}

/* Small coral count pill rendered inside the hamburger Filter menu
   item when filters are active. */
.hamburger-filter-count{min-width:18px;height:16px;border-radius:999px;padding:0 6px;background:color-mix(in srgb,var(--coral) 28%,transparent);color:var(--coral);font-family:var(--sans);font-size:10px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}

/* ── Board History modal ──────────────────────────────────────────
   Lists aggregated card.history entries from every card in every tab
   of the workshop, sorted newest-first. Each row shows actor, action,
   card name, tab name, and a relative timestamp. */
.bh-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.65);z-index:10000;display:flex;align-items:center;justify-content:center;animation:bhFadeIn .15s ease-out}
@keyframes bhFadeIn{from{opacity:0}to{opacity:1}}
.bh-modal{width:680px;max-width:92vw;max-height:80vh;background:var(--dark);border:1px solid var(--border-d);border-radius:14px;box-shadow:0 24px 60px rgba(0,0,0,.55);display:flex;flex-direction:column;overflow:hidden;animation:bhSlideIn .2s cubic-bezier(.22,1,.36,1)}
@keyframes bhSlideIn{from{opacity:0;transform:translateY(6px) scale(.98)}to{opacity:1;transform:none}}
.bh-head{display:flex;align-items:center;gap:10px;padding:16px 20px;border-bottom:1px solid var(--border-d);flex-shrink:0}
.bh-head svg{width:18px;height:18px;color:var(--coral);flex-shrink:0}
.bh-head-title{font-size:15px;font-weight:600;color:var(--off-white);flex:1}
.bh-head-close{background:none;border:0;color:var(--muted);font-size:22px;line-height:1;cursor:pointer;padding:4px 8px;border-radius:6px;transition:background .12s,color .12s}
.bh-head-close:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.bh-body{flex:1;overflow-y:auto;padding:8px 0}
.bh-empty{padding:48px 20px;text-align:center;color:var(--muted);font-size:13px}
.bh-row{display:flex;align-items:flex-start;gap:11px;padding:11px 20px;border-bottom:1px solid rgba(255,255,255,.04);transition:background .12s;cursor:pointer}
.bh-row:hover{background:rgba(255,255,255,.04)}
.bh-row-dot{width:6px;height:6px;border-radius:50%;background:var(--coral);flex-shrink:0;margin-top:7px}
.bh-row-body{flex:1;min-width:0}
.bh-row-actor{font-size:13px;font-weight:600;color:var(--cream);margin-bottom:2px}
.bh-row-text{font-size:12px;color:var(--muted);line-height:1.45}
.bh-row-text strong{color:var(--cream);font-weight:600}
.bh-row-time{font-size:11px;color:var(--muted);flex-shrink:0;white-space:nowrap;margin-top:1px}

/* ── View picker dropdown (replaces inline view buttons) ─────────── */
.ws-view-picker-wrap{position:relative;display:inline-flex;align-items:center;margin-right:6px}
.workshop-view-btn.ws-view-picker{display:inline-flex;align-items:center;gap:7px;padding:0 10px;height:30px;border:0;background:transparent}
.workshop-view-btn.ws-view-picker:hover{background:rgba(255,255,255,.06);border:0}
.ws-view-picker svg:not(.caret){width:14px;height:14px;color:var(--off-white);flex-shrink:0}
.ws-view-picker .ws-view-picker-label{font-weight:600;color:var(--off-white);font-size:13px}
.ws-view-picker .caret{width:10px;height:10px;opacity:.6;flex-shrink:0;transition:transform .15s}
.ws-view-picker.is-open .caret{transform:rotate(180deg)}
.ws-view-picker.is-open{background:rgba(255,255,255,.06)}
.ws-view-picker-menu{display:none;position:absolute;top:100%;left:0;margin-top:6px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.55);z-index:9000;min-width:200px;padding:5px}
.ws-view-picker-menu.open{display:block;animation:wsViewMenuIn .15s ease-out}
@keyframes wsViewMenuIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
.ws-view-picker-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px 11px;background:transparent;border:0;color:var(--cream);cursor:pointer;border-radius:6px;font-size:13px;text-align:left;font-family:var(--sans);transition:background .12s}
.ws-view-picker-item:hover{background:rgba(255,255,255,.06)}
.ws-view-picker-item.active{color:var(--off-white);background:rgba(124,92,255,.10)}
.ws-view-picker-item svg{width:14px;height:14px;color:var(--off-white);flex-shrink:0}
.ws-view-picker-item.active svg{color:var(--coral)}

/* ── Generic toolbar dropdown menu (Color / Customize / Stacked by) ── */
.ws-toolbar-menu{background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.55);padding:5px;min-width:200px;animation:wsViewMenuIn .14s ease-out}
.ws-toolbar-menu-wide{min-width:240px;max-height:340px;overflow-y:auto}
.ws-toolbar-menu-head{padding:8px 11px 6px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.ws-toolbar-menu-item{display:flex;align-items:center;gap:9px;width:100%;padding:8px 11px;background:transparent;border:0;color:var(--cream);cursor:pointer;border-radius:6px;font-size:13px;text-align:left;font-family:var(--sans);transition:background .12s}
.ws-toolbar-menu-item:hover{background:rgba(255,255,255,.06)}
.ws-toolbar-menu-item.active{color:var(--off-white);background:color-mix(in srgb,var(--coral) 14%,transparent)}
.ws-toolbar-menu-row{display:flex;align-items:center;gap:9px;padding:7px 11px;cursor:pointer;border-radius:6px;font-size:13px;color:var(--cream);transition:background .12s}
.ws-toolbar-menu-row:hover{background:rgba(255,255,255,.06)}
.ws-toolbar-menu-row input[type="checkbox"]{accent-color:var(--coral);cursor:pointer;width:14px;height:14px}
.ws-toolbar-menu-empty{padding:14px 12px;color:var(--muted);font-size:12px;text-align:center}
.ws-toolbar-swatch{width:12px;height:12px;border-radius:3px;flex-shrink:0;display:inline-block}

/* ── Customize view popup (Airtable-style) ────────────────────────
   Scope label + header search + per-field row with iOS-style toggle +
   type icon + name + footer with Hide all / Show all bulk actions.
   Scope is whichever view (board/group/calendar) the user is on. */
.cc-fields-menu{min-width:320px;max-height:480px;display:flex;flex-direction:column;padding:0;overflow:hidden}
.cc-fields-scope{padding:9px 14px 4px;font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;font-weight:600;flex-shrink:0}
.cc-fields-scope strong{color:var(--cream);font-weight:700;letter-spacing:.2px;text-transform:none}
.cc-fields-search-wrap{position:relative;padding:6px 12px 8px;border-bottom:1px solid var(--border-d);flex-shrink:0}
.cc-fields-search-icon{position:absolute;left:22px;top:50%;transform:translateY(-50%);width:13px;height:13px;color:var(--muted);pointer-events:none;opacity:.7}
.cc-fields-search{width:100%;padding:7px 10px 7px 30px;background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);font-size:13px;font-family:var(--sans);box-sizing:border-box;outline:none;transition:border-color .12s,background .12s}
.cc-fields-search:focus{border-color:var(--coral);background:rgba(255,255,255,.06)}
.cc-fields-search::placeholder{color:var(--muted)}
.cc-fields-list{padding:6px 0;overflow-y:auto;flex:1;min-height:0}
.cc-field-row{display:flex;align-items:center;gap:11px;padding:7px 12px;cursor:default;transition:background .12s}
.cc-field-row:hover{background:rgba(255,255,255,.04)}
.cc-toggle{position:relative;width:30px;height:17px;border-radius:999px;background:rgba(255,255,255,.18);border:0;cursor:pointer;flex-shrink:0;padding:0;transition:background .15s}
.cc-toggle.on{background:var(--coral)}
.cc-toggle-knob{position:absolute;top:2px;left:2px;width:13px;height:13px;background:#fff;border-radius:50%;transition:transform .18s cubic-bezier(.22,1,.36,1);box-shadow:0 1px 2px rgba(0,0,0,.35);pointer-events:none}
.cc-toggle.on .cc-toggle-knob{transform:translateX(13px)}
.cc-toggle:hover{filter:brightness(1.1)}
.cc-field-icon{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;color:var(--muted);flex-shrink:0}
.cc-field-icon svg{width:14px;height:14px}
.cc-field-name{font-size:13px;color:var(--cream);font-weight:500;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cc-fields-footer{display:flex;border-top:1px solid var(--border-d);flex-shrink:0}
.cc-fields-foot-btn{flex:1;padding:11px 12px;background:transparent;border:0;color:var(--muted);font-size:13px;font-family:var(--sans);font-weight:500;cursor:pointer;transition:background .12s,color .12s}
.cc-fields-foot-btn:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.cc-fields-foot-btn:first-child{border-right:1px solid var(--border-d)}

/* Card color-stripe — when a tab has colorByField set, the left edge
   of each kanban card gets a 3px stripe in the field option's color. */
.kanban-card[data-card-color]::before{content:'';position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:2px;background:var(--card-color, var(--coral))}
.kanban-card[data-card-color]{padding-left:14px}

/* Tab right-click context menu */
.workshop-tab-ctx{position:fixed;z-index:10200;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.55);padding:5px;min-width:170px;display:none}
.workshop-tab-ctx.open{display:block;animation:wsViewMenuIn .14s ease-out}
.workshop-tab-ctx button{display:flex;align-items:center;gap:9px;width:100%;padding:7px 11px;background:transparent;border:0;color:var(--cream);cursor:pointer;border-radius:6px;font-size:13px;text-align:left;font-family:var(--sans);transition:background .12s}
.workshop-tab-ctx button:hover{background:rgba(255,255,255,.06)}
.workshop-tab-ctx button.danger{color:var(--danger-text)}
.workshop-tab-ctx button svg{width:13px;height:13px;flex-shrink:0;opacity:.85}
/* Duplicate submenu — expands to the right on hover of the parent
   "Duplicate ▸" row, mirroring native macOS context-menu sub-arrows. */
.workshop-tab-ctx .wstc-sub-wrap{position:relative}
.workshop-tab-ctx .wstc-sub-trigger{width:100%}
.workshop-tab-ctx .wstc-sub-arrow{margin-left:auto;color:var(--muted);font-size:11px;line-height:1;transition:color .12s}
.workshop-tab-ctx .wstc-sub-wrap:hover .wstc-sub-arrow,
.workshop-tab-ctx .wstc-sub-wrap.force-open .wstc-sub-arrow{color:var(--cream)}
.workshop-tab-ctx .wstc-sub{display:none;position:absolute;top:-5px;left:100%;margin-left:4px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.55);padding:5px;min-width:180px;z-index:10210;animation:wsViewMenuIn .14s ease-out}
.workshop-tab-ctx .wstc-sub-wrap:hover .wstc-sub,
.workshop-tab-ctx .wstc-sub-wrap.force-open .wstc-sub{display:block}
.workshop-tab-ctx .wstc-sub button{width:100%}
.workshop-view-btn{padding:0 16px;height:31px;line-height:1;border:1px solid var(--border-d);border-radius:6px;background:none;font-family:var(--sans);font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:all .15s;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;flex-shrink:0}
.workshop-view-btn:hover{color:var(--cream);border-color:rgba(255,255,255,.2)}
.workshop-view-btn.active{background:var(--state-hover);color:var(--cream);border-color:rgba(255,255,255,.15)}
/* Board (kanban) view tabs: no outline; the active tab reads via its background. Balance the
   top/bottom padding around the tab strip so it isn't lopsided. */
#page-workshop.active .workshop-views .workshop-view-btn,
#page-custom-workshop.active .workshop-views .workshop-view-btn{border-color:transparent}
#page-workshop.active .workshop-views .workshop-view-btn:hover,
#page-custom-workshop.active .workshop-views .workshop-view-btn:hover{border-color:transparent;background:rgba(255,255,255,.05)}
#page-workshop.active .workshop-views .workshop-view-btn.active,
#page-custom-workshop.active .workshop-views .workshop-view-btn.active{border-color:transparent}
/* Project accent: the active view tab and the editable-title outline take the
   project's own icon colour. Scoped to .has-ws-accent so a project with no icon
   colour keeps the default treatment exactly as-is. */
.has-ws-accent .workshop-views .workshop-view-btn.active{
  background:color-mix(in srgb,var(--ws-accent) 18%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ws-accent) 48%,transparent)}
.has-ws-accent .workshop-views .workshop-view-btn.active:hover{
  background:color-mix(in srgb,var(--ws-accent) 26%,transparent)}
/* The rename input takes the workshop accent on its underline. No outline: the
   title already sits in its own filled container (see the focus carve-out at the
   end of this file) and a ring around 34px display type is a second edge. */
.has-ws-accent .ws-page-title-input{--ws-title-underline:var(--ws-accent)}
/* …and the editable title's hover/focus fill tints to the same accent, so the
   highlight and the underline read as one colour: the project's or channel's own. */
.has-ws-accent .ws-page-title.is-editable:hover,.has-ws-accent .ws-page-title.is-editable:focus-within{
  background:color-mix(in srgb,var(--ws-accent) 14%,transparent);
  border-color:color-mix(in srgb,var(--ws-accent) 45%,transparent)}
.has-ws-accent .workshop-views .workshop-view-btn:focus-visible{outline-color:var(--ws-accent)}
#page-workshop.active .workshop-views,
#page-custom-workshop.active .workshop-views{padding-bottom:14px!important}

/* Airtable-style toolbar buttons — icon + label pair with no visible
   border, hover-only background. Used for Filter / Sort / Hide / etc.
   The .ws-toolbar-btn class overrides .workshop-view-btn paddings and
   border. */
.ws-toolbar-btn{padding:0 9px;border:0;background:transparent;gap:6px;font-size:13px;color:var(--muted);font-weight:500;height:30px}
.ws-toolbar-btn:hover{background:rgba(255,255,255,.06);color:var(--cream);border:0}
.ws-toolbar-btn svg:not(.caret){width:14px;height:14px;color:var(--muted);opacity:.85;flex-shrink:0}
.ws-toolbar-btn:hover svg:not(.caret){color:var(--cream);opacity:1}
.ws-toolbar-btn-label{line-height:1;letter-spacing:.1px}
/* Active state — when the toolbar action has data attached (a filter,
   sort, hidden fields), the button glows in coral with a subtle bg
   pill, mirroring Airtable's "1 hidden field" blue pill. */
.ws-toolbar-btn.is-active{background:color-mix(in srgb,var(--coral) 18%,transparent);color:var(--coral)}
.ws-toolbar-btn.is-active svg:not(.caret){color:var(--coral);opacity:1}
.ws-toolbar-btn.is-active:hover{background:color-mix(in srgb,var(--coral) 26%,transparent)}
/* Icon-only variant for the leftmost hamburger menu button — square
   padding so the icon stays centered, no text label. */
.ws-toolbar-iconbtn{padding:0 8px;gap:0;min-width:30px;justify-content:center}
.ws-toolbar-iconbtn svg:not(.caret){width:20px;height:20px}
/* When the calendar tab-nav is mounted in the toolbar, IT takes the
   auto-margin shove to the right. The presence bar's own
   margin-left:auto needs to be neutralized or both items would split
   the free space (leaving presence stuck in the middle). */
.workshop-views:has([data-cal-tab-nav]) .presence-bar{margin-left:0!important}
.workshop-view-btn[draggable="true"]{cursor:grab}.workshop-view-btn.ws-view-dragging{opacity:.35;cursor:grabbing}.workshop-view-btn.ws-view-drag-over{border-color:var(--coral);color:var(--cream)}
/* "···" dots-options button — same height as other tab buttons but with
   tighter horizontal padding so the three dots are centered. Inherits
   height:31px from .workshop-view-btn — we just tweak the dot spacing. */
.workshop-view-btn-dots{padding:0 10px;letter-spacing:2px;font-size:14px}
/* Calendar Prev/Month/Next nav — fade+slide in from the right when calendar
   tab is activated, slide out when switching away. Staggered per-child
   via inline animation-delay set in JS. */
/* Workshop view-switch fade — applies to whichever view becomes visible
   when the user clicks Board/Calendar/Group/Journal. Outgoing view is
   simply display:none'd; the incoming view runs this animation so the
   swap feels intentional instead of an instant flicker. */
@keyframes wsViewFadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
@keyframes calNavIn{from{opacity:0;transform:translateX(8px)}to{opacity:1;transform:translateX(0)}}
@keyframes calNavOut{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(8px)}}
@keyframes calNavLabelFlip{0%{opacity:0;transform:translateY(-4px)}55%{opacity:1;transform:translateY(1px)}100%{opacity:1;transform:translateY(0)}}
/* Wrap-level entry/exit — animates the OVERALL width so trailing controls
   (presence bar, ··· menu) slide smoothly instead of jumping into place
   when the calendar nav appears or disappears.
   • Enter: max-width grows 0 → 400px. The wrap's intrinsic width caps it
     well below 400px, so the visible expansion is 0 → intrinsic over the
     first ~half of the animation, then it sits at full size.
   • Exit: the wrap's pixel width is pinned via JS before the animation
     starts (collapsing from `auto` doesn't interpolate). The keyframe
     leaves `from` empty so the start state = pinned width, end state = 0. */
@keyframes calNavWrapIn{from{max-width:0;opacity:0}to{max-width:400px;opacity:1}}
@keyframes calNavWrapOut{from{opacity:1}to{width:0;opacity:0;padding-left:0;padding-right:0;margin-left:0;margin-right:0}}
.workshop-filter-btn{display:inline-flex;align-items:center;gap:7px;padding:7px 12px}
.workshop-filter-btn svg{width:13px;height:13px;opacity:.88;flex-shrink:0}
.workshop-filter-btn .caret{width:11px;height:11px;opacity:.65}
.workshop-filter-btn .filter-count{
  min-width:16px;height:16px;border-radius:999px;padding:0 5px;
  display:none;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--coral) 28%,transparent);color:var(--coral);font-family:var(--sans);font-size:10px;font-weight:700;
  margin-left:2px
}
.workshop-filter-btn.has-filters .filter-count{display:inline-flex}
.workshop-filter-btn.open{background:rgba(255,255,255,.08);color:var(--cream)}
.workshop-filter-btn.is-active.open{background:color-mix(in srgb,var(--coral) 26%,transparent);color:var(--coral)}
.workshop-filter-btn.open{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.24);color:var(--cream)}
/* Sort button matches .workshop-view-btn exactly (same height,
   padding, border, radius) so the tab strip reads as one cohesive
   row of controls. Active state uses the gold accent to distinguish
   it from view-tab active (white-on-dark). */
.workshop-sort-btn{
  padding:0 9px;height:30px;line-height:1;
  border:0;border-radius:6px;background:transparent;
  font-family:var(--sans);font-size:13px;font-weight:500;color:var(--muted);
  cursor:pointer;transition:background .15s,color .15s;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  box-sizing:border-box;flex-shrink:0
}
.workshop-sort-btn:hover{color:var(--cream);background:rgba(255,255,255,.06)}
.workshop-sort-btn.active{color:var(--coral);background:color-mix(in srgb,var(--coral) 18%,transparent)}
.workshop-sort-btn svg{width:14px;height:14px;opacity:.85;flex-shrink:0}
.workshop-sort-btn:hover svg{opacity:1}
.workshop-sort-btn.active svg{color:var(--coral);opacity:1}
.workshop-sort-dropdown{position:absolute;top:100%;right:0;margin-top:4px;min-width:140px;background:var(--dark);border:1px solid var(--border-d);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.4);z-index:50;display:none}
.workshop-sort-dropdown.open{display:block}
.workshop-sort-option{padding:8px 12px;font-size:12px;color:var(--cream);cursor:pointer;transition:background .1s}
.workshop-sort-option:hover{background:var(--state-hover)}
.workshop-sort-option.active{color:var(--gold)}
.workshop-sort-option:hover>.workshop-sort-submenu{display:block}
.workshop-sort-submenu{display:none;position:absolute;left:100%;top:-1px;min-width:130px;background:var(--dark);border:1px solid var(--border-d);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.4);z-index:51}
.workshop-filter-panel{
  position:fixed;z-index:9600;display:none;width:min(560px,calc(100vw - 28px));
  max-height:min(72vh,520px);overflow:hidden;border:1px solid var(--border-d);border-radius:12px;
  background:var(--dark);box-shadow:0 24px 60px rgba(0,0,0,.55)
}
.workshop-filter-panel.visible{display:flex;flex-direction:column}
/* #3 — Mobile: the filter is a full-screen sheet, not a dropdown. */
body[data-mobile-mode="app"] #workshopFilterPanel{
  position:fixed !important;left:0 !important;right:0 !important;bottom:0 !important;top:auto !important;
  width:100% !important;max-width:100% !important;max-height:86dvh !important;height:auto !important;
  border:1px solid var(--border-d) !important;border-bottom:none !important;border-radius:18px 18px 0 0 !important;
  z-index:10050 !important;box-shadow:0 -14px 44px rgba(0,0,0,.5) !important;
  overflow-y:auto !important;-webkit-overflow-scrolling:touch;
  padding-bottom:calc(24px + env(safe-area-inset-bottom,0px));
  animation:wfSheetUp .28s cubic-bezier(.22,1,.36,1)
}
@keyframes wfSheetUp{from{transform:translateY(100%)}to{transform:translateY(0)}}
/* grab-handle affordance at the top of the sheet */
body[data-mobile-mode="app"] #workshopFilterPanel .wf-msheet-head::after{
  content:"";position:absolute;top:6px;left:50%;transform:translateX(-50%);
  width:38px;height:4px;border-radius:999px;background:rgba(255,255,255,.18)
}
.wf-msheet-head{
  position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;
  padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;border-bottom:1px solid var(--border-d);
  background:var(--dark)
}
.wf-msheet-title{font-family:var(--serif);font-size:20px;color:var(--off-white)}
.wf-msheet-done{
  border:0;background:var(--coral);color:#fff;font-weight:600;font-size:14px;font-family:var(--sans);
  padding:8px 18px;border-radius:999px;cursor:pointer
}
.wf-header{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 14px;border-bottom:1px solid var(--border-d)
}
.wf-header-left{display:flex;align-items:center;gap:8px}
.wf-rule-badge{
  display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:6px;
  background:rgba(140,114,219,.14);color:var(--purple,#8c72db);font-size:11px;font-weight:700;
  font-family:var(--sans);cursor:pointer;border:1px solid rgba(140,114,219,.32)
}
.wf-rule-badge svg{width:12px;height:12px}
.wf-add-inline{
  background:none;border:none;color:var(--muted);font-size:12px;font-family:var(--sans);
  cursor:pointer;padding:4px 8px;transition:color .12s
}
.wf-add-inline:hover{color:var(--cream)}
.wf-header-right{display:flex;align-items:center;gap:8px}
.wf-reset-btn{
  background:none;border:none;color:var(--muted);font-size:12px;font-family:var(--sans);
  cursor:pointer;padding:4px 8px;transition:color .12s
}
.wf-reset-btn:hover{color:var(--cream)}
.wf-save-btn{
  padding:5px 14px;border-radius:8px;border:none;
  background:var(--purple,#8c72db);color:#fff;font-size:11px;font-weight:700;
  font-family:var(--sans);cursor:pointer;transition:opacity .12s;
  display:inline-flex;align-items:center;gap:5px
}
.wf-save-btn:hover{opacity:.85}
.wf-save-btn svg{width:12px;height:12px}
.wf-body{padding:10px 14px;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
.wf-row{
  display:flex;align-items:center;gap:6px;padding:6px 0
}
.wf-row-label{font-size:12px;color:var(--muted);min-width:42px;flex-shrink:0}
.wf-row select,.wf-row input{
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;
  color:var(--cream);font-family:var(--sans);font-size:13px;padding:7px 11px;outline:none;
  color-scheme:dark;transition:border-color .12s,background .12s
}
.wf-row select:hover,.wf-row input:hover{border-color:rgba(255,255,255,.2)}
.wf-row select:focus,.wf-row input:focus{border-color:color-mix(in srgb,var(--purple,#8c72db) 60%,transparent)}
.wf-row select{cursor:pointer;-webkit-appearance:none;appearance:none;padding-right:28px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center}
.wf-row .wf-field-select{min-width:110px}
.wf-row .wf-cond-select{min-width:100px}
.wf-row .wf-value-input{flex:1;min-width:100px}
.wf-row .wf-value-select{flex:1;min-width:100px}
/* Person filter button — overrides the browser's default button background
   so it matches the dark select/input styling alongside it. Without this
   the button renders with the OS-default light grey background, making
   the avatar + name nearly invisible. */
.wf-row .wf-person-btn{
  background:rgba(255,255,255,.06);
  border:1px solid var(--border-d);
  border-radius:7px;
  color:var(--cream);
  font-family:var(--sans);
  font-size:12px;
  padding:5px 28px 5px 8px;
  outline:none;
  cursor:pointer;
  transition:border-color .12s,background .12s;
  min-height:30px;
  gap:6px
}
.wf-row .wf-person-btn:hover{background:rgba(255,255,255,.09)}
.wf-row .wf-person-btn:focus{border-color:rgba(74,144,217,.55)}
.wf-row .wf-person-btn .user-mini-avatar{flex-shrink:0}
/* The person popover menu — matches wf-row-menu styling. */
.wf-person-menu{
  position:absolute;z-index:9700;background:var(--dark);border:1px solid var(--border-d);
  border-radius:8px;padding:4px;min-width:220px;max-height:320px;overflow-y:auto;
  box-shadow:0 12px 32px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.04)
}
.wf-person-menu button{
  display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border:none;background:none;
  color:var(--cream);font-size:12px;font-family:var(--sans);cursor:pointer;border-radius:6px;
  text-align:left;transition:background .1s
}
.wf-person-menu button:hover{background:rgba(255,255,255,.06)}
.wf-person-menu button.is-active{background:rgba(124,92,255,.14);color:var(--coral)}
.wf-person-menu button.is-active .wf-person-check{margin-left:auto;color:var(--coral)}
.wf-person-menu button .user-mini-avatar{flex-shrink:0}.wf-row-menu-btn{
  width:28px;height:28px;border-radius:6px;border:1px solid transparent;background:none;
  color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;
  font-size:14px;letter-spacing:1px;transition:all .12s;flex-shrink:0
}
.wf-row-menu-btn:hover{border-color:var(--border-d);color:var(--cream);background:rgba(255,255,255,.04)}
.wf-row-menu{
  position:absolute;z-index:9700;background:var(--dark);border:1px solid var(--border-d);
  border-radius:8px;padding:4px;min-width:140px;box-shadow:0 8px 24px rgba(0,0,0,.5)
}
.wf-row-menu button{
  display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border:none;background:none;
  color:var(--cream);font-size:12px;font-family:var(--sans);cursor:pointer;border-radius:6px;
  transition:background .1s
}
.wf-row-menu button:hover{background:rgba(255,255,255,.06)}
.wf-row-menu button.danger{color:var(--danger-text)}
.wf-row-menu button.danger:hover{background:rgba(239,68,68,.1)}
.wf-footer{padding:8px 14px;border-top:1px solid var(--border-d);display:flex;align-items:center;gap:10px}
.wf-done-sm{margin-left:auto;padding:5px 14px;border-radius:8px;border:0;cursor:pointer;background:var(--coral);color:#fff;font:600 12px var(--sans)}
.wf-done-sm:hover{filter:brightness(1.08)}
.workshop-filter-panel .wf-field-item:focus-visible,.workshop-filter-panel button:focus-visible{outline:1px solid var(--coral);outline-offset:-1px}
.wf-add-rule{
  display:flex;align-items:center;gap:6px;width:100%;padding:6px 8px;border:none;background:none;
  color:var(--muted);font-size:12px;font-family:var(--sans);cursor:pointer;border-radius:6px;
  transition:all .12s
}
.wf-add-rule:hover{color:var(--cream);background:rgba(255,255,255,.04)}
.wf-add-rule svg{width:14px;height:14px}
.wf-field-picker{padding:4px 0}
.wf-field-item{
  display:flex;align-items:center;gap:8px;width:100%;padding:7px 12px;border:none;background:none;
  color:var(--cream);font-size:13px;font-family:var(--sans);cursor:pointer;border-radius:6px;
  transition:background .1s
}
.wf-field-item:hover{background:rgba(255,255,255,.06)}
.wf-field-item .wf-field-icon{font-size:14px;width:20px;text-align:center;color:var(--muted);flex-shrink:0}
.wf-delete-all{
  display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;
  color:var(--muted);font-size:12px;font-family:var(--sans);cursor:pointer;border-radius:6px;
  transition:all .1s;border-top:1px solid var(--border-d);margin-top:4px
}
.wf-delete-all:hover{color:var(--danger-text);background:rgba(239,68,68,.06)}
.wf-delete-all svg{width:14px;height:14px}
#workshopBoardView,#pbBoardView,#cwBoardView{padding-bottom:210px}
.cw-dropdown{display:none;position:absolute;top:100%;right:0;margin-top:4px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:4px;min-width:160px;z-index:300;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.cw-dropdown.open{display:block}
.cw-dropdown button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;color:var(--cream);font-family:var(--sans);font-size:12px;cursor:pointer;border-radius:6px;transition:background .12s;white-space:nowrap}
.cw-dropdown button:hover{background:var(--state-hover)}
.cw-dropdown button svg{flex-shrink:0}
.cw-dropdown-danger{color:var(--danger-text)!important}
.cw-dropdown-danger:hover{background:rgba(239,68,68,.12)!important}
/* Card right-click context menu */
.card-ctx-menu{display:none;position:fixed;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:4px;min-width:180px;z-index:10100;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.card-ctx-menu.open{display:block}
.card-ctx-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;color:var(--cream);font-family:var(--sans);font-size:12px;cursor:pointer;border-radius:6px;transition:background .12s;white-space:nowrap;text-align:left}
.card-ctx-menu button:hover{background:var(--state-hover)}
.card-ctx-menu button svg{flex-shrink:0;width:14px;height:14px}
.card-ctx-menu .ctx-danger{color:var(--danger-text)!important}
.card-ctx-menu .ctx-danger:hover{background:rgba(239,68,68,.12)!important}
.card-ctx-menu .ctx-separator{height:1px;background:var(--border-d);margin:4px 0}
.card-ctx-menu .ctx-submenu-wrap{position:relative}
.card-ctx-menu .ctx-submenu{display:none;position:absolute;left:100%;top:-4px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:4px;min-width:160px;z-index:10101;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.card-ctx-menu .ctx-submenu-wrap:hover .ctx-submenu{display:block}
.card-ctx-menu .ctx-submenu button{padding:6px 12px;font-size:12px}
.card-ctx-menu .ctx-col-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.card-ctx-menu .ctx-arrow{margin-left:auto;opacity:.4;font-size:10px}
.card-ctx-menu .ctx-shift-only{display:none!important}
body.shift-held .card-ctx-menu .ctx-shift-only{display:flex!important}
/* Editable area right-click context menu */
.edit-ctx-menu{display:none;position:fixed;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:4px;min-width:160px;z-index:10100;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.edit-ctx-menu.open{display:block}
.edit-ctx-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;color:var(--cream);font-family:var(--sans);font-size:12px;cursor:pointer;border-radius:6px;transition:background .12s;white-space:nowrap;text-align:left}
.edit-ctx-menu button:hover{background:var(--state-hover)}
.edit-ctx-menu button:disabled{opacity:.35;cursor:default;pointer-events:none}
.edit-ctx-menu .ctx-separator{height:1px;background:var(--border-d);margin:4px 0}
.edit-ctx-menu .ctx-kbd{margin-left:auto;font-size:10px;color:var(--muted);font-family:var(--sans)}
.kanban-card.mirrored-card{border-left:3px solid var(--teal);opacity:.9}
.kanban-card.mirrored-card::after{display:none}
.routed-source-badge{font-size:10px;padding:1px 6px;border-radius:3px;background:rgba(255,255,255,.08);color:var(--coral);border-left:2px solid var(--coral)}
/* Due date */
.kanban-card-due{font-size:10px;color:var(--muted);display:inline-flex;align-items:center;gap:3px}
.kanban-card-due.overdue{color:var(--prio-high);font-weight:600}
.kanban-card-due.soon{color:var(--gold)}
.due-date-input{background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:5px;color:var(--cream);font-family:var(--sans);font-size:12px;padding:5px 8px;outline:none;color-scheme:dark}
.due-date-input:focus{border-color:var(--coral)}
/* Trigger for the app's own date picker — same shell as .due-date-input above so
   swapping off the native <input type="date"> changed the popover, not the field. */
.due-date-btn{display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:5px;color:var(--cream);font-family:var(--sans);font-size:12px;font-weight:500;padding:5px 8px;cursor:pointer;transition:border-color .12s,background .12s}
.due-date-btn:hover:not(:disabled){background:rgba(255,255,255,.09);border-color:var(--hairline-2)}
.due-date-btn:disabled{cursor:default;opacity:var(--opacity-disabled,.45)}
.due-date-btn.gv-edit-open{border-color:var(--coral)}
.due-date-btn svg{flex-shrink:0;color:var(--muted)}
.due-date-btn .hd-date-btn-text.is-empty{color:var(--muted)}
html[data-theme="light"] .due-date-btn{background:var(--bg-inset);color:var(--off-white)}
/* Calendar view */
.calendar-container{padding:0 2px;transition:box-shadow .15s ease;display:flex;flex-direction:column;flex:1;min-height:0}
/* Workshop + child-workshop calendar fills the entire pane edge-to-edge —
   no black gap above the SUN/MON header, no padding on the sides, no
   margin between the tab strip and the grid. The parent pane's padding
   is zeroed below (#workshopCalendarView / #cwCalendarView rule). */
#workshopCalendarView .calendar-container,
#cwCalendarView .calendar-container { margin-left: 0; margin-right: 0; padding: 0; }
/* Overview's master-view calendar — escape the pane's horizontal padding
   with negative margins so the grid + sidebar run edge-to-edge. Right
   side has zero margin/padding so the sidebar's cards sit flush
   against the page edge (no black gap on the right). */
#mvCalendarPane .calendar-container { margin-left: -36px; margin-right: -36px; padding: 0 0 0 12px; }
@media (max-width: 700px) {
  #workshopCalendarView .calendar-container,
  #cwCalendarView .calendar-container { margin-left: 0; margin-right: 0; padding: 0; }
  #mvCalendarPane .calendar-container { margin-left: -16px; margin-right: -16px; padding: 0 8px; }
}
.calendar-toolbar{display:flex;align-items:center;gap:12px;margin-bottom:12px;flex-wrap:wrap}
.calendar-toolbar-left{display:flex;align-items:center;gap:10px}
.calendar-toolbar-right{display:flex;align-items:center;gap:24px;margin-left:auto}
.calendar-toolbar-select{background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);padding:4px 10px;font-size:11px;font-family:var(--sans);cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%23999990' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;padding-right:24px}
.calendar-toolbar-select:focus{border-color:var(--coral);outline:none}
.calendar-toolbar-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.calendar-toolbar-toggle{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--muted);cursor:pointer;user-select:none}
.calendar-toolbar-toggle input{accent-color:var(--coral);cursor:pointer}
.calendar-nav{display:flex;align-items:center;gap:24px}
.calendar-nav-btn{background:none;border:1px solid var(--border-d);border-radius:6px;color:var(--muted);cursor:pointer;padding:5px 12px;font-size:12px;transition:all .15s}
.calendar-nav-btn:hover{color:var(--cream);border-color:rgba(255,255,255,.2)}
.calendar-month{font-family:var(--sans);font-size:14px;font-weight:600;letter-spacing:.2px;color:var(--cream);min-width:160px;text-align:center}
/* minmax(0,1fr) instead of bare 1fr: by default grid tracks compute their minimum
   as the natural width of the largest child, so a card with long unbroken text
   (e.g. "Curriculum MKT Video_24_You") would force a column wider than 1/7 of
   the viewport, pushing the right side of the grid off-screen. minmax(0,1fr)
   pins the minimum to zero and lets cell text truncate normally. */
.calendar-grid{
  display:grid;
  grid-template-columns:repeat(7,minmax(0,1fr));
  /* First row is the day-of-week labels (SUN MON TUE …) — pin it to
     a compact 22px so it stops eating ~1/7 of the calendar's vertical
     space. All subsequent rows (the actual week rows) auto-fill 1fr
     and split the remaining height equally. */
  grid-template-rows:22px;
  /* Week rows: at least 160px (enough for the day number + 3 chips + the
     "+N more" line) and grow to 1fr to fill a tall pane. On short laptop
     viewports the 160px floor wins, so the grid scrolls vertically instead
     of squishing every row and clipping the bottom weeks. */
  grid-auto-rows:minmax(160px,1fr);
  gap:1px;background:rgba(255,255,255,.04);
  border-radius:8px;overflow:hidden auto;flex:1;min-height:0
}
/* Calendar layout: grid + side panel side-by-side, both filling vertical
   space available in the pane. */
.cal-with-sidebar{display:flex;gap:16px;align-items:stretch;flex:1;min-height:0}
.cal-grid-wrap{flex:1;min-width:0;display:flex;flex-direction:column}
.cal-sidebar{width:300px;flex-shrink:0;display:flex;flex-direction:column;gap:14px;min-height:0;overflow:hidden}
.cal-side-card{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:10px;padding:14px;display:flex;flex-direction:column;min-height:0}
.cal-side-card.cal-side-upcoming{flex:1 1 0;min-height:0;overflow:hidden}
/* Upcoming day-window selector — small inline dropdown in the header
   that lets the user change the look-ahead window (3/7/14/30/60/90).
   Matches the calendar's dark-on-dark aesthetic. */
.cal-up-days-select{
  background:rgba(255,255,255,.05);
  color:var(--muted);
  border:1px solid var(--border-d);
  border-radius:6px;
  font-family:var(--sans);
  font-size:11px;
  font-weight:500;
  padding:3px 6px;
  cursor:pointer;
  outline:none;
  transition:background .12s,color .12s,border-color .12s;
}
.cal-up-days-select:hover{background:var(--state-hover);color:var(--cream);border-color:rgba(255,255,255,.18)}
.cal-up-days-select:focus{border-color:var(--coral);color:var(--cream)}
.cal-side-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:12px;gap:8px}
.cal-side-title{font-family:var(--sans);font-size:13px;font-weight:600;color:var(--off-white);letter-spacing:.2px}
.cal-side-link{font-size:11px;color:var(--muted);cursor:pointer;transition:color .15s;white-space:nowrap}
.cal-side-link:hover{color:var(--coral)}
.cal-stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.cal-stat-card{background:var(--bg-inset);border:1px solid var(--hairline-2);border-radius:8px;padding:10px;display:flex;align-items:center;gap:10px;cursor:pointer;transition:background .15s,border-color .15s,transform .15s}
.cal-stat-card:hover{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.1);transform:translateY(-1px)}
.cal-stat-card.cal-stat-card-active{background:rgba(124,92,255,.12);border-color:rgba(124,92,255,.4);box-shadow:0 0 0 1px rgba(124,92,255,.25) inset}
.cal-stat-card.cal-stat-card-active .cal-stat-num{color:var(--coral)}
.cal-stat-icon{width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.cal-stat-icon svg{width:16px;height:16px}
.cal-stat-icon-violet{background:rgba(146,109,222,.15);color:#b794d6}
.cal-stat-icon-amber{background:rgba(232,197,71,.15);color:var(--gold)}
.cal-stat-icon-green{background:rgba(115,172,131,.15);color:var(--green)}
.cal-stat-icon-red{background:rgba(239,68,68,.15);color:var(--danger-text)}
.cal-stat-num{font-family:var(--sans);font-size:20px;font-weight:700;color:var(--off-white);line-height:1}
.cal-stat-label{font-size:10px;color:var(--muted);margin-top:3px;letter-spacing:.2px}
.cal-side-empty{font-size:11px;color:var(--muted);font-style:italic;padding:6px 0}
.cal-upcoming-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;overflow-y:auto;max-height:100%;min-height:0}
.cal-upcoming-item{padding:10px 4px;border-top:1px solid rgba(255,255,255,.05);display:flex;align-items:stretch;gap:10px;cursor:pointer;transition:background .15s;border-radius:7px}
.cal-upcoming-item:first-child{border-top:0}
.cal-upcoming-item:hover{background:rgba(255,255,255,.05)}
.cal-upcoming-item.hidden{display:none}
/* When (time or short date) on the far left, then a colour bar in the stage colour */
.cal-upcoming-when{flex:none;width:44px;font-size:11px;font-weight:600;color:var(--text-3);padding-top:1px;white-space:nowrap}
.cal-upcoming-bar{flex:none;width:3px;align-self:stretch;border-radius:3px;min-height:26px}
.cal-upcoming-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;margin-top:5px}
.cal-upcoming-text{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:2px}
.cal-upcoming-title{font-size:13px;color:var(--text-1);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-upcoming-date{font-size:11px;color:var(--text-3);font-weight:500}
/* Recent Mentions section (master view only) — compact mention rows. */
.cal-side-mentions{flex:1;overflow:hidden}
.cal-mentions-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;overflow-y:auto;min-height:0}
.cal-mention-item{display:flex;align-items:flex-start;gap:8px;padding:9px 4px;border-top:1px solid rgba(255,255,255,.04);cursor:pointer;transition:background .15s}
.cal-mention-item:first-child{border-top:0}
.cal-mention-item:hover{background:rgba(255,255,255,.05)}
.cal-mention-item.unread{background:rgba(124,92,255,.06)}
.cal-mention-item.unread:hover{background:rgba(124,92,255,.1)}
.cal-mention-avatar{width:24px;height:24px;border-radius:50%;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;overflow:hidden;font-size:13px;background:rgba(255,255,255,.08)}
.cal-mention-avatar img{width:100%;height:100%;object-fit:cover}
.cal-mention-body{flex:1;min-width:0}
.cal-mention-head{display:flex;align-items:baseline;gap:4px;flex-wrap:wrap;font-size:11px}
.cal-mention-actor{font-weight:600;color:var(--off-white)}
.cal-mention-on{color:var(--muted)}
.cal-mention-card{color:var(--cream);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:140px;padding-right:.14em}
.cal-mention-when{color:var(--muted);margin-left:auto;font-size:10px}
.cal-mention-quote{font-size:11px;color:var(--cream);margin-top:3px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.calendar-day{min-width:0}
.calendar-day-label{
  padding:0 4px;text-align:center;
  font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;
  color:var(--muted);background:var(--dark);
  /* Pin the weekday header row to the top while the grid scrolls so the
     SUN…SAT labels stay visible on short viewports. */
  position:sticky;top:0;z-index:4;
  /* Center the text vertically inside the compact 22px row. */
  display:flex;align-items:center;justify-content:center;line-height:1
}
.calendar-day{min-height:160px;background:var(--dark);padding:8px;display:flex;flex-direction:column;gap:3px;transition:background .1s}
.calendar-day:hover{background:color-mix(in srgb,#fff 4%,var(--dark))}
.calendar-day-num{font-size:12px;font-weight:600;color:var(--muted);margin-bottom:4px}
.calendar-day.today .calendar-day-num{color:var(--coral);background:rgba(124,92,255,.15);width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700}
/* Other-month cells: dimmed via opacity only — no background tint,
   no extra greying on content. Whole cell drops to 30% opacity which
   pulls everything (day number, chips, status pills) down together.
   Stays interactive — accepts drops, click-to-add, etc. Hovering
   lifts the cell so the user gets feedback when they mean to act. */
.calendar-day.other-month{opacity:.3;background:var(--dark)}
.calendar-day.other-month:hover{opacity:.6}
/* Coral "MAY 1" label on the first day of the current month — the
   only month-boundary marker the eye really needs once the rest of
   the row is dimmed at 30%. */
.calendar-day:not(.other-month) .calendar-day-num.is-month-start{
  color:var(--coral);font-weight:700
}
.calendar-day-num.is-month-start .cdn-mon{
  font-size:10px;font-weight:600;letter-spacing:.5px;
  text-transform:uppercase;margin-right:1px
}
.calendar-day-card{font-size:11px;padding:5px 8px;border-radius:6px;background:var(--cal-card-bg,rgba(255,255,255,.06));cursor:pointer;color:var(--cream);transition:background .1s;display:flex;flex-direction:column;align-items:flex-start;gap:2px;line-height:1.25;min-height:24px}
/* Pop-in animation when a NEW chip first appears in the calendar.
   Applied by _calMarkNewChips after each render to any chip whose
   card.id wasn't in the previous render. Scale-up + fade + faint
   coral pulse so the user can see exactly what was just added. */
.calendar-day-card.is-just-added{
  animation:calChipPopIn .42s cubic-bezier(.22,1,.36,1) both
}
@keyframes calChipPopIn{
  0%   {opacity:0;transform:scale(.6);box-shadow:0 0 0 0 rgba(124,92,255,.0)}
  40%  {opacity:1;transform:scale(1.06);box-shadow:0 0 0 4px rgba(124,92,255,.18)}
  100% {opacity:1;transform:scale(1);box-shadow:0 0 0 0 rgba(124,92,255,0)}
}
@media(prefers-reduced-motion:reduce){
  .calendar-day-card.is-just-added{animation:none}
}
.calendar-day-card:hover{background:var(--cal-card-hover,rgba(255,255,255,.1))}
.calendar-day-card .cdc-line{display:flex;align-items:center;gap:6px;width:100%;min-width:0}
.calendar-day-card .cdc-dot{width:7px;height:7px;border-radius:50%;background:var(--cal-dot-color,var(--muted));flex-shrink:0}
.calendar-day-card .cdc-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;font-weight:500}
.calendar-day-card .cdc-status{margin-left:13px;font-size:8.5px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;padding:1px 5px;border-radius:3px;background:var(--cal-status-bg,rgba(255,255,255,.10));color:var(--cal-status-color,var(--cream));max-width:calc(100% - 13px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Compact chip at narrow viewports — the second-line status pill takes
   real vertical estate the day cell can't spare on smaller screens.
   Hide it and tighten chip padding so more chips fit per day. */
@media (max-width: 1500px){
  .calendar-day-card{padding:4px 7px;min-height:20px;font-size:11px;gap:0}
  .calendar-day-card .cdc-status{display:none}
  .calendar-day-card .cdc-dot{width:6px;height:6px}
}
@media (max-width: 1280px){
  .cal-sidebar{width:240px}
  .calendar-day-card{padding:3px 6px;font-size:10px;border-radius:5px}
}
@media (max-width: 1100px){
  .cal-sidebar{width:200px}
  .calendar-day-card .cdc-text{font-size:10px}
}
.calendar-day-card.dup-target{outline:2px dashed var(--green);background:rgba(115,172,131,.12)}
.calendar-day-overflow{font-size:10px;color:var(--muted);padding:2px 6px;cursor:pointer;text-align:center;transition:color .12s,background .12s;border-radius:4px}
.calendar-day-overflow:hover{color:var(--cream);background:rgba(255,255,255,.06)}
/* Multi-select state for calendar items — outline + tinted background uses the
   chip's OWN column status color (via --cal-dot-color which the engine sets on
   each chip inline). So a yellow "WAITING FOR FILES" chip highlights yellow, a
   green "POSTED" chip highlights green, etc. Falls back to coral if a chip has
   no column color set. */
.calendar-day-card.is-selected{
  outline:1px solid var(--cal-dot-color, var(--coral));
  outline-offset:0;
  box-shadow:0 2px 10px color-mix(in srgb, var(--cal-dot-color, var(--coral)) 22%, transparent);
  background:color-mix(in srgb, var(--cal-dot-color, var(--coral)) 22%, var(--cal-card-bg, rgba(255,255,255,.06)));
  position:relative;z-index:2
}
/* "Cut" items: dashed border in the chip's column color + reduced opacity. */
.calendar-day-card.is-cut{
  opacity:.55;
  outline:1px dashed var(--cal-dot-color, var(--coral));
  outline-offset:0;
}
/* Day-view item selection — mirrors .calendar-day-card.is-selected, but the
   stripe (left border) gives us a cleaner anchor for the outline than the
   chip background does. Uses the same --cdm-color variable that's already
   set inline per row. */
.cdm-item.is-selected{
  outline:2px solid var(--cdm-color, var(--coral));
  outline-offset:1px;
  background:color-mix(in srgb, var(--cdm-color, var(--coral)) 14%, rgba(255,255,255,.025));
  border-color:transparent;
  position:relative;z-index:2
}
.cdm-item.is-cut{
  opacity:.55;
  outline:2px dashed var(--cdm-color, var(--coral));
  outline-offset:1px;
}
/* Active paste-target day cell (last clicked) — subtle coral outline so user
   knows where cmd+v will drop things. */
.calendar-day.cal-active-day{
  box-shadow:inset 0 0 0 1.5px rgba(124,92,255,.55);
  background:color-mix(in srgb, var(--coral) 4%, var(--dark));
}
/* Day expansion popover — opens when "+N more" is clicked. Shows every card
   for that day using the same chip markup as the calendar. */
.cal-day-popover{position:fixed;z-index:10050;background:#15151a;border:1px solid var(--border-d);
  border-radius:12px;box-shadow:0 24px 60px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.04);
  padding:0;display:flex;flex-direction:column;max-height:70vh;animation:calDayPopIn .15s ease-out}
@keyframes calDayPopIn{from{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:none}}
.cal-day-popover-head{display:flex;align-items:center;gap:10px;padding:14px 14px 10px;border-bottom:1px solid var(--border-d)}
.cal-day-popover-date{flex:1;font-size:13px;font-weight:700;color:var(--cream);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cal-day-popover-count{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);padding:3px 8px;border-radius:999px;background:rgba(255,255,255,.06);white-space:nowrap}
.cal-day-popover-close{background:none;border:0;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;padding:0;transition:background .12s,color .12s}
.cal-day-popover-close:hover{background:var(--state-hover);color:var(--cream)}
.cal-day-popover-list{display:flex;flex-direction:column;gap:4px;padding:10px;overflow-y:auto;min-height:0}
.cal-day-popover-item{cursor:pointer}
/* ── Day-view expand transition ────────────────────────────────────────
   Clicking "+N more" on a day cell switches the calendar to Day view. The
   source cell briefly lifts + scales while its peers dim, then the Day
   view fades in. No modal — the calendar itself becomes the day view. */
.cal-grid-wrap.cal-day-expanding .calendar-day:not(.cal-day-expanding-source){
  transition:opacity .14s ease,transform .14s ease;
  opacity:.25;
}
.cal-day-expanding-source{
  position:relative;z-index:3;
  transition:transform .16s cubic-bezier(.22,1,.36,1),box-shadow .16s ease,background .16s ease;
  transform:scale(1.04);
  box-shadow:0 14px 40px rgba(0,0,0,.4),0 0 0 1px rgba(124,92,255,.45) inset;
  background:rgba(124,92,255,.06) !important;
}
.cal-day-view{animation:calDayViewIn .22s cubic-bezier(.22,1,.36,1) both}
@keyframes calDayViewIn{from{opacity:0;transform:scale(.985)}to{opacity:1;transform:none}}
.cdm-item{display:flex;align-items:flex-start;gap:12px;padding:12px 14px;border-radius:10px;background:rgba(255,255,255,.025);border:1px solid var(--border-d);cursor:pointer;transition:background .12s,border-color .12s,transform .08s}
.cdm-item:hover{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.12)}
.cdm-item:active{transform:scale(.998)}
.cdm-item .cdm-stripe{width:3px;align-self:stretch;border-radius:2px;background:var(--cdm-color, var(--muted));flex-shrink:0;margin:2px 0}
.cdm-item .cdm-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}
.cdm-item .cdm-title-row{display:flex;align-items:center;gap:8px;min-width:0;flex-wrap:wrap}
.cdm-item .cdm-title{font-size:14px;font-weight:600;color:var(--cream);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.cdm-item .cdm-status{font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;padding:2px 7px;border-radius:4px;background:var(--cdm-status-bg, rgba(255,255,255,.08));color:var(--cdm-color, var(--cream));white-space:nowrap;flex-shrink:0}
.cdm-item .cdm-meta-row{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--muted);flex-wrap:wrap;min-width:0}
.cdm-item .cdm-meta-row .cdm-workspace{display:inline-flex;align-items:center;gap:5px;font-weight:500}
.cdm-item .cdm-meta-row .cdm-workspace img,
.cdm-item .cdm-meta-row .cdm-workspace .cdm-ws-fallback{width:14px;height:14px;border-radius:3px;object-fit:cover;background:rgba(255,255,255,.10);display:inline-flex;align-items:center;justify-content:center;font-size:8px;color:var(--cream);font-weight:700}
.cdm-item .cdm-meta-row .cdm-sep{opacity:.5}
.cdm-item .cdm-meta-row .cdm-assignees{display:inline-flex;align-items:center}
.cdm-item .cdm-meta-row .cdm-assignees > *{margin-left:-4px}
.cdm-item .cdm-meta-row .cdm-assignees > *:first-child{margin-left:0}
/* ── Calendar view-mode toggle (Day / Week / Month) ───────────────────
   Three-segment pill rendered next to the prev/label/next nav in the
   workshop tab strip. Active segment uses the coral accent. */
/* Segmented control — Day | Week | Month inside one shared border
   with vertical dividers between segments instead of gaps. Matches
   the .workshop-view-btn height and color palette so it reads as a
   single unit but the segments still look like buttons. */
.cal-view-toggle{
  display:inline-flex;align-items:stretch;
  background:none;
  border:1px solid var(--border-d);border-radius:6px;
  padding:0;height:31px;
  overflow:hidden;flex-shrink:0
}
.cal-view-toggle button{
  appearance:none;background:none;border:0;
  border-left:1px solid var(--border-d);
  padding:0 16px;height:100%;line-height:1;
  font-family:var(--sans);font-size:12px;font-weight:500;color:var(--muted);
  cursor:pointer;transition:background .12s,color .12s;
  display:inline-flex;align-items:center;justify-content:center;
  box-sizing:border-box;flex-shrink:0;
  text-transform:capitalize;letter-spacing:0;border-radius:0
}
.cal-view-toggle button:first-child{border-left:0}
.cal-view-toggle button:hover{color:var(--cream);background:rgba(255,255,255,.04)}
.cal-view-toggle button.is-active{background:var(--state-hover);color:var(--cream)}

/* Same segmented treatment for the month-nav group (Prev | Month | Next). */
.cal-month-nav{
  display:inline-flex !important;align-items:stretch;gap:0 !important;
  background:none;
  border:1px solid var(--border-d);border-radius:6px;
  padding:0;height:31px;
  overflow:hidden;flex-shrink:0
}
.cal-month-nav .workshop-view-btn{
  border:0 !important;border-radius:0 !important;
  border-left:1px solid var(--border-d) !important;
  height:100% !important;padding:0 14px !important;
  background:none !important
}
.cal-month-nav .workshop-view-btn:first-child{border-left:0 !important}
.cal-month-nav .workshop-view-btn:hover{background:rgba(255,255,255,.04) !important;color:var(--cream)}
.cal-month-nav [data-cal-tab-nav-label]{
  pointer-events:auto;cursor:pointer !important;
  color:var(--cream) !important;font-weight:600 !important
}

/* ── Week view ─────────────────────────────────────────────────────────
   Seven equal columns showing one week. Same chip styling as month view
   but cells are taller and don't compress past 3 items (since space is
   plentiful). */
.cal-week-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;background:var(--border-d);border:1px solid var(--border-d);border-radius:8px;overflow:hidden;flex:1;min-height:0}
.cal-week-day{background:var(--dark);padding:10px;display:flex;flex-direction:column;gap:4px;min-width:0;min-height:300px;overflow-y:auto}
.cal-week-day.today{background:color-mix(in srgb,var(--coral) 5%,var(--dark))}
.cal-week-day-head{display:flex;flex-direction:column;gap:2px;padding-bottom:8px;margin-bottom:4px;border-bottom:1px solid var(--border-d);flex-shrink:0}
.cal-week-day-name{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.cal-week-day-num{font-size:18px;font-weight:700;color:var(--cream);line-height:1}
.cal-week-day.today .cal-week-day-num{color:var(--coral)}
.cal-week-day-empty{font-size:10px;color:var(--muted);opacity:.6;padding:8px 0}

/* ── Day view ─────────────────────────────────────────────────────────
   Single-day vertical list with a prominent header. Same chip styling
   as the day-view modal for visual consistency. */
.cal-day-view{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.02)}
.cal-day-view-head{padding:22px 26px 18px;border-bottom:1px solid var(--border-d);flex-shrink:0;display:flex;align-items:center;gap:14px}
.cal-day-view-head .cdv-weekday{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin-bottom:4px}
.cal-day-view-head .cdv-date{font-size:24px;font-weight:700;color:var(--cream);line-height:1.1}
.cal-day-view-head .cdv-today-pill{display:inline-block;margin-left:10px;font-size:9px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--coral);background:rgba(124,92,255,.14);padding:3px 8px;border-radius:999px;vertical-align:middle;position:relative;top:-3px}
.cal-day-view-head .cdv-count{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);padding:4px 10px;border-radius:999px;background:rgba(255,255,255,.06);white-space:nowrap}
.cal-day-view-body{flex:1;min-height:0;overflow-y:auto;padding:18px 22px;display:flex;flex-direction:column;gap:8px}
.cal-day-view-empty{padding:60px 20px;text-align:center;color:var(--muted);font-size:13px}
.calendar-unscheduled{margin-top:16px;padding:14px;background:rgba(255,255,255,.02);border:1px solid var(--border-d);border-radius:8px}
.calendar-unscheduled-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:8px}
.calendar-day.drag-over{background:rgba(232,197,71,.12) !important;outline:2px dashed var(--gold)}
/* ── Unscheduled items drawer (sticky bottom of calendar) ── */
.cal-unscheduled{margin-top:14px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.03);overflow:hidden;flex-shrink:0}
.cal-unscheduled-header{display:flex;align-items:center;gap:10px;padding:12px 16px;cursor:pointer;user-select:none;font-size:12px;font-weight:600;color:var(--cream);transition:background .12s}
.cal-unscheduled-header:hover{background:rgba(255,255,255,.04)}
.cal-unscheduled-header .cu-caret{transition:transform .15s;font-size:10px;color:var(--muted)}
.cal-unscheduled.open .cu-caret{transform:rotate(180deg)}
.cal-unscheduled-header .cu-icon{font-size:14px;line-height:1}
.cal-unscheduled-header .cu-count{margin-left:auto;background:var(--coral);color:#fff;font-size:10px;font-weight:700;padding:2px 8px;border-radius:20px;min-width:22px;text-align:center}
.cal-unscheduled-header .cu-hint{font-size:10px;color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0;margin-right:4px}
.cal-unscheduled-body{display:none;padding:10px 14px 14px;max-height:0;transition:max-height .25s ease,padding .15s ease;overflow:hidden}
.cal-unscheduled.open .cal-unscheduled-body{display:block;max-height:280px;overflow-y:auto}
.cal-unscheduled-list{display:flex;flex-direction:column}
.cal-unscheduled-empty{padding:18px;text-align:center;color:var(--muted);font-size:12px}
/* Match the .cal-upcoming-item flat row style: no card background or
   border, just a 1px top divider between rows. Keeps the drag class
   intact for the existing drag handlers. */
.cal-unscheduled-chip{display:flex;align-items:flex-start;gap:8px;padding:9px 4px;border-top:1px solid rgba(255,255,255,.04);cursor:grab;transition:background .15s}
.cal-unscheduled-chip:first-child{border-top:0}
.cal-unscheduled-chip:hover{background:rgba(255,255,255,.05)}
.cal-unscheduled-chip:active{cursor:grabbing}
.cal-unscheduled-chip .cu-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;margin-top:5px}
.cal-unscheduled-chip .cu-text-wrap{flex:1;min-width:0}
.cal-unscheduled-chip .cu-title{font-size:12px;color:var(--cream);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-unscheduled-chip .cu-subtitle{font-size:10px;color:var(--muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.group-section.drag-over{outline:2px dashed var(--gold);outline-offset:-2px}
/* Group (table) view */
.group-view{display:flex;flex-direction:column;gap:12px}
.group-section{border:1px solid var(--border-d);border-radius:8px}
.group-header{display:flex;align-items:center;gap:10px;padding:12px 16px;cursor:pointer;transition:background .1s;user-select:none;border-radius:8px 8px 0 0}
.group-header:hover{background:rgba(255,255,255,.02)}
.group-header-bar{width:4px;height:24px;border-radius:2px;flex-shrink:0}
.group-header-name{font-size:15px;font-weight:700;color:var(--cream)}
.group-header-count{font-family:var(--sans);font-size:12px;color:var(--muted);background:var(--bg-inset);padding:2px 7px;border-radius:10px}
.group-chevron{margin-left:auto;color:var(--muted);font-size:14px;transition:transform .2s}
.group-section.collapsed .group-chevron{transform:rotate(-90deg)}
.group-section.collapsed .group-body{display:none}
.group-table{width:100%;overflow-x:auto}
.group-table-header,.group-table-row{display:grid;gap:0;border-bottom:1px solid var(--border-d)}
.group-table-header{background:rgba(255,255,255,.02)}
.group-table-header span{padding:8px 14px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.group-table-header span.group-col-header{overflow:visible;position:relative}
.group-table-row{border-bottom:1px solid rgba(255,255,255,.03);transition:background .1s;cursor:pointer}
.group-table-row:hover{background:rgba(255,255,255,.03)}
.group-table-row:last-child{border-bottom:none}
.group-table-cell{padding:10px 14px;font-family:var(--sans);font-size:13px;color:var(--cream);display:flex;align-items:center;gap:6px;overflow:hidden}
.group-table-cell.task-name{font-size:14px;font-weight:500}
.group-table-cell .status-badge{font-size:10px;padding:2px 8px;border-radius:3px;font-weight:600;white-space:nowrap}
.group-add-row{padding:10px 14px;font-size:13px;color:var(--muted);cursor:pointer;transition:color .15s}
.group-add-row:hover{color:var(--coral)}
.group-add-col{padding:7px 8px;font-size:14px;color:var(--muted);cursor:pointer;transition:color .15s;background:none;border:none;font-family:var(--sans)}
.group-add-col:hover{color:var(--coral)}
.group-col-header{position:relative;cursor:default}
.group-col-header:hover .group-col-remove{opacity:1}
.group-col-remove{position:absolute;top:2px;right:4px;background:none;border:none;color:var(--muted);cursor:pointer;font-size:10px;opacity:0;transition:opacity .15s;padding:0 2px}
.group-col-remove:hover{color:var(--coral)}
.group-inline-edit{background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:4px;color:var(--cream);font-family:var(--sans);font-size:11px;padding:3px 6px;outline:none;width:100%;max-width:120px;}
.group-inline-edit:focus{border-color:var(--coral)}

/* ─── Flat group view (spreadsheet style) ─────────────────────────────
   A single flat table: one sticky header row, all cards listed beneath
   it. Status pill in the first column; date cells get an urgency
   background (red for overdue / today, amber for the next 7 days).
   The flat view is the ONLY thing rendered into #workshopGroupView /
   #cwGroupView / #pbGroupView, so we zero those containers' padding
   completely (rule below this block). The wrapper then fills the
   full available space with no edge gaps. */
.group-view-flat{
  margin:0;
  height:100%;
  min-height:100%;
  overflow:hidden;
  display:flex;flex-direction:column
}
/* Pull the group-view container up so the table sits flush against the tab strip.
   FLAT mode only — grouped mode gets the kanban frame below. -6px matches the project
   tab strip's real 6px margin (the old -14px overlapped the strip by 8px). */
#workshopGroupView:not(:has(> .group-view-grouped)),
#cwGroupView:not(:has(> .group-view-grouped)),
#pbGroupView:not(:has(> .group-view-grouped)){
  padding:0 !important;
  margin-top:0
}
/* Line the flat List table up with the KANBAN pane exactly. #cwBoardView sits at
   margin-top/padding-top 0, so its first .kanban-col starts .workshop-views' 6px
   margin-bottom below the tab strip. The List pane used to be pulled up -6px and
   then its table re-added 14px, landing the header 8px LOWER than the columns.
   Scoped to the project List panes: the in-app admin tables reuse .gv-flat-table
   and keep their 14px inset. max-height drops 36px -> 22px because only the 22px
   bottom margin is left to account for. */
#workshopGroupView > .group-view-flat > .gv-flat-table,
#cwGroupView > .group-view-flat > .gv-flat-table,
#pbGroupView > .group-view-flat > .gv-flat-table{margin-top:0 !important;max-height:calc(100% - 22px)}
/* GROUPED mode: same envelope as the kanban pane (#workshopBoardView: 16px sides, 12px
   bottom, 0 top) so the group containers line up with the board columns exactly. */
#workshopGroupView:has(> .group-view-grouped),
#cwGroupView:has(> .group-view-grouped),
#pbGroupView:has(> .group-view-grouped){padding:0 16px 12px !important;margin-top:0}
/* The List panes never scroll sideways themselves. They are declared overflow-y:auto,
   and a box with one axis auto and the other visible computes BOTH to auto — so a wide
   table made the whole pane scroll horizontally, taking the tab strip's alignment and
   the row's left edge with it. Both List modes carry their own horizontal scroller
   (.gv-flat-table when flat, .group-view-grouped when grouped), so the pane can clip.
   Scoped to the List panes: Canvas is a freeform surface and keeps its own scrolling. */
#workshopGroupView,#cwGroupView,#pbGroupView{overflow-x:hidden}
.gv-flat-table{
  /* No top border — the workshop-views' border-bottom acts as the divider
     between the tab strip and the table. */
  border:0;border-radius:0;
  background:var(--surface-container);
  /* Horizontal + vertical scroll inside the wrapper. Header row stays
     sticky to the top so column labels never scroll off. */
  overflow:auto;
  flex:1;min-height:0
}
.gv-flat-header{
  display:grid;gap:0;
  background:var(--surface-container);
  border-bottom:1px solid var(--border-d);
  position:sticky;top:0;z-index:2;
  /* Same min-width strategy as rows — sum of grid track minimums. With
     fixed-width column tracks (no `fr`), this resolves identically to
     each row, so header + rows align column-for-column. */
  min-width:min-content
}
/* Inner shell — keeps header + rows in one block so they share a
   horizontal scroll envelope when the column total exceeds viewport. */
.gv-flat-shell{display:flex;flex-direction:column;min-width:min-content;width:100%}
.gv-flat-header .gv-flat-col{
  display:flex;align-items:center;justify-content:flex-start;text-align:left;
  padding:10px 14px;
  font-family:var(--sans);
  font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.6px;
  color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  border-right:1px solid var(--border-d);
  /* Click to sort, click-and-drag (>5px) to reorder. */
  cursor:pointer;
  user-select:none;-webkit-user-select:none;
  position:relative;
  transition:color .12s,background .12s
}
.gv-flat-header .gv-flat-col:hover{color:var(--cream);background:rgba(255,255,255,.04)}
/* The dragged column lifts visually — coral border + shadow — but its
   bounding box stays in the header row (Y axis is locked by the JS,
   which only sets translate3d on the X axis). */
.gv-flat-header .gv-flat-col.is-col-dragging{
  background:rgba(124,92,255,.10);
  color:var(--cream);
  cursor:grabbing;
  box-shadow:0 8px 22px rgba(0,0,0,.45),0 0 0 1px var(--coral) inset;
  border-radius:6px;
  z-index:20
}
/* The add-column (+) slot isn't draggable/sortable — kill its pointer cursor. */
.gv-flat-header .gv-flat-col.gv-flat-add{cursor:default}
.gv-flat-header .gv-flat-col.gv-flat-add:hover{background:transparent}
/* Show ↑/↓ sort indicator in coral when active. */
.gv-flat-header .gv-flat-col svg{vertical-align:middle}

/* Resize handle — thin invisible strip on the right edge of every
   header cell. Cursor turns to col-resize on hover; a coral line lights
   up while the user is actively dragging the handle so they can see
   exactly which column they're sizing. */
.gv-col-resize{
  position:absolute;top:0;right:-2px;bottom:0;
  width:8px;cursor:col-resize;z-index:5;
  /* Sit on top of the cell's right border. The line only paints on hover/active. */
  background:transparent;
  transition:background .12s
}
.gv-col-resize::after{
  content:'';position:absolute;top:0;bottom:0;left:3px;width:2px;
  background:transparent;border-radius:1px;
  transition:background .12s
}
.gv-col-resize:hover::after{background:rgba(124,92,255,.6)}
.gv-flat-col.is-col-resizing{
  background:rgba(124,92,255,.06)
}
.gv-flat-col.is-col-resizing .gv-col-resize::after{background:var(--coral)}
/* While any column is being resized, force col-resize cursor everywhere
   so the user gets continuous feedback even if their pointer drifts off
   the handle. */
body:has(.gv-flat-col.is-col-resizing){cursor:col-resize !important}
body:has(.gv-flat-col.is-col-resizing) *{cursor:col-resize !important;user-select:none}
.gv-flat-header .gv-flat-col:last-child{border-right:none}
.gv-flat-header .gv-flat-col.group-col-header{cursor:default;position:relative}
.gv-flat-header .gv-flat-col.group-col-header:hover .group-col-remove{opacity:1}
.gv-flat-add{display:flex;align-items:center;justify-content:center;padding:0 !important}
.gv-flat-add .group-add-col{padding:6px 8px}

.gv-flat-row{
  display:grid;gap:0;
  border-bottom:1px solid var(--border-d);
  transition:background .1s;cursor:pointer;
  /* min-width:min-content gives EVERY row the same minimum width =
     sum of each grid column's minimum size. Identical across rows
     regardless of content (no max-content-per-row drift), so the same
     grid-template-columns string resolves to identical column widths.
     The grid template uses fixed widths (no `fr`) so the resolved
     widths match between header + rows even at wider viewports. */
  min-width:min-content;
  /* Stable row height — any cell with multi-line content (e.g. wrapped
     tag pills) would otherwise stretch its row taller than its
     neighbours, producing a ragged table. Lock the row + force each
     cell to the same height so the grid stays even. */
  min-height:42px;align-items:stretch
}
.gv-flat-row:hover{background:rgba(255,255,255,.04)}
.gv-flat-row:last-child{border-bottom:none}
/* Multi-select state — mirrors .kanban-card.card-selected styling so
   the same Cmd/Shift/click conventions apply across the app. */
.gv-flat-row.row-selected{background:color-mix(in srgb, var(--coral) 14%, transparent);box-shadow:inset 3px 0 0 var(--coral)}
.gv-flat-row.row-selected:hover{background:color-mix(in srgb, var(--coral) 20%, transparent)}
.gv-flat-cell{
  padding:10px 14px;
  font-family:var(--sans);font-size:13px;color:var(--cream);
  display:flex;align-items:center;justify-content:flex-start;gap:6px;
  border-right:1px solid rgba(255,255,255,.04);
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis;
  text-align:left;
  min-height:42px;height:42px;box-sizing:border-box;
  position:relative;
  /* Empty-state dash should sit at the cell's left padding — same X
     position in every row, regardless of which cells around it are
     filled. Without an explicit left-anchor the flex centering of
     :empty inline spans (the muted "—" from renderPropertyValue)
     could appear to drift between rows. */
  line-height:1.4
}
.gv-flat-cell > *{flex-shrink:0}
.gv-flat-cell .prop-pill,
.gv-flat-cell > span,
.gv-flat-cell > div{min-width:0}
.gv-flat-cell:last-child{border-right:none}
.gv-flat-cell-title{font-size:13px;font-weight:500;display:flex;align-items:center;gap:8px}
.gv-flat-cell-title .group-table-cell{padding:0;display:contents}
/* Asana-style inline complete toggle in the list/group view. Faint circle by
   default, brightens on row hover, solid green check once complete. */
.gv-complete-toggle{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
  width:20px;height:20px;border-radius:50%;cursor:pointer;color:var(--muted);opacity:.4;
  transition:color .15s,opacity .15s,transform .12s}
.gv-flat-row:hover .gv-complete-toggle{opacity:.8}
.gv-complete-toggle:hover{color:var(--green,#86c06c);opacity:1;transform:scale(1.1)}
.gv-complete-toggle.is-done{color:var(--green,#86c06c);opacity:1}
.gv-flat-completed .gv-flat-cell-title{text-decoration:line-through;text-decoration-color:rgba(134,192,108,.85);text-decoration-thickness:2.5px}
.gv-flat-completed{opacity:.62}
.gv-flat-completed:hover{opacity:.85}

/* Status cell — the colored fill IS the cell. No inner pill container.
   Hover lifts the fill slightly so the user sees it's interactive. */
.gv-flat-cell-status{
  padding:8px 12px;
  font-family:var(--sans);font-size:13px;font-weight:500;line-height:1.4;
  text-transform:none;letter-spacing:0;
  cursor:pointer;
  transition:background .12s;
  overflow:hidden
}
.gv-flat-cell-status:hover .gv-status-text{
  background:color-mix(in srgb, var(--gv-status-color, #888) 30%, #1c1c20)
}
/* Status renders as a subtle dark pill tinted by the status color (was bright gold text — hard to read). */
.gv-status-text{
  display:inline-block;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  vertical-align:middle;
  padding:5px 10px;border-radius:6px;font-weight:600;
  background:color-mix(in srgb, var(--gv-status-color, #888) 20%, #1c1c20);
  color:var(--gv-status-color, var(--cream))
}

/* Other editable cells — show a subtle inset coral outline on hover so
   the affordance is obvious without painting a background tint that
   makes the cell look misaligned against its neighbors. The outline
   is inset (box-shadow inset) so it doesn't affect layout. */
.gv-flat-cell-editable{cursor:pointer;transition:box-shadow .1s}
.gv-flat-cell-editable:hover{box-shadow:inset 0 0 0 1.5px rgba(124,92,255,.55)}
.gv-flat-cell-editable.gv-edit-open{box-shadow:inset 0 0 0 1.5px var(--coral)}

/* ── Inline edit popovers (status picker, date editor, select picker) ── */
.gv-edit-popover{
  /* Fill/blur/border/shadow come from the shared liquid-glass rule at the end of
     this file — this is a floating menu like every other one (Design Rules ▸
     Liquid glass). Only geometry lives here. */
  border-radius:10px;
  padding:5px;min-width:200px;max-width:280px;max-height:50vh;overflow-y:auto;
  font-family:var(--sans);
  animation:gvEditPopIn .14s ease-out both
}
@keyframes gvEditPopIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.gv-person-editor{max-height:300px;overflow-y:auto}
.gv-person-editor .gv-sp-row .card-avatar{flex:0 0 auto}
.gv-edit-popover .gv-sp-row{
  display:flex;align-items:center;gap:9px;
  width:100%;padding:8px 11px;border-radius:6px;
  background:none;border:0;color:var(--cream);
  font-size:13px;font-weight:500;text-align:left;
  font-family:var(--sans);
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:background .12s
}
.gv-edit-popover .gv-sp-row:hover{background:rgba(255,255,255,.06)}
.gv-edit-popover .gv-sp-row.is-active{
  background:color-mix(in srgb, var(--gv-row-color, #888) 14%, transparent);
  color:var(--gv-row-color, var(--cream))
}
.gv-edit-popover .gv-sp-dot{
  width:10px;height:10px;border-radius:50%;flex-shrink:0;
  background:var(--gv-row-color, #888);
  box-shadow:0 0 0 2px color-mix(in srgb, var(--gv-row-color, #888) 25%, transparent)
}
.gv-edit-popover .gv-sp-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Date / text editor wrappers */
.gv-edit-popover.gv-date-editor,
.gv-edit-popover.gv-text-editor{padding:10px;display:flex;flex-direction:column;gap:8px;min-width:260px}
.gv-edit-popover.gv-date-editor{min-width:280px}
.gv-edit-popover .gv-date-row{display:flex;gap:6px;align-items:center}
.gv-edit-popover .gv-date-input,
.gv-edit-popover .gv-text-input{
  flex:1;min-width:0;
  width:100%;font-size:13px;color:var(--cream);
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);
  border-radius:7px;padding:8px 10px;outline:none;
  transition:border-color .12s,background .12s
}
.gv-edit-popover .gv-date-input:focus,
.gv-edit-popover .gv-text-input:focus{
  border-color:var(--coral);
  outline:none !important;
  box-shadow:0 0 0 2px rgba(124,92,255,.18) !important;
  -webkit-tap-highlight-color:transparent
}
/* Suppress browser-default blue focus rings everywhere inside the
   popover — Safari/Chrome paint a system-blue glow on inputs/buttons
   when focused which doesn't match the app's coral palette. */
.gv-edit-popover input,
.gv-edit-popover button,
.gv-edit-popover [contenteditable]{
  outline:none !important;
  -webkit-tap-highlight-color:transparent
}
.gv-edit-popover input:focus,
.gv-edit-popover button:focus,
.gv-edit-popover [contenteditable]:focus,
.gv-edit-popover input:focus-visible,
.gv-edit-popover button:focus-visible,
.gv-edit-popover [contenteditable]:focus-visible{
  outline:none !important;box-shadow:none
}
.gv-edit-popover .gv-date-input:focus,
.gv-edit-popover .gv-text-input:focus{
  /* keep our custom coral glow above */
  box-shadow:0 0 0 2px rgba(124,92,255,.18) !important
}
.gv-edit-popover .gv-date-input.is-invalid{
  border-color:#f87171;animation:gvDateShake .35s ease-in-out
}
@keyframes gvDateShake{
  0%,100%{transform:translateX(0)}
  20%,60%{transform:translateX(-3px)}
  40%,80%{transform:translateX(3px)}
}
.gv-edit-popover .gv-date-cal-toggle{
  appearance:none;background:rgba(255,255,255,.04);border:1px solid var(--border-d);
  color:var(--muted);cursor:pointer;
  width:34px;height:34px;border-radius:7px;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .12s,color .12s,border-color .12s
}
.gv-edit-popover .gv-date-cal-toggle:hover,
.gv-edit-popover .gv-date-cal-toggle.is-active{
  background:rgba(124,92,255,.12);border-color:var(--coral);color:var(--coral)
}

/* ─── Custom month-grid calendar (dark themed, matches app) ─────────
   Sits BELOW the date input inside the same popover so it never covers
   the field being edited. */
.gv-edit-popover .gv-date-cal{
  margin-top:2px;padding:8px;
  background:rgba(255,255,255,.025);border:1px solid var(--border-d);border-radius:9px
}
.gv-cal-head{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:2px 4px 8px
}
.gv-cal-month{font-size:13px;font-weight:700;color:var(--cream);letter-spacing:-.1px}
.gv-cal-nav{
  appearance:none;background:none;border:0;color:var(--muted);cursor:pointer;
  width:28px;height:28px;border-radius:6px;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .12s,color .12s
}
.gv-cal-nav:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.gv-cal-dow{
  display:grid;grid-template-columns:repeat(7,1fr);
  text-align:center;font-size:9px;font-weight:700;text-transform:uppercase;
  letter-spacing:.4px;color:var(--muted);padding:0 0 4px
}
.gv-cal-grid{
  display:grid;grid-template-columns:repeat(7,1fr);gap:2px
}
.gv-cal-day{
  appearance:none;background:none;border:0;color:var(--cream);
  font-size:12px;font-weight:500;font-family:var(--sans);
  height:30px;border-radius:6px;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .1s,color .1s,box-shadow .1s
}
.gv-cal-day:hover{background:var(--state-hover)}
.gv-cal-day.is-other{color:rgba(255,255,255,.25)}
.gv-cal-day.is-other:hover{background:rgba(255,255,255,.05);color:rgba(255,255,255,.5)}
.gv-cal-day.is-today{
  color:var(--coral);font-weight:700;
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--coral) 50%, transparent)
}
.gv-cal-day.is-selected{
  background:var(--coral);color:#fff;font-weight:700;
  box-shadow:0 2px 6px rgba(124,92,255,.4)
}
.gv-cal-day.is-selected:hover{background:#d44e2a}
.gv-cal-foot{
  display:flex;justify-content:flex-end;padding-top:6px;margin-top:6px;
  border-top:1px solid var(--border-d)
}
.gv-cal-today{
  appearance:none;background:none;border:0;
  color:var(--coral);cursor:pointer;
  font-size:12px;font-weight:600;font-family:var(--sans);
  padding:5px 10px;border-radius:6px;
  transition:background .12s
}
.gv-cal-today:hover{background:rgba(124,92,255,.1)}.gv-edit-popover .gv-edit-actions{display:flex;gap:6px;justify-content:flex-end;padding-top:2px}
.gv-edit-popover .gv-edit-clear,
.gv-edit-popover .gv-edit-done{
  appearance:none;border:0;background:transparent;
  color:var(--muted);cursor:pointer;
  padding:7px 14px;border-radius:6px;font-size:12px;font-weight:500;
  font-family:var(--sans);
  transition:background .12s,color .12s
}
.gv-edit-popover .gv-edit-clear:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.gv-edit-popover .gv-edit-done{background:var(--coral);color:#fff;font-weight:600}
.gv-edit-popover .gv-edit-done:hover{background:#d44e2a}

/* Mobile: full-width bottom sheet for inline editors so taps don't land
   off-screen on narrow viewports. */
body[data-mobile-mode="app"] .gv-edit-popover{
  left:12px !important;right:12px !important;
  bottom:calc(20px + env(safe-area-inset-bottom,0px)) !important;
  top:auto !important;
  max-width:none !important;width:auto !important;
  border-radius:14px;
  animation:gvEditPopInMobile .2s cubic-bezier(.22,1,.36,1) both
}
@keyframes gvEditPopInMobile{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}

/* Date-urgency tints — a soft colored fill behind the date string so
   the user can see the date column's status at a glance. Matches the
   reference image's red/amber date columns. */
/* Mockup → due dates are plain COLORED TEXT (soft coral), no filled cell blocks. */
.gv-flat-cell-date.gv-flat-cell-overdue{ background:none;color:var(--danger-text);font-weight:500 }
.gv-flat-cell-date.gv-flat-cell-today{ background:none;color:#fda4af;font-weight:500 }
.gv-flat-cell-date.gv-flat-cell-soon{ background:none;color:#fda4af;font-weight:500 }
.gv-flat-cell-date.gv-flat-cell-overdue *,
.gv-flat-cell-date.gv-flat-cell-today *,
.gv-flat-cell-date.gv-flat-cell-soon *{color:inherit !important}

.gv-flat-empty{
  padding:30px 16px;text-align:center;
  color:var(--muted);font-size:13px
}
.gv-flat-add-row{
  padding:11px 14px;font-size:13px;color:var(--muted);
  cursor:pointer;transition:color .15s,background .12s;
  border-top:1px solid var(--border-d)
}
.gv-flat-add-row:hover{color:var(--coral);background:rgba(255,255,255,.02)}

/* (Responsive overrides not needed — the container padding is zeroed
   at every breakpoint via the !important rule above.) */

/* Mobile flat-table tweaks — keep horizontal scroll, smaller padding */
body[data-mobile-mode="app"] .gv-flat-table{border-radius:0;border-left:0;border-right:0}
body[data-mobile-mode="app"] .gv-flat-header .gv-flat-col{padding:9px 10px;font-size:11px}
body[data-mobile-mode="app"] .gv-flat-cell{padding:9px 10px;font-size:13px;min-height:40px}
body[data-mobile-mode="app"] .gv-flat-cell-title{font-size:14px}
body[data-mobile-mode="app"] .gv-status-pill{font-size:10px;padding:3px 8px}/* Journal view */
.journal-view{max-width:800px}
.journal-new{display:flex;gap:8px;margin-bottom:18px}
.journal-new-btn{padding:8px 18px;border:1px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.06);font-family:var(--sans);font-size:12px;font-weight:500;color:var(--cream);cursor:pointer;transition:all .15s}
.journal-new-btn:hover{border-color:var(--coral);color:var(--coral)}
.journal-entries{display:flex;flex-direction:column;gap:10px}
.journal-entry{border:1px solid var(--border-d);border-radius:8px;padding:16px 18px;transition:background .15s;cursor:pointer}
.journal-entry:hover{background:rgba(255,255,255,.03)}
.journal-entry-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.journal-entry-date{font-size:11px;color:var(--muted);font-family:var(--sans)}
.journal-entry-title{font-size:14px;font-weight:600;color:var(--cream)}
.journal-entry-preview{font-size:12px;color:var(--muted);line-height:1.6;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}
.journal-entry.expanded .journal-entry-preview{display:block;-webkit-line-clamp:unset;overflow:visible}
.journal-entry-actions{display:flex;gap:8px;margin-top:10px;padding-top:10px;border-top:1px solid var(--border-d)}
.journal-entry-actions button{background:none;border:none;font-family:var(--sans);font-size:11px;color:var(--muted);cursor:pointer;padding:2px 6px;transition:color .15s}
.journal-entry-actions button:hover{color:var(--coral)}
.journal-editor{border:1px solid var(--border-d);border-radius:8px;padding:16px 18px;margin-bottom:14px;background:rgba(255,255,255,.02)}
.journal-editor input{display:block;width:100%;background:none;border:none;outline:none;font-family:var(--serif);font-size:20px;color:var(--cream);padding:0 0 10px;border-bottom:1px solid var(--border-d);margin-bottom:10px}
.journal-editor input::placeholder{color:var(--muted)}
.journal-editor .journal-body-wrap{position:relative}
.journal-editor .card-modal-description{min-height:150px;max-height:340px}
.journal-editor .card-desc-toolbar-bar .desc-tb-btn{color:rgba(255,255,255,.24)}
.journal-editor .card-desc-toolbar-bar .desc-tb-btn:hover{color:rgba(255,255,255,.55)}
.journal-upload-status{font-size:11px;color:var(--muted);margin-left:5px}
.journal-editor-btns{display:flex;gap:8px;margin-top:12px;justify-content:flex-end}
.journal-editor-btns button{padding:7px 16px;border-radius:6px;font-family:var(--sans);font-size:12px;cursor:pointer;transition:all .15s}
.journal-editor-btns .journal-save{background:var(--coral);color:var(--white);border:none;font-weight:600}
.journal-editor-btns .journal-save:hover{opacity:.85}
.journal-editor-btns .journal-cancel{background:none;border:1px solid var(--border-d);color:var(--muted)}
.journal-editor-btns .journal-cancel:hover{color:var(--cream);border-color:rgba(255,255,255,.2)}
/* Custom field modal */
.field-modal-overlay{position:fixed;inset:0;z-index:10100;background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px)}
.field-modal{background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:24px;max-width:340px;width:100%}
.field-modal h3{font-family:var(--serif);font-size:18px;margin-bottom:14px;color:var(--cream)}
.field-modal label{display:block;font-size:11px;color:var(--muted);margin-bottom:4px;margin-top:10px}
.field-modal select,.field-modal input{display:block;width:100%;padding:8px 10px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);font-family:var(--sans);font-size:12px;outline:none;}
.field-modal select:focus,.field-modal input:focus{border-color:var(--coral)}

/* LOGS PANEL */
.logs-panel{font-family:var(--sans);font-size:12px;line-height:1.7;background:var(--dark);border-radius:10px;padding:16px 20px;min-height:300px;max-height:calc(100vh - 280px);overflow-y:auto;color:var(--cream)}
.log-line{padding:3px 0;border-bottom:1px solid rgba(255,255,255,.03);display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.log-line .log-ts{color:var(--muted);flex-shrink:0;min-width:70px;font-size:11px}
.log-line .log-msg{flex:1;word-break:break-word;min-width:120px}
.log-level-badge{font-size:9px;font-weight:700;letter-spacing:.5px;padding:1px 5px;border-radius:3px;flex-shrink:0;text-align:center;min-width:36px;display:inline-block}
.log-level-badge.log-error{background:rgba(239,68,68,.15);color:var(--danger-text)}
.log-level-badge.log-warn{background:rgba(231,206,58,.12);color:var(--gold)}
.log-level-badge.log-info{background:rgba(115,172,131,.12);color:var(--green)}
.log-line.log-error .log-msg{color:var(--coral)}
.log-line.log-warn .log-msg{color:var(--gold)}
.log-line.log-info .log-msg{color:var(--green)}
.log-meta{color:var(--muted);font-size:10px;background:rgba(255,255,255,.04);padding:1px 5px;border-radius:3px;margin-right:4px;max-width:45%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}
.logs-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.logs-header h3{font-family:var(--serif);font-size:18px;font-weight:400}
.logs-refresh-btn{background:rgba(255,255,255,.06);border:1px solid var(--border-d);color:var(--muted);font-size:11px;padding:5px 12px;border-radius:6px;cursor:pointer;font-family:var(--sans);transition:all .15s}
.logs-refresh-btn:hover{color:var(--off-white);background:rgba(255,255,255,.1)}

/* MOBILE */
.mobile-toggle{display:none;position:fixed;top:12px;left:12px;z-index:200;width:44px;height:44px;border-radius:10px;background:var(--dark);border:1px solid var(--border-d);cursor:pointer;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.4)}
.mobile-toggle span{display:block;width:18px;height:2px;background:var(--white);border-radius:2px;position:relative}
.mobile-toggle span::before,.mobile-toggle span::after{content:'';position:absolute;left:0;width:100%;height:2px;background:var(--white);border-radius:2px}
.mobile-toggle span::before{top:-5px}.mobile-toggle span::after{top:5px}
.sidebar-close{display:none;width:44px;height:44px;border-radius:8px;border:1px solid var(--border-d);background:rgba(255,255,255,.06);color:var(--cream);font-size:20px;line-height:1;cursor:pointer;align-items:center;justify-content:center;transition:background .15s}
.sidebar-close:hover{background:rgba(255,255,255,.12)}
.sidebar-overlay{display:none;position:fixed;inset:0;z-index:99;background:rgba(0,0,0,.5);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}
.sidebar.open+.sidebar-overlay{display:block}

@media(max-width:900px){
  .sidebar{transform:translateX(-100%)}
  .sidebar.open{transform:translateX(0);box-shadow:0 0 60px rgba(0,0,0,.6)}
  .main{margin-left:0}
  .board-bottom-fade{left:0;height:170px}
  .mobile-toggle{display:flex}
  .sidebar-close{display:flex;position:absolute;top:12px;right:12px}
  .topbar{padding:0 16px 0 66px;height:52px}
  .profile-trigger{padding:5px}
  .profile-trigger-meta,.profile-chevron{display:none}
  .profile-dropdown{width:min(300px,calc(100vw - 28px));right:-6px}
  .content{padding:20px 16px 60px}
  #workshopBoardView,#pbBoardView,#cwBoardView{padding-bottom:170px}
  .stats{grid-template-columns:1fr 1fr}
  .panels{grid-template-columns:1fr}
  .kanban{overflow-x:auto;flex-direction:row;-webkit-overflow-scrolling:touch;padding-bottom:12px}
  .kanban-col{min-width:260px;max-width:260px;flex-shrink:0}
  .quick-links{grid-template-columns:1fr}
  .group-table{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .calendar-day{min-height:60px}
  .sidebar-nav a{min-height:44px}
  #page-chatroom.active{margin:-20px -16px -60px;height:calc(100% + 80px)}
  .hub-chat{height:calc(100dvh - 240px)}
}
@media(max-width:768px){
  .content{padding:16px 12px 80px}
  #page-chatroom.active{margin:-16px -12px -80px;height:calc(100% + 96px)}
  .topbar{padding:0 12px 0 66px}
  .stats{gap:10px}
  .card-modal-overlay{padding:0;align-items:flex-end}
  .card-modal{max-width:100%;max-height:92vh;max-height:92dvh;max-height:92svh;border-radius:14px 14px 0 0;padding:20px 16px}
  .card-modal-title{font-size:18px;white-space:normal}
  .table-shell th{padding:8px 10px;font-size:10px}
  .table-shell td{padding:8px 10px;font-size:12px}
  .group-table{font-size:11px}
}
@media(max-width:500px){
  .stats{grid-template-columns:1fr}
}
/* Touch-friendly tap targets */
@media(hover:none) and (pointer:coarse){
  .sidebar-nav a{min-height:44px}
  .topbar-btn{min-height:44px;padding-left:14px;padding-right:14px}
  .kanban-add{min-height:44px;display:flex;align-items:center}
  .app-close-btn{width:44px;height:44px}
  .kanban-card{padding:12px}
  .content,.sidebar,.card-modal{-webkit-overflow-scrolling:touch}
}
/* ==================== MOBILE APP-SHELL MODE ==================== */
/* Activated when body[data-mobile-mode="app"] is set (auto by initMobileApp
   below 768px). Hides desktop chrome, shows the bottom-nav + drawer +
   dashboard pattern that matches the mockups. */
/* ============================================================================
   MOBILE UI REBUILD (2026-07) — reference design-token vocabulary.
   The redesign mockup uses an rgba(var(--ink),α) text-hierarchy plus a
   --surface / --bg / --bg2 / --line surface system. We introduce those token
   NAMES here, scoped to body[data-mobile-mode="app"], so DESKTOP IS UNTOUCHED.
   Dark is the default; the html[data-theme="light"] variant supplies the
   light values. Pixel display fonts (Silkscreen / Pixelify Sans) drive the
   retro micro-labels. --purple / --prio-high already match the mockup's
   #7c5cff / #ff6b6b so we alias rather than redefine them.
   ============================================================================ */
body[data-mobile-mode="app"]{
  --ink:235,235,245;            /* primary text as rgb → rgba(var(--ink),α) */
  --ink-solid:#f2f2f5;          /* fully-opaque primary text */
  --line:255,255,255;           /* hairline / border rgb → rgba(var(--line),α) */
  --bg:#0d0d10;                 /* app page background */
  --bg2:#09090b;                /* deepest screen background (behind blur) */
  --bg3:#26262c;                /* raised background */
  --surface:#1a1a1f;            /* card / sheet surface */
  --surface-rgb:26,26,31;       /* surface as rgb for translucency */
  --bg2-rgb:9,9,11;             /* --bg2 as rgb (mockup header/sheet blur) */
  --m-accent:#7c5cff;           /* brand purple (== --purple) */
  --m-accent-soft:#a78bfa;      /* soft purple — pills, active icons */
  --m-overdue:#ff6b6b;          /* overdue / high-priority red (== --prio-high) */
  /* Bottom hotbar selection travel. Longer + springier than the top tab strips
     (--tab-slide-dur) because the pill crosses the full width of the screen, so the
     same 300ms reads as a jump rather than a glide. */
  --m-hotbar-slide-dur:380ms;
  --m-hotbar-slide-ease:cubic-bezier(.34,1.4,.44,1);
  --pixel:var(--font-pixel);     /* uppercase micro-labels */
  --pixel-id:var(--font-pixel);  /* ids / tags */
}
html[data-theme="light"] body[data-mobile-mode="app"]{
  --ink:28,28,33;
  --ink-solid:#17171b;
  --line:0,0,0;
  --bg:#e9e9ec;
  --bg2:#f4f4f6;
  --bg3:#dcdce2;
  --surface:#ffffff;
  --surface-rgb:255,255,255;
  --bg2-rgb:244,244,246;
}
.m-app-header,.m-app-home,.m-drawer,.m-drawer-backdrop,.m-bottom-nav{display:none}
body[data-mobile-mode="app"] .sidebar,
body[data-mobile-mode="app"] .topbar,
body[data-mobile-mode="app"] .mobile-toggle,
body[data-mobile-mode="app"] #rightSidebar,
body[data-mobile-mode="app"] .members-panel,
body[data-mobile-mode="app"] .global-right-sidebar{display:none !important}
body[data-mobile-mode="app"] .main{margin-left:0 !important}
body[data-mobile-mode="app"] .content{padding:0 !important}
body[data-mobile-mode="app"] .m-app-header{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  position:fixed;top:0;left:0;right:0;z-index:50;
  padding:12px 16px;padding-top:calc(12px + env(safe-area-inset-top,0px));
  /* #6 Liquid Glass — translucent so content scrolls visibly under the heavy blur,
     a hairline inner stroke up top + a soft drop shadow below. */
  background:rgba(10,10,9,.55);
  backdrop-filter:blur(40px) saturate(180%);-webkit-backdrop-filter:blur(40px) saturate(180%);
  border-bottom:1px solid var(--border-d);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),0 6px 24px rgba(0,0,0,.22);
  min-height:var(--m-topbar-h)
}
/* Header brand: the workspace pfp circle acts as the menu button (no
   separate hamburger). The title shows the workspace's company name
   (e.g. "Sauce Media", "RealRealJapan"), centered. */
.m-app-pfp-btn{
  appearance:none;background:none;border:0;padding:0;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  flex-shrink:0;display:inline-flex;align-items:center;justify-content:center
}
.m-app-pfp{
  width:32px;height:32px;border-radius:50%;            /* mockup: 32px */
  display:inline-flex;align-items:center;justify-content:center;
  overflow:hidden;background:transparent;color:#fff;
  font-size:13px;font-weight:700;letter-spacing:.3px;
  transition:transform .12s
}
.m-app-pfp-btn:active .m-app-pfp{transform:scale(.92)}
.m-app-pfp:not(:has(img)){
  background:linear-gradient(135deg,#7c3aed,#a78bfa);
  box-shadow:0 0 0 1px rgba(255,255,255,.08) inset
}
.m-app-pfp img{width:100%;height:100%;object-fit:cover;border-radius:50%}
/* Tiny workspace icon inline before the workspace name: [icon] Sauce Media ⌄ */
.m-app-brand-icon{
  flex-shrink:0;width:22px;height:22px;border-radius:50%;overflow:hidden;   /* mockup: 22px circle */
  display:inline-flex;align-items:center;justify-content:center;
  font-size:9px;font-weight:700;letter-spacing:.2px;color:#fff;line-height:1;
  background:linear-gradient(140deg,#8b5cf6,#6366f1)
}
.m-app-brand-icon:has(img){background:none;box-shadow:none}
.m-app-brand-icon img{width:100%;height:100%;object-fit:cover}
.m-app-brand-icon:empty{display:none}
.m-app-header-brand{flex:1;display:flex;align-items:center;min-width:0;justify-content:center;position:relative}
/* 32 — IG-style switcher trigger: workspace name + chevron, comfortable 44pt tap target. */
.m-app-brand-trigger{display:inline-flex;align-items:center;gap:5px;max-width:100%;background:none;border:0;padding:10px 8px;min-height:44px;cursor:pointer;color:var(--cream);-webkit-tap-highlight-color:transparent}
.m-app-brand-trigger:active{opacity:.7}
/* 33 — kill the box: the shared .client-switch-trigger (defined later) adds a bg+border+radius
   pill, which we DON'T want on the mobile header. Bare text + chevron on the header bg. */
body[data-mobile-mode="app"] .m-app-brand-trigger.client-switch-trigger{background:none;border:0;border-radius:0;max-width:none;padding:10px 8px;font-size:16px;color:var(--ink-solid)}
body[data-mobile-mode="app"] .m-app-brand-trigger.client-switch-trigger:hover{background:none}
.m-app-brand-chev{width:15px;height:15px;flex-shrink:0;opacity:.75;transition:transform .22s cubic-bezier(.34,1.56,.64,1)}
.client-switch-wrap.open .m-app-brand-chev{transform:rotate(180deg)}
.m-app-header-title{
  font-size:16px;font-weight:600;color:var(--ink-solid);letter-spacing:.2px;   /* mockup: 600 16px */
  line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px
}
.m-app-header-actions{display:flex;align-items:center;gap:4px;min-width:40px;justify-content:flex-end}
.m-app-header-btn-left{margin-right:auto}
.m-app-header-btn{
  position:relative;width:40px;height:40px;border-radius:10px;
  background:none;border:0;color:var(--cream);cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .12s
}
.m-app-header-btn svg{width:22px;height:22px}
.m-app-header-btn:hover{background:rgba(255,255,255,.06)}
.m-app-header-btn.has-dot::after{
  content:'';position:absolute;top:9px;right:9px;width:8px;height:8px;
  border-radius:50%;background:var(--coral);border:2px solid #0a0a09
}
/* Mobile dashboard intentionally disabled — Overview is the landing. The
   element is gone from the DOM; these rules are kept defensively as a
   no-op so any stale references can't accidentally surface it. */
body[data-mobile-mode="app"] .m-app-home{display:none !important}
.m-app-home-greeting{padding:4px 4px 6px}
.m-app-greeting-name{font-size:24px;font-weight:700;color:var(--cream);margin:0 0 6px;line-height:1.15;letter-spacing:-.3px}
.m-app-greeting-sub{font-size:14px;color:var(--muted);margin:0;line-height:1.4}
.m-app-stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.m-stat-card{
  display:flex;align-items:center;gap:12px;padding:14px;
  background:rgba(255,255,255,.03);border:1px solid var(--border-d);
  border-radius:14px;cursor:pointer;transition:background .12s,transform .08s;
  -webkit-tap-highlight-color:transparent
}
.m-stat-card:active{transform:scale(.98);background:rgba(255,255,255,.05)}
.m-stat-card-icon{
  width:42px;height:42px;border-radius:11px;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center
}
.m-stat-card-icon svg{width:20px;height:20px}
.m-stat-card-icon.violet{background:rgba(139,92,246,.16);color:#a78bfa}
.m-stat-card-icon.amber{background:rgba(245,158,11,.16);color:#fbbf24}
.m-stat-card-icon.green{background:rgba(34,197,94,.14);color:#4ade80}
.m-stat-card-icon.red{background:rgba(239,68,68,.16);color:#f87171}
.m-stat-card-meta{display:flex;flex-direction:column;min-width:0}
.m-stat-card-num{font-size:22px;font-weight:700;color:var(--cream);line-height:1}
.m-stat-card-label{font-size:12px;color:var(--muted);margin-top:3px;letter-spacing:.1px}
.m-app-card{
  background:rgba(255,255,255,.025);border:1px solid var(--border-d);
  border-radius:16px;overflow:hidden
}
.m-app-card-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:16px 16px 4px
}
.m-app-card-title{font-size:15px;font-weight:600;color:var(--cream)}
.m-app-card-title-sub{font-size:12px;font-weight:400;color:var(--muted);margin-left:4px}
.m-app-card-link{font-size:12px;font-weight:500;color:var(--coral);cursor:pointer}
.m-app-card-body{padding:8px 12px 14px;display:flex;flex-direction:column}
.m-task-row{
  display:flex;align-items:center;gap:12px;padding:11px 8px;
  border-radius:10px;cursor:pointer;transition:background .1s;
  -webkit-tap-highlight-color:transparent
}
.m-task-row:not(:last-child){border-bottom:1px solid rgba(255,255,255,.04)}
.m-task-row:active{background:rgba(255,255,255,.05)}
.m-task-row-icon{
  width:34px;height:34px;border-radius:9px;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.06);overflow:hidden;font-size:18px
}
.m-task-row-icon img{width:100%;height:100%;object-fit:cover;border-radius:9px}
.m-task-row-time{
  font-size:12px;color:var(--muted);font-weight:500;
  min-width:62px;text-align:left;flex-shrink:0
}
.m-task-row-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.m-task-row-title{font-size:14px;font-weight:500;color:var(--cream);line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-task-row-sub{font-size:12px;color:var(--muted);line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-task-row-pill{
  font-size:9px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  padding:3px 8px;border-radius:6px;white-space:nowrap;flex-shrink:0
}
.m-task-row-pill.due{background:rgba(245,158,11,.15);color:#fbbf24}
.m-task-row-pill.overdue{background:rgba(239,68,68,.15);color:#f87171}
.m-task-row-empty{padding:24px 12px;text-align:center;color:var(--muted);font-size:12px}
.m-app-more-btn{
  display:flex;align-items:center;justify-content:center;gap:6px;
  width:calc(100% - 16px);margin:6px 8px 4px;padding:10px;
  border-radius:10px;background:rgba(255,255,255,.04);
  border:0;color:var(--cream);font-size:13px;font-weight:500;
  cursor:pointer;-webkit-tap-highlight-color:transparent
}
.m-app-more-btn:active{background:rgba(255,255,255,.07)}
/* Drawer */
body[data-mobile-mode="app"] .m-drawer-backdrop{
  display:block;position:fixed;inset:0;z-index:90;
  background:rgba(0,0,0,.55);backdrop-filter:blur(2px);
  opacity:0;pointer-events:none;transition:opacity .18s ease
}
body[data-mobile-mode="app"][data-drawer="open"] .m-drawer-backdrop{
  opacity:1;pointer-events:auto
}
body[data-mobile-mode="app"] .m-drawer{
  display:flex;flex-direction:column;
  position:fixed;top:0;left:0;bottom:0;width:min(320px,86vw);
  background:#0a0a09;border-right:1px solid var(--border-d);
  z-index:100;transform:translateX(-100%);
  transition:transform .22s cubic-bezier(.22,1,.36,1);
  padding-bottom:env(safe-area-inset-bottom,0px);
  overflow:hidden
}
body[data-mobile-mode="app"][data-drawer="open"] .m-drawer{transform:translateX(0)}
/* Server banner — gradient (or workspace banner image) with a fade-to-dark
   strip at the bottom so the server pfp + name sit cleanly on top. The
   close button floats top-right. */
.m-drawer-banner{
  position:relative;flex-shrink:0;width:100%;height:96px;
  background:linear-gradient(135deg,#1a0a2e 0%,#16213e 30%,#0f3460 60%,#533483 100%);
  background-size:cover;background-position:center;
  padding-top:env(safe-area-inset-top,0px)
}
.m-drawer-banner-fade{
  position:absolute;left:0;right:0;bottom:0;height:48px;
  background:linear-gradient(to bottom,transparent,#0a0a09);pointer-events:none
}
.m-drawer-close{
  position:absolute;top:calc(8px + env(safe-area-inset-top,0px));right:8px;
  width:36px;height:36px;border:0;border-radius:50%;
  background:rgba(0,0,0,.4);backdrop-filter:blur(8px);
  color:var(--cream);cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;
  -webkit-tap-highlight-color:transparent;z-index:2
}
.m-drawer-close svg{width:18px;height:18px}
.m-drawer-close:hover{background:rgba(0,0,0,.6)}
/* Server pfp circle + name block — sits just below the banner, slightly
   overlapping (negative margin-top). Transparent bg so the icon image
   reads cleanly; falls back to a bordered monogram when no image. */
.m-drawer-server-block{
  display:flex;align-items:center;gap:12px;
  padding:0 14px 14px;margin-top:-22px;position:relative;z-index:1;
  flex-shrink:0
}
.m-drawer-server-icon{
  width:54px;height:54px;border-radius:50%;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:transparent;color:#fff;
  font-size:16px;font-weight:700;letter-spacing:.3px;
  overflow:hidden;
  /* Subtle ring so the circle reads against the banner edge it overlaps. */
  border:3px solid #0a0a09;
  box-shadow:0 4px 14px rgba(0,0,0,.4)
}
.m-drawer-server-icon:not(:has(img)){
  background:linear-gradient(135deg,#7c3aed,#a78bfa)
}
.m-drawer-server-icon img{width:100%;height:100%;object-fit:cover;border-radius:50%}
.m-drawer-server-meta{display:flex;flex-direction:column;gap:2px;min-width:0;padding-top:18px}
.m-drawer-server-name{font-size:16px;font-weight:700;color:var(--cream);line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-drawer-server-sub{font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-drawer-nav{
  flex:1;overflow-y:auto;padding:8px;
  display:flex;flex-direction:column;gap:2px;
  border-top:1px solid var(--border-d);margin-top:4px
}
.m-drawer-section{
  font-size:10px;font-weight:700;letter-spacing:1.3px;
  text-transform:uppercase;color:var(--muted);
  padding:14px 12px 6px
}
.m-drawer-item{
  display:flex;align-items:center;gap:12px;
  padding:12px 12px;border-radius:10px;
  background:none;border:0;color:var(--off-white);
  font-size:14px;font-weight:500;text-align:left;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:background .1s
}
.m-drawer-item svg{width:20px;height:20px;flex-shrink:0;color:var(--muted)}
.m-drawer-item:hover{background:rgba(255,255,255,.05)}
.m-drawer-item:active{background:var(--state-hover)}
.m-drawer-item.active{background:rgba(139,92,246,.13);color:#c4b5fd}
.m-drawer-item.active svg{color:#a78bfa}
/* Workspace icons in the nav list — circle, transparent bg, falls back to
   monogram only when no image. */
.m-drawer-item-icon{
  width:28px;height:28px;border-radius:50%;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  overflow:hidden;background:transparent;
  font-size:11px;font-weight:700;color:var(--cream)
}
.m-drawer-item-icon:not(:has(img)){
  background:rgba(255,255,255,.06);border:1px solid var(--border-d)
}
.m-drawer-item-icon img{width:100%;height:100%;object-fit:cover;border-radius:50%}
.m-drawer-profile{
  display:flex;align-items:center;gap:12px;
  margin:8px;padding:12px;border-radius:12px;
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);
  cursor:pointer;-webkit-tap-highlight-color:transparent
}
.m-drawer-profile-avatar{
  width:38px;height:38px;border-radius:50%;
  background:rgba(255,255,255,.08);overflow:hidden;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center
}
.m-drawer-profile-avatar img{width:100%;height:100%;object-fit:cover}
.m-drawer-profile-meta{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.m-drawer-profile-name{font-size:13px;font-weight:600;color:var(--cream);line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-drawer-profile-status{font-size:11px;color:var(--muted);display:inline-flex;align-items:center;gap:5px}
.m-drawer-profile-dot{width:7px;height:7px;border-radius:50%;background:#22c55e}
/* Bottom nav */
body[data-mobile-mode="app"] .m-bottom-nav{
  display:flex;align-items:center;justify-content:space-around;
  position:fixed;bottom:0;left:0;right:0;z-index:60;
  padding:8px 8px calc(8px + env(safe-area-inset-bottom,0px));
  /* #6 Liquid Glass — same translucent material as the top header so the hotbar (and all its
     variants: default Home/Projects/Settings, switcher Add/Back/Manage, task-open + project-open
     bars — all this one element with swapped contents) reads as frosted glass with content
     visible underneath. Hairline inner stroke + a soft upward drop shadow. */
  background:rgba(12,12,11,.55);
  backdrop-filter:blur(40px) saturate(180%);-webkit-backdrop-filter:blur(40px) saturate(180%);
  border-top:1px solid var(--border-d);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),0 -6px 24px rgba(0,0,0,.22);
  gap:4px
}
/* ============================================================================
   MOBILE UI REBUILD — shell chrome (masked-blur header + floating glass island)
   Reference: turn 2 (Home/Board). The header loses its hard border and instead
   fades content under a masked backdrop-blur; the bottom nav detaches from the
   edge into a rounded floating "Liquid Glass" island. Both are theme-aware via
   --surface-rgb / --line, and scoped to mobile app mode (desktop untouched).
   ============================================================================ */
/* ── Header: masked-blur backdrop layer, no hard border/line ── */
body[data-mobile-mode="app"] .m-app-header{
  background:transparent;
  backdrop-filter:none;-webkit-backdrop-filter:none;
  border-bottom:0;
  box-shadow:none;
  padding-bottom:18px;                     /* room for the mask fade below the row */
  overflow:visible
}
body[data-mobile-mode="app"] .m-app-header::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  backdrop-filter:blur(30px) saturate(180%);-webkit-backdrop-filter:blur(30px) saturate(180%);
  /* exact mockup: rgba(244,244,246,.82) → .08, masked to fade at 58% */
  background:linear-gradient(to bottom,rgba(var(--bg2-rgb),0.82),rgba(var(--bg2-rgb),0.08));
  -webkit-mask-image:linear-gradient(to bottom,#000 58%,transparent);
          mask-image:linear-gradient(to bottom,#000 58%,transparent)
}
/* ── Bottom nav: floating rounded Liquid Glass island (exact mockup values) ── */
body[data-mobile-mode="app"] .m-bottom-nav{
  left:16px;right:16px;
  bottom:calc(22px + env(safe-area-inset-bottom,0px));   /* mockup: 22px */
  height:var(--m-island-h);min-height:0;                 /* #20 — tighter (was 64px) */
  padding:0 var(--m-gap);justify-content:space-around;gap:0;
  border-radius:var(--m-radius-island);
  background:rgba(var(--surface-rgb),0.72);              /* light = rgba(255,255,255,.72) */
  backdrop-filter:blur(36px) saturate(200%);-webkit-backdrop-filter:blur(36px) saturate(200%);
  border:0.5px solid rgba(var(--line),0.14);border-top:0.5px solid rgba(var(--line),0.14);
  box-shadow:inset 0 0.8px 0 rgba(255,255,255,0.75),inset 0 -0.6px 0 rgba(0,0,0,0.06),0 16px 36px rgba(0,0,0,0.55)
}
/* #9 — the bottom hotbar's sliding selection pill (was display:none, so light mode had
   NO active highlight at all once the static active bg was removed). Show it and give it a
   filled soft-purple in both themes so the selected tab reads. */
body[data-mobile-mode="app"] #mBottomNav .m-pill-thumb{
  display:block !important;border-color:transparent;
  background:color-mix(in srgb,var(--purple) 18%,transparent);
}
html[data-theme="light"] body[data-mobile-mode="app"] #mBottomNav .m-pill-thumb{
  background:color-mix(in srgb,var(--purple) 15%,transparent);
}
.m-bn-item{
  position:relative;z-index:1;
  flex:0 0 58px;width:58px;display:flex;flex-direction:column;align-items:center;gap:2px;
  min-height:0;padding:0;border:0;background:none;cursor:pointer;
  color:rgba(var(--ink),0.5);font-size:10px;font-weight:600;
  border-radius:12px;transition:color .22s ease;
  -webkit-tap-highlight-color:transparent
}
.m-bn-item svg{width:24px;height:24px}
.m-bn-item.is-active{color:#6b46d9;background:transparent}   /* mockup active = #6b46d9 */
.m-bn-item:active{opacity:.7}
.m-bn-label{line-height:1}
/* Mobile DMs tab unread dot — small accent dot at the upper-right of the chat icon. The [hidden]
   rule needs class-level specificity so it beats the base .m-bn-dot below (UA [hidden] would lose). */
.m-bn-item .m-bn-dot{position:absolute;top:2px;right:15px;width:9px;height:9px;border-radius:50%;background:#ff3b30;border:1.5px solid rgba(12,12,11,.9);pointer-events:none}
.m-bn-item .m-bn-dot[hidden]{display:none}
html[data-theme="light"] .m-bn-item .m-bn-dot{border-color:rgba(255,255,255,.92)}
/* #6 — Projects button shows the columns icon normally and a back-arrow when a
   project board is open (.m-bn-back, toggled by mobileSyncPageFromNavigate). */
.m-bn-item .m-bn-ico-back{display:none}
.m-bn-item.m-bn-back .m-bn-ico-proj{display:none}
.m-bn-item.m-bn-back .m-bn-ico-back{display:inline-block}
/* When a project board is open: left = Project Settings (gear), right = "+". The home /
   settings variants hide; the gear / plus variants show. Labels swap to match. */
.m-bn-ico-gear,.m-bn-ico-plus,.m-bn-label-gear,.m-bn-label-plus{display:none}
body[data-board-open] .m-bn-item[data-mnav="home"] .m-bn-ico-home,
body[data-board-open] .m-bn-item[data-mnav="home"] .m-bn-label-home,
body[data-board-open] .m-bn-item[data-mnav="settings"] .m-bn-ico-settings,
body[data-board-open] .m-bn-item[data-mnav="settings"] .m-bn-label-settings{display:none}
body[data-board-open] .m-bn-item[data-mnav="home"] .m-bn-ico-gear,
body[data-board-open] .m-bn-item[data-mnav="settings"] .m-bn-ico-plus{display:inline-block}
body[data-board-open] .m-bn-item[data-mnav="home"] .m-bn-label-gear,
body[data-board-open] .m-bn-item[data-mnav="settings"] .m-bn-label-plus{display:block}
/* The "+" reads as the primary action — tint it brand purple. */
body[data-board-open] .m-bn-item[data-mnav="settings"] .m-bn-ico-plus{color:#6b46d9}
body[data-board-open] .m-bn-item[data-mnav="settings"]{color:#6b46d9}
/* #5 — Files destination shows in the Home hotbar (Home/Projects/Files/Settings); hidden
   when a board is open, where the hotbar swaps to Modify/Back/Add. */
body[data-board-open] .m-bn-files{display:none}
/* Inline add-task affordances removed on mobile — add-task is the hotbar "+".
   (Only the task-add rows; the "Add property" column control stays.) */
body[data-mobile-mode="app"] .kanban-add,
body[data-mobile-mode="app"] .group-add-row,
body[data-mobile-mode="app"] .gv-flat-add-row{display:none !important}
/* Mobile: move the calendar's month/view picker (Day/Week/Month + ‹ Month ›) to a sticky
   row at the BOTTOM, just above the hotbar. It normally lives top-right in the toolbar;
   position:fixed lifts it out so the top of the calendar shows only the day-of-week header
   + grid. The nav only exists while the calendar view is active, so this is self-scoping. */
body[data-mobile-mode="app"] [data-cal-tab-nav]{
  position:fixed;left:0;right:0;bottom:calc(var(--m-hotbar-h,64px) + env(safe-area-inset-bottom,0px));
  z-index:49;margin:0 !important;
  display:flex !important;align-items:center;justify-content:center;gap:10px;
  padding:8px 12px;min-height:54px;box-sizing:border-box;
  /* #6 Liquid Glass — match the hotbar material. */
  background:rgba(10,10,9,.55);
  -webkit-backdrop-filter:blur(40px) saturate(180%);backdrop-filter:blur(40px) saturate(180%);
  border-top:1px solid var(--border-d);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),0 -6px 24px rgba(0,0,0,.22)
}
/* Consolidate the board calendar's bottom controls into ONE edge-to-edge row:
   ‹  June 2026  [Day | Week | Month]  ›
   Arrows pin to the far edges (absolute), the month label + view-toggle pill centre.
   Scoped to the board pages so the agency master-view calendar is left alone. */
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] .cal-month-nav,
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] .cal-month-nav{display:contents}
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] [data-cal-tab-nav-label],
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] [data-cal-tab-nav-label]{
  order:1;min-width:0 !important;width:auto;font-size:14px;font-weight:700;color:var(--cream);
  padding:0;white-space:nowrap
}
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] .cal-view-toggle,
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] .cal-view-toggle{order:2}
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] .cal-nav-arrow,
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] .cal-nav-arrow{
  position:absolute;top:50%;transform:translateY(-50%);
  width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;
  padding:0;font-size:26px;line-height:1;color:var(--cream);background:none;border:0;border-radius:10px
}
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] .cal-nav-arrow:active,
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] .cal-nav-arrow:active{background:var(--state-hover)}
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] .cal-nav-prev,
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] .cal-nav-prev{left:8px}
body[data-mobile-mode="app"] #page-workshop [data-cal-tab-nav] .cal-nav-next,
body[data-mobile-mode="app"] #page-custom-workshop [data-cal-tab-nav] .cal-nav-next{right:8px}
/* Give the board title a touch more breathing room from the fixed top bar. */
body[data-mobile-mode="app"] #wsHeaderMain,
body[data-mobile-mode="app"] #wsHeaderCw{padding-top:4px}
/* ── Mobile board: a horizontal STAGE SELECTOR (pills, scroll-x) above a single
   stage's cards shown as a clean full-width vertical LIST. One axis at a time:
   pills scroll horizontally, cards scroll vertically. No gradients; uses the
   existing per-column --col-color as the pill dot. ── */
body[data-mobile-mode="app"] .m-stage-bar{
  display:flex;gap:8px;overflow-x:auto;overflow-y:hidden;
  /* Item I — full-bleed: break out to the full viewport width regardless of any parent
     padding, so the tab strip's background reaches both screen edges. */
  width:100vw;margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);margin-top:8px;   /* tightened gap below the header (rhythm) */
  padding:12px 12px 6px;scrollbar-width:none;-webkit-overflow-scrolling:touch;   /* more above, less below */
  position:sticky;top:0;z-index:8;
  background:var(--bg-board,#18181b);border-bottom:1px solid var(--border-d);
}
/* Item I — delete-board trash button, centered above the bottom hotbar (child boards only). */
.m-board-trash{display:none !important}  /* "Delete board" pill removed */
body[data-mobile-mode="app"] .m-stage-bar::-webkit-scrollbar{display:none}
.m-stage-pill{
  position:relative;z-index:1;
  flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;
  padding:8px 13px;border-radius:999px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.04);color:var(--muted);
  font-size:13px;font-weight:600;font-family:var(--sans);cursor:pointer;
  min-height:38px;white-space:nowrap;-webkit-tap-highlight-color:transparent;
  transition:color .22s ease,border-color .22s ease;
}
.m-stage-pill.is-active{   /* Item A — highlight is the sliding thumb */
  background:transparent;color:var(--off-white);border-color:transparent;
}
.m-stage-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.m-stage-nm{min-width:0;overflow:hidden;text-overflow:ellipsis;max-width:42vw}
.m-stage-ct{font-size:11px;color:var(--muted);background:rgba(255,255,255,.08);
  padding:1px 7px;border-radius:10px;font-weight:700}
.m-stage-pill.is-active .m-stage-ct{color:var(--cream)}
/* Card-list: stack columns full-width, show only the active stage */
body[data-mobile-mode="app"] .kanban{
  flex-direction:column !important;scroll-snap-type:none !important;
  overflow-x:hidden !important;gap:0 !important;padding:0 !important;align-items:stretch;
}
body[data-mobile-mode="app"] .kanban-col{
  min-width:100% !important;max-width:100% !important;flex:none !important;
  max-height:none !important;border:0 !important;border-radius:0 !important;
  background:transparent !important;display:none !important;
  padding:12px 12px calc(84px + env(safe-area-inset-bottom,0px)) !important;
}
body[data-mobile-mode="app"] .kanban-col.m-stage-active{display:flex !important}
body[data-mobile-mode="app"] .kanban-col .kanban-col-header-bar,
body[data-mobile-mode="app"] .kanban-col > .kanban-col-header{display:none !important}
body[data-mobile-mode="app"] .kanban-col-body{max-height:none !important;overflow:visible !important}
body[data-mobile-mode="app"] .kanban-cards{min-height:40px}
body[data-mobile-mode="app"] .kanban-add{border-radius:10px;margin-bottom:12px;padding:13px;font-size:12px}
/* ============================================================================
   MOBILE UI REBUILD — Board (turn 2 'board'). Reference: token-based stage
   pills (soft-purple active), and task cards as clean surface cards with a
   left color bar (stage colour) + a bold 16px title. Mobile-scoped.
   ============================================================================ */
/* Stage-selector pills — retheme onto the ink/line tokens so they read in both
   light and dark, with a solid soft-purple active thumb (mockup). */
body[data-mobile-mode="app"] .m-stage-bar{background:var(--bg);border-bottom:0}
/* Shape from the mobile tab tokens — the stage bar is a pill bar like any other. */
body[data-mobile-mode="app"] .m-stage-pill{
  border:0;background:rgba(var(--line),0.07);color:rgba(var(--ink),0.7);
  height:var(--m-tab-h);min-height:var(--m-tab-h);border-radius:var(--m-tab-radius);
  padding:0 var(--m-tab-pad-x);font-size:var(--m-tab-font);font-weight:var(--m-tab-weight)
}
body[data-mobile-mode="app"] .m-stage-pill.is-active{color:#16121f}
body[data-mobile-mode="app"] .m-stage-bar{gap:var(--m-tab-gap)}
body[data-mobile-mode="app"] .m-stage-bar .m-pill-thumb{background:var(--m-accent-soft);border:0;border-radius:var(--m-tab-radius)}
body[data-mobile-mode="app"] .m-stage-ct{background:rgba(var(--line),0.08);color:rgba(var(--ink),0.5)}
body[data-mobile-mode="app"] .m-stage-pill.is-active .m-stage-ct{background:rgba(0,0,0,0.16);color:#16121f}
/* Task cards — surface + left stage-colour bar + bold title */
/* NB: a global `.kanban-card{…!important}` redesign rule sets bg/radius/shadow,
   so the mobile overrides need !important to land (desktop stays untouched). */
body[data-mobile-mode="app"] .kanban-card{
  position:relative;min-height:0;margin-bottom:11px !important;
  padding:14px 15px 14px 22px !important;border-radius:16px !important;font-size:16px;
  background:var(--surface) !important;border:0 !important;
  box-shadow:inset 4px 0 0 var(--col-color,var(--purple)),0 1px 3px rgba(0,0,0,.05) !important
}
body[data-mobile-mode="app"] .kanban-card:active{transform:scale(.99)}
body[data-mobile-mode="app"] .kanban-card-text{font-size:16px;font-weight:600;color:var(--ink-solid);line-height:1.32;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
/* Board title — big serif-free heading like the mockup */
body[data-mobile-mode="app"] #wsHeaderMain,
body[data-mobile-mode="app"] #wsHeaderCw{--page-title-size:29px;--page-title-weight:700;
  --page-title-tracking:.2px;--page-title-color:var(--ink-solid)}
/* ── Mobile Home: attention-inbox sections as a horizontal tab bar ──
   Mirrors .m-stage-bar / .m-stage-pill (same look + behavior). Shows exactly
   ONE section at a time (Needs Response, Assigned To Me, Upcoming Planning,
   Unscheduled). The desktop "Overview" stat row (.hi-stats) and page header
   (.hi-top) are hidden on mobile. */
body[data-mobile-mode="app"] #page-dashboard{left:0 !important;top:0 !important}
body[data-mobile-mode="app"] .home-inbox{
  position:fixed;left:0;right:0;
  /* #28 — track the REAL header height (measured into --m-app-header-h, which already
     includes the safe-area inset) so a taller-than-54px header can't cover the pill bar. */
  top:var(--m-app-header-h, calc(54px + env(safe-area-inset-top,0px)));bottom:0;height:auto;
  padding:0 0 calc(74px + env(safe-area-inset-bottom,0px)) !important;
  overflow-y:auto;-webkit-overflow-scrolling:touch;z-index:1;
}
/* Same condition: the desktop greeting + stat row are redundant *next to the
   pill bar*, not in general. Without the bar they are the only chrome Home has,
   and the sync note is the one thing a recovering inbox needs to say. */
body[data-mobile-mode="app"] .home-inbox:has(.m-home-tabs) .hi-top,
body[data-mobile-mode="app"] .home-inbox:has(.m-home-tabs) .hi-stats{display:none !important}
/* The sync note is NOT hidden on mobile at all. It only renders when the inbox is
   recovering, and "Home is recovering — refreshing this view now" is exactly what
   the phone needs to say instead of looking broken. */
body[data-mobile-mode="app"] .home-inbox .hi-sync-note{margin:0 var(--m-gutter) 12px}
/* #6 — mobile Home page title, matching the Projects/Settings heading (sans 30/700). */
body[data-mobile-mode="app"] .m-home-title{
  font-family:var(--sans);font-size:30px;font-weight:700;letter-spacing:.3px;line-height:1.2;
  color:var(--ink-solid);padding:14px 16px 8px;margin:0;
}
/* #7 — empty-state icon (replaces the 🎉 emoji) sits inline before the text. */
body[data-mobile-mode="app"] .hi-empty-ico{vertical-align:-3px;margin-right:7px;opacity:.6}
body[data-mobile-mode="app"] .m-home-tabs{
  display:flex;gap:8px;overflow-x:auto;overflow-y:hidden;flex-wrap:nowrap;
  padding:12px 12px 6px;scrollbar-width:none;-webkit-overflow-scrolling:touch;   /* more above, less below */
  touch-action:pan-x;overscroll-behavior-x:contain;   /* let the finger pan horizontally with momentum */
  position:sticky;top:0;z-index:8;margin-top:8px;   /* tightened gap below the workspace header (rhythm) */
  background:var(--bg-board,#18181b);border-bottom:1px solid var(--border-d);
}
/* Every horizontal mobile pill bar should pan freely (the sliding-thumb is observer-driven,
   it must never intercept the scroll touch). */
body[data-mobile-mode="app"] .m-stage-bar,
body[data-mobile-mode="app"] #mTaskTabs,
body[data-mobile-mode="app"] .cm-m-pills,
body[data-mobile-mode="app"] .azp-tmpl-pills{
  touch-action:pan-x;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;flex-wrap:nowrap
}
body[data-mobile-mode="app"] .m-home-tabs::-webkit-scrollbar{display:none}
.m-home-tab{
  position:relative;z-index:1;
  flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;
  padding:8px 13px;border-radius:999px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.04);color:var(--muted);
  font-size:13px;font-weight:600;font-family:var(--sans);cursor:pointer;
  min-height:38px;white-space:nowrap;-webkit-tap-highlight-color:transparent;
  transition:color .22s ease,border-color .22s ease;
}
.m-home-tab.is-active{   /* Item A — highlight is the sliding thumb */
  background:transparent;color:var(--off-white);border-color:transparent;
}
.m-home-tab-nm{min-width:0;overflow:hidden;text-overflow:ellipsis;max-width:50vw}
.m-home-tab-ct{font-size:11px;color:var(--muted);background:rgba(255,255,255,.08);
  padding:1px 7px;border-radius:10px;font-weight:700}
.m-home-tab.is-active .m-home-tab-ct{color:var(--cream)}
/* One section at a time: collapse the dashboard grid (.hh-grid, or legacy
   .hi-grid) to a single column and show only the pill-selected .hi-card. The
   normal render nests cards in .hh-main / .hh-rail, so flatten those too. */
body[data-mobile-mode="app"] .home-inbox .hi-grid,
body[data-mobile-mode="app"] .home-inbox .hh-grid{display:block !important;gap:0 !important}
body[data-mobile-mode="app"] .home-inbox .hh-main,
body[data-mobile-mode="app"] .home-inbox .hh-rail{display:block !important;min-width:0}
/* One section at a time — but ONLY once the pill bar that switches between them
   actually exists. Hiding every .hi-card unconditionally meant any Home state
   that didn't get a tab bar rendered a COMPLETELY BLANK page: the recovery
   render (paintHomeFallback) emits one .hi-card and never builds the bar, and
   the desktop header/sync-note it also emits are hidden below — so the whole
   inbox painted nothing but background. The same held for the boot race where
   Home renders before data-mobile-mode lands.
   `:has()` makes the hide conditional on the bar being present; in a browser
   without :has() support the selector is simply dropped, which stacks the
   sections instead of hiding them. Either way the failure mode is "shows too
   much", never "shows nothing". */
body[data-mobile-mode="app"] .home-inbox:has(.m-home-tabs) .hi-card{
  display:none !important;
}
body[data-mobile-mode="app"] .home-inbox .hi-card{border-left:0 !important;border-right:0 !important}
body[data-mobile-mode="app"] .home-inbox .hi-card.m-home-tab-active{display:block !important}
/* The .m-home-tabs pill bar already labels the active section, so the per-card
   heading is a duplicate on mobile. Hide it (kept in the DOM — renderMobileHomeTabs
   reads its text to build the pill labels). */
body[data-mobile-mode="app"] .home-inbox .hi-card .hi-card-head,
body[data-mobile-mode="app"] .home-inbox .hi-card .hh-card-head{display:none !important}
/* ============================================================================
   MOBILE UI REBUILD — Home (My Tasks). Reference turn 2 'home': solid
   soft-purple filter pills, one grouped surface card (radius 22), spacious rows
   with a circle check, the status pill wrapped under the title, and a red
   overdue date. Mobile-scoped — the desktop dashboard is untouched.
   ============================================================================ */
/* Filter/section pills → solid soft-purple active (mockup) */
/* #11 — was var(--bg) (a shade off the page → an off-white band in light). Match the
   page canvas (--bg-main == --bg-app in both themes) so the tab bar reads seamless. */
body[data-mobile-mode="app"] .m-home-tabs{background:var(--bg-main);border-bottom:0;padding:14px 16px 4px;margin-top:0}
/* Shape from the mobile tab tokens (tokens.css → Design Rules #dr-mobile). */
body[data-mobile-mode="app"] .m-home-tab{
  border:0;background:rgba(var(--line),0.07);color:rgba(var(--ink),0.7);
  height:var(--m-tab-h);min-height:var(--m-tab-h);padding:0 var(--m-tab-pad-x);
  border-radius:var(--m-tab-radius);font-size:var(--m-tab-font);font-weight:var(--m-tab-weight)
}
body[data-mobile-mode="app"] .m-home-tab.is-active{color:#16121f}
body[data-mobile-mode="app"] .m-home-tabs{gap:var(--m-tab-gap)}
body[data-mobile-mode="app"] .m-home-tabs .m-pill-thumb{background:var(--m-accent-soft);border:0;border-radius:var(--m-tab-radius)}
body[data-mobile-mode="app"] .m-home-tab.is-active .m-home-tab-ct{background:rgba(0,0,0,0.16);color:#16121f}
/* Grouped surface card */
body[data-mobile-mode="app"] .home-inbox .hi-card{
  background:var(--surface) !important;border:0 !important;border-radius:22px !important;
  margin:6px 12px 0 !important;overflow:hidden
}
body[data-mobile-mode="app"] .hh-tasks .hh-card-body,
body[data-mobile-mode="app"] .home-inbox .hi-card-body{padding:2px 0 6px}
/* Section header — OVERDUE · n */
body[data-mobile-mode="app"] .ht-group-head{
  font-size:13px;font-weight:600;letter-spacing:.6px;color:rgba(var(--ink),0.45);
  text-transform:uppercase;padding:14px 16px 8px
}
body[data-mobile-mode="app"] .ht-group-head .m-list-group-icon{margin-left:-5px;color:var(--gv-group-color,#888)}
body[data-mobile-mode="app"] .ht-group-head .m-list-group-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .ht-group-head .m-list-group-name[contenteditable="true"]{white-space:normal;overflow:visible;text-overflow:clip;text-transform:none}
body[data-mobile-mode="app"] .ht-gcount{font-size:12px;color:rgba(var(--ink),0.5);background:rgba(var(--line),0.08);border-radius:9px;padding:1px 7px;margin-left:2px}
/* Rows: exact mockup — [check] [title / pill] [date] [chevron], gap 13, pad
   13px 15px, an absolute 0.5px hairline inset 15px on the left. */
body[data-mobile-mode="app"] .ht-row{
  display:grid;grid-template-columns:22px minmax(0,1fr) auto 7px;
  grid-template-areas:'check title due chev' 'check stage due chev';
  column-gap:13px;row-gap:6px;align-items:center;
  padding:13px 15px;border-radius:0;border-bottom:0;position:relative
}
body[data-mobile-mode="app"] .ht-row::before{content:'';position:absolute;left:15px;right:0;bottom:0;height:0.5px;background:rgba(var(--line),0.07)}
body[data-mobile-mode="app"] .ht-group .ht-row:last-of-type::before{display:none}
body[data-mobile-mode="app"] .ht-row::after{
  content:'';grid-area:chev;justify-self:end;width:7px;height:12px;background:rgba(var(--ink),0.3);
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 7 12'><path d='M1 1l5 5-5 5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat center/contain;
          mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 7 12'><path d='M1 1l5 5-5 5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat center/contain
}
/* Checkbox: a 22px ring (border), border 2px rgba(ink,.32). The green completed
   check (set on .hi-row-completing) replaces it. */
body[data-mobile-mode="app"] .ht-check{grid-area:check;align-self:center;width:22px;height:22px;border:2px solid rgba(var(--ink),0.32);border-radius:50%;box-sizing:border-box;background:none;padding:0}
body[data-mobile-mode="app"] .ht-check.is-readonly{cursor:default;pointer-events:none}
body[data-mobile-mode="app"] .ht-check svg{display:none}
body[data-mobile-mode="app"] .hi-row-completing .ht-check{border:0}
body[data-mobile-mode="app"] .hi-row-completing .ht-check svg{display:block;width:22px;height:22px}
body[data-mobile-mode="app"] .ht-main{grid-area:title;min-width:0}
body[data-mobile-mode="app"] .ht-title{font-size:16px;font-weight:600;color:var(--ink-solid);letter-spacing:.1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body[data-mobile-mode="app"] .ht-proj{display:none}      /* mockup surfaces the status pill, not the project name */
body[data-mobile-mode="app"] .ht-due{grid-area:due;align-self:center;display:flex;flex-direction:column;align-items:flex-end;gap:3px;width:auto;min-width:0;font-size:13px;font-weight:600;color:#ff6b6b}
body[data-mobile-mode="app"] .ht-due.today{color:var(--gold)}
body[data-mobile-mode="app"] .ht-due.week{color:rgba(var(--ink),0.5)}
/* #8 — workspace icon (dot) + name under the date, small + muted, single line */
body[data-mobile-mode="app"] .ht-wsline{display:inline-flex;align-items:center;gap:5px;max-width:130px;font-size:11px;font-weight:500;color:rgba(var(--ink),0.42);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body[data-mobile-mode="app"] .ht-ws-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%}
body[data-mobile-mode="app"] .ht-stagecell{grid-area:stage}
body[data-mobile-mode="app"] .ht-stage{font-size:11px;font-weight:700;letter-spacing:.3px;padding:2px 9px;border-radius:6px}
/* ── Mobile Projects: full-page vertical board/project picker ──
   Replaces the slide-in drawer on mobile. Full screen (not a sidebar), no
   profile chip, centered action buttons, no filter/options controls. */
#page-projects{display:none}
body[data-mobile-mode="app"] #page-projects.active{
  display:block;position:fixed;left:0;right:0;top:0;bottom:0;margin:0;z-index:1;
  /* #1 — start below the REAL header (measured into --m-app-header-h, ~74px incl
     safe-area) so the Projects title lines up with Home's at x16/y88, not the stale 54px. */
  padding-top:var(--m-app-header-h, calc(74px + env(safe-area-inset-top,0px)));
  padding-bottom:calc(74px + env(safe-area-inset-bottom,0px));
  overflow-y:auto;-webkit-overflow-scrolling:touch;background:var(--bg-main,#1a1a19);
}
.m-projects{max-width:640px;margin:0 auto}
.m-projects-head{padding:8px 16px 8px;text-align:center}   /* tightened gap above the title (rhythm) */
.m-projects-title{font-family:var(--serif);font-size:24px;font-weight:400;color:var(--off-white);margin:0 0 8px}
/* Action buttons centered on mobile */
.m-projects-actions{display:flex;justify-content:center;flex-wrap:wrap;gap:10px}
.m-projects-actions:empty{display:none}
.m-projects-add{
  appearance:none;border:1px solid color-mix(in srgb,var(--purple) 45%,transparent);
  background:color-mix(in srgb,var(--purple) 16%,transparent);color:var(--off-white);
  font-family:var(--sans);font-size:13px;font-weight:600;padding:10px 18px;border-radius:999px;
  cursor:pointer;min-height:40px;-webkit-tap-highlight-color:transparent;transition:background .12s;
}
.m-projects-add:active{background:color-mix(in srgb,var(--purple) 26%,transparent)}
.m-projects-list{padding:8px 12px 24px;display:flex;flex-direction:column;gap:8px}
.m-project-row{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:13px 14px;border-radius:12px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.04);color:var(--off-white);
  font-family:var(--sans);font-size:15px;font-weight:600;cursor:pointer;
  min-height:58px;-webkit-tap-highlight-color:transparent;transition:background .12s;
}
/* Layered press tint (see the swipe-row note further down) — a bare rgba() here
   would make the row translucent while held. */
.m-project-row:active{background:linear-gradient(var(--state-hover),rgba(255,255,255,.08)),var(--surface)}
.m-project-icon{
  width:36px;height:36px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.06);flex-shrink:0;color:var(--cream);overflow:hidden;
}
.m-project-icon svg{width:18px;height:18px}
.m-project-icon.mono{font-size:12px;font-weight:700}
.m-project-icon img{width:100%;height:100%;border-radius:9px;object-fit:cover}
.m-project-nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-project-chev{width:18px;height:18px;color:var(--muted);flex-shrink:0}
/* B — connected-card (iOS Notes) list + swipe-to-action rows. One rounded surface,
   rows joined by hairline dividers (no gaps), each row swipes left to reveal
   Share / Delete. */
body[data-mobile-mode="app"] .m-projects-list{
  display:block;padding:0;margin:0 12px 24px;gap:0;
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);
  border-radius:12px;overflow:hidden;
}
body[data-mobile-mode="app"] .m-project-swipe{position:relative;overflow:hidden}
body[data-mobile-mode="app"] .m-project-swipe:not(:last-child){border-bottom:1px solid var(--border-d)}
body[data-mobile-mode="app"] .m-projects-list .m-project-row{
  position:relative;z-index:1;border:0;border-radius:0;margin:0;
  background:#141312; /* opaque so the action drawer behind it stays hidden when closed */
  transform:translateX(0);transition:transform .22s cubic-bezier(.22,1,.36,1);
  touch-action:pan-y;will-change:transform;
}
body[data-mobile-mode="app"] .m-projects-list .m-project-row:active{background:#1b1a18}
/* Folder header rows are swipeable too — the opaque .m-folder-row is the element that slides. */
body[data-mobile-mode="app"] .m-folder-swipe .m-folder-row{
  position:relative;z-index:1;transform:translateX(0);
  transition:transform .22s cubic-bezier(.22,1,.36,1);touch-action:pan-y;will-change:transform;
}
/* A swipe row's own presentation must not depend on which LIST it happens to render in.
   The opaque fill, the stacking, the slide transform and touch-action were all scoped to
   `.m-projects-list` — but the mobile Projects page container is `#mProjectsList.m-projects`,
   which that selector does not match. On that page project rows therefore fell back to the
   base `.m-project-row` (background: rgba(255,255,255,.04) — 4% white, i.e. see-through)
   with NO z-index, NO transform transition and NO touch-action. The action drawer behind
   showed straight through the row, the label painted on top of the Share/Delete buttons,
   and the swipe didn't animate.
   Folder rows were fine because their equivalent rule is not list-scoped — which is exactly
   why folders worked and projects didn't. Scoping to the swipe wrapper fixes it everywhere
   the row is swipeable, whatever list contains it. --surface is theme-aware, so this covers
   light mode too. */
body[data-mobile-mode="app"] .m-project-swipe > .m-project-row{
  position:relative;z-index:1;border:0;border-radius:0;margin:0;
  background:var(--surface);
  transform:translateX(0);transition:transform .22s cubic-bezier(.22,1,.36,1);
  touch-action:pan-y;will-change:transform;
}
body[data-mobile-mode="app"] .m-folder-swipe .m-folder-toggle{width:100%}
body[data-mobile-mode="app"] .m-project-actions{
  position:absolute;top:0;right:0;bottom:0;display:flex;z-index:0;
}
/* The action drawer is only ever a SWIPE affordance. It used to sit permanently
   behind the row and rely on the row's opaque fill to stay hidden — so the
   instant anything made that fill translucent (notably the row's own :active
   press state, a plain rgba() highlight) the pills flashed into view on a
   simple TAP. Take the fill out of the equation: the drawer is not rendered at
   all unless the row is mid-swipe (.is-swiping, set by the swipe engine once a
   gesture engages) or parked open (.is-open). A tap can no longer reveal it,
   whatever the row's background happens to be.
   `visibility` (not display) so the pills keep their layout box and the reveal
   animation still has something to slide out from. */
body[data-mobile-mode="app"] .m-project-swipe .m-project-actions{visibility:hidden}
body[data-mobile-mode="app"] .m-project-swipe.is-open .m-project-actions,
body[data-mobile-mode="app"] .m-project-swipe.is-swiping .m-project-actions{visibility:visible}
body[data-mobile-mode="app"] .m-proj-act{
  width:var(--m-swipe-act-w);border:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  color:#fff;font-family:var(--sans);font-size:11px;font-weight:600;cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
body[data-mobile-mode="app"] .m-proj-act svg{width:var(--m-icon-sm);height:var(--m-icon-sm)}
/* iOS system colors — the henshu theme's --coral is purple, so hardcode the
   destructive (red) / share (blue) action pills for clarity. */
body[data-mobile-mode="app"] .m-proj-more{background:#5c5c66}
body[data-mobile-mode="app"] .m-proj-share{background:#0a84ff}
body[data-mobile-mode="app"] .m-proj-delete{background:#ff3b30}
/* ============================================================================
   MOBILE UI REBUILD — Projects (turn 13 'projects'). Reference: big left title
   + subtitle, one rounded --bg2 list card with hairline rows, colored icon
   tiles, 17px names, chevron. Swipe actions (More/Share/Delete) kept.
   ============================================================================ */
/* #1 — same padding/left-inset as .m-home-title (was 8px 18px 0 → x18/y62). */
body[data-mobile-mode="app"] .m-projects-head{text-align:left;padding:14px var(--m-gutter) 8px}
body[data-mobile-mode="app"] .m-projects-title{
  font-family:var(--sans);font-size:var(--m-title);font-weight:700;letter-spacing:.3px;line-height:1.2;
  color:var(--ink-solid);margin:0
}
body[data-mobile-mode="app"] .m-projects-sub{margin-top:5px;font-size:13px;font-weight:500;color:rgba(var(--ink),0.45)}
/* #2 — match the Settings card container exactly (.ms-set-card): translucent
   white fill + hairline border + radius 12, so Projects reads like Home/Settings. */
body[data-mobile-mode="app"] .m-projects-list{
  background:rgba(255,255,255,.05);border:1px solid var(--border-d);
  border-radius:var(--m-radius-card);margin:var(--m-gap) var(--m-gutter) 24px
}
body[data-mobile-mode="app"] .m-project-swipe:not(:last-child){border-bottom:0.5px solid rgba(var(--line),0.07)}
body[data-mobile-mode="app"] .m-projects-list .m-project-row{
  background:var(--surface);padding:var(--m-pad) 15px;min-height:var(--m-row-h)
}
/* Press highlight — LAYERED over the opaque surface, never replacing it.
   `background:rgba(...)` on its own made the row see-through for the duration
   of the touch, which is what put the swipe pills on screen the moment you
   tapped a project. A gradient stop-pair paints the same 5% tint as its own
   layer while --surface stays underneath, so the row is opaque at every moment
   of the press. Any future press state on a swipe row must follow this shape. */
body[data-mobile-mode="app"] .m-project-swipe > .m-project-row:active,
body[data-mobile-mode="app"] .m-projects-list .m-project-row:active{
  background:linear-gradient(rgba(var(--line),0.05),rgba(var(--line),0.05)),var(--surface);
}
body[data-mobile-mode="app"] .m-folder-swipe .m-folder-row:active{
  background:linear-gradient(rgba(var(--line),0.05),rgba(var(--line),0.05)),var(--surface);
}
/* One accent drives the whole tile: the container tint and the glyph colour are both
   derived from --proj-accent, which _mProjIcon / _mFolderRowHtml set from the project's
   (palette-snapped) colour. Unset → the brand purple, so an uncoloured project still
   reads as ours rather than inheriting the row's white label colour. */
body[data-mobile-mode="app"] .m-project-icon{
  width:var(--m-icon-tile);height:var(--m-icon-tile);border-radius:var(--m-icon-tile-radius);
  background:color-mix(in srgb,var(--proj-accent,var(--m-accent)) 16%,transparent);
  color:var(--proj-accent,var(--m-accent-soft))
}
body[data-mobile-mode="app"] .m-proj-ico-emoji{font-size:18px}
body[data-mobile-mode="app"] .m-project-icon svg{width:var(--m-icon-md);height:var(--m-icon-md)}
body[data-mobile-mode="app"] .m-project-nm{font-size:17px;font-weight:600;color:var(--ink-solid)}
body[data-mobile-mode="app"] .m-project-chev{width:var(--m-icon-xs);height:var(--m-icon-xs);color:rgba(var(--ink),0.3)}
/* ── Mobile Settings: full page, all controls reachable ──
   Desktop renders a 220px left nav + body. On mobile the legacy @media rule
   hid .ss-nav entirely (only one pane reachable). Instead, give the settings
   page the full screen and turn the nav into a horizontal scrolling pill bar
   so every section (plus Edit Profile) stays reachable — no sidebar shrink. */
body[data-mobile-mode="app"] #page-settings.active{
  position:fixed !important;left:0;right:0;top:0;bottom:0;margin:0 !important;height:auto !important;
  /* #1 — same real-header offset as Home/Projects so the Settings title aligns at x16/y88. */
  padding:var(--m-app-header-h, calc(74px + env(safe-area-inset-top,0px))) 0 0 0 !important;
  display:flex;flex-direction:column;overflow:hidden;z-index:1;background:var(--bg-main,#1a1a19);
}
body[data-mobile-mode="app"] #page-settings .ss-wrap{flex-direction:column;overflow:hidden;flex:1;min-height:0}
body[data-mobile-mode="app"] #page-settings .ss-nav{
  display:flex !important;width:100% !important;flex-direction:row;flex-shrink:0;
  overflow-x:auto;overflow-y:hidden;gap:7px;align-items:center;
  border-right:none;border-bottom:1px solid var(--border-d);
  padding:10px 12px;scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
body[data-mobile-mode="app"] #page-settings .ss-nav::-webkit-scrollbar{display:none}
/* Section labels + separators don't belong in a horizontal pill bar */
body[data-mobile-mode="app"] #page-settings .ss-nav-section,
body[data-mobile-mode="app"] #page-settings .ss-nav-sep{display:none !important}
body[data-mobile-mode="app"] #page-settings .ss-nav-item{
  width:auto;flex:0 0 auto;white-space:nowrap;border-radius:999px;min-height:38px;
  border:1px solid var(--border-d);background:rgba(255,255,255,.04);padding:8px 14px;
}
body[data-mobile-mode="app"] #page-settings .ss-nav-item.active{
  background:color-mix(in srgb,var(--coral) 16%,transparent);
  border-color:color-mix(in srgb,var(--coral) 45%,transparent);
}
body[data-mobile-mode="app"] #page-settings .ss-nav-editprofile{
  background:color-mix(in srgb,var(--purple) 18%,transparent);
  border-color:color-mix(in srgb,var(--purple) 45%,transparent);color:var(--off-white);
}
body[data-mobile-mode="app"] #page-settings .ss-body{
  flex:1;width:100%;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:18px 16px calc(80px + env(safe-area-inset-bottom,0px)) !important;
}
/* Split panes (e.g. Workspace Profile) stack on mobile instead of side-by-side */
/* #2 — was `display:block !important`, which overrode ssNavigate's inline
   display:none and pinned the Workspace Profile pane permanently visible on
   mobile (it overlapped every other settings tab). Stack the split columns via
   flex-direction instead, leaving visibility under ssNavigate's control. */
body[data-mobile-mode="app"] #page-settings .ss-pane-split{flex-direction:column;gap:16px;align-items:stretch}
/* ── D — Mobile Settings: iOS grouped menu + full-screen sheets ── */
#ssMobileMenu,#ssSheetHeader,#ssSheetHotbar{display:none}
/* #14 — settings sub-page bottom Back/Home hotbar (shown only when a section is open). */
/* #6 — settings sub-page navigation: a Back-only FLOATING island (matching the
   .m-bottom-nav Liquid-Glass hotbar) instead of an in-flow bottom bar, with the
   4-icon nav hidden underneath it. */
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open #ssSheetHotbar{
  display:flex;align-items:center;justify-content:center;gap:0;
  position:fixed;left:16px;right:16px;bottom:calc(22px + env(safe-area-inset-bottom,0px));
  height:56px;min-height:0;padding:0 8px;z-index:60;border-radius:30px;
  background:rgba(var(--surface-rgb),0.72);
  backdrop-filter:blur(36px) saturate(200%);-webkit-backdrop-filter:blur(36px) saturate(200%);
  border:0.5px solid rgba(var(--line),0.14);
  box-shadow:inset 0 0.8px 0 rgba(255,255,255,0.75),inset 0 -0.6px 0 rgba(0,0,0,0.06),0 16px 36px rgba(0,0,0,0.55);
}
/* Hide the 4-icon bottom nav while a settings section sheet is open. */
body[data-mobile-mode="app"]:has(#settingsWrap.ss-sheet-open) #mBottomNav{display:none !important}
body[data-mobile-mode="app"] #page-settings .ss-tabbar{display:none !important}   /* the mobile menu replaces the tab strip (.ss-nav was this rule's pre-rename target) */
body[data-mobile-mode="app"] #ssMobileMenu{
  display:block;flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:8px 16px calc(80px + env(safe-area-inset-bottom,0px));
}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open #ssMobileMenu{display:none}
/* Panes hidden in the menu view; presented as a scrolling sheet when a row is opened. */
body[data-mobile-mode="app"] #page-settings .ss-body{display:none}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-body{display:block;flex:1;min-height:0;overflow-y:auto}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open #ssSheetHeader{display:flex}
#ssSheetHeader{align-items:center;padding:10px 12px;border-bottom:1px solid var(--border-d);position:sticky;top:0;background:var(--bg-main,#1a1a19);z-index:3;flex-shrink:0}
.ss-sheet-back{background:none;border:0;color:var(--off-white);cursor:pointer;display:inline-flex;align-items:center;padding:4px;margin-right:6px;-webkit-tap-highlight-color:transparent}
.ss-sheet-title{font-family:var(--sans);font-size:17px;font-weight:600;color:var(--off-white)}
.ms-set-head{padding:6px 0 4px}
/* #1 — match the unified mobile page title (Home/Projects): sans 30/700, +.3px, ink-solid. */
.ms-set-h1{font-family:var(--sans);font-size:30px;font-weight:700;letter-spacing:.3px;line-height:1.2;color:var(--ink-solid);margin:0 0 12px}
.ms-set-search{display:flex;align-items:center;gap:8px;background:rgba(255,255,255,.07);border-radius:10px;padding:9px 12px;margin-bottom:16px;color:var(--muted)}
.ms-set-search svg{width:16px;height:16px;flex-shrink:0}
.ms-set-search input{flex:1;min-width:0;background:none;border:0;outline:0;color:var(--off-white);font-family:var(--sans);font-size:16px}
.ms-set-sec-label{font-size:12px;font-weight:600;color:var(--muted);padding:16px 4px 7px}
.ms-set-card{background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:12px;overflow:hidden;margin-bottom:16px}
.ms-set-row,.ms-set-profile{display:flex;align-items:center;gap:13px;width:100%;text-align:left;border:0;background:none;cursor:pointer;color:var(--off-white);font-family:var(--sans);min-height:50px;padding:11px 14px;-webkit-tap-highlight-color:transparent}
.ms-set-card .ms-set-row:not(:last-child){border-bottom:1px solid var(--border-d)}
.ms-set-row:active,.ms-set-profile:active{background:rgba(255,255,255,.05)}
.ms-set-profile{padding:14px;min-height:72px}
.ms-set-ico{width:29px;height:29px;border-radius:7px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff}
.ms-set-ico svg{width:18px;height:18px}
.ms-set-ico-emoji{font-size:16px}
.ms-set-pfpwrap{flex-shrink:0;width:50px;height:50px;border-radius:50%;overflow:hidden;display:inline-flex}
.ms-set-pfpwrap img{width:50px;height:50px;border-radius:50%;object-fit:cover}
.ms-set-pfp{width:50px;height:50px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;background:var(--coral);color:#fff;font-weight:700;font-size:20px}
.ms-set-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ms-set-title{font-size:16px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms-set-sub{font-size:13px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms-set-status{font-size:13px;color:var(--muted);margin-right:2px;flex-shrink:0}
.ms-set-chev{width:17px;height:17px;color:var(--muted);opacity:.55;flex-shrink:0}
.ms-set-danger .ms-set-title{color:var(--danger-text)}
.ms-set-about{text-align:center;color:var(--muted);font-size:12px;padding:6px 0 24px}
/* ============================================================================
   MOBILE UI REBUILD — Settings (turn 11 'settings'). Grouped surface cards,
   30px title, uppercase section labels, larger colored icon tiles — all on the
   ink/surface tokens so light + dark both read correctly.
   ============================================================================ */
body[data-mobile-mode="app"] .ms-set-h1{font-size:30px;font-weight:700;letter-spacing:.3px;color:var(--ink-solid);margin:0 0 4px}
body[data-mobile-mode="app"] .ms-set-search{background:var(--surface);border-radius:13px;padding:0 15px;min-height:46px;color:rgba(var(--ink),0.4);margin-bottom:8px}
body[data-mobile-mode="app"] .ms-set-row{padding:12px 15px;gap:13px}
body[data-mobile-mode="app"] .ms-set-search input{color:var(--ink-solid)}
body[data-mobile-mode="app"] .ms-set-sec-label{font-size:12px;font-weight:600;letter-spacing:.8px;text-transform:uppercase;color:rgba(var(--ink),0.45);padding:22px 4px 8px}
body[data-mobile-mode="app"] .ms-set-card{background:var(--surface);border:0;border-radius:16px;margin-bottom:4px}
body[data-mobile-mode="app"] .ms-set-card .ms-set-row:not(:last-child){border-bottom:0.5px solid rgba(var(--line),0.07)}
body[data-mobile-mode="app"] .ms-set-profile{background:var(--surface);border-radius:16px}
body[data-mobile-mode="app"] .ms-set-row:active,body[data-mobile-mode="app"] .ms-set-profile:active{background:rgba(var(--line),0.04)}
body[data-mobile-mode="app"] .ms-set-ico{width:38px;height:38px;border-radius:10px}
body[data-mobile-mode="app"] .ms-set-ico svg{width:20px;height:20px}
body[data-mobile-mode="app"] .ms-set-title{font-size:16px;font-weight:500;color:var(--ink-solid)}
body[data-mobile-mode="app"] .ms-set-sub,body[data-mobile-mode="app"] .ms-set-status{color:rgba(var(--ink),0.45)}
body[data-mobile-mode="app"] .ms-set-chev{color:rgba(var(--ink),0.3);opacity:1}
body[data-mobile-mode="app"] .ms-set-about{color:rgba(var(--ink),0.3)}

/* ============================================================================
   Fix B — inline-editable mobile "My Profile" pane (merged Edit Profile). Big
   tap-to-change avatar + iOS grouped cards; rows match the Settings sub-page
   aesthetic (rgba surface, hairline dividers, radius 12). Light + dark via tokens.
   ============================================================================ */
body[data-mobile-mode="app"] .mpf-avatar-wrap{display:flex;flex-direction:column;align-items:center;gap:7px;padding:6px 0 16px}
body[data-mobile-mode="app"] .mpf-avatar{position:relative;width:92px;height:92px;border-radius:50%;border:0;padding:0;cursor:pointer;background:var(--purple-tint,rgba(124,92,255,.16));display:inline-flex;align-items:center;justify-content:center;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .mpf-avatar:active{transform:scale(.97)}
body[data-mobile-mode="app"] .mpf-avatar img{width:92px;height:92px;border-radius:50%;object-fit:cover;display:block}
body[data-mobile-mode="app"] .mpf-avatar-mono{font-family:var(--sans);font-size:36px;font-weight:700;color:var(--m-accent,#7c5cff)}
body[data-mobile-mode="app"] .mpf-avatar-cam{position:absolute;right:-1px;bottom:-1px;width:30px;height:30px;border-radius:50%;background:var(--m-accent,#7c5cff);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(0,0,0,.35);border:2px solid var(--surface)}
body[data-mobile-mode="app"] .mpf-avatar-name{font-family:var(--sans);font-size:20px;font-weight:700;color:var(--ink-solid)}
body[data-mobile-mode="app"] .mpf-avatar-sub{font-size:13px;color:rgba(var(--ink),0.5);margin-top:-3px}
body[data-mobile-mode="app"] .mpf-label{font-size:12px;font-weight:600;color:rgba(var(--ink),0.5);text-transform:uppercase;letter-spacing:.5px;padding:14px 6px 7px}
body[data-mobile-mode="app"] .mpf-card{background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:12px;overflow:hidden}
body[data-mobile-mode="app"] .mpf-card-pad{padding:12px 14px}
body[data-mobile-mode="app"] .mpf-field{display:flex;align-items:center;gap:12px;min-height:50px;padding:8px 14px}
body[data-mobile-mode="app"] .mpf-field:not(:last-child),
body[data-mobile-mode="app"] .mpf-row:not(:last-child){border-bottom:1px solid rgba(var(--line),0.08)}
body[data-mobile-mode="app"] .mpf-flabel{flex:0 0 82px;font-family:var(--sans);font-size:15px;font-weight:500;color:var(--ink-solid)}
body[data-mobile-mode="app"] .mpf-finput{flex:1;min-width:0;background:none;border:0;outline:0;text-align:right;color:var(--ink-solid);font-family:var(--sans);font-size:16px}
body[data-mobile-mode="app"] .mpf-finput::placeholder{color:rgba(var(--ink),0.35)}
body[data-mobile-mode="app"] .mpf-field-area{align-items:flex-start}
body[data-mobile-mode="app"] .mpf-ftext{text-align:left;resize:none;line-height:1.4;padding-top:2px;font-size:15px}
body[data-mobile-mode="app"] .mpf-field-ro .mpf-fval{flex:1;text-align:right;color:rgba(var(--ink),0.5);font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .mpf-row{display:flex;align-items:center;width:100%;min-height:50px;padding:8px 14px;border:0;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .mpf-row:active{background:rgba(var(--line),0.05)}
body[data-mobile-mode="app"] .mpf-row-r{margin-left:auto;display:flex;align-items:center;gap:3px;color:rgba(var(--ink),0.4)}
body[data-mobile-mode="app"] .mpf-row-hint{font-size:15px;color:rgba(var(--ink),0.4)}
body[data-mobile-mode="app"] .mpf-status{min-height:18px;text-align:center;font-size:12px;color:rgba(var(--ink),0.45);padding:12px 0 4px}
body[data-mobile-mode="app"] .mpf-status-ok{color:var(--green,#73ac83)}
body[data-mobile-mode="app"] .mpf-status-err{color:#ff6b6b}
/* Change-password slide-up sheet */
body[data-mobile-mode="app"] .mpf-pw-ov{position:fixed;inset:0;z-index:10055;background:rgba(0,0,0,.42);opacity:0;transition:opacity .2s ease}
body[data-mobile-mode="app"] .mpf-pw-ov.show{opacity:1}
body[data-mobile-mode="app"] .mpf-pw-sheet{position:absolute;left:0;right:0;bottom:0;background:var(--surface);border-radius:20px 20px 0 0;padding:8px 18px calc(18px + env(safe-area-inset-bottom,0px));transform:translateY(100%);transition:transform .26s cubic-bezier(.22,1,.36,1);display:flex;flex-direction:column;gap:10px}
body[data-mobile-mode="app"] .mpf-pw-ov.show .mpf-pw-sheet{transform:translateY(0)}
body[data-mobile-mode="app"] .mpf-pw-grip{width:38px;height:4px;border-radius:2px;background:rgba(var(--ink),0.2);margin:6px auto 4px}
body[data-mobile-mode="app"] .mpf-pw-title{font-family:var(--sans);font-size:18px;font-weight:700;color:var(--ink-solid);text-align:center;margin-bottom:2px}
body[data-mobile-mode="app"] .mpf-pw-input{width:100%;font-size:16px;padding:12px 14px;border-radius:12px;background:rgba(var(--line),0.06);border:1px solid var(--border-d);color:var(--ink-solid);font-family:var(--sans)}
body[data-mobile-mode="app"] .mpf-pw-msg{min-height:15px;font-size:13px;text-align:center;color:rgba(var(--ink),0.5)}
body[data-mobile-mode="app"] .mpf-pw-err{color:#ff6b6b}
body[data-mobile-mode="app"] .mpf-pw-save{padding:13px;border-radius:12px;border:0;background:var(--m-accent,#7c5cff);color:#fff;font-family:var(--sans);font-size:16px;font-weight:600;cursor:pointer}
body[data-mobile-mode="app"] .mpf-pw-save:disabled{opacity:.6}
body[data-mobile-mode="app"] .mpf-pw-cancel{padding:11px;border-radius:12px;border:0;background:none;color:rgba(var(--ink),0.5);font-family:var(--sans);font-size:15px;font-weight:600;cursor:pointer}
/* 24 — Discord/iOS-mobile styling for the INSIDE of each Settings sheet. The panes use
   .ss-section / .ss-field blocks; turn each section into a grouped rounded card with full-
   width inputs + muted section headers, so the sheet content matches the outer list rather
   than the desktop form. Scoped to the open sheet on mobile; desktop untouched. */
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-body{padding:14px 16px calc(80px + env(safe-area-inset-bottom,0px))}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-pane > h2{font-family:var(--sans);font-size:13px;font-weight:600;color:var(--muted);text-transform:none;letter-spacing:0;margin:6px 4px 10px;padding:0}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-pane .ss-desc{padding:0 4px;margin-bottom:14px;font-size:13px;color:var(--muted)}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-section{background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:12px;padding:14px;margin-bottom:16px}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-section h3{font-family:var(--sans);font-size:12px;font-weight:600;color:var(--muted);margin:0 0 10px}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-field{display:flex;flex-direction:column;gap:6px;margin-bottom:10px}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-field:last-child{margin-bottom:0}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-field label{font-size:13px;color:var(--cream);font-weight:500}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-pane input[type=text],
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-pane input[type=email],
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-pane input[type=password],
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-pane textarea{width:100%;font-size:16px;padding:11px 12px;border-radius:10px;background:rgba(255,255,255,.05);border:1px solid var(--border-d);color:var(--off-white)}
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-hr{display:none}
/* list rows (members / roles) — connected rows with hairline dividers, Discord-style */
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .ss-member-row,
body[data-mobile-mode="app"] #settingsWrap.ss-sheet-open .rp-role-row{padding:12px 4px;border-bottom:1px solid rgba(255,255,255,.07)}
/* ── Client switcher (top bar + mobile header) — fix 3 ──
   Reuses the .sidebar-client-* item styling for the dropdown body. */
.client-switch-wrap{position:relative;display:flex;align-items:center}
.client-switch-trigger{
  display:inline-flex;align-items:center;gap:6px;max-width:200px;
  background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:8px;
  color:var(--cream);font-family:var(--sans);font-size:13px;font-weight:600;
  padding:6px 10px;cursor:pointer;transition:background .12s;-webkit-tap-highlight-color:transparent;
}
.client-switch-trigger:hover{background:rgba(255,255,255,.09)}
.client-switch-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.client-switch-caret{width:14px;height:14px;flex-shrink:0;opacity:.7;transition:transform .15s}
.client-switch-wrap.open .client-switch-caret{transform:rotate(180deg)}
.client-switch-menu{
  display:none;position:absolute;top:calc(100% + 6px);right:0;
  min-width:230px;max-width:280px;max-height:60vh;overflow-y:auto;
  background:var(--dark);border:1px solid var(--border-d);border-radius:10px;
  box-shadow:0 8px 28px rgba(0,0,0,.5);padding:6px;z-index:300;
}
.client-switch-wrap.open .client-switch-menu{display:block}
/* Mobile header: icon-only trigger; menu pinned under the fixed header */
.m-client-switch-btn{padding:8px;max-width:none;background:transparent;border:none;border-radius:8px;color:var(--cream)}
/* 29 — spotlight search button (left of the client switcher) */
.m-header-search-btn{display:inline-flex;align-items:center;justify-content:center;padding:8px;background:transparent;border:none;border-radius:8px;color:var(--cream);cursor:pointer;-webkit-tap-highlight-color:transparent}
.m-header-search-btn svg{width:21px;height:21px}
body[data-mobile-mode="app"] .m-header-search-btn{color:rgba(var(--ink),0.7)}
.m-header-search-btn:active{background:var(--state-hover)}
.m-app-header-actions{display:flex;align-items:center;gap:2px}
/* #13 — notifications bell (mirrors the search button) + unread badge */
.m-header-notif-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:8px;background:transparent;border:none;border-radius:8px;color:var(--cream);cursor:pointer;-webkit-tap-highlight-color:transparent}
.m-header-notif-btn svg{width:21px;height:21px}
body[data-mobile-mode="app"] .m-header-notif-btn{color:rgba(var(--ink),0.7)}
.m-header-notif-btn:active{background:var(--state-hover)}
html[data-theme="light"] .m-header-notif-btn{color:var(--cream)}
.m-notif-badge{display:none;position:absolute;top:3px;right:3px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--color-error);color:#fff;font:700 10px/16px var(--sans);text-align:center;box-sizing:border-box}
.m-notif-badge.on{display:block}
/* mobile notifications sheet rows */
.m-notif-row{display:flex;align-items:flex-start;gap:11px;text-align:left}
.m-notif-ico{flex-shrink:0;font-size:17px;line-height:1.2;color:var(--coral,#8c72db);display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px}
.m-notif-ico svg{width:18px;height:18px;display:block}
.m-notif-tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.m-notif-title{font-size:14px;font-weight:600;color:var(--ink-solid)}
.m-notif-sub{font-size:13px;color:rgba(var(--ink),0.5);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.m-notif-time{flex-shrink:0;font-size:11px;color:rgba(var(--ink),0.4);white-space:nowrap}
.m-notif-row.unread .m-notif-title::after{content:'';display:inline-block;width:7px;height:7px;margin-left:6px;border-radius:50%;background:var(--color-error);vertical-align:middle}
.m-client-switch-btn:hover,.m-client-switch-btn:active{background:rgba(255,255,255,.06)}
.m-client-switch-btn svg{width:20px;height:20px}
/* #4 — Mobile: client switcher is a full-screen sheet, not a dropdown. */
body[data-mobile-mode="app"] .m-header-client-wrap .client-switch-menu{
  position:fixed !important;inset:0 !important;top:0 !important;right:0 !important;left:0 !important;
  width:100% !important;max-width:100% !important;min-width:0 !important;
  height:100dvh !important;max-height:100dvh !important;
  border:0 !important;border-radius:0 !important;box-shadow:none !important;
  z-index:10050 !important;padding:0 0 calc(24px + env(safe-area-inset-bottom,0px)) !important;
  overflow-y:auto !important;-webkit-overflow-scrolling:touch;
}
.csw-msheet-head{
  position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;
  padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;border-bottom:1px solid var(--border-d);
  background:var(--dark)
}
.csw-msheet-title{font-family:var(--serif);font-size:20px;color:var(--off-white)}
.csw-msheet-sec{padding:18px 16px 6px;font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.csw-msheet-done{
  border:0;background:var(--coral);color:#fff;font-weight:600;font-size:14px;font-family:var(--sans);
  padding:8px 18px;border-radius:999px;cursor:pointer
}
body[data-mobile-mode="app"] .m-header-client-wrap .client-switch-menu .sidebar-client-row,
body[data-mobile-mode="app"] .m-header-client-wrap .client-switch-menu .sidebar-clients-item{padding:14px 16px}
/* ── Item C — iOS-alarm-clock-style 3D wheel client switcher (mobile) ── */
body[data-mobile-mode="app"][data-cw-open] .m-header-client-wrap .client-switch-menu{padding:0 !important;overflow:hidden !important}
.cw-sheet{display:flex;flex-direction:column;height:100dvh;background:var(--black)}
.cw-top{flex-shrink:0;padding:calc(14px + env(safe-area-inset-top,0px)) 16px 10px}
.cw-search-wrap{display:flex;align-items:center;gap:8px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:12px;padding:10px 12px}
.cw-search-ic{width:18px;height:18px;color:var(--muted);flex-shrink:0}
.cw-search{flex:1;min-width:0;background:none;border:0;outline:none;color:var(--off-white);font-family:var(--sans);font-size:15px}
.cw-search::placeholder{color:var(--muted)}
.cw-wheel{
  flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  perspective:900px;perspective-origin:center center;
  scroll-snap-type:y mandatory;position:relative;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 24%,#000 76%,transparent);
  mask-image:linear-gradient(180deg,transparent,#000 24%,#000 76%,transparent);
}
.cw-wheel::-webkit-scrollbar{display:none}
.cw-pad{height:calc(50% - 32px)}
.cw-item{
  height:64px;scroll-snap-align:center;
  display:flex;align-items:center;gap:14px;width:100%;
  background:none;border:0;cursor:pointer;padding:0 24px;
  color:var(--cream);font-family:var(--sans);text-align:left;
  transform-origin:center center;will-change:transform,opacity,filter;
  transition:color .15s;-webkit-tap-highlight-color:transparent;
}
.cw-av{width:40px;height:40px;border-radius:50%;flex-shrink:0;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--purple) 22%,transparent);color:#fff;font-size:14px;font-weight:700}
.cw-av-img{width:100%;height:100%;object-fit:cover;border-radius:50%;display:block}
.cw-name{flex:1;min-width:0;font-size:19px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:baseline;gap:7px}
.cw-tag{font-size:11px;color:var(--muted);font-weight:500;flex-shrink:0}
.cw-check{width:20px;height:20px;color:var(--purple);flex-shrink:0}
.cw-item.cw-centered{color:var(--off-white)}
.cw-item.cw-centered .cw-name{font-weight:700}
.cw-hint{flex-shrink:0;text-align:center;color:var(--muted);font-size:12px;padding:8px 0 calc(80px + env(safe-area-inset-bottom,0px))}
.cw-loading{padding:48px;text-align:center;color:var(--muted)}
/* Swap hotbar — Add Client / Back / Manage Client (shown only while the wheel is open) */
.m-cw-hotbar{display:none}
body[data-mobile-mode="app"][data-cw-open] #mBottomNav{display:none}
/* #19 — Manage Clients / switcher hotbar matches the floating Liquid-Glass island
   (was a flat, opaque, edge-to-edge dark bar). Theme-aware via --surface-rgb / --line. */
body[data-mobile-mode="app"][data-cw-open] .m-cw-hotbar{
  display:flex;align-items:center;justify-content:space-around;
  position:fixed;left:16px;right:16px;bottom:calc(22px + env(safe-area-inset-bottom,0px));z-index:10060;
  height:56px;padding:0 8px;gap:0;border-radius:30px;
  background:rgba(var(--surface-rgb),0.72);
  backdrop-filter:blur(36px) saturate(200%);-webkit-backdrop-filter:blur(36px) saturate(200%);
  border:0.5px solid rgba(var(--line),0.14);
  box-shadow:inset 0 0.8px 0 rgba(255,255,255,0.75),inset 0 -0.6px 0 rgba(0,0,0,0.06),0 16px 36px rgba(0,0,0,0.55)
}
.m-cw-hb-item{
  flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:2px;
  min-height:0;padding:6px 14px;border:0;background:none;cursor:pointer;
  color:rgba(var(--ink),0.6);font-size:10px;font-weight:600;border-radius:14px;
  -webkit-tap-highlight-color:transparent
}
.m-cw-hb-item svg{width:21px;height:21px}
.m-cw-hb-item:active{opacity:.6}
.m-cw-hb-back{color:var(--m-accent,#7c5cff)}
/* ── Item D — mobile Canvas: searchable, categorized note list + editor sheet ── */
body[data-mobile-mode="app"] .mcanvas{display:flex;flex-direction:column;padding:12px 14px calc(92px + env(safe-area-inset-bottom,0px))}
.mcanvas-search-row{display:flex;align-items:center;gap:8px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:12px;padding:10px 12px;margin-bottom:18px}
.mcanvas-search-ic{width:18px;height:18px;color:var(--muted);flex-shrink:0}
.mcanvas-search{flex:1;min-width:0;background:none;border:0;outline:none;color:var(--off-white);font-family:var(--sans);font-size:15px}
.mcanvas-search::placeholder{color:var(--muted)}
.mcanvas-sec-head{font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--muted);padding:0 2px 10px;display:flex;align-items:center;gap:8px}
.mcanvas-sec-ct{background:rgba(255,255,255,.08);color:var(--cream);border-radius:10px;padding:1px 8px;font-size:11px;font-weight:700}
.mcanvas-list{display:flex;flex-direction:column;gap:8px}
.mcanvas-note{display:flex;align-items:stretch;gap:0;width:100%;text-align:left;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:12px;padding:0;cursor:pointer;overflow:hidden;-webkit-tap-highlight-color:transparent}
.mcanvas-note:active{background:rgba(255,255,255,.06)}
.mcanvas-note-bar{width:4px;align-self:stretch;background:var(--mcn-color,var(--gold));flex-shrink:0}
.mcanvas-note-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;padding:13px 14px}
.mcanvas-note-title{font-size:15px;font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mcanvas-note-prev{font-size:13px;color:var(--muted);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.mcanvas-note-chev{width:18px;height:18px;color:var(--muted);flex-shrink:0;align-self:center;margin-right:12px}
.mcanvas-empty{padding:40px 0;text-align:center;color:var(--muted);font-style:italic;font-size:13px}
/* ============================================================================
   MOBILE UI REBUILD — Canvas notes (turn 6 'noteopen'). Surface note cards with
   a left colour bar, ink text, surface search — on the tokens so light + dark
   read correctly (was white-tint, near-invisible on light).
   ============================================================================ */
body[data-mobile-mode="app"] .mcanvas-search-row{background:var(--surface);border:0;border-radius:13px}
body[data-mobile-mode="app"] .mcanvas-search{color:var(--ink-solid)}
body[data-mobile-mode="app"] .mcanvas-sec-head{color:rgba(var(--ink),0.45);letter-spacing:.8px}
body[data-mobile-mode="app"] .mcanvas-sec-ct{background:rgba(var(--line),0.08);color:rgba(var(--ink),0.5)}
body[data-mobile-mode="app"] .mcanvas-note{background:var(--surface);border:0;border-radius:14px;box-shadow:0 1px 3px rgba(0,0,0,.05)}
body[data-mobile-mode="app"] .mcanvas-note:active{background:var(--surface);transform:scale(.99)}
body[data-mobile-mode="app"] .mcanvas-note-title{color:var(--ink-solid);font-size:16px}
body[data-mobile-mode="app"] .mcanvas-note-prev{color:rgba(var(--ink),0.5)}
body[data-mobile-mode="app"] .mcanvas-note-chev{color:rgba(var(--ink),0.3)}
body[data-mobile-mode="app"] .m-canvas-fab{
  display:inline-flex;align-items:center;justify-content:center;position:fixed;
  right:18px;bottom:calc(76px + env(safe-area-inset-bottom,0px));z-index:55;
  width:52px;height:52px;border-radius:50%;border:0;cursor:pointer;color:#fff;
  background:linear-gradient(135deg,#7c3aed,#a78bfa);box-shadow:0 8px 24px rgba(124,58,237,.45);
  -webkit-tap-highlight-color:transparent;transition:transform .14s
}
body[data-mobile-mode="app"] .m-canvas-fab:active{transform:scale(.92)}
.m-canvas-fab svg{width:26px;height:26px}
.mcanvas-note-sheet{display:none}
body[data-mobile-mode="app"] .mcanvas-note-sheet.open{display:flex;flex-direction:column;position:fixed;inset:0;z-index:10070;background:var(--black)}
/* #24 — the canvas note editor was black even in light mode (hardcoded var(--black)); the
   text (--off-white) adapts but the surface didn't, so it read "fully dark". Flip the
   surface in light mode. */
html[data-theme="light"] body[data-mobile-mode="app"] .mcanvas-note-sheet.open{background:var(--bg-main)}
.mcns-head{position:relative;flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:calc(14px + env(safe-area-inset-top,0px)) 14px 12px;border-bottom:1px solid var(--border-d)}
.mcns-head::before{content:'';position:absolute;left:0;top:0;width:100%;height:3px;background:var(--mcn-color,var(--gold))}
.mcns-back{display:inline-flex;align-items:center;gap:6px;background:none;border:0;color:var(--off-white);font-family:var(--sans);font-size:16px;font-weight:600;cursor:pointer;-webkit-tap-highlight-color:transparent}
.mcns-back svg{width:22px;height:22px}
.mcns-del{background:none;border:0;color:#ff453a;cursor:pointer;padding:4px;-webkit-tap-highlight-color:transparent}
.mcns-del svg{width:21px;height:21px}
.mcns-body{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:18px 18px calc(24px + env(safe-area-inset-bottom,0px));font-family:var(--sans);font-size:16px;line-height:1.6;color:var(--off-white);outline:none}
.mcns-body:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}
/* Mobile-specific overview tweaks — the desktop overview already adapts via
   existing @media rules; we just need to add bottom padding so the bottom
   nav doesn't cover the last day cell, and pull the calendar's top margin
   up to sit under the new app header. */
body[data-mobile-mode="app"] #page-master-view.active{
  margin:0 !important;padding-top:62px !important;padding-bottom:90px !important;
  height:100% !important
}
/* Mobile calendar header layout: two-row grid.
     Row 1: month nav centered, filter icon (no text) pinned to the right
     Row 2: day/week/month view-toggle centered
   The tab-nav wrapper that holds (viewToggle + monthNav) becomes
   display:contents so its children participate directly in the grid. */
body[data-mobile-mode="app"] #page-master-view.active .workshop-views{
  display:grid !important;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas:
    "spacer-l month-nav  filter"
    "view-tg  view-tg    view-tg";
  align-items:center;gap:8px 10px;
  padding:10px 14px 8px !important;
  overflow:visible !important;flex-wrap:nowrap;
  min-height:0
}
body[data-mobile-mode="app"] #page-master-view.active .workshop-views > [data-cal-tab-nav]{
  display:contents
}
body[data-mobile-mode="app"] #page-master-view.active .workshop-views .cal-month-nav{
  grid-area: month-nav;justify-self:center;gap:2px
}
body[data-mobile-mode="app"] #page-master-view.active .workshop-views .cal-view-toggle{
  grid-area: view-tg;justify-self:center;height:36px
}
body[data-mobile-mode="app"] #page-master-view.active .workshop-views .mv-filter-wrap{
  grid-area: filter;justify-self:end
}
/* Filter button on mobile: icon-only, no text */
body[data-mobile-mode="app"] #page-master-view.active .mv-filter-btn{
  width:38px;height:38px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  gap:0
}
body[data-mobile-mode="app"] #page-master-view.active .mv-filter-btn span,
body[data-mobile-mode="app"] #page-master-view.active .mv-filter-btn .mv-filter-caret{
  display:none !important
}
body[data-mobile-mode="app"] #page-master-view.active .mv-filter-btn svg:first-child{
  width:18px;height:18px
}
/* "+ Add" button is redundant on mobile (the bottom-nav [+] does this) */
body[data-mobile-mode="app"] #page-master-view.active .mv-add-btn{display:none !important}
/* Tighter Prev / Next on mobile so they don't overflow the row */
body[data-mobile-mode="app"] #page-master-view.active .cal-month-nav .workshop-view-btn{
  padding:6px 10px;font-size:12px;min-width:0
}
body[data-mobile-mode="app"] #page-master-view.active .cal-month-nav [data-cal-tab-nav-label]{
  min-width:140px !important;font-size:14px;font-weight:700
}

body[data-mobile-mode="app"] #mvCalendarPane{padding:8px 12px 28px !important}
body[data-mobile-mode="app"] .cal-with-sidebar{flex-direction:column}
body[data-mobile-mode="app"] .cal-sidebar{width:100% !important;margin-top:14px}
body[data-mobile-mode="app"] .calendar-day{min-height:54px;padding:4px}
/* ============================================================================
   MOBILE UI REBUILD — Calendar (turn 2 'cal'). Palette alignment: a purple
   "today" circle (was a coral-orange tint that clashed with the purple ink),
   ink day/weekday labels, a soft-purple Day/Week/Month toggle, and clean
   (bg-less) grid cells. The compact month grid + add-FAB already exist.
   ============================================================================ */
body[data-mobile-mode="app"] .calendar-day{background:transparent !important}
body[data-mobile-mode="app"] .calendar-day.other-month{background:transparent !important;opacity:.35}
/* NB: a later global `.calendar-day-num{color:rgba(235,235,245,.7)!important}`
   hardcodes near-white numbers (invisible on light theme) — beat it with an
   !important token colour, mobile-scoped. */
body[data-mobile-mode="app"] .calendar-day-num{color:rgba(var(--ink),0.75) !important}
body[data-mobile-mode="app"] .calendar-day.today .calendar-day-num{background:var(--m-accent) !important;color:#fff !important}
body[data-mobile-mode="app"] .calendar-day-label{color:rgba(var(--ink),0.4)}
body[data-mobile-mode="app"] .cal-view-toggle{background:rgba(var(--line),0.06) !important;border-radius:14px}
body[data-mobile-mode="app"] .cal-view-toggle button.is-active{background:var(--m-accent-soft) !important;color:#16121f !important;border-radius:10px}
/* ── Item B — Google-Calendar-style mobile month grid for the per-Project Calendar
   view (#workshopCalendarView / #cwCalendarView). Full-bleed 7-col grid filling the
   viewport (dvh), compact day cells with up to 3 task pills + "+N", today-circle,
   swipe between months, bottom-right add-FAB. Mobile only. ── */
body[data-mobile-mode="app"] #workshopCalendarView .cal-sidebar,
body[data-mobile-mode="app"] #cwCalendarView .cal-sidebar{display:none !important}
/* The active calendar view (shown via style.display='') must be a flex column so the grid
   chain can stretch to fill the page (hidden views keep their inline display:none). */
body[data-mobile-mode="app"] #workshopCalendarView,
body[data-mobile-mode="app"] #cwCalendarView{display:flex;flex-direction:column;min-height:0}
body[data-mobile-mode="app"] #workshopCalendarView .cal-with-sidebar,
body[data-mobile-mode="app"] #cwCalendarView .cal-with-sidebar{flex-direction:column;gap:0;flex:1;min-height:0}
/* padding-bottom reserves the fixed consolidated controls bar so the grid ends above it. */
body[data-mobile-mode="app"] #workshopCalendarView .calendar-container,
body[data-mobile-mode="app"] #cwCalendarView .calendar-container{padding:0 0 var(--cal-ctrls-h,54px);margin:0;flex:1;min-height:0;display:flex;flex-direction:column}
body[data-mobile-mode="app"] #workshopCalendarView .cal-grid-wrap,
body[data-mobile-mode="app"] #cwCalendarView .cal-grid-wrap{flex:1;min-height:0;display:flex;flex-direction:column}
/* Fit the WHOLE month on one screen: the grid flex-fills the space between the project
   header and the consolidated bottom controls bar, and divides it into a 14px weekday
   label row + N equal week rows (minmax(0,1fr) lets them shrink to fit — no scroll, so the
   first week can never get clipped). The container reserves the fixed controls bar below. */
body[data-mobile-mode="app"] #workshopCalendarView .calendar-grid,
body[data-mobile-mode="app"] #cwCalendarView .calendar-grid{
  flex:1 1 auto;min-height:0;height:auto;
  grid-template-rows:14px;grid-auto-rows:minmax(0,1fr);
  gap:1px;border-radius:0;background:var(--border-d);overflow:hidden;
}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-label,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-label{
  font-size:9px;font-weight:700;letter-spacing:.4px;color:var(--muted);
  text-transform:uppercase;display:flex;align-items:center;justify-content:center;
  background:var(--black);padding:0;margin:0
}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day{
  min-height:0;padding:3px 3px 2px;gap:2px;background:var(--black);
  align-items:stretch;overflow:hidden
}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day.other-month,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day.other-month{opacity:.34}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-num,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-num{
  font-size:11px;font-weight:600;color:var(--cream);margin:0 0 1px;align-self:flex-start;
  width:19px;height:19px;display:inline-flex;align-items:center;justify-content:center;border-radius:50%
}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day.today .calendar-day-num,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day.today .calendar-day-num{
  background:var(--purple);color:#fff;font-weight:700
}
/* On the tight mobile grid the "May 1" month-start label doesn't fit — show just the number. */
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-num.is-month-start .cdn-mon,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-num.is-month-start .cdn-mon{display:none}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-num.is-month-start,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-num.is-month-start{color:var(--cream);font-size:11px;padding:0}
/* Task pills: thin colored bars carrying the column color; up to 3, then "+N". */
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-card,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-card{
  padding:1px 4px;border-radius:3px;min-height:0;gap:0;
  background:color-mix(in srgb,var(--cal-dot-color,#999) 26%,transparent);
  border-left:2px solid var(--cal-dot-color,#999)
}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-card .cdc-dot,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-card .cdc-dot,
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-card .cdc-status,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-card .cdc-status{display:none}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-card .cdc-line,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-card .cdc-line{gap:0;width:100%}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-card .cdc-text,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-card .cdc-text{
  font-size:9px;line-height:1.4;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%
}
body[data-mobile-mode="app"] #workshopCalendarView .calendar-day-overflow,
body[data-mobile-mode="app"] #cwCalendarView .calendar-day-overflow{
  font-size:8.5px;color:var(--muted);padding:0 2px;font-weight:600;margin-top:1px
}
/* Bottom-right add-FAB (created/toggled by _enhanceMobileCalendar). */
.m-cal-fab{display:none !important}  /* purple calendar "+" FAB removed (leaked across views) */
/* Mobile Overview: hide chips entirely and show a small colored dot per
   day that has items. Tapping the day opens the pull-up sheet with the
   full task list. The dot is positioned absolutely below the day number. */
body[data-mobile-mode="app"] #page-master-view .calendar-day-card,
body[data-mobile-mode="app"] #page-master-view .calendar-day-overflow{display:none}
body[data-mobile-mode="app"] #page-master-view .calendar-day{
  position:relative;min-height:60px;padding:8px 4px 16px;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  cursor:pointer
}
body[data-mobile-mode="app"] #page-master-view .calendar-day-num{
  font-size:14px;font-weight:500;color:var(--cream);
  width:30px;height:30px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  background:none;margin-bottom:0
}
body[data-mobile-mode="app"] #page-master-view .calendar-day.today .calendar-day-num{
  background:#7c3aed;color:#fff;font-weight:600
}
body[data-mobile-mode="app"] #page-master-view .calendar-day.other-month{opacity:.3}
/* Numbered count badge under busy days on the mobile month grid. Set by
   _decorateMobileCalendarDots which writes the count into data-count and
   appends the .m-day-count element. 1–99 shown literally, anything more
   becomes "99+". */
body[data-mobile-mode="app"] #page-master-view .m-day-count{
  position:absolute;bottom:5px;left:50%;transform:translateX(-50%);
  min-width:20px;height:20px;padding:0 6px;border-radius:10px;
  background:rgba(139,92,246,.22);color:#c4b5fd;
  font-size:11px;font-weight:700;line-height:20px;text-align:center;
  font-variant-numeric:tabular-nums;letter-spacing:.1px;
  box-shadow:0 0 0 1px rgba(139,92,246,.18) inset;
  pointer-events:none
}
body[data-mobile-mode="app"] #page-master-view .calendar-day.today .m-day-count{
  background:rgba(255,255,255,.18);color:#fff;
  box-shadow:0 0 0 1px rgba(255,255,255,.22) inset
}
/* Bump the day cell a bit so the bigger badge has breathing room. */
body[data-mobile-mode="app"] #page-master-view .calendar-day{min-height:68px;padding-bottom:28px}
body[data-mobile-mode="app"] #page-master-view .calendar-day-label{
  font-size:10px;font-weight:600;color:var(--muted);padding:6px 2px;
  background:transparent
}
body[data-mobile-mode="app"] #page-master-view .calendar-grid{
  gap:0;background:transparent;border:0
}
body[data-mobile-mode="app"] #page-master-view .calendar-grid > *{background:transparent}
/* Hide the desktop sidebar (At a Glance / Upcoming) on mobile — the day
   sheet covers the same information surface. */
body[data-mobile-mode="app"] #page-master-view .cal-sidebar{display:none}

/* All pages in app-mode: pad below header / above nav so content isn't
   hidden by the fixed bars. */
/* Mobile: drop the board's file-tree breadcrumb (Sauce Media › Project). The workspace
   name is already in the top bar and the project name is in the big title below — the
   crumb is redundant. Scoped to the board headers so Home's "Home" crumb is untouched. */
body[data-mobile-mode="app"] #wsHeaderMain .ws-breadcrumb,
body[data-mobile-mode="app"] #wsHeaderCw .ws-breadcrumb{display:none}
body[data-mobile-mode="app"] .page.active{
  padding-top:var(--m-app-header-h, calc(56px + env(safe-area-inset-top,0px))) !important;padding-bottom:100px !important
}
/* Workshop/board pages use NEGATIVE margins on desktop to bleed into .content's
   28/36/60px padding. On mobile .content padding is 0, so that bleed had no padding
   to escape — the negative TOP margin (-16px) yanked the project title + view-switcher
   up BEHIND the fixed .m-app-header (which is taller than any guessed inset once the
   iOS safe-area/notch inflates it), so they vanished. Definitive fix: zero the bleed and
   reserve the EXACT header/hotbar heights (measured into --m-app-header-h / --m-hotbar-h
   by _syncMAppHeaderInset; the calc() fallbacks cover the first paint + the notch).
   100dvh tracks the iOS address bar shrinking mid-scroll. */
body[data-mobile-mode="app"] #page-workshop.active,
body[data-mobile-mode="app"] #page-custom-workshop.active{
  margin:0 !important;
  width:100% !important;max-width:100% !important;
  height:100dvh !important;
  padding-top:var(--m-app-header-h, calc(56px + env(safe-area-inset-top,0px))) !important;
  padding-bottom:var(--m-hotbar-h, calc(60px + env(safe-area-inset-bottom,0px))) !important;
}

/* ── Mobile card-modal polish ────────────────────────────────────────
   The desktop card modal already drops to a bottom sheet at ≤768px, but
   it still suffers from a couple of mobile UX issues:
     1) iOS Safari zooms in whenever you focus an input whose font-size
        is < 16px — typing in a comment, title, or description causes a
        jarring zoom-in that doesn't reset cleanly. Force all editable
        text in the modal to ≥16px on mobile to suppress the zoom.
     2) Touch scrolling inside the modal body was inheriting momentum
        from the parent .content area, which causes "rubber-band" fights
        between the modal and the page. Force momentum scrolling on the
        modal itself and lock the page beneath while it's open.
     3) The drag-handle bar at the top makes the bottom-sheet read as
        dismissable on mobile. */
/* FULL-SCREEN card modal on mobile (not a bottom sheet). The container
   takes over the entire viewport so properties have room to breathe and
   nothing gets clipped behind a sheet edge. */
/* Mobile card modal: top-left back arrow replaces the top-right close X */
.m-card-back{display:none}
body[data-mobile-mode="app"] .m-card-back{
  display:inline-flex;align-items:center;justify-content:center;
  width:40px;height:40px;margin:-4px 8px 0 -8px;flex-shrink:0;
  border:0;background:none;color:var(--cream);cursor:pointer;border-radius:10px;
  -webkit-tap-highlight-color:transparent;
}
body[data-mobile-mode="app"] .m-card-back:active{background:rgba(255,255,255,.06)}
body[data-mobile-mode="app"] .card-modal-x{display:none !important}
body[data-mobile-mode="app"] .card-modal-overlay{
  padding:0 !important;
  align-items:stretch !important;justify-content:stretch !important;
  background:var(--bg) !important;
  z-index:10000;
  overscroll-behavior:contain
}
body[data-mobile-mode="app"] .card-modal{
  max-width:100% !important;
  width:100% !important;
  /* #13/#C1 — was height:100vh, which let content overflow past the top/bottom with no
     internal scroll on iOS Safari (the dynamic address bar makes 100vh taller than the
     visible area). Use the svh cascade: svh is the SMALL viewport (address bar shown),
     so the card never exceeds the visible area and always scrolls internally. dvh/vh are
     fallbacks for browsers without svh; the last supported unit wins. */
  height:100vh !important;height:100dvh !important;height:100svh !important;
  max-height:100vh !important;max-height:100dvh !important;max-height:100svh !important;
  min-height:0 !important;
  overflow-y:auto !important;
  border-radius:0 !important;
  border:0 !important;
  /* #1 — tighten horizontal gutters to match the app's .content (12px) so the
     full-screen card uses the full mobile width instead of leaving dead space. */
  padding:calc(14px + env(safe-area-inset-top,0px)) 12px calc(24px + env(safe-area-inset-bottom,0px)) !important;
  -webkit-overflow-scrolling:touch !important;
  overscroll-behavior:contain;
  /* 3 — one normal scroll container: no snap, no smooth auto-scroll that fights the user
     when they scroll up to the header. */
  scroll-snap-type:none !important;scroll-behavior:auto !important;
  position:relative;
  background:var(--bg) !important
}
/* ============================================================================
   MOBILE UI REBUILD — Task detail (turn 4 'task'). Big title, uppercase muted
   section labels, description/properties/subtasks as surface cards, soft-purple
   tab pills, and the task action-bar as a floating rounded glass island.
   ============================================================================ */
body[data-mobile-mode="app"] .card-modal-title{font-size:var(--m-title) !important;font-weight:700 !important;letter-spacing:.2px;color:var(--ink-solid) !important;line-height:1.15}
body[data-mobile-mode="app"] .card-modal-section-title{font-size:var(--m-label);letter-spacing:.8px;color:rgba(var(--ink),0.45)}
/* Description content reads as a rounded surface card (mockup) */
body[data-mobile-mode="app"] .card-modal-description,
body[data-mobile-mode="app"] .card-modal-description-preview{
  background:var(--surface);border-radius:var(--m-radius-surface);padding:var(--m-pad) 15px;border:0;
  color:rgba(var(--ink),0.9);font-size:var(--m-body);line-height:1.6;min-height:110px
}
/* Tab pills — soft-purple active thumb, ink tokens */
body[data-mobile-mode="app"] .m-task-tab{border:0;background:rgba(var(--line),0.06);color:rgba(var(--ink),0.7)}
body[data-mobile-mode="app"] .m-task-tab.is-active{color:#16121f}
body[data-mobile-mode="app"] #mTaskTabs .m-pill-thumb{background:var(--m-accent-soft);border:0;border-radius:999px}
/* Task action bar → floating rounded glass island (mockup) */
body[data-mobile-mode="app"] #mTaskNav.open{
  left:var(--m-gutter);right:var(--m-gutter);bottom:calc(16px + env(safe-area-inset-bottom,0px));
  padding:0 var(--m-gap);height:var(--m-island-h);border-radius:var(--m-radius-island);border-top:0;
  background:rgba(var(--surface-rgb),0.72);
  backdrop-filter:blur(36px) saturate(200%);-webkit-backdrop-filter:blur(36px) saturate(200%);
  border:0.5px solid rgba(var(--line),0.14);
  box-shadow:inset 0 0.8px 0 rgba(255,255,255,0.5),inset 0 -0.6px 0 rgba(0,0,0,0.06),0 16px 36px rgba(0,0,0,0.32)
}
body[data-mobile-mode="app"] .m-tn-item{color:rgba(var(--ink),0.55);font-size:10px;font-weight:600}
body[data-mobile-mode="app"] .m-tn-back{color:var(--ink-solid)}
/* 3 — when a task is open the card is full-screen; hide the workspace header so the card's
   own top row ("Created by …") isn't tucked behind it or fighting the scroll. */
/* #2 — when a task is open, ONLY the task hotbar (#mTaskNav: Subtasks/Back/Properties)
   should show. The main bottom nav (Modify/Back/Add) was left visible, stacking a second
   hotbar under the floating task island. Hide it (and the workspace header) while open. */
body[data-mobile-mode="app"][data-card-open] .m-app-header,
body[data-mobile-mode="app"][data-card-open] .m-bottom-nav{display:none !important}
/* No drag-handle pseudo-element in full-screen mode. */
body[data-mobile-mode="app"] .card-modal::before{display:none !important}

/* #1 — the "Created … by …" + status line must never overflow the viewport on
   mobile. On a narrow screen the date + the status dropdown couldn't both fit on
   one line (the line had flex-wrap:nowrap), so the status control was pushed past
   the right edge and clipped. Let the line wrap and keep its parts within bounds. */
body[data-mobile-mode="app"] .card-modal-meta{flex-wrap:wrap;gap:6px 10px}
body[data-mobile-mode="app"] .card-modal-meta > #cardModalDate{min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] #cardModalColWrap{max-width:100%}
body[data-mobile-mode="app"] #cardModalColWrap .ms-dropdown{max-width:100%}
body[data-mobile-mode="app"] #cardModalColWrap .status-badge{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 2 — Instagram-style action row below the description (mobile only): Comments + Share
   on the left, the status pill (relocated from the header) on the right. */
#mCardActionRow{display:none}
body[data-mobile-mode="app"] #mCardActionRow{display:flex;align-items:center;gap:20px;padding:10px 2px 14px;margin-bottom:8px;border-bottom:1px solid var(--border-d)}
body[data-mobile-mode="app"] .m-card-act{display:inline-flex;align-items:center;gap:6px;background:none;border:0;padding:2px;color:var(--off-white);cursor:pointer;font-family:var(--sans);-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .m-card-act:active{opacity:.6}
body[data-mobile-mode="app"] .m-card-act svg{width:var(--m-icon-xl);height:var(--m-icon-xl)}
body[data-mobile-mode="app"] .m-card-act-ct{font-size:14px;font-weight:600;color:var(--cream)}
body[data-mobile-mode="app"] .m-card-act-spacer{flex:1}
body[data-mobile-mode="app"] #mCardActionRow #cardModalColWrap{margin-left:auto;flex-shrink:0;max-width:60%}
/* 1 — mobile task-detail top tabs: pill bar (matches Home/Settings section switchers). */
#mTaskTabs{display:none}
/* #1 — room to breathe: the pill row sat flush against the description card (0px gap),
   and overflow-x:auto forces overflow-y:auto which was clipping the pills. Add bottom
   margin so the description no longer crowds/covers the tabs, and a hair more vertical
   padding so no pill (or its active thumb) gets clipped. */
body[data-mobile-mode="app"] #mTaskTabs{display:flex;gap:7px;overflow-x:auto;overflow-y:hidden;margin:2px -12px 16px;padding:10px 12px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
body[data-mobile-mode="app"] #mTaskTabs > .m-task-tab:last-child{margin-right:0}
body[data-mobile-mode="app"] #mTaskTabs::-webkit-scrollbar{display:none}
/* Shape comes from the mobile tab tokens (tokens.css → Design Rules #dr-mobile).
   Only color/border live here. */
body[data-mobile-mode="app"] .m-task-tab{position:relative;z-index:1;box-sizing:border-box;flex:0 0 auto;white-space:nowrap;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);font-family:var(--sans);font-size:var(--m-tab-font);font-weight:var(--m-tab-weight);padding:0 var(--m-tab-pad-x);border-radius:var(--m-tab-radius);min-height:var(--m-tab-h);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:color .22s ease,border-color .22s ease}
body[data-mobile-mode="app"] .m-task-tab.is-active{background:transparent;border-color:transparent;color:var(--off-white)}   /* Item A — highlight is the sliding thumb */
/* #7 — Main/Files/Review/Publish/History were natural-width pills in an overflow-x:auto
   strip, so the 5th tab clipped off-screen in portrait. Make them equal-width segments
   that divide the bar; they fit both portrait and landscape (the strip no longer scrolls). */
body[data-mobile-mode="app"] #mTaskTabs{gap:var(--m-tab-gap);overflow:hidden}
body[data-mobile-mode="app"] #mTaskTabs .m-task-tab{
  flex:1 1 0;min-width:0;padding:0 4px;text-align:center;
  display:flex;align-items:center;justify-content:center;
}
/* The card modal gives every button inside it a 38px touch floor. That rule is
   more specific than the tab rule, so it — not --m-tab-h — was deciding the tab
   height, and raising the token would have had no effect. Re-assert the token
   for the tab pill so the design-rules value really is the parent. */
body[data-mobile-mode="app"] .card-modal button.m-task-tab{min-height:var(--m-tab-h)}
body[data-mobile-mode="app"] #cardModalTabs{display:none !important}   /* desktop tab bar replaced by #mTaskTabs on mobile */
/* Item A — IG-style sliding selection thumb, shared by every mobile pill bar (bottom
   hotbar + Home/Stage/Task/Publish top tabs). One thumb per bar slides to the active
   item; the bar is the track, items are transparent, the thumb is the moving highlight. */
.m-pillbar{position:relative}
.m-pill-thumb{
  position:absolute;left:0;top:0;z-index:0;box-sizing:border-box;
  background:color-mix(in srgb,var(--purple) 20%,transparent);
  border:1px solid color-mix(in srgb,var(--purple) 42%,transparent);
  border-radius:999px;pointer-events:none;opacity:0;
  transition:transform var(--tab-slide-dur) var(--tab-slide-ease),width var(--tab-slide-dur) var(--tab-slide-ease),height var(--tab-slide-dur) var(--tab-slide-ease),opacity .15s ease;
}
.m-pill-thumb.show{opacity:1}
/* The bottom hotbar's thumb reads better with no outline (filled tab highlight). */
#mBottomNav .m-pill-thumb{border-color:transparent;background:color-mix(in srgb,var(--purple) 16%,transparent)}
/* 15 — IG-style comments sheet. Inline comments hidden on mobile (reached via the
   action-row Comments button); shown only when moved into the sheet. */
/* 26/33 — comments as a 40vh bottom sheet over a dim+blur backdrop. The container stays
   laid out (visibility-toggled, not display:none) so the panel slide + backdrop fade BOTH
   transition cleanly on open AND close. Backdrop is a ::before so it fades independent of
   the panel. */
#mCommentsSheet{
  position:fixed;inset:0;z-index:10060;
  display:flex;flex-direction:column;justify-content:flex-end;
  visibility:hidden;pointer-events:none;
  transition:visibility 0s linear .34s;   /* on close: stay visible through the slide-out */
}
#mCommentsSheet::before{
  content:'';position:absolute;inset:0;
  background:rgba(0,0,0,.82);   /* item 8: opaque enough to hide the task behind (was .45, see-through) */
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  opacity:0;transition:opacity .3s ease;
}
body[data-mobile-mode="app"] #cardModalCommentsGlobal{display:none !important}
#mCommentsSheet.open{visibility:visible;pointer-events:auto;transition:visibility 0s}
#mCommentsSheet.open::before{opacity:1}
.m-csheet-panel{
  position:relative;display:flex;flex-direction:column;
  height:95vh;height:95dvh;max-height:95dvh;
  background:#0a0a09;border-radius:18px 18px 0 0;border-top:1px solid var(--border-d);
  box-shadow:0 -12px 40px rgba(0,0,0,.5);overflow:hidden;
  transform:translateY(100%);
  transition:transform .34s cubic-bezier(.22,1,.36,1);
  will-change:transform
}
/* Snap offset is driven inline by JS (translateY); .open just guarantees the panel is on
   screen before the JS applies the default 75dvh snap. */
#mCommentsSheet.open .m-csheet-panel{transform:translateY(20vh)}
.m-csheet-grabber{flex-shrink:0;display:flex;align-items:center;justify-content:center;padding:8px 0 4px;cursor:grab;touch-action:none}
.m-csheet-grip{width:38px;height:5px;border-radius:999px;background:rgba(255,255,255,.22)}
.m-csheet-head{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:6px 16px 12px;border-bottom:1px solid var(--border-d)}
.m-csheet-title{font-family:var(--sans);font-size:17px;font-weight:700;color:var(--off-white)}
.m-csheet-x{background:none;border:0;color:var(--off-white);cursor:pointer;display:inline-flex;padding:4px;-webkit-tap-highlight-color:transparent}
.m-csheet-body{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding:12px 14px calc(14px + env(safe-area-inset-bottom,0px))}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentsGlobal{display:block !important}
/* The moved comments component carries its own "Comments" section title; the sheet header
   already shows the big "Comments" + close button, so hide the duplicate inside the sheet. */
body[data-mobile-mode="app"] #mCommentsSheet .card-modal-section-title{display:none}
/* ── IG-style composer row (mobile comments sheet) ──
   [avatar] [input pill ........] [image] [mic] [Send].  Idle: avatar + mic + attach.
   Typing (.has-content): avatar→add-image, mic+attach hide, purple Send appears. */
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput{
  position:sticky;bottom:0;z-index:2;background:#0a0a09;
  display:flex;align-items:flex-end;gap:6px;margin-top:6px;
  padding:8px 12px calc(8px + env(safe-area-inset-bottom,0px));
}
body[data-mobile-mode="app"] #mCommentsSheet #cardCommentInput{
  flex:1 1 auto;min-width:0;border-radius:18px;background:rgba(255,255,255,.06);
  padding:9px 14px !important;max-height:120px;
}
/* mic + attach → static flex items to the right of the pill; hidden once typing */
body[data-mobile-mode="app"] #mCommentsSheet .comment-mic-btn,
body[data-mobile-mode="app"] #mCommentsSheet .comment-attach-btn{
  position:static !important;transform:none !important;flex:0 0 auto;
  width:30px;height:30px;display:flex;align-items:center;justify-content:center;
  margin:0 0 3px 0;color:rgba(255,255,255,.55);
}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput.has-content .comment-mic-btn,
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput.has-content .comment-attach-btn{display:none}
/* left avatar / add-image */
body[data-mobile-mode="app"] #mCommentsSheet .m-cmt-avatar{
  flex:0 0 auto;width:30px;height:30px;padding:0;border:0;background:none;cursor:default;
  display:flex;align-items:center;justify-content:center;margin-bottom:3px;-webkit-tap-highlight-color:transparent;
}
.m-cmt-avatar .m-cmt-av-pfp{display:flex;transition:opacity .12s}
.m-cmt-avatar .m-cmt-av-add{display:none;color:var(--cream)}
.m-cmt-avatar .m-cmt-av-add svg{width:23px;height:23px}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput.has-content .m-cmt-avatar{cursor:pointer}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput.has-content .m-cmt-av-pfp{display:none}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput.has-content .m-cmt-av-add{display:flex}
/* purple Send (paper-plane) — only with content */
body[data-mobile-mode="app"] #mCommentsSheet .m-cmt-send{
  flex:0 0 auto;width:34px;height:34px;padding:0;border:0;background:none;cursor:pointer;
  display:none;align-items:center;justify-content:center;margin-bottom:1px;-webkit-tap-highlight-color:transparent;
}
body[data-mobile-mode="app"] #mCommentsSheet .m-cmt-send svg{width:25px;height:25px;color:var(--purple,#8c72db)}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput.has-content .m-cmt-send{display:flex;animation:cmtSendIn .12s ease both}
@keyframes cmtSendIn{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:scale(1)}}
html[data-theme="light"] body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput{background:var(--bg2)}
html[data-theme="light"] body[data-mobile-mode="app"] #mCommentsSheet #cardCommentInput{background:var(--surface)}
/* The card's delete area belongs to the desktop modal, not the comments sheet — hide it here. */
body[data-mobile-mode="app"] #mCommentsSheet #cardModalDeleteArea{display:none !important}
/* ============================================================================
   MOBILE UI REBUILD — Comments sheet (turn 4 'comments'). IG-style: a --bg2
   sheet with a 26px top radius, 22px title, avatar + name + time comment rows
   on the ink tokens, and a rounded surface composer pill.
   ============================================================================ */
body[data-mobile-mode="app"] .m-csheet-panel{background:var(--bg2);border-radius:26px 26px 0 0;border-top:0}
body[data-mobile-mode="app"] .m-csheet-grip{background:rgba(var(--ink),0.2)}
body[data-mobile-mode="app"] .m-csheet-head{border-bottom:0.5px solid rgba(var(--line),0.07);padding:6px 18px 12px}
body[data-mobile-mode="app"] .m-csheet-title{font-size:22px;color:var(--ink-solid);letter-spacing:.2px}
body[data-mobile-mode="app"] .m-csheet-x{color:rgba(var(--ink),0.7)}
body[data-mobile-mode="app"] #mCommentsSheet .card-comment{border-bottom:0 !important;padding:8px 0 14px;font-size:14px}
body[data-mobile-mode="app"] #mCommentsSheet .card-comment-author{font-size:14px;color:var(--ink-solid)}
body[data-mobile-mode="app"] #mCommentsSheet .card-comment-time{font-size:12px;color:rgba(var(--ink),0.4)}
body[data-mobile-mode="app"] #mCommentsSheet .card-comment-text{font-size:14px;color:rgba(var(--ink),0.85);line-height:1.5;margin-top:3px}
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput{background:var(--bg2);border-top:0.5px solid rgba(var(--line),0.07)}
body[data-mobile-mode="app"] #mCommentsSheet #cardCommentInput{background:var(--surface);border-radius:20px}
/* The legacy floating mention popup is replaced by the full-area picker on mobile. Hide it
   globally (setupMentionPopup re-parents it to <body>, so a sheet-scoped selector misses it;
   on mobile the comment composer only ever lives in the sheet, so this is safe). */
body[data-mobile-mode="app"] #commentMentionPopup{display:none !important}
/* ── Full-area @-mention picker (replaces the comment list while typing @) ── */
.m-cmt-mpick{display:none;flex-direction:column;gap:1px;padding:6px 4px 10px;overflow-y:auto;-webkit-overflow-scrolling:touch;animation:cmtPickIn .16s ease both}
.m-cmt-mpick.open{display:flex}
@keyframes cmtPickIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.m-cmt-mpick-row{display:flex;align-items:center;gap:11px;width:100%;padding:9px 10px;border:0;background:none;cursor:pointer;border-radius:10px;text-align:left;font-family:var(--sans);-webkit-tap-highlight-color:transparent}
.m-cmt-mpick-row:active{background:rgba(255,255,255,.06)}
.m-cmt-mpick-av{flex:0 0 auto;display:flex;width:36px;height:36px;border-radius:50%;overflow:hidden}
.m-cmt-mpick-av img,.m-cmt-mpick-av svg{width:36px !important;height:36px !important;object-fit:cover;border-radius:50%} /* hard cap so a real photo can't blow up (matches the desktop mention-popup fix) */
.m-cmt-mpick-meta{display:flex;flex-direction:column;min-width:0;gap:1px}
.m-cmt-mpick-name{font-size:14px;font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.m-cmt-mpick-handle{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.m-cmt-mpick-empty{padding:24px;text-align:center;color:var(--muted);font-size:13px}
html[data-theme="light"] .m-cmt-mpick-row:active{background:rgba(0,0,0,.05)}
/* 16/26/33 — iOS-Messages long-press overlay: blurred backdrop + a centered sharp group
   (reaction picker / selected-comment clone / context menu). Backdrop fade + each part's
   entrance are keyframe animations (play reliably from display:none) tuned to land together
   as ONE coordinated motion — picker drops in from above, clone lifts, menu rises from below. */
#mCommentLP{display:none}
#mCommentLP.open{display:block}
.mlp-backdrop{position:fixed;inset:0;z-index:10080;background:rgba(0,0,0,.48);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);animation:mlpFade .22s ease both}
.mlp-stage{position:fixed;inset:0;z-index:10082;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:24px;pointer-events:none}
.mlp-stage > *{pointer-events:auto}
@keyframes mlpFade{from{opacity:0}to{opacity:1}}
@keyframes mlpPick{from{opacity:0;transform:translateY(-10px) scale(.96)}to{opacity:1;transform:none}}
@keyframes mlpLift{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
@keyframes mlpMenu{from{opacity:0;transform:translateY(12px) scale(.97)}to{opacity:1;transform:none}}
.mlp-picker{animation:mlpPick .24s cubic-bezier(.22,1.1,.36,1) both}
.mlp-clone{animation:mlpLift .24s cubic-bezier(.22,1.1,.36,1) both}
.mlp-menu{animation:mlpMenu .24s cubic-bezier(.22,1.1,.36,1) both}
.mlp-clone{max-width:88vw;background:var(--dark);border:1px solid var(--border-d);border-radius:12px;padding:10px 12px;box-shadow:0 10px 32px rgba(0,0,0,.55);max-height:40vh;overflow:hidden}
.mlp-clone .card-comment{position:static !important}
.mlp-picker{display:flex;gap:4px;background:var(--dark);border:1px solid var(--border-d);border-radius:999px;padding:6px 8px;box-shadow:0 8px 28px rgba(0,0,0,.5)}
.mlp-react{background:none;border:0;font-size:24px;line-height:1;padding:4px;cursor:pointer;-webkit-tap-highlight-color:transparent;border-radius:50%}
.mlp-react:active{background:rgba(255,255,255,.12)}
.mlp-plus{font-size:20px;color:var(--cream);width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center}
.mlp-menu{min-width:220px;max-width:80vw;background:var(--dark);border:1px solid var(--border-d);border-radius:14px;overflow:hidden;box-shadow:0 8px 28px rgba(0,0,0,.5)}
.mlp-ts{padding:9px 16px;font-size:11px;color:var(--muted);border-bottom:1px solid rgba(255,255,255,.06)}
.mlp-row{display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:0;color:var(--off-white);font-family:var(--sans);font-size:16px;padding:13px 16px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.mlp-row:not(:last-child){border-bottom:1px solid rgba(255,255,255,.06)}
.mlp-row:active{background:rgba(255,255,255,.05)}
.mlp-row svg{width:19px;height:19px;flex-shrink:0;margin-left:14px}
.mlp-danger{color:#ff453a}
/* 21 — iOS-native-style confirmation alert (centralized via showConfirmAlert). */
.m-alert-overlay{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(0,0,0,.45);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);opacity:0;transition:opacity .2s ease}
.m-alert-overlay.open{opacity:1}
.m-alert-card{width:270px;max-width:90vw;background:rgba(34,34,36,.92);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,.1);border-radius:16px;overflow:hidden;text-align:center;transform:scale(.85);opacity:0;transition:transform .22s cubic-bezier(.34,1.56,.64,1),opacity .18s ease}
.m-alert-overlay.open .m-alert-card{transform:scale(1);opacity:1}
.m-alert-title{font-family:var(--sans);font-size:17px;font-weight:600;color:#fff;padding:20px 18px 0}
.m-alert-msg{font-family:var(--sans);font-size:13px;color:rgba(235,235,235,.7);padding:6px 18px 0;line-height:1.42;white-space:pre-wrap}
.m-alert-actions{display:flex;margin-top:18px;border-top:1px solid rgba(255,255,255,.12)}
.m-alert-actions.one{flex-direction:column}
.m-alert-actions.two .m-alert-btn:first-child{border-right:1px solid rgba(255,255,255,.12)}
.m-alert-btn{flex:1;background:none;border:0;padding:13px 8px;font-family:var(--sans);font-size:16px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.m-alert-btn:active{background:var(--state-hover)}
.m-alert-cancel{color:#fff;font-weight:400}
.m-alert-confirm{color:#0a84ff;font-weight:600}
.m-alert-danger{color:#ff453a;font-weight:600}
/* 17 — task-detail bottom nav (Subtasks / Back / Properties) shown over the card modal. */
#mTaskNav{display:none}
/* #8 — this rule used to override the island above with a flat edge-to-edge near-black
   bar (bottom:0, no radius). Rebuild it to match the main .m-bottom-nav Liquid-Glass
   island exactly (rounded, floating, translucent surface) so the task hotbar reads the
   same as the primary hotbar. z-index stays above the card modal (10001). */
body[data-mobile-mode="app"] #mTaskNav.open{
  display:flex;align-items:center;justify-content:space-around;
  position:fixed;left:16px;right:16px;bottom:calc(22px + env(safe-area-inset-bottom,0px));z-index:10001;
  height:56px;min-height:0;padding:0 8px;gap:0;border-radius:30px;
  background:rgba(var(--surface-rgb),0.72);
  backdrop-filter:blur(36px) saturate(200%);-webkit-backdrop-filter:blur(36px) saturate(200%);
  border:0.5px solid rgba(var(--line),0.14);
  box-shadow:inset 0 0.8px 0 rgba(255,255,255,0.75),inset 0 -0.6px 0 rgba(0,0,0,0.06),0 16px 36px rgba(0,0,0,0.55)
}
.m-tn-item{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;min-height:var(--m-touch-min,44px);padding:4px 3px;border:0;background:none;cursor:pointer;color:var(--muted);font-family:var(--sans);font-size:11px;font-weight:500;border-radius:12px;-webkit-tap-highlight-color:transparent}
.m-tn-item:active{background:rgba(255,255,255,.06)}
.m-tn-item svg{width:var(--m-icon-lg,22px);height:var(--m-icon-lg,22px)}
.m-tn-back{color:var(--off-white)}
/* leave room for the task nav so card content isn't hidden behind it */
body[data-mobile-mode="app"][data-card-open] .card-modal{padding-bottom:calc(74px + env(safe-area-inset-bottom,0px)) !important}
/* Subtasks + Properties move out of the body on mobile into their own sheets. */
body[data-mobile-mode="app"] #cardModalTabMain #cardModalSubtasksInline,
body[data-mobile-mode="app"] #cardModalTabMain #cardModalCustomFields{display:none !important}
.m-fsheet{display:none;position:fixed;inset:0;z-index:10062;background:#0a0a09}
body[data-mobile-mode="app"] .m-fsheet.open{display:flex;flex-direction:column}
/* #3 — full-screen task sub-pages (Subtasks / Properties / Status) get a bottom Back
   hotbar instead of a top-right X. Flows as the last flex child, below the scroll body. */
.m-fsheet-hotbar{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:8px;padding:10px 16px calc(10px + env(safe-area-inset-bottom,0px));border-top:1px solid var(--border-d)}
.m-fsheet-hb-back{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:9px 26px;border:0;border-radius:999px;background:rgba(255,255,255,.07);color:var(--off-white);font-family:var(--sans);font-size:14px;font-weight:600;cursor:pointer;-webkit-tap-highlight-color:transparent}
.m-fsheet-hb-back:active{background:rgba(255,255,255,.13)}
.m-fsheet-hb-back svg{width:18px;height:18px}
body[data-mobile-mode="app"] .m-fsheet-hotbar{border-top-color:rgba(var(--line),0.09)}
body[data-mobile-mode="app"] .m-fsheet-hb-back{background:rgba(var(--line),0.07);color:var(--ink-solid)}
body[data-mobile-mode="app"] .m-fsheet .m-csheet-body #cardModalSubtasksInline,
body[data-mobile-mode="app"] .m-fsheet .m-csheet-body #cardModalCustomFields,
body[data-mobile-mode="app"] .m-secsheet .m-csheet-body #cardModalSubtasksInline,
body[data-mobile-mode="app"] .m-secsheet .m-csheet-body #cardModalCustomFields{display:block !important}
/* 19 — status full-page picker options */
.m-status-list{display:flex;flex-direction:column}
.m-status-opt{display:flex;align-items:center;gap:12px;width:100%;background:none;border:0;border-bottom:1px solid rgba(255,255,255,.06);color:var(--off-white);font-family:var(--sans);font-size:16px;padding:15px 8px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.m-status-opt:active{background:rgba(255,255,255,.05)}
.m-status-dot{width:12px;height:12px;border-radius:50%;flex-shrink:0}
.m-status-nm{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-status-check{width:18px;height:18px;color:var(--coral);flex-shrink:0}
/* 18/4 — description toolbar hidden until focused; shown as a keyboard-accessory bar.
   !important is required because openCardModal sets an inline display:flex on this element. */
/* 27 — no custom formatting toolbar on mobile; the description uses the native iOS keyboard. */
body[data-mobile-mode="app"] #cardDescToolbar{display:none !important}
/* Task-detail polish — description fills the available vertical space (no dead void above
   the action row); the delete icon is white like the others (red only in the confirm alert);
   completed state shows a green strikethrough title + filled green check. */
body[data-mobile-mode="app"] #cardModalDescription{min-height:max(200px, calc(100dvh - 360px)) !important;overflow-y:auto}
body[data-mobile-mode="app"] .m-card-act-del{color:var(--off-white)}
body[data-mobile-mode="app"] #cardModalTitle.m-title-complete{
  text-decoration:line-through;text-decoration-color:var(--green,#86c06c);text-decoration-thickness:3px;color:var(--muted)
}
body[data-mobile-mode="app"] .m-card-act-complete.is-complete svg{width:26px;height:26px}

/* ANTI-ZOOM: every editable field in the modal must be ≥16px. This is
   the single most important fix — iOS uses 16px as the threshold below
   which it zooms in on focus. */
body[data-mobile-mode="app"] .card-modal input,
body[data-mobile-mode="app"] .card-modal textarea,
body[data-mobile-mode="app"] .card-modal select,
body[data-mobile-mode="app"] .card-modal [contenteditable="true"],
body[data-mobile-mode="app"] .card-modal .card-modal-title,
body[data-mobile-mode="app"] .card-modal .card-modal-description,
body[data-mobile-mode="app"] .card-modal .comment-input,
body[data-mobile-mode="app"] .card-modal .kanban-input{
  font-size:16px !important;
  /* line-height bumped to match the larger font cleanly */
  line-height:1.45;
}
body[data-mobile-mode="app"] .card-modal .card-modal-title{font-size:20px !important;line-height:1.25}
/* Tappable controls (44px minimum target) */
body[data-mobile-mode="app"] .card-modal button{min-height:38px}
body[data-mobile-mode="app"] .card-modal .card-modal-close,
body[data-mobile-mode="app"] .card-modal .modal-close{min-width:44px;min-height:44px}

/* Modal body should be the only scroll container — disable page scroll
   beneath when modal is open. The existing closeCardModal already runs
   `document.body.style.overflow` tweaks via the day-sheet helper, but
   the card modal doesn't — add a defensive rule here too. */
body[data-mobile-mode="app"]:has(.card-modal-overlay:not([style*="display: none"])){
  overflow:hidden
}

/* Inputs inside the modal: looser tap targets + better spacing */
body[data-mobile-mode="app"] .card-modal .comment-input,
body[data-mobile-mode="app"] .card-modal .reply-input{
  padding:12px 14px !important;border-radius:12px !important
}
/* The description editor — comfortable touch padding + lift toolbar buttons */
body[data-mobile-mode="app"] .card-modal .card-modal-description{
  min-height:120px;padding:12px 14px !important;border-radius:12px !important
}
body[data-mobile-mode="app"] .card-modal .card-modal-desc-toolbar button,
body[data-mobile-mode="app"] .card-modal #cardDescToolbar button{
  min-width:36px;min-height:36px;font-size:14px !important
}
/* The native date picker tap target was tiny */
body[data-mobile-mode="app"] .card-modal input[type="date"],
body[data-mobile-mode="app"] .card-modal input[type="datetime-local"]{
  min-height:42px;padding:10px 12px !important
}
/* Tabs (Main / History / +) — bump touch targets */
body[data-mobile-mode="app"] .card-modal .card-modal-tab{padding:10px 14px !important;font-size:14px !important;flex:0 0 auto;white-space:nowrap}
/* #14b — card tabs scroll horizontally instead of wrapping/overflowing on mobile */
body[data-mobile-mode="app"] .card-modal .card-modal-tabs{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:none}
body[data-mobile-mode="app"] .card-modal .card-modal-tabs::-webkit-scrollbar{height:0}
/* Comments list: comfortable spacing */
body[data-mobile-mode="app"] .card-modal .card-comment{padding:12px !important}
body[data-mobile-mode="app"] .card-modal .card-comment-text{font-size:14px;line-height:1.5}

/* Force-circle every avatar on mobile. The desktop CSS already sets
   border-radius:50% on .card-avatar / .user-mini-avatar, but flex
   containers + iOS Safari occasionally stretch them into ovals when
   width/height get clobbered by surrounding flex shrink. aspect-ratio
   pins them to 1:1 and flex-shrink:0 prevents the squish. */
body[data-mobile-mode="app"] .card-avatar,
body[data-mobile-mode="app"] .user-mini-avatar,
body[data-mobile-mode="app"] .prop-person-dropdown-item .card-avatar,
body[data-mobile-mode="app"] .prop-person-dropdown-item .user-mini-avatar{
  aspect-ratio:1 / 1 !important;
  flex-shrink:0 !important;
  border-radius:50% !important;
  overflow:hidden !important
}
body[data-mobile-mode="app"] .card-avatar img,
body[data-mobile-mode="app"] .user-mini-avatar img{
  width:100% !important;height:100% !important;
  aspect-ratio:1 / 1 !important;
  object-fit:cover !important;
  border-radius:50% !important;
  display:block
}

/* Properties panel — pills/values need to wrap cleanly on mobile so they
   don't overflow the row and bleed under the field label. */
body[data-mobile-mode="app"] .card-modal .property-row,
body[data-mobile-mode="app"] .card-modal .card-modal-property-row{
  flex-wrap:wrap !important;align-items:flex-start !important;
  gap:8px;padding:10px 0
}
body[data-mobile-mode="app"] .card-modal .property-label,
body[data-mobile-mode="app"] .card-modal .card-modal-property-label{
  font-size:13px !important;min-width:110px !important;flex-shrink:0
}
body[data-mobile-mode="app"] .card-modal .property-value,
body[data-mobile-mode="app"] .card-modal .card-modal-property-value{
  flex:1;min-width:0;flex-wrap:wrap !important;gap:6px !important
}
/* Property pills (status, person, tags, mirror, etc.) — keep them compact
   and never overflowing their row. */
body[data-mobile-mode="app"] .card-modal .prop-pill{
  font-size:13px !important;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
body[data-mobile-mode="app"] .card-modal .prop-pill-add,
body[data-mobile-mode="app"] .card-modal .prop-pill-remove{min-width:24px;min-height:24px}

/* ── Unified property popups on mobile ───────────────────────────────
   Every property-related dropdown — Person picker, multi-select picker,
   color picker, field-type picker, ctx menu (Route to…) — shares the
   EXACT same bottom-sheet look: full-width, anchored to the bottom,
   shows roughly 3 items at once, scrolls for more. Inline JS-set
   left/top positioning is overridden with !important so nothing spills
   off-screen on phones. */
body[data-mobile-mode="app"] .prop-person-dropdown,
body[data-mobile-mode="app"] .prop-multi-dropdown,
body[data-mobile-mode="app"] .prop-color-picker,
body[data-mobile-mode="app"] .prop-type-picker,
body[data-mobile-mode="app"] .prop-ctx-menu{
  position:fixed !important;
  left:12px !important;right:12px !important;top:auto !important;
  bottom:calc(20px + env(safe-area-inset-bottom,0px)) !important;
  width:auto !important;max-width:none !important;
  /* Constrain min-width so JS-set inline values (e.g. min-width:200px)
     don't make the sheet narrower than the screen on small phones. */
  min-width:0 !important;
  /* Roughly 3 items at ~52px each + ~12px padding = 168px. Headers /
     search inputs add ~60px when present. Cap at ~280px so the sheet
     stays compact and the user sees the calendar context behind it. */
  max-height:min(48vh,280px) !important;
  border-radius:16px !important;
  padding:14px !important;
  background:#15151a !important;
  border:1px solid var(--border-d) !important;
  box-shadow:0 -8px 32px rgba(0,0,0,.45),0 0 0 1px rgba(255,255,255,.04) !important;
  z-index:10100 !important;
  overflow-y:auto !important;
  overscroll-behavior:contain !important;
  -webkit-overflow-scrolling:touch !important;
  /* Slide-up entry animation so it reads as a sheet, not a popup. */
  animation:mPropDdIn .22s cubic-bezier(.22,1,.36,1) both
}
@keyframes mPropDdIn{
  from{opacity:0;transform:translateY(20px)}
  to{opacity:1;transform:none}
}
/* Drag-handle visual at the top of every property sheet for consistency. */
body[data-mobile-mode="app"] .prop-person-dropdown::after,
body[data-mobile-mode="app"] .prop-multi-dropdown::after,
body[data-mobile-mode="app"] .prop-color-picker::after,
body[data-mobile-mode="app"] .prop-type-picker::after,
body[data-mobile-mode="app"] .prop-ctx-menu::after{
  content:'';position:sticky;top:0;left:0;right:0;
  display:block;width:38px;height:4px;border-radius:2px;
  background:rgba(255,255,255,.18);
  margin:-6px auto 8px;
  pointer-events:none
}
/* Search input inside any property dropdown — full width, no iOS zoom. */
body[data-mobile-mode="app"] .prop-person-dropdown-search,
body[data-mobile-mode="app"] .prop-multi-dropdown input,
body[data-mobile-mode="app"] .prop-multi-dropdown-search{
  width:100% !important;
  font-size:16px !important;
  padding:11px 12px !important;
  border-radius:10px !important;
  margin-bottom:8px;box-sizing:border-box;
  background:rgba(255,255,255,.06);border:1px solid var(--border-d);color:var(--cream);outline:none
}
/* List items inside any property dropdown: touch-sized, consistent. */
body[data-mobile-mode="app"] .prop-person-dropdown-item,
body[data-mobile-mode="app"] .prop-multi-dropdown-item,
body[data-mobile-mode="app"] .prop-ctx-menu button{
  padding:12px !important;
  min-height:48px;font-size:14px !important;
  border-radius:10px;
  display:flex;align-items:center;gap:10px;
  width:100%;box-sizing:border-box;
  background:none;border:0;color:var(--cream);
  text-align:left;cursor:pointer
}
body[data-mobile-mode="app"] .prop-person-dropdown-item:active,
body[data-mobile-mode="app"] .prop-multi-dropdown-item:active,
body[data-mobile-mode="app"] .prop-ctx-menu button:active{background:rgba(255,255,255,.06)}
body[data-mobile-mode="app"] .prop-color-picker{
  padding:18px 14px !important;
  justify-content:center;flex-wrap:wrap;gap:8px
}
/* Backdrop behind any property dropdown so taps outside dismiss it
   without showing through to the card modal weirdly. */
body[data-mobile-mode="app"] .prop-person-dropdown::before,
body[data-mobile-mode="app"] .prop-multi-dropdown::before,
body[data-mobile-mode="app"] .prop-color-picker::before,
body[data-mobile-mode="app"] .prop-type-picker::before,
body[data-mobile-mode="app"] .prop-ctx-menu::before{
  content:'';position:fixed;inset:0;z-index:-1;
  background:rgba(0,0,0,.5);backdrop-filter:blur(3px);
  animation:mPropDdBdIn .22s ease both
}
@keyframes mPropDdBdIn{from{opacity:0}to{opacity:1}}

/* ---- Toast / inline confirm ---- */
/* ==================== CLIENT-FACING SHUTTLE MODE ==================== */
/* When a non-Sauce-Media user is on a shuttle board, simplify cards
   so they see Title + Due + Status only. Hide internal metadata. */
body[data-shuttle-mode="client"] .kanban-card-tag { display: none !important; }
body[data-shuttle-mode="client"] .kanban-card .kanban-card-people-stack,
body[data-shuttle-mode="client"] .kanban-card .card-people-row,
body[data-shuttle-mode="client"] .kanban-card .person-avatar:nth-child(n+2) { display: none !important; }
body[data-shuttle-mode="client"] .kanban-card-meta { font-size: 11px; }
body[data-shuttle-mode="client"] .kanban-card { padding: 12px 14px; margin-bottom: 10px; }
/* Boost card title legibility on client view */
body[data-shuttle-mode="client"] .kanban-card-text,
body[data-shuttle-mode="client"] .kanban-card-title { font-size: 14px !important; line-height: 1.35; }
/* Action-required cue: card with .needs-client-action gets a coral pulse */
body[data-shuttle-mode="client"] .kanban-card.needs-client-action {
  border-color: var(--color-warning) !important;
  box-shadow: 0 0 0 1px var(--color-warning), 0 4px 18px rgba(255,180,84,.18);
}
body[data-shuttle-mode="client"] .kanban-card.needs-client-action::before {
  content: "ACTION NEEDED";
  display: inline-block;
  background: var(--coral); color: #fff;
  font-size: 9px; font-weight: 700; letter-spacing: .5px;
  padding: 2px 6px; border-radius: 3px; margin-bottom: 6px;
}
/* Client-only board header banner (rendered via JS into #clientBoardHeader) */
.client-board-header { display: none; }
body[data-shuttle-mode="client"] .client-board-header {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 24px; margin: 0 0 12px;
  background: linear-gradient(90deg, rgba(124,92,255,.08), transparent);
  border-bottom: 1px solid var(--border-d);
}
.client-board-header .cbh-title { font-family: var(--serif); font-size: 22px; color: var(--white); }
.client-board-header .cbh-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.client-board-header .cbh-legend { display: flex; gap: 14px; font-size: 11px; color: var(--cream); }
.client-board-header .cbh-legend span::before {
  content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--coral); margin-right: 5px; vertical-align: middle;
}
.client-board-header .cbh-legend .lg-action::before { background: var(--coral); }
.client-board-header .cbh-legend .lg-prog::before   { background: var(--gold); }
.client-board-header .cbh-legend .lg-done::before   { background: var(--green); }
/* Empty column / empty board copy for clients */
body[data-shuttle-mode="client"] .kanban-col-cards:empty::before {
  content: "No tasks in this stage.";
  display: block; padding: 14px 8px; font-size: 12px; color: var(--muted); text-align: center;
}
/* Toasts anchor BOTTOM-RIGHT and slide in from the right edge — one plain dark style for
   every tier (no colored side bars, no icons). Newest sits closest to the corner. */
.toast-container{position:fixed;bottom:calc(14px + env(safe-area-inset-bottom,0px));top:auto;right:14px;left:auto;transform:none;z-index:99999;display:flex;flex-direction:column;gap:8px;align-items:flex-end;pointer-events:none;max-width:calc(100vw - 24px)}
/* Mobile: clear the bottom hotbar. */
body[data-mobile-mode="app"] .toast-container{bottom:calc(64px + env(safe-area-inset-bottom,0px))}
.toast{background:rgba(48,48,51,.94);border:1px solid rgba(255,255,255,.12);border-radius:999px;padding:9px 16px;font-size:13px;color:var(--off-white);box-shadow:0 6px 22px rgba(0,0,0,.45);pointer-events:auto;display:flex;align-items:center;gap:9px;animation:toastDrop .18s ease-out;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);max-width:280px;text-align:center}
/* Toasts that carry BUTTONS (confirm + undo) are one component with one
   geometry — the design rules ask for a single toast style, and these two can
   be on screen at the same time (a delete confirm stacked under the undo from
   the previous delete), where any difference reads as two unrelated widgets.
   Confirm used to pad 12px 16px against undo's 6px 7px 6px 16px: same 13px
   text, same 30px buttons, but 56px vs 44px tall — 27% bigger, side by side
   (measured, owner report Aug 13). The tighter box wins because the button is
   the tallest thing in the row: symmetric 12px padding just adds dead space
   above and below it. Pill radius is dropped for the same reason it always
   was — a row of buttons needs a card, not a lozenge. */
.toast.confirm,.toast.toast-undo{border-radius:14px;padding:6px 7px 6px 16px;gap:12px;text-align:left}
.toast.confirm{max-width:560px}
.toast.confirm .toast-msg{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left}
/* One button size across both, so the action rows line up when stacked. */
.toast.confirm .toast-btn,.toast.toast-undo .toast-btn{padding:5px 13px;font-size:12px}
/* Keyframe NAMES kept (JS animates by name) — motion is now a right-edge slide. The 30px
   overshoot keeps the element fully off-screen at the start so no edge sliver flashes. */
@keyframes toastDrop{from{opacity:0;transform:translateX(calc(100% + 30px))}to{opacity:1;transform:translateX(0)}}
@keyframes toastDropOut{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(calc(100% + 30px))}}
.toast-msg{flex:1}
.toast-actions{display:flex;gap:8px;flex-shrink:0}
.toast-btn{padding:6px 16px;border-radius:8px;border:none;font-size:12px;font-weight:600;cursor:pointer;transition:all .15s}
.toast-btn.cancel{background:var(--bg-inset);color:var(--muted)}
.toast-btn.cancel:hover{background:rgba(255,255,255,.15);color:var(--cream)}
.toast-btn.danger{background:var(--color-error,#ef4444);color:#fff}
.toast-btn.danger:hover{filter:brightness(1.12)}
.toast-btn.primary{background:var(--purple);color:#fff}
.toast-btn.primary:hover{background:rgba(255,255,255,.22)}
/* Sticky (error) toasts: dismiss X. */
.toast-x{flex:none;width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:var(--bg-inset);color:var(--muted);font-size:12px;line-height:1;cursor:pointer}
.toast-x:hover{background:rgba(255,255,255,.2);color:var(--off-white)}
/* Undo countdown ring — pure CSS drain, no text. 50.27 = 2*pi*8. */
.toast-undo-btn{display:inline-flex;align-items:center;gap:7px}
.undo-ring{transform:rotate(-90deg);flex:none}
.undo-ring-fg{stroke-dashoffset:0;animation:undoRingDrain var(--undo-drain-ms,5000ms) linear forwards}
@keyframes undoRingDrain{from{stroke-dashoffset:0}to{stroke-dashoffset:50.27}}
@media(prefers-reduced-motion:reduce){.undo-ring-fg{animation:none}}
@keyframes toastIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}
@keyframes toastOut{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(12px)}}
/* ── Unified drag & drop (shared across kanban/list/calendar) ── */
.dnd-stack-ghost{filter:drop-shadow(0 12px 28px rgba(0,0,0,.45))}
.dnd-stack-count{position:absolute;top:-8px;right:-8px;z-index:11;min-width:20px;height:20px;border-radius:10px;background:var(--purple);color:#fff;font:700 11px var(--sans);display:flex;align-items:center;justify-content:center;padding:0 5px;box-shadow:0 2px 8px rgba(0,0,0,.4)}
.cal-day-add{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;color:var(--cream);font:13px var(--sans);padding:9px 11px;outline:none;box-sizing:border-box}
.cal-day-add:focus{border-color:var(--purple)}
/* ==================== PRESENCE INDICATORS ==================== */
.presence-overlay{position:absolute;bottom:4px;right:6px;display:flex;align-items:center;gap:0;pointer-events:none;z-index:2}
/* Pencil-in-circle: avatar-sized filled circle in the EDITOR'S color; stacks overlap like pfps. */
.presence-pencil{flex-shrink:0;width:24px;height:24px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--surf-2,#131315);box-shadow:0 1px 4px rgba(0,0,0,.45);margin-left:-7px}
.presence-pencil:first-child{margin-left:0}
.presence-pencil svg{width:12px;height:12px}

/* ── Multiplayer cursors ── */
.mp-cursor-layer{position:absolute;inset:0;overflow:visible;pointer-events:none;z-index:40}
.mp-cursor{position:absolute;left:0;top:0;pointer-events:auto;will-change:transform}
.mp-cursor svg{display:block;filter:drop-shadow(0 1px 3px rgba(0,0,0,.5))}
/* Ring cursor. The ring is neutral so it reads on any background; the person's colour is
   the pupil, which keeps identity legible without tinting the whole marker. ONE shape at
   all times — the per-hover variants that grew/hollowed/collapsed it are gone.
   No size transition: nothing animates these any more, and a transition here would only
   risk fighting the per-frame translate3d that _mpStep writes to the parent. */
.mp-cursor-ring{position:absolute;left:0;top:0;display:block;width:22px;height:22px;border-radius:50%;
  /* Centred ON the point. The parent carries the per-frame translate3d, so the hotspot is
     (0,0) of .mp-cursor; without this the ring's TOP-LEFT would sit there and every cursor
     would render ~11px down-right of where that person actually is. Centring also makes the
     hover states grow outward from the point instead of lurching down-right. */
  transform:translate(-50%,-50%);
  border:1.5px solid rgba(255,255,255,.92);box-sizing:border-box;
  box-shadow:0 1px 4px rgba(0,0,0,.45), inset 0 0 0 1px rgba(0,0,0,.28);
  transition:none}
.mp-cursor-dot{position:absolute;left:50%;top:50%;width:7px;height:7px;border-radius:50%;
  background:var(--mp-c,var(--coral));transform:translate(-50%,-50%);transition:none}

.mp-cursor-name{position:absolute;left:15px;top:11px;font:600 11px var(--sans);color:#fff;padding:2px 7px;border-radius:6px;white-space:nowrap;opacity:0;transition:opacity .12s ease;box-shadow:0 2px 8px rgba(0,0,0,.35)}
.mp-cursor:hover .mp-cursor-name{opacity:1}
.mp-eye-btn{height:34px;width:36px;display:inline-flex;align-items:center;justify-content:center;border-radius:9px;background:rgba(255,255,255,.08);color:var(--white,#fff);border:none;cursor:pointer;transition:background .14s}
.mp-eye-btn:hover{background:rgba(255,255,255,.14)}
.mp-eye-btn.off{color:var(--muted);background:rgba(255,255,255,.04)}
.presence-more-badge{font-size:9px;font-weight:700;color:var(--muted);margin-left:1px}
.presence-active{animation:presenceBreathe 4s ease-in-out infinite}
@keyframes presenceBreathe{0%,100%{outline-color:var(--presence-outline-color,rgba(255,255,255,.12))}50%{outline-color:rgba(255,255,255,.12)}}
.card-self-selected{animation:selfBreathe 4s ease-in-out infinite}
@keyframes selfBreathe{0%,100%{outline-color:var(--self-outline-color,var(--coral))}50%{outline-color:rgba(255,255,255,.12)}}
.presence-remote-cursor{display:inline;position:relative;border-left:2px solid var(--presence-cursor-color,#3498db);margin-left:-1px;margin-right:-1px;pointer-events:auto;animation:presenceCursorBlink 1.1s ease-in-out infinite}
.presence-remote-cursor::after{content:attr(data-presence-name);position:absolute;bottom:100%;left:-1px;background:var(--presence-cursor-color,#3498db);color:#fff;font-size:9px;font-weight:600;font-family:var(--sans);padding:1px 5px;border-radius:3px 3px 3px 0;white-space:nowrap;pointer-events:none;line-height:1.3;opacity:0;transition:opacity .15s}
.presence-remote-cursor.presence-cursor-flash::after{animation:presenceNameFlash 2s ease forwards}
.presence-remote-cursor:hover::after{opacity:.9!important;animation:none}
@keyframes presenceNameFlash{0%{opacity:.9}70%{opacity:.9}100%{opacity:0}}
@keyframes presenceCursorBlink{0%,100%{opacity:1}50%{opacity:.35}}
.relay-cursor{position:absolute;pointer-events:none;z-index:10;transition:left .08s ease,top .08s ease}
.relay-cursor-line{width:2px;height:1.2em;background:var(--relay-cursor-color,#f59e0b);border-radius:1px}
.relay-cursor-label{position:absolute;bottom:calc(100% + 2px);left:-1px;background:var(--relay-cursor-color,#f59e0b);color:#fff;font-size:9px;font-weight:600;font-family:var(--sans);padding:2px 6px;border-radius:4px 4px 4px 0;white-space:nowrap;line-height:1.3;transform-origin:bottom left}
.relay-cursor.relay-cursor-entering .relay-cursor-label{animation:relayNamePop .35s cubic-bezier(.34,1.56,.64,1) forwards}
.relay-cursor.relay-cursor-entering .relay-cursor-line{animation:relayLinePop .25s cubic-bezier(.34,1.56,.64,1) forwards}
.relay-cursor.relay-cursor-fading .relay-cursor-label,.relay-cursor.relay-cursor-fading .relay-cursor-line{animation:relayFadeOut .4s ease forwards}
@keyframes relayNamePop{0%{opacity:0;transform:translateY(4px) scale(.7)}50%{transform:translateY(-2px) scale(1.06)}100%{opacity:1;transform:translateY(0) scale(1)}}
@keyframes relayLinePop{0%{opacity:0;transform:scaleY(0)}100%{opacity:1;transform:scaleY(1)}}
@keyframes relayFadeOut{0%{opacity:1;transform:translateY(0) scale(1)}100%{opacity:0;transform:translateY(-4px) scale(.85)}}
.presence-viewers{font-size:10px;color:var(--text-3);font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px;line-height:1;padding:2px 0}
.presence-typing-row{display:flex;align-items:center;gap:6px;padding:6px 0 2px;font-size:11px}
.presence-typing-text{font-weight:500}
.presence-typing-dots{display:inline-flex;gap:3px}
.presence-typing-dots span{width:4px;height:4px;border-radius:50%;animation:chatDot 1.2s infinite}
.presence-typing-dots span:nth-child(2){animation-delay:.2s}
.presence-typing-dots span:nth-child(3){animation-delay:.4s}
/* ==================== WHO'S ONLINE BAR ==================== */
.presence-bar{display:flex;align-items:center;gap:8px;padding:4px 12px;min-height:28px;font-size:11px;color:var(--muted);border-bottom:1px solid var(--border-d);background:rgba(255,255,255,.015);flex-shrink:0}
.presence-bar:empty{display:none}
.presence-bar-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--text-3);margin-right:2px;white-space:nowrap}
.presence-bar-users{display:flex;align-items:center;gap:0;flex-wrap:nowrap}
.presence-bar-avatar{width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:#fff;flex-shrink:0;margin-left:-4px;border:2px solid var(--bg);position:relative;cursor:default;transition:transform .15s,z-index 0s}
.presence-bar-avatar:first-child{margin-left:0}
.presence-bar-avatar:hover{transform:scale(1.15);z-index:5}
.presence-bar-avatar img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.presence-bar-tooltip{position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);background:var(--card-bg);border:1px solid var(--border-d);border-radius:6px;padding:4px 8px;font-size:10px;font-weight:500;color:var(--off-white);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s;z-index:10;box-shadow:0 4px 12px rgba(0,0,0,.4)}
.presence-bar-avatar:hover .presence-bar-tooltip{opacity:1}
.presence-bar-activity{font-size:9px;color:rgba(255,255,255,.35);display:block;margin-top:1px}
.presence-bar-dot{width:6px;height:6px;border-radius:50%;background:#2ecc71;position:absolute;bottom:-1px;right:-1px;border:1.5px solid var(--bg);animation:presenceDotPulse 3s ease-in-out infinite}
@keyframes presenceDotPulse{0%,100%{opacity:1}50%{opacity:.5}}

/* ==================== CHAT ROOMS ==================== */
#page-chatroom.active{margin:-28px -36px -60px;height:calc(100% + 88px);display:flex!important;flex-direction:column;overflow:hidden}
#page-chatroom>.panel{background:none;border:none;border-radius:0;padding:0;flex:1;min-height:0;display:flex;flex-direction:column}
#page-chatroom .chatroom-messages-wrap{padding-top:8px}
.chatroom-layout{display:flex;flex-direction:column;flex:1;min-height:0}
.chatroom-channel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border-d);flex-shrink:0}
.chatroom-channel-info{display:flex;align-items:center;gap:8px}
.chatroom-channel-hash{color:var(--muted);font-size:22px;font-weight:300;line-height:1;opacity:.5}
.chatroom-channel-name{font-family:var(--serif);font-size:17px;font-weight:600;color:var(--cream)}
.chatroom-channel-type-icon{color:var(--muted);display:flex;align-items:center}
.chatroom-messages-wrap{flex:1;overflow-y:auto;display:flex;flex-direction:column;padding:8px 0}
.cr-msg-row{display:flex;align-items:flex-start;gap:16px;padding:3px 16px;position:relative;min-height:28px}
.cr-msg-row:not(.cr-msg-grouped){margin-top:10px}
.cr-msg-row:first-child{margin-top:0}
.cr-msg-row:hover{background:rgba(255,255,255,.02)}
.cr-msg-row.reactable>.reaction-hover-tools{top:-36px;right:16px}
.cr-msg-avatar{width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;color:var(--cream);flex-shrink:0;overflow:hidden}
.cr-msg-avatar img{width:100%;height:100%;object-fit:cover}
/* The generated pixel/robot face arrives as a span-wrapped SVG, not an img. */
.cr-msg-avatar > span,.cr-msg-avatar > svg{width:100%;height:100%;display:block}
.cr-msg-body{flex:1;min-width:0}
.cr-msg-meta{display:flex;align-items:baseline;gap:8px;margin-bottom:1px}
.cr-msg-author{font-size:15px;font-weight:600;color:var(--cr-au,var(--cream));cursor:pointer;transition:color .1s}
.cr-msg-author:hover{color:var(--coral)}
.cr-msg-time{font-size:11px;color:var(--muted);font-family:var(--sans)}
.cr-msg-text{font-size:14px;color:var(--cream);line-height:1.5;word-break:break-word}
.cr-msg-edit{display:flex;flex-direction:column;gap:8px;margin:2px 0}
.cr-edit-ta{width:100%;min-height:38px;max-height:200px;resize:none;background:var(--bg-inset,rgba(255,255,255,.05));border:1px solid var(--border-d);border-radius:10px;padding:9px 12px;color:var(--cream);font-family:var(--sans);font-size:14px;line-height:1.5;outline:none}
.cr-edit-ta:focus{border-color:var(--coral)}
.cr-edit-actions{display:flex;gap:8px;justify-content:flex-end}
.cr-edit-btn{padding:6px 14px;border-radius:8px;font-family:var(--sans);font-size:13px;font-weight:600;cursor:pointer;border:1px solid var(--border-d);background:transparent;color:var(--cream);transition:background .14s,border-color .14s}
.cr-edit-btn.cr-edit-cancel:hover{background:rgba(255,255,255,.06)}
.cr-edit-btn.cr-edit-save{background:var(--coral);border-color:var(--coral);color:#fff}
.cr-edit-btn.cr-edit-save:hover{background:#e0552c}
.cr-msg-grouped{min-height:22px}
.cr-msg-grouped .cr-msg-spacer{width:40px;flex-shrink:0;position:relative}
/* The hover timestamp aligns with the message's FIRST LINE, not the middle of the row.
   The spacer stretches to the whole message, so the old top:50% centred it against the
   full height — right for a one-liner, and progressively further off the taller the
   message got (a photo or a multi-line reply dragged it far down).

   --cr-line-h lives on the ROW because custom properties inherit downward only: the
   spacer is a SIBLING of the text, so a token set on .cr-msg-text could never reach it.
   Each message variant sets its own, so the two can never drift apart. */
.cr-msg-row,.cr-msg-grouped{--cr-line-h:21px}                    /* 14px x 1.5 */
.cr-msg-row:has(.cr-msg-jumbo),.cr-msg-grouped:has(.cr-msg-jumbo){--cr-line-h:28.35px}
#dmMessages .cr-msg-row,#dmMessages .cr-msg-grouped{--cr-line-h:19.88px}
.cr-msg-grouped:hover .cr-msg-spacer::after{content:attr(data-time);font-size:9px;color:var(--muted);font-family:var(--sans);position:absolute;top:0;left:0;right:0;height:var(--cr-line-h,21px);display:flex;align-items:center;justify-content:center;white-space:nowrap;line-height:1}
.cr-date-sep{display:flex;align-items:center;gap:12px;margin:18px 16px 14px}
.cr-date-sep::before,.cr-date-sep::after{content:'';flex:1;height:1px;background:var(--border-d)}
.cr-date-sep span{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);white-space:nowrap}
/* New messages top bar (Discord-style) */
.cr-new-msg-bar{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;padding:6px 16px;background:var(--blue);color:#fff;font-size:12px;font-weight:600;cursor:pointer;transition:opacity .2s;border-radius:0 0 8px 8px;margin:0 8px;box-shadow:0 2px 8px rgba(0,0,0,.3)}
.cr-new-msg-bar:hover{filter:brightness(1.1)}
.cr-new-msg-bar-text{display:flex;align-items:center;gap:6px}
.cr-new-msg-bar-action{font-size:11px;font-weight:500;opacity:.9;display:flex;align-items:center;gap:4px}
/* NEW message divider (red line with badge) */
.cr-new-divider{display:flex;align-items:center;gap:0;margin:12px 0 8px;position:relative}
.cr-new-divider::before{content:'';flex:1;height:1.5px;background:var(--coral)}
.cr-new-divider::after{content:'NEW';font-size:9px;font-weight:700;letter-spacing:.5px;color:#fff;background:var(--coral);padding:1px 6px;border-radius:3px;flex-shrink:0;margin-left:0}
/* The composer sits OVER the message list rather than below it, so what scrolls past goes
   under the glass instead of stopping at a hard edge. The scroller reserves its height in
   padding (kept in sync by _crSyncComposerInset), so nothing is ever hidden behind it. */
.chatroom-input-wrap{padding:0 16px 18px;flex-shrink:0;
  position:absolute;left:0;right:0;bottom:0;z-index:5;background:none;pointer-events:none}
.chatroom-input-wrap > *{pointer-events:auto}
/* No blurred strip above the bar. The glass belongs to the container itself; blurring the
   band above it smeared the message sitting there and read as a smudge over the content
   rather than as a surface. Messages pass under the bar's own glass edge instead. */
#page-chatroom .cr-main-col,#page-dm .cr-main-col,#page-dm .dm-chat-area{position:relative}
.chatroom-input-bar{display:flex;align-items:center;gap:2px;background:rgba(255,255,255,.09);border-radius:11px;padding:4px 6px}
.chatroom-input-btn{width:38px;height:38px;border:none;background:transparent;color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:8px;transition:color .15s;flex-shrink:0}
.chatroom-input-btn:hover{color:var(--cream)}
/* 46px/13px was the original single-row bar. The composer grew a tool row underneath, and
   the channel corrected the field with an id-scoped override — which the DM, using the same
   class, never inherited, so its box stood 39px taller. The corrected values belong to the
   CLASS, so both messengers get them from one place. */
.chatroom-input{flex:1;min-height:24px;padding:2px 0;border:none;background:transparent;color:var(--off-white);font-family:var(--sans);font-size:15px;outline:none;resize:none;overflow-y:auto;line-height:1.5;max-height:220px;box-sizing:border-box}
.chatroom-input::placeholder{color:var(--muted)}
/* Voice-memo mic button: turns red + pulses + shows an mm:ss timer while recording. */
.cr-voice-btn.recording{color:#e5484d}
.cr-voice-btn.recording svg{animation:crVoicePulse 1s ease-in-out infinite}
@keyframes crVoicePulse{0%,100%{opacity:1}50%{opacity:.4}}
.cr-voice-btn.recording::after{content:attr(data-rectime);position:absolute;font-size:9px;font-weight:700;color:#e5484d;transform:translateY(15px);white-space:nowrap}
.cr-voice-btn{position:relative}
/* Voice-memo playback bubble */
.dmx-att-audio{display:flex;align-items:center;gap:7px;background:var(--bg-inset);border:1px solid var(--border-d);border-radius:14px;padding:5px 10px 5px 12px;max-width:280px;font-size:15px}
.dmx-att-audio audio{height:32px;max-width:230px}
.dm-pending-atts{display:flex;flex-wrap:wrap;gap:8px;padding:10px 6px 4px}
/* Empty, it still drew 14px of padding and pushed the whole bar taller than a channel's. */
.dm-pending-atts:empty{display:none}
/* overflow:visible so the corner × is not sliced off; the × sits fully inside instead of
   straddling the corner, which is what got clipped. */
.dm-pending-att{position:relative;border-radius:9px;overflow:visible;border:1px solid var(--border-d);background:rgba(255,255,255,.05)}
.dm-pending-att img{width:58px;height:58px;object-fit:cover;display:block}
.dm-pending-att .dm-att-name{display:inline-flex;align-items:center;max-width:150px;padding:9px 11px;font-size:12px;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dm-pending-att-x{position:absolute;top:4px;right:4px;width:18px;height:18px;border-radius:50%;background:rgba(0,0,0,.65);color:#fff;border:none;cursor:pointer;font-size:12px;line-height:16px;padding:0}
.dm-pending-att.is-failed{border-color:var(--danger-text);background:var(--color-error-tint)}
.dm-pending-att-retry{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);border:0;border-radius:999px;padding:4px 8px;background:var(--surface-raised);color:var(--cream);font:inherit;font-size:10px;font-weight:700;cursor:pointer}
.cr-msg-atts{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}
.cr-msg-att-img{max-width:260px;max-height:220px;border-radius:10px;border:1px solid var(--border-d);display:block}
.cr-msg-att-file{display:inline-flex;align-items:center;padding:7px 12px;border-radius:9px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);color:var(--cream);font-size:13px;text-decoration:none;transition:background .14s}
.cr-msg-att-file:hover{background:rgba(255,255,255,.1)}
.chatroom-send{display:none}
.cr-typing-indicator{padding:0 16px 4px;min-height:20px;flex-shrink:0}
.cr-typing-row{display:flex;align-items:center;gap:6px;font-size:11px}
.cr-typing-text{color:rgba(255,255,255,.35);font-weight:500}
.cr-typing-dots{display:inline-flex;gap:3px}
.cr-typing-dots span{width:4px;height:4px;border-radius:50%;background:rgba(255,255,255,.3);animation:chatDot 1.2s infinite}
.cr-typing-dots span:nth-child(2){animation-delay:.2s}
.cr-typing-dots span:nth-child(3){animation-delay:.4s}
/* Voice room banner */
.voice-room-banner{display:flex;align-items:center;gap:14px;padding:20px 24px;border-radius:12px;border:1px solid rgba(115,172,131,.25);background:rgba(115,172,131,.07);margin-bottom:16px}
.voice-room-icon{font-size:32px;flex-shrink:0}
.voice-room-info{flex:1}
.voice-room-title{font-size:15px;font-weight:700;color:var(--off-white);margin-bottom:4px}
.voice-room-sub{font-size:12px;color:var(--muted)}
.voice-join-btn{padding:9px 20px;border-radius:8px;border:none;background:var(--green);color:#fff;font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer;transition:opacity .15s;flex-shrink:0}
.voice-join-btn:hover{opacity:.85}
.voice-join-btn.leave{background:rgba(255,255,255,.08);border:1px solid var(--border-d);color:var(--coral)}
.voice-join-btn.leave:hover{background:rgba(239,68,68,.1)}
.voice-members-list{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.voice-member-chip{display:flex;align-items:center;gap:6px;padding:5px 12px;border-radius:20px;background:rgba(115,172,131,.12);border:1px solid rgba(115,172,131,.2);font-size:12px;color:var(--cream)}
.voice-member-chip .vm-dot{width:6px;height:6px;border-radius:50%;background:var(--green);animation:presenceDotPulse 3s ease-in-out infinite}

/* Client styles */
.client-card-avatar{width:40px;height:40px;border-radius:50%;background:rgba(124,92,255,.12);display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;color:var(--coral);flex-shrink:0}
.client-status{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:20px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px}
.client-status.active{background:rgba(115,172,131,.12);color:var(--green)}
.client-status.onboarding{background:rgba(124,92,255,.12);color:var(--coral)}
.client-status.inactive{background:rgba(255,255,255,.06);color:var(--muted)}
.client-progress{display:flex;gap:6px;margin-top:12px}
.client-progress-step{flex:1;height:4px;border-radius:2px;background:rgba(255,255,255,.08)}
.client-progress-step.done{background:var(--green)}
.client-progress-step.current{background:var(--coral)}
/* Client Manager — Search & Filter */
.cm-search-bar{display:flex;align-items:center;gap:10px;margin-bottom:18px}
.cm-search-input{flex:1;padding:9px 14px;border:1px solid var(--border-d);border-radius:8px;background:rgba(255,255,255,.04);color:var(--cream);font-size:13px;font-family:var(--sans);outline:none}
.cm-search-input:focus{border-color:var(--coral)}
.cm-search-input::placeholder{color:var(--muted)}
.cm-filter-btn{padding:6px 14px;border:1px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.04);color:var(--muted);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;cursor:pointer;transition:all .15s;font-family:var(--sans)}
.cm-filter-btn:hover{background:var(--state-hover);color:var(--cream)}
.cm-filter-btn.active{background:rgba(124,92,255,.12);color:var(--coral);border-color:rgba(124,92,255,.3)}
/* Client Manager — Detail View */
.cm-detail-back{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:12px;cursor:pointer;margin-bottom:16px;transition:color .15s}
.cm-detail-back:hover{color:var(--cream)}
.cm-detail-header{display:flex;align-items:center;gap:16px;margin-bottom:24px;flex-wrap:wrap}
.cm-detail-avatar{width:56px;height:56px;border-radius:50%;background:rgba(124,92,255,.12);display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:700;color:var(--coral);flex-shrink:0}
.cm-team-chips{display:flex;flex-wrap:wrap;gap:7px;align-items:center}
.cm-team-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px 4px 5px;border-radius:20px;background:rgba(255,255,255,.05);border:1px solid var(--border-d);font-size:12px;color:var(--cream)}
.cm-team-chip img{width:18px;height:18px;border-radius:50%;object-fit:cover;flex-shrink:0}
.cm-team-dot{width:8px;height:8px;border-radius:50%;background:var(--coral);flex-shrink:0}
.cm-team-name{font-weight:500;white-space:nowrap}
.cm-team-x{cursor:pointer;opacity:.4;font-size:13px;line-height:1;transition:opacity .15s,color .15s}
.cm-team-x:hover{opacity:1;color:var(--coral)}
.cm-team-add{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:50%;border:1px dashed var(--border-d);color:var(--muted);cursor:pointer;font-size:15px;line-height:1;transition:border-color .15s,color .15s,background .15s}
.cm-team-add:hover{border-color:var(--coral);color:var(--coral);background:rgba(124,92,255,.08)}
.cm-detail-name{font-family:var(--serif);font-size:24px;color:var(--off-white);font-weight:400}
.cm-detail-actions{margin-left:auto;display:flex;gap:8px}
.cm-detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:18px}
@media(max-width:768px){.cm-detail-grid{grid-template-columns:1fr}}
.cm-detail-panel{background:rgba(255,255,255,.02);border:1px solid var(--border-d);border-radius:10px;padding:18px 20px}
.cm-detail-panel-title{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);margin-bottom:12px}
.cm-detail-row{display:flex;justify-content:space-between;align-items:baseline;padding:5px 0;font-size:13px}
.cm-detail-row .label{color:var(--muted)}
.cm-detail-row .value{color:var(--cream);text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Client Manager — Onboarding Stepper */
.cm-stepper{display:flex;align-items:flex-start;gap:0;margin-bottom:18px;padding:18px 20px;background:rgba(255,255,255,.02);border:1px solid var(--border-d);border-radius:10px}
.cm-step{display:flex;flex-direction:column;align-items:center;flex:1;position:relative}
.cm-step-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;border:2px solid rgba(255,255,255,.1);color:var(--muted);background:transparent;transition:all .2s;z-index:1}
.cm-step.done .cm-step-circle{background:var(--green);border-color:var(--green);color:#fff}
.cm-step.active .cm-step-circle{background:var(--coral);border-color:var(--coral);color:#fff}
.cm-step-label{font-size:10px;color:var(--muted);margin-top:6px;text-align:center;text-transform:uppercase;letter-spacing:.3px;font-weight:600}
.cm-step.done .cm-step-label{color:var(--green)}
.cm-step.active .cm-step-label{color:var(--coral)}
.cm-step-status{font-size:9px;color:var(--muted);margin-top:2px;text-align:center}
.cm-step-line{position:absolute;top:16px;left:calc(50% + 18px);right:calc(-50% + 18px);height:2px;background:rgba(255,255,255,.08)}
.cm-step.done .cm-step-line{background:var(--green)}
.cm-step:last-child .cm-step-line{display:none}
/* Client Manager — Quick Links */
.cm-quick-links{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:18px}
@media(max-width:768px){.cm-quick-links{grid-template-columns:repeat(2,1fr)}}
.cm-quick-link{display:flex;flex-direction:column;align-items:center;gap:4px;padding:16px 10px;background:rgba(255,255,255,.02);border:1px solid var(--border-d);border-radius:10px;cursor:pointer;transition:all .15s;text-decoration:none}
.cm-quick-link:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.15)}
.cm-quick-link.disabled{opacity:.35;pointer-events:none}
.cm-quick-link-icon{font-size:22px}
.cm-quick-link-label{font-size:11px;font-weight:600;color:var(--cream);text-transform:uppercase;letter-spacing:.3px}
.cm-quick-link-sub{font-size:10px;color:var(--muted);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
/* Client Manager — Notes */
.cm-notes-panel{margin-bottom:18px}
.cm-notes-textarea{width:100%;min-height:80px;padding:12px 16px;border:1px solid var(--border-d);border-radius:8px;background:rgba(255,255,255,.04);color:var(--cream);font-size:13px;font-family:var(--sans);outline:none;resize:vertical;box-sizing:border-box;line-height:1.5}
.cm-notes-textarea:focus{border-color:var(--coral)}
.cm-notes-textarea::placeholder{color:var(--muted)}
/* Wizard — Package Selector */
.ob-package-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:6px}
.ob-package-opt{padding:14px;border:1px solid var(--border-d);border-radius:10px;cursor:pointer;transition:all .15s;text-align:center;background:rgba(255,255,255,.02)}
.ob-package-opt:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.15)}
.ob-package-opt.selected{border-color:var(--coral);background:rgba(124,92,255,.08)}
.ob-package-opt .pkg-name{font-size:14px;font-weight:600;color:var(--cream)}
.ob-package-opt .pkg-price{font-size:11px;color:var(--muted);margin-top:2px}
/* Wizard — Action States */
.ob-skip{display:block;text-align:center;font-size:12px;color:var(--muted);cursor:pointer;margin-top:12px;transition:color .15s}
.ob-skip:hover{color:var(--cream)}
.ob-success{display:flex;align-items:center;gap:8px;padding:12px 16px;background:rgba(115,172,131,.1);border:1px solid rgba(115,172,131,.2);border-radius:8px;color:var(--green);font-size:13px;margin-top:12px}
.ob-loading{display:flex;align-items:center;gap:8px;padding:12px 16px;color:var(--muted);font-size:13px;margin-top:12px}
.ob-loading::before{content:'';width:16px;height:16px;border:2px solid rgba(255,255,255,.15);border-top-color:var(--coral);border-radius:50%;animation:spin 1s linear infinite;flex-shrink:0}
.ob-info{padding:14px 18px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:8px;margin-top:10px;font-size:13px;color:var(--cream);line-height:1.5}
.ob-action-btn{padding:10px 22px;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;transition:all .15s;font-family:var(--sans)}
.ob-action-btn.primary{background:var(--coral);color:#fff}
.ob-action-btn.primary:hover{filter:brightness(1.1)}
.ob-action-btn.primary:disabled{opacity:.4;cursor:default;filter:none}
.ob-action-btn.secondary{background:rgba(255,255,255,.06);color:var(--cream);border:1px solid var(--border-d)}
.ob-action-btn.secondary:hover{background:rgba(255,255,255,.1)}
.ob-url-input{margin-top:8px;width:100%;padding:8px 12px;border:1px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.04);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none;box-sizing:border-box}
.ob-url-input:focus{border-color:var(--coral)}
/* Clickable table rows */
.table-shell tr.clickable{cursor:pointer;transition:background .1s}
.table-shell tr.clickable:hover{background:rgba(255,255,255,.04)}
/* Inline editable fields */
.cm-editable{cursor:pointer;border-bottom:1px dashed transparent;transition:border-color .15s;padding-bottom:1px}
.cm-editable:hover{border-bottom-color:rgba(255,255,255,.25)}
.cm-inline-input{background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:4px;color:var(--cream);font-family:var(--sans);font-size:13px;padding:2px 6px;outline:none;width:100%;max-width:220px;box-sizing:border-box}
.cm-inline-input:focus{border-color:var(--coral)}
.cm-contract-section{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cm-contract-upload-btn{font-size:11px;padding:4px 12px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);cursor:pointer;font-family:var(--sans);transition:all .15s}
.cm-contract-upload-btn:hover{border-color:var(--coral);background:rgba(124,92,255,.08);color:var(--coral)}
.cm-step-action{margin-top:6px;font-size:10px;padding:3px 10px;border-radius:4px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);cursor:pointer;font-family:var(--sans);transition:all .15s}
.cm-step-action:hover{border-color:var(--coral);background:rgba(124,92,255,.1);color:var(--coral)}
.cm-step.done .cm-step-action{display:none}
/* Scope row */
.ob-scope-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px 14px}
.ob-scope-grid label{margin-top:6px}
/* === Chat Room Enhanced Topbar === */
.cr-topbar{display:none}
.cr-topbar-left{display:flex;align-items:center;gap:8px;min-width:0;flex:1}
.cr-topbar-hash{color:var(--muted);font-size:20px;font-weight:300;opacity:.5;flex-shrink:0}
.cr-topbar-name{font-family:var(--serif);font-size:16px;font-weight:600;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cr-topbar-type-icon{color:var(--muted);display:flex;align-items:center;flex-shrink:0}
.cr-topbar-divider{width:1px;height:24px;background:var(--border-d);flex-shrink:0;margin:0 4px}
.cr-topbar-topic{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;cursor:pointer;transition:color .15s}
.cr-topbar-topic:hover{color:var(--cream)}
.cr-topbar-topic.empty{font-style:italic;opacity:.5}
.cr-topbar-actions{display:flex;align-items:center;gap:2px;flex-shrink:0;margin-left:auto}
.cr-topbar-icon-btn{width:32px;height:32px;border:none;background:none;color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:6px;transition:all .15s;position:relative}
.cr-topbar-icon-btn:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.cr-topbar-icon-btn.active{color:var(--coral)}
.cr-topbar-icon-btn svg{width:18px;height:18px}
.cr-topbar-search{display:none;align-items:center;gap:6px}
.cr-topbar-search.open{display:flex}
.cr-topbar-search input{width:180px;padding:5px 10px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none}
.cr-topbar-search input:focus{border-color:var(--coral)}
/* === Members Sidebar === */
.cr-body-wrap{display:flex;flex:1;min-height:0;overflow:hidden}
.cr-main-col{display:flex;flex-direction:column;flex:1;min-width:0}
.cr-members-sidebar{width:var(--sidebar-w);flex-shrink:0;background:var(--dark);overflow-y:auto;display:flex;flex-direction:column}
.cr-members-sidebar.hidden{display:none}
.cr-members-section-header{padding:18px 16px 6px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.7px;color:var(--muted)}
.cr-member-row{display:flex;align-items:center;gap:12px;padding:8px 16px;cursor:pointer;border-radius:4px;margin:0 8px;transition:background .12s}
.cr-member-row:hover{background:rgba(255,255,255,.04)}
.cr-member-avatar-wrap{position:relative;flex-shrink:0}
.cr-member-avatar{width:36px;height:36px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;color:var(--cream);overflow:hidden}
.cr-member-avatar img{width:100%;height:100%;object-fit:cover}
.cr-member-dot{position:absolute;bottom:-1px;right:-1px;width:12px;height:12px;border-radius:50%;border:2.5px solid var(--bg);box-sizing:border-box}
.cr-member-dot.online{background:var(--green)}
.cr-member-dot.offline{background:var(--muted)}
.cr-member-info{min-width:0;flex:1}
.cr-member-name{font-size:14px;font-weight:600;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cr-member-name.offline{opacity:.45}
.cr-member-role{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cr-member-badge{font-size:9px;font-weight:700;padding:2px 6px;border-radius:3px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0}
.cr-member-badge.admin{background:rgba(124,92,255,.15);color:var(--coral)}
.cr-member-badge.bot{background:rgba(88,166,255,.15);color:#58a6ff}
.cr-topic-edit{display:flex;align-items:center;gap:6px;flex:1;min-width:0}
.cr-topic-edit input{flex:1;padding:3px 8px;border-radius:4px;border:1px solid var(--coral);background:rgba(255,255,255,.04);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none}
@media(max-width:768px){.cr-members-sidebar{display:none !important}}

/* === User Profile Popout Card === */
.cr-profile-popout{position:absolute;z-index:10200;bottom:0;left:0;right:0;top:0;overflow:hidden;overflow-y:auto;background:#050507;/* No left border and no cast shadow: this fills the sidebar, it does not sit beside
   it. The 1px border also pushed everything inside 1px right, which is enough to stop
   the identity row landing exactly on the workspace card it is meant to replace. */animation:crSlideUp .25s cubic-bezier(.22,1,.36,1);display:flex;flex-direction:column}
.cr-profile-popout.closing{animation:crSlideDown .2s ease forwards}
@keyframes crPopOut{from{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}
@keyframes crSlideUp{from{opacity:0;transform:translateY(40%)}to{opacity:1;transform:translateY(0)}}
@keyframes crSlideDown{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(40%)}}
@keyframes crPopIn{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}
.cr-profile-popout-overlay{position:fixed;inset:0;z-index:10199}
.cr-profile-banner{height:108px;background:linear-gradient(135deg,#1a0a2e 0%,#0f3460 50%,#533483 100%);position:relative}
.cr-profile-banner::after{content:'';position:absolute;bottom:0;left:0;right:0;height:40px;background:linear-gradient(to bottom,transparent,var(--dark));pointer-events:none;z-index:1}
.cr-profile-edit-overlay{position:absolute;inset:0;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s;cursor:pointer;z-index:2}
.cr-profile-edit-overlay:hover{opacity:1}
.cr-profile-edit-overlay svg{filter:drop-shadow(0 1px 3px rgba(0,0,0,.4))}
.cr-profile-avatar-wrap{position:relative;display:inline-block;cursor:pointer}
.cr-profile-avatar-wrap .cr-profile-edit-overlay{border-radius:50%}
.cr-profile-avatar-row{display:flex;align-items:flex-end;padding:0 16px;margin-top:-28px;position:relative;z-index:1}
/* ── The profile takes the workspace card's SLOT ───────────────────────────────────
   Sliding a separate card up over the workspace card reads as two things stacked. The
   panel should feel like your name and face taking that place over — so this row is
   built to the workspace card's exact geometry: the same -24px/12px inset, the same
   56px height, 14px radius, glass fill and border, and a 42px round badge with a
   15/700 name over an 11/500 sub, matching .sidebar-ws-nav line for line. Change
   .sidebar-ws-card and this has to move with it; they are deliberately twins. */
.cr-profile-idcard{
  align-items:center;
  margin:-24px 12px 0;padding:6px 8px 6px 10px;
  border-radius:14px;gap:8px;
  background:rgba(255,255,255,0.08);
  backdrop-filter:blur(18px) saturate(180%);-webkit-backdrop-filter:blur(18px) saturate(180%);
  border:1px solid rgba(255,255,255,0.2);
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.28),0 10px 28px rgba(0,0,0,0.3);
  flex-shrink:0;box-sizing:border-box;min-height:56px;position:relative;
}
.cr-profile-idcard .cr-profile-avatar-wrap{position:relative;flex:none}
/* 42px and NO ring: the workspace badge has neither a border nor a lift, and a 56px
   avatar with a 4px dark ring is what made this read as a different component. */
.cr-profile-idcard .cr-profile-avatar-lg{width:42px;height:42px;border:0;font-size:15px}
.cr-profile-idcard .cr-profile-dot-lg{width:12px;height:12px;border-width:2px;bottom:0;right:0}
.cr-profile-idtext{display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;line-height:1.2}
.cr-profile-idtext strong{font:700 15px var(--sans);color:var(--white);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-profile-idsub{font:500 11px var(--sans);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-profile-avatar-lg{width:56px;height:56px;border-radius:50%;border:4px solid var(--dark);background:#2a2a28;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:700;color:var(--cream);overflow:hidden;box-sizing:border-box}
.cr-profile-avatar-lg img{width:100%;height:100%;object-fit:cover}
.cr-profile-dot-lg{position:absolute;bottom:2px;right:2px;width:14px;height:14px;border-radius:50%;border:3px solid var(--dark);box-sizing:border-box}
.cr-profile-dot-lg.online{background:var(--green)}
.cr-profile-dot-lg.offline{background:var(--muted)}
.cr-profile-body{padding:14px 12px 16px}
.cr-profile-name{font-size:18px;font-weight:700;color:var(--cream);margin-bottom:2px}
.cr-profile-title{font-size:12px;color:var(--muted);margin-bottom:10px}
.cr-profile-sep{height:1px;background:var(--border-d);margin:10px 0}
.cr-profile-section-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:6px;margin-top:14px}
.cr-profile-info-row{display:flex;align-items:center;gap:8px;font-size:11px;margin-bottom:4px}
.cr-profile-info-label{color:var(--muted);min-width:50px}
.cr-profile-info-value{color:var(--cream);word-break:break-all}
.cr-profile-roles{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;align-items:center}
/* The two footer actions were inline-styled with a border, their own radius and their
   own hover colours. Borderless, on the state token, like every other action. */
.cr-profile-foot{margin-top:auto;padding:12px;display:flex;gap:8px;flex-shrink:0;
  border-top:1px solid var(--hairline)}
/* Log Out is the only action down here and it is destructive, so it says so at rest
   rather than on hover — and it carries no fill. A chip around a single full-width
   action is a container drawn around nothing. */
.cr-profile-foot-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:7px;
  background:none;border:0;border-radius:9px;padding:9px 10px;
  font:600 12px var(--sans);color:var(--text-2);cursor:pointer;transition:background .14s ease,color .14s ease}
.cr-profile-foot-btn:hover{background:var(--state-hover);color:var(--cream)}
.cr-profile-foot-btn.is-danger{color:var(--danger-text,#ff6b6b)}
.cr-profile-foot-btn.is-danger:hover{background:color-mix(in srgb,var(--danger-text,#ff6b6b) 14%,transparent);color:var(--danger-text,#ff6b6b)}
/* The account switcher on the identity card — the workspace caret's twin, so the two
   cards offer the same gesture in the same place. */
.cr-profile-idcaret{width:28px;height:28px;flex:none;border:none;background:none;border-radius:8px;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-2);
  transition:background .14s ease,color .14s ease}
.cr-profile-idcaret:hover{background:rgba(255,255,255,0.1);color:#fff}
.cr-profile-idcaret svg{width:18px;height:18px;display:block;transition:transform .18s ease}
.cr-profile-idcaret.open svg{transform:rotate(180deg)}
/* Position ONLY. Everything else — the shell, the rows, the cascade-in, the hover
   magnification — comes from .server-dropdown itself, which this element now carries.
   A second set of values here is exactly how the two switchers would drift apart. */
/* Nothing positional of its own: the shared open-state rule above places it, exactly as
   it places the workspace one. */
.cr-acct-dropdown{z-index:220}
/* The workspace list gets its cascade from an #sdWorkspaceList-scoped rule; this list
   wants the same one. */
.cr-acct-dropdown.open>.server-dropdown-item{animation:sdCascadeIn .26s cubic-bezier(.21,.61,.35,1) backwards;animation-delay:calc(var(--sd-i,0)*26ms)}
.cr-acct-dropdown .server-dropdown-item:hover .sd-ws-row{transform:scale(1.08)}
.cr-acct-dropdown .server-dropdown-item:hover+.server-dropdown-item .sd-ws-row{transform:scale(1.03)}
/* .server-dropdown-sep already exists further down — reused, not redefined. */
/* A role chip is a pill; it reads the pill contract rather than its own five numbers. */
.cr-profile-role{display:inline-flex;align-items:center;gap:var(--pill-gap);
  height:var(--pill-h);padding:0 var(--pill-pad-x);border-radius:var(--pill-radius);border:0;
  background:var(--surface-inset);font-size:var(--pill-font-size);font-weight:var(--pill-font-weight);
  color:var(--pill-ink);box-sizing:border-box;line-height:1}
.cr-profile-role-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.cr-profile-role-x{margin-left:2px;cursor:pointer;opacity:.4;font-size:13px;line-height:1;transition:opacity .15s}
.cr-profile-role:hover .cr-profile-role-x{opacity:.8}
.cr-profile-role-x:hover{opacity:1;color:var(--coral)}
.cr-profile-role-add{cursor:pointer;justify-content:center;min-width:22px;padding:3px 6px;color:var(--muted);border-style:dashed;transition:all .15s}
.cr-profile-role-add:hover{background:rgba(255,255,255,.1);color:var(--cream)}
.cr-profile-msg-wrap{margin-top:10px}
/* Fields are INSET surfaces with no outline — the same treatment the composer and the
   search field wear. The 1px border on a 4%-white fill was a third style for "a thing you
   type into". Focus is shown by the fill lifting, not by a stroke appearing. */
.cr-profile-msg-input{width:100%;padding:9px 12px;border-radius:9px;border:0;
  background:var(--surface-inset);color:var(--cream);font-size:13px;font-family:var(--sans);
  outline:none;box-sizing:border-box;transition:background .14s ease}
.cr-profile-msg-input::placeholder{color:var(--text-3)}
.cr-profile-msg-input:hover{background:var(--state-hover)}
.cr-profile-msg-input:focus{background:var(--state-hover)}
.cr-profile-msg-input:focus{border-color:var(--coral)}
.cr-profile-msg-input::placeholder{color:var(--muted)}
.sidebar-bottom-actions{display:flex;align-items:center;gap:4px;padding:4px 12px 2px;border-top:1px solid var(--border-d);margin-top:4px}
.sidebar-bottom-btn{background:none;border:none;color:var(--muted);font-size:11px;font-weight:500;cursor:pointer;font-family:var(--sans);display:flex;align-items:center;gap:5px;padding:5px 8px;border-radius:6px;transition:all .15s}
.sidebar-bottom-btn:hover{color:var(--cream);background:rgba(255,255,255,.06)}
.sidebar-logout-btn:hover{color:var(--danger-text);background:rgba(239,68,68,.08)}
.sidebar-switch-btn{margin-left:auto}
/* Account switch popup panel */
.acct-switch-panel{position:fixed;bottom:60px;left:16px;width:280px;background:var(--dark);border:1px solid var(--border-d);border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.6);z-index:300;opacity:0;transform:translateY(8px) scale(.96);transition:opacity .2s ease,transform .2s cubic-bezier(.22,1,.36,1);overflow:hidden}
.acct-switch-panel.visible{opacity:1;transform:translateY(0) scale(1)}
.acct-switch-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px 10px;border-bottom:1px solid var(--border-d)}
.acct-switch-title{font-size:14px;font-weight:600;color:var(--off-white)}
.acct-switch-close{background:none;border:none;color:var(--muted);font-size:18px;cursor:pointer;padding:0 4px;line-height:1;transition:color .12s}
.acct-switch-close:hover{color:var(--cream)}
.acct-switch-body{padding:8px;max-height:300px;overflow-y:auto}
.acct-switch-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;margin-bottom:2px;position:relative;transition:background .12s}
.acct-switch-clickable{cursor:pointer}
.acct-switch-clickable:hover{background:rgba(255,255,255,.06)}
.acct-switch-active{background:rgba(255,255,255,.04)}
.acct-switch-avatar{width:36px;height:36px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;font-size:14px;font-weight:600;color:var(--muted)}
.acct-switch-avatar img{width:100%;height:100%;object-fit:cover;border-radius:50%}
.acct-switch-info{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.acct-switch-name{font-size:13px;font-weight:600;color:var(--off-white);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-switch-email{font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-switch-check{width:18px;height:18px;border-radius:50%;background:var(--green);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.acct-switch-remove{position:absolute;top:6px;right:6px;background:none;border:none;color:var(--muted);font-size:14px;cursor:pointer;padding:2px 5px;line-height:1;border-radius:4px;opacity:0;transition:all .12s}
.acct-switch-row:hover .acct-switch-remove{opacity:1}
.acct-switch-remove:hover{color:var(--danger-text);background:rgba(239,68,68,.1)}
.acct-switch-footer{padding:8px 12px;border-top:1px solid var(--border-d)}
.acct-switch-add{background:none;border:none;color:var(--cream);font-size:12px;font-weight:500;cursor:pointer;font-family:var(--sans);display:flex;align-items:center;gap:6px;padding:8px 6px;border-radius:6px;transition:background .12s;width:100%}
.acct-switch-add:hover{background:rgba(255,255,255,.06)}
/* Create room modal */
.create-room-type-sel{display:flex;gap:8px;margin-bottom:16px}
.create-room-type-btn{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px;border-radius:10px;border:1.5px solid var(--border-d);background:rgba(255,255,255,.03);cursor:pointer;transition:all .15s;font-family:var(--sans)}
.create-room-type-btn:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.18)}
.create-room-type-btn.active{border-color:var(--coral);background:rgba(124,92,255,.08)}
.create-room-type-icon{font-size:22px;line-height:1}
.create-room-type-label{font-size:12px;font-weight:700;color:var(--cream)}
.create-room-type-desc{font-size:10px;color:var(--muted)}



/* ==================== SPOTLIGHT SEARCH ==================== */
.spotlight-overlay{position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.65);backdrop-filter:blur(6px);display:flex;align-items:flex-start;justify-content:center;padding-top:14vh;opacity:0;pointer-events:none;transition:opacity .15s ease}
.spotlight-overlay.open{opacity:1;pointer-events:all}
.spotlight-box{width:min(620px,90vw);background:var(--dark);border:1px solid rgba(255,255,255,.15);border-radius:14px;box-shadow:0 24px 60px rgba(0,0,0,.7),0 0 0 1px rgba(255,255,255,.05);overflow:hidden;transform:scale(.96) translateY(-10px);transition:transform .15s ease,opacity .15s ease;opacity:0}
.spotlight-overlay.open .spotlight-box{transform:scale(1) translateY(0);opacity:1}
.spotlight-input-row{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid rgba(255,255,255,.06)}
.spotlight-search-icon{flex-shrink:0;color:var(--muted)}
.spotlight-input{flex:1;background:none;border:none;outline:none;font-family:var(--sans);font-size:16px;color:var(--off-white);caret-color:var(--coral)}
.spotlight-input::placeholder{color:var(--muted)}
.spotlight-esc-kbd{font-size:11px;color:var(--muted);background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:5px;padding:2px 7px;font-family:var(--sans);flex-shrink:0;cursor:pointer}
.spotlight-results{max-height:420px;overflow-y:auto;padding:6px 6px 4px}
.spotlight-group-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);padding:8px 12px 4px;margin-top:2px}
.spotlight-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:8px;cursor:pointer;transition:background .1s;user-select:none}
.spotlight-item:hover{background:rgba(255,255,255,.07)}
.spotlight-item.active{background:rgba(124,92,255,.14);outline:none}
.spotlight-item-icon{width:28px;height:28px;border-radius:7px;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0;color:rgba(255,255,255,.45)}
.spotlight-item-icon.round{border-radius:50%}
body[data-mobile-mode="app"] .spotlight-item-icon.round{border-radius:50%}
.spotlight-item-icon svg{width:14px;height:14px}
.spotlight-item-body{flex:1;min-width:0}
.spotlight-item-title{font-size:13px;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.spotlight-item-sub{font-size:11px;color:var(--muted);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.spotlight-item-badge{font-size:10px;font-weight:600;padding:2px 8px;border-radius:20px;flex-shrink:0;color:var(--muted);background:rgba(255,255,255,.07)}
.spotlight-item-badge.badge-task,.spotlight-item-badge.badge-board,.spotlight-item-badge.badge-room{color:var(--muted);background:rgba(255,255,255,.07)}
.spotlight-empty{padding:32px 20px;text-align:center;color:var(--muted);font-size:13px}
.spotlight-empty-icon{font-size:30px;margin-bottom:8px;opacity:.4}
.spotlight-footer{display:flex;align-items:center;gap:16px;padding:9px 16px;border-top:1px solid rgba(255,255,255,.06);font-size:10px;color:var(--muted)}
.spotlight-footer-key{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:4px;padding:1px 6px;font-family:var(--sans);margin-right:4px;font-size:10px}
/* Back arrow + X-clear are mobile-only affordances; hidden on desktop. */
.spotlight-back,.spotlight-clear{display:none}
/* ── Mobile spotlight: full-screen, iOS rows, no ESC pill, no footer ── */
body[data-mobile-mode="app"] .spotlight-overlay{padding:0;background:var(--black);backdrop-filter:none;align-items:stretch}
body[data-mobile-mode="app"] .spotlight-box{width:100%;height:100dvh;max-width:none;border:0;border-radius:0;box-shadow:none;display:flex;flex-direction:column;transform:none;background:var(--bg-main)}
body[data-mobile-mode="app"] .spotlight-overlay.open .spotlight-box{transform:none}
body[data-mobile-mode="app"] .spotlight-input-row{position:sticky;top:0;z-index:2;gap:8px;padding:calc(12px + env(safe-area-inset-top,0px)) 14px 12px;background:var(--bg-main);border-bottom:1px solid var(--border-d)}
body[data-mobile-mode="app"] .spotlight-back{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;background:none;border:0;color:var(--off-white);cursor:pointer;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .spotlight-back svg{width:24px;height:24px}
body[data-mobile-mode="app"] .spotlight-search-icon{display:none}
body[data-mobile-mode="app"] .spotlight-input{flex:1;min-width:0;font-size:17px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:11px;padding:10px 12px;color:var(--off-white)}
body[data-mobile-mode="app"] .spotlight-esc-kbd{display:none}
body[data-mobile-mode="app"] .spotlight-footer{display:none}
body[data-mobile-mode="app"] .spotlight-clear{display:none;align-items:center;justify-content:center;width:30px;height:30px;flex-shrink:0;background:rgba(255,255,255,.08);border:0;border-radius:50%;color:var(--cream);cursor:pointer;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .spotlight-overlay.has-text .spotlight-clear{display:inline-flex}
body[data-mobile-mode="app"] .spotlight-clear svg{width:15px;height:15px}
body[data-mobile-mode="app"] .spotlight-results{flex:1;max-height:none;overflow-y:auto;padding:14px 14px calc(20px + env(safe-area-inset-bottom,0px))}
body[data-mobile-mode="app"] .spotlight-group-label{font-size:12px;letter-spacing:.6px;padding:14px 6px 8px}
/* iOS rows grouped into a rounded card per section: give each item a card-ish surface
   with hairline dividers. (The result list is flat; we card the whole results pane.) */
body[data-mobile-mode="app"] .spotlight-item{padding:12px 14px;border-radius:0;background:rgba(255,255,255,.04);margin:0}
body[data-mobile-mode="app"] .spotlight-item+.spotlight-item{border-top:1px solid rgba(255,255,255,.06)}
body[data-mobile-mode="app"] .spotlight-item:first-of-type{border-radius:13px 13px 0 0}
body[data-mobile-mode="app"] .spotlight-item:last-of-type{border-radius:0 0 13px 13px}
body[data-mobile-mode="app"] .spotlight-item.active,
body[data-mobile-mode="app"] .spotlight-item:active{background:var(--purple-soft)}
body[data-mobile-mode="app"] .spotlight-item-icon{width:34px;height:34px;border-radius:9px}
body[data-mobile-mode="app"] .spotlight-item-icon svg{width:17px;height:17px}
body[data-mobile-mode="app"] .spotlight-item-title{font-size:15px}
body[data-mobile-mode="app"] .spotlight-item-sub{font-size:13px}
/* ============================================================================
   MOBILE UI REBUILD — Spotlight (turn 5 'search'). Token alignment: --bg2 sheet,
   surface result rows, purple-tint icon tiles, ink text, uppercase group labels.
   Grouping + type badges already exist. Mobile-scoped.
   ============================================================================ */
body[data-mobile-mode="app"] .spotlight-input{background:var(--surface);border:0;color:var(--ink-solid)}
body[data-mobile-mode="app"] .spotlight-input-row{background:var(--bg2);border-bottom:0}
body[data-mobile-mode="app"] .spotlight-item{background:var(--surface)}
body[data-mobile-mode="app"] .spotlight-item+.spotlight-item{border-top-color:rgba(var(--line),0.06)}
body[data-mobile-mode="app"] .spotlight-item-title{color:var(--ink-solid);font-size:16px}
body[data-mobile-mode="app"] .spotlight-item-sub{color:rgba(var(--ink),0.45)}
body[data-mobile-mode="app"] .spotlight-group-label{color:rgba(var(--ink),0.4);letter-spacing:.8px}
body[data-mobile-mode="app"] .spotlight-item-icon{background:var(--purple-tint);color:var(--m-accent-soft)}
body[data-mobile-mode="app"] .spotlight-item::after{background:rgba(var(--ink),0.3)}
body[data-mobile-mode="app"] .spotlight-item::after{content:"";flex-shrink:0;width:8px;height:14px;margin-left:4px;-webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><polyline points='9 18 15 12 9 6' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat center/contain;mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><polyline points='9 18 15 12 9 6' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat center/contain;background:var(--muted)}

/* ==================== WORKSPACE SWITCHER ==================== */
.ws-switch-trigger{
  display:flex;align-items:center;gap:8px;width:100%;cursor:pointer;
  padding:4px 6px;border-radius:8px;border:none;background:none;
  font-family:var(--sans);text-align:left;transition:background .15s;
  min-width:0;
}
.ws-switch-trigger:hover{background:var(--state-hover)}
.ws-switch-logo{width:28px;height:28px;border-radius:50%;object-fit:cover;flex-shrink:0;display:none}
.ws-switch-emoji{width:28px;height:28px;border-radius:50%;background:rgba(255,255,255,.08);border:1px solid var(--border-d);display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0}
.ws-switch-name{font-family:var(--serif);font-size:20px;font-weight:400;letter-spacing:-.5px;color:var(--off-white);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Feedback form — one style, used by the Help sheet and the settings section alike. */
.fb-kinds{display:flex;flex-wrap:wrap;gap:6px}
.fb-kind{padding:6px 11px;border-radius:8px;border:1px solid var(--border-d);background:transparent;
  color:var(--muted);font:600 12px var(--sans);cursor:pointer;transition:border-color .12s,color .12s,background .12s}
.fb-kind:hover{border-color:color-mix(in srgb,var(--purple,#7c5cff) 50%,transparent);color:var(--cream)}
.fb-kind.on{border-color:var(--purple,#7c5cff);background:color-mix(in srgb,var(--purple,#7c5cff) 14%,transparent);color:var(--off-white)}
.fb-msg{font-size:11.5px;color:var(--muted)}
.fb-msg.is-err{color:var(--pink,#de3f7f)}
.sbnav-fb-sep{display:flex;align-items:center;gap:10px;margin:16px 0 10px;font-size:11px;color:var(--muted);
  letter-spacing:.4px;text-transform:uppercase;font-weight:700}
.sbnav-fb-sep::before,.sbnav-fb-sep::after{content:'';flex:1;height:1px;background:var(--border-d)}

/* Cross-workspace unread. Same visual language as the sidebar's project dots so the two
   read as one system: a purple-tinted count pill, not a second competing accent. */
.ws-unread-slot{display:inline-flex;align-items:center;margin-left:auto;padding-left:8px;flex:none}
.ws-unread{
  display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 6px;
  border-radius:9px;font:700 10px var(--sans);line-height:1;font-variant-numeric:tabular-nums;
  /* Literal fallback: --purple is declared under html[data-brand="saucemedia"], not at the
     root, so on any other brand color-mix() would be invalid and drop the background. */
  background:color-mix(in srgb,var(--purple,#7c5cff) 30%,transparent);color:var(--text-1,#ECEAF3);
}
/* The row itself brightens, so an unread workspace is legible without reading the number. */
#sdWorkspaceList .server-dropdown-item.has-unread .sdi-label{color:var(--off-white);font-weight:600}
/* Roll-up on the closed trigger — the whole point is not having to open the dropdown to
   find out. Anchored to the trigger's top-right, and it must not push the layout. */
.ws-switch-trigger{position:relative}
.ws-switch-unread{
  position:absolute;top:0;right:2px;
  display:inline-flex;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 5px;
  border-radius:9px;font:700 10px var(--sans);line-height:1;font-variant-numeric:tabular-nums;
  background:var(--purple,#7c5cff);color:#fff;pointer-events:none;
  box-shadow:0 0 0 2px var(--dark,#141416);   /* punches it out of whatever sits behind */
  animation:wsUnreadIn .22s cubic-bezier(.22,1,.36,1);
}
@keyframes wsUnreadIn{from{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}
.ws-switch-caret{flex-shrink:0;color:rgba(255,255,255,.35);transition:transform .15s}
.ws-switch-trigger:hover .ws-switch-caret,.ws-switch-trigger.open .ws-switch-caret{color:rgba(255,255,255,.6)}
.ws-switch-dropdown{
  position:fixed;z-index:9999;
  background:var(--dark);border:1px solid var(--border-d);border-radius:10px;
  box-shadow:0 8px 32px rgba(0,0,0,.5);padding:4px;min-width:220px;
  opacity:0;transform:scale(.96) translateY(-6px);pointer-events:none;
  transition:opacity .15s ease,transform .15s ease;
}
.ws-switch-dropdown.open{opacity:1;transform:scale(1) translateY(0);pointer-events:all}
.ws-switch-section-label{font-size:9px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);padding:8px 12px 4px;margin-top:2px}
.ws-switch-item{
  display:flex;align-items:center;gap:10px;padding:8px 12px;
  border-radius:8px;cursor:pointer;transition:background .1s;user-select:none;
  font-size:12px;font-weight:500;color:var(--cream);
}
.ws-switch-item:hover{background:var(--state-hover)}
.ws-switch-item.active{color:var(--off-white);background:rgba(255,255,255,.06)}
.ws-switch-item-emoji{width:22px;height:22px;border-radius:50%;background:rgba(255,255,255,.07);border:1px solid var(--border-d);display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0}
.ws-switch-item-logo{width:22px;height:22px;border-radius:50%;object-fit:cover;flex-shrink:0}
.ws-switch-item-logo-fallback{display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,.08);font-size:12px;line-height:1;font-weight:600;color:var(--white,#fff)}
.ws-switch-item-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-switch-item-check{flex-shrink:0;opacity:0;color:var(--green)}
.ws-switch-item.active .ws-switch-item-check{opacity:1}
.ws-switch-divider{height:1px;background:var(--border-d);margin:4px 0}
.ws-switch-kbd{font-family:var(--sans);font-size:9px;color:var(--muted);background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:4px;padding:1px 5px;flex-shrink:0}
/* ==================== FLAVORS (THEMES) ==================== */
.flavor-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(108px,1fr));gap:8px;margin-top:14px}
.flavor-swatch{position:relative;border-radius:10px;overflow:hidden;cursor:pointer;border:2px solid transparent;transition:border-color .15s,transform .15s;aspect-ratio:16/10}
.flavor-swatch:hover{transform:translateY(-2px)}
.flavor-swatch.active{border-color:var(--coral)}
.flavor-swatch-bg{position:absolute;inset:0}
.flavor-swatch-accent{position:absolute;top:50%;left:50%;transform:translate(-50%,-60%);width:36px;height:10px;border-radius:3px;opacity:.9}
.flavor-swatch-emoji{position:absolute;top:5px;left:7px;font-size:13px;line-height:1}
.flavor-swatch-check{position:absolute;top:5px;right:6px;width:16px;height:16px;border-radius:50%;background:var(--coral);color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s}
.flavor-swatch.active .flavor-swatch-check{opacity:1}
.flavor-swatch-label{position:absolute;bottom:0;left:0;right:0;padding:4px 6px;background:rgba(0,0,0,.6);font-size:9px;font-weight:700;color:#fff;text-align:center;text-transform:uppercase;letter-spacing:.5px;backdrop-filter:blur(4px)}
/* ==================== THEME FLAVOR OVERRIDES ==================== */

/* -- Theme transition -- */
html.flavor-transitioning,
html.flavor-transitioning *,
html.flavor-transitioning *::before,
html.flavor-transitioning *::after{transition:background .45s ease,background-color .45s ease,color .45s ease,border-color .45s ease,box-shadow .45s ease,opacity .45s ease !important}
/* -- Gothic Castle -- */
@keyframes gothicFlicker{0%,93%,100%{opacity:1}94%{opacity:.8}95%{opacity:1}96%{opacity:.88}}

/* ═══════ EASTER EGGS ═══════ */
/* 1. Coin particle effect */
@keyframes eeCoinflight{0%{transform:translate(0,0) rotate(0deg) scale(1);opacity:1}60%{opacity:1}100%{transform:translate(var(--ee-cx),var(--ee-cy)) rotate(var(--ee-cr)) scale(.4);opacity:0}}
.ee-coin{position:fixed;z-index:99999;pointer-events:none;font-size:18px;line-height:1;will-change:transform,opacity;animation:eeCoinflight .85s cubic-bezier(.25,.46,.45,.94) forwards}
/* ── Widget: Coin Fountain ── */
.wdg-coin-body{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:6px;cursor:pointer;user-select:none;transition:opacity .15s}.wdg-coin-body:hover{opacity:.82}
.wdg-coin-emoji{font-size:34px;line-height:1;filter:drop-shadow(0 2px 10px rgba(231,206,58,.55));transition:transform .1s}.wdg-coin-body:active .wdg-coin-emoji{transform:scale(.88)}
.wdg-coin-label{font-family:var(--sans);font-size:10px;font-weight:700;color:var(--gold);letter-spacing:1.5px;text-transform:uppercase}
.wdg-coin-sub{font-family:var(--sans);font-size:9px;color:var(--muted)}
/* ── Voice Channel Widget ── */
.vc-widget-grid{display:flex;flex-wrap:wrap;gap:8px;padding:8px;align-content:start;overflow-y:auto;flex:1}
.vc-user-card{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 8px;border-radius:10px;background:rgba(255,255,255,.04);border:2px solid var(--border-d);transition:all .15s;flex:1 0 100px;max-width:160px}
.vc-user-card .vc-avatar{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:var(--black);flex-shrink:0}
.vc-user-card .vc-name{font-size:12px;font-weight:700;color:var(--cream);text-align:center;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vc-user-card .vc-status-text{font-size:9px;color:var(--muted);text-align:center;line-height:1.3}
.vc-user-card .vc-badge{font-size:8px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;padding:2px 7px;border-radius:4px}
/* ── Text Channel Widget ── */
.tc-widget-msgs{flex:1;overflow-y:auto;padding:4px 8px;display:flex;flex-direction:column;gap:2px}
.tc-msg{display:flex;gap:8px;padding:6px 4px}
.tc-msg-avatar{width:28px;height:28px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;color:var(--cream);flex-shrink:0}
.tc-msg-body{flex:1;min-width:0}
.tc-msg-author{font-size:11px;font-weight:700;color:var(--cream);display:inline}
.tc-msg-time{font-size:9px;color:var(--muted);margin-left:6px}
.tc-msg-text{font-size:12px;color:var(--off-white);line-height:1.4;word-break:break-word}
.tc-input-row{display:flex;gap:4px;padding:6px 8px;border-top:1px solid var(--border-d);flex-shrink:0}
.tc-input{flex:1;padding:6px 10px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.06);color:var(--off-white);font-family:var(--sans);font-size:12px;outline:none}
.tc-input::placeholder{color:var(--muted)}
.tc-send-btn{padding:6px 12px;border-radius:6px;border:none;background:var(--coral);color:#fff;font-size:11px;font-weight:700;cursor:pointer;font-family:var(--sans)}
/* ── Quick Links Widget ── */
.ql-widget-list{display:flex;flex-direction:column;gap:2px;overflow-y:auto;flex:1;padding:4px 0}
.ql-widget-item{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;transition:background .12s;text-decoration:none;color:var(--cream)}
.ql-widget-item:hover{background:rgba(255,255,255,.06)}
.ql-widget-icon{width:26px;height:26px;border-radius:6px;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0}
.ql-widget-name{font-size:12px;font-weight:600;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ql-edit-row{display:flex;gap:4px;padding:6px 8px;border-top:1px solid var(--border-d);flex-shrink:0;flex-wrap:wrap}
.ql-edit-input{flex:1;min-width:60px;padding:5px 8px;border-radius:4px;border:1px solid var(--border-d);background:rgba(255,255,255,.06);color:var(--cream);font-size:11px;font-family:var(--sans);outline:none}
/* ── Client YT Feed Widget ── */
.ytfeed-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px;overflow-y:auto;padding:4px;flex:1}
.ytfeed-card{border-radius:8px;overflow:hidden;background:rgba(255,255,255,.03);border:1px solid var(--border-d);cursor:pointer;transition:border-color .12s}
.ytfeed-card:hover{border-color:rgba(255,255,255,.15)}
.ytfeed-thumb{width:100%;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;font-size:22px;color:rgba(255,255,255,.3)}
.ytfeed-info{padding:8px}
.ytfeed-title{font-size:11px;font-weight:700;color:var(--cream);line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ytfeed-channel{font-size:10px;color:var(--muted);margin-top:3px}
.ytfeed-stats{font-size:9px;color:var(--muted);margin-top:2px;display:flex;gap:8px}
/* 3. Logo shimmer */
@keyframes eeSauceShimmer{0%{text-shadow:none}25%{text-shadow:0 0 16px rgba(231,206,58,.7),0 0 32px rgba(231,206,58,.3)}55%{text-shadow:0 0 16px rgba(236,92,49,.7),0 0 32px rgba(236,92,49,.3)}80%{text-shadow:0 0 14px rgba(58,158,165,.6),0 0 28px rgba(58,158,165,.25)}100%{text-shadow:none}}
.ee-logo-pulse{animation:eeSauceShimmer 1s ease-in-out forwards!important}

/* ── Workspace Settings (Discord-style) ─────────────────── */
.ss-wrap{display:flex;flex:1;min-height:0;overflow:hidden}
.ss-nav{width:220px;flex-shrink:0;background:var(--dark);padding:12px 8px;overflow-y:auto;border-right:1px solid var(--border-d)}
.ss-nav-section{padding:6px 10px 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.7px;color:var(--muted);margin-top:8px}
.ss-nav-section:first-child{margin-top:0}
.ss-nav-item{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--cream);border:none;background:none;width:100%;text-align:left;font-family:var(--sans);transition:background .12s}
.ss-nav-item:hover{background:rgba(255,255,255,.06)}
.ss-nav-item.active{background:rgba(124,92,255,.12);color:var(--coral)}
.ss-nav-item svg{width:16px;height:16px;flex-shrink:0;opacity:.6}
.ss-nav-item.active svg{opacity:1}
.ss-nav-sep{height:1px;background:var(--border-d);margin:6px 10px}
.ss-nav-item.danger{color:var(--danger-text)}
.ss-body{flex:1;overflow-y:auto;padding:14px 16px 60px}
.ss-pane-split{display:flex;gap:32px;align-items:flex-start}
.ss-profile-scroll{flex:1;min-width:0;max-width:480px}
.ss-profile-preview-wrap{position:sticky;top:0;flex-shrink:0}
.ss-body h2{font-family:var(--serif);font-size:22px;color:var(--cream);margin-bottom:4px;font-weight:400}
.ss-body .ss-desc{font-size:12px;color:var(--muted);margin-bottom:24px}
.ss-section{margin-bottom:32px}
.ss-section h3{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin-bottom:10px}
.ss-field{margin-bottom:16px}
.ss-field label{display:block;font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}
.ss-field input[type="text"],.ss-field textarea,.ss-field select{width:100%;padding:8px 12px;background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;color:var(--cream);font-size:13px;font-family:var(--sans);outline:none;transition:border .15s;box-sizing:border-box}
.ss-field input:focus,.ss-field textarea:focus,.ss-field select:focus{border-color:var(--coral)}
.ss-field textarea{min-height:80px;resize:vertical}
.ss-btn{padding:8px 18px;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;border:none;font-family:var(--sans);transition:all .15s}
.ss-btn-primary{background:var(--coral);color:#fff}
.ss-btn-primary:hover{opacity:.85}
.ss-btn-secondary{background:rgba(255,255,255,.06);color:var(--cream);border:1px solid var(--border-d)}
.ss-btn-secondary:hover{background:rgba(255,255,255,.1)}
.ss-btn-danger{background:none;color:var(--color-error,#ef4444);border:1px solid var(--color-error,#ef4444)}
.ss-btn-danger:hover{background:var(--color-error,#ef4444);color:#fff}
.ss-btn-sm{padding:5px 12px;font-size:11px}
.ss-hr{border:none;border-top:1px solid var(--border-d);margin:24px 0}
.ss-card{border:1px solid var(--border-d);border-radius:10px;padding:16px;background:rgba(255,255,255,.02)}
.ss-card+.ss-card{margin-top:10px}
.ss-inline-form{display:flex;gap:8px;align-items:center}
.ss-inline-form input{flex:1}
.ss-tag{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;background:rgba(255,255,255,.06);border-radius:12px;font-size:11px;color:var(--cream);margin:2px 4px 2px 0}
.ss-tag button{background:none;border:none;color:var(--muted);cursor:pointer;font-size:13px;padding:0 0 0 2px;line-height:1}
.ss-tag button:hover{color:var(--coral)}

/* Role picker for invite form */
.ss-role-picker{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.ss-role-picker-label{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;font-weight:700;margin-right:4px}
.ss-role-pill{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:14px;font-size:11px;font-weight:600;cursor:pointer;border:1px solid var(--border-d);background:rgba(255,255,255,.03);color:var(--muted);transition:all .15s;user-select:none}
.ss-role-pill:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.ss-role-pill.selected{border-color:currentColor;color:var(--cream)}
.ss-role-pill .ss-role-pill-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}

/* Server profile preview card */
.ss-app-preview{width:380px;border-radius:10px;overflow:hidden;border:1px solid var(--border-d);background:var(--black);flex-shrink:0;box-shadow:0 8px 32px rgba(0,0,0,.4);display:flex;flex-direction:column}
.ss-ap-titlebar{height:28px;background:rgba(255,255,255,.04);display:flex;align-items:center;padding:0 10px;gap:8px;border-bottom:1px solid rgba(255,255,255,.06)}
.ss-ap-dots{display:flex;gap:5px}
.ss-ap-dots span{width:8px;height:8px;border-radius:50%}
.ss-ap-dots span:nth-child(1){background:#ff5f57}
.ss-ap-dots span:nth-child(2){background:#febc2e}
.ss-ap-dots span:nth-child(3){background:#28c840}
.ss-ap-title{font-size:10px;color:var(--muted);letter-spacing:.3px}
.ss-ap-body{display:flex;height:280px}
.ss-ap-sidebar{width:110px;background:var(--dark);border-right:1px solid rgba(255,255,255,.06);display:flex;flex-direction:column;flex-shrink:0}
.ss-ap-sidebar-banner{height:44px;position:relative;flex-shrink:0}
.ss-ap-sidebar-icon{width:28px;height:28px;border-radius:50%;position:absolute;bottom:-10px;left:8px;background:linear-gradient(135deg,var(--coral),var(--coral-shade));border:2px solid var(--dark);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:var(--cream);overflow:hidden}
.ss-ap-sidebar-icon img{width:100%;height:100%;object-fit:cover}
.ss-ap-sidebar-name{font-size:9px;font-weight:700;color:var(--cream);padding:14px 8px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ss-ap-sidebar-desc{font-size:7px;color:var(--muted);padding:2px 8px 0;line-height:1.4;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:10px}
.ss-ap-sidebar-nav{padding:8px 4px;display:flex;flex-direction:column;gap:1px}
.ss-ap-nav-item{display:flex;align-items:center;gap:4px;font-size:8px;padding:4px 6px;border-radius:4px;color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ss-ap-nav-item svg{width:8px;height:8px;flex-shrink:0}
.ss-ap-nav-item.active{background:var(--bg-inset);color:var(--cream)}
.ss-ap-main{flex:1;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-main)}
.ss-ap-topbar{height:24px;padding:0 10px;font-size:9px;font-weight:600;color:var(--cream);display:flex;align-items:center;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0}
.ss-ap-widgets{padding:8px;display:grid;grid-template-columns:1fr 1fr;gap:6px;overflow:hidden}
.ss-ap-widget{background:rgba(255,255,255,.04);border-radius:6px;padding:8px;border:1px solid rgba(255,255,255,.06)}
.ss-ap-w-label{font-size:7px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:4px}
.ss-ap-w-val{font-size:18px;font-weight:700;font-family:var(--serif);color:var(--cream)}
.ss-ap-w-chart{grid-column:span 2}
.ss-ap-chart-bars{display:flex;align-items:flex-end;gap:4px;height:32px;margin-top:4px}
.ss-ap-chart-bars div{flex:1;background:var(--coral);border-radius:2px 2px 0 0;opacity:.7;min-width:0}
.ss-ap-w-list{grid-column:span 2}
.ss-ap-list-row{font-size:8px;color:var(--cream);padding:3px 0;display:flex;align-items:center;gap:4px;border-bottom:1px solid rgba(255,255,255,.03)}
.ss-ap-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0}

/* Workspace invite email preview card */
.ss-email-preview-block{margin-top:14px}
.ss-email-preview-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.7px;color:var(--muted);margin:0 0 8px 2px}
.ss-kb-prev{width:380px;border-radius:10px;overflow:hidden;border:1px solid var(--border-d);background:var(--black);box-shadow:0 8px 32px rgba(0,0,0,.4);display:flex;flex-direction:column}
.ss-kb-top{height:24px;display:flex;align-items:center;gap:3px;padding:0 10px;border-bottom:1px solid rgba(255,255,255,.06);background:var(--bg-main)}
.ss-kb-tab{font-size:8px;font-weight:600;color:var(--muted);padding:3px 8px;border-radius:5px}
.ss-kb-tab.on{background:var(--purple-soft,rgba(124,92,255,.16));color:var(--cream)}
.ss-kb-cols{display:flex;gap:6px;padding:8px;align-items:flex-start;background:var(--bg-main);min-height:150px}
.ss-kb-col{flex:1;background:var(--bg-inset);border:1px solid var(--hairline,rgba(255,255,255,.05));border-radius:7px;padding:6px;min-width:0}
.ss-kb-colh{display:flex;align-items:center;gap:4px;font-size:7.5px;font-weight:700;color:var(--cream);margin-bottom:6px;letter-spacing:.2px}
.ss-kb-colh .n{margin-left:auto;color:var(--muted);font-weight:600}
.ss-kb-dot{width:5px;height:5px;border-radius:2px;flex-shrink:0}
.ss-kb-t{background:var(--dark);border:1px solid var(--hairline,rgba(255,255,255,.06));border-radius:5px;padding:5px 6px;margin-bottom:5px}
.ss-kb-t:last-child{margin-bottom:0}
.ss-kb-t-title{font-size:7.5px;font-weight:600;color:var(--cream);line-height:1.35;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ss-kb-t-meta{display:flex;align-items:center;gap:3px;min-height:9px}
.ss-kb-pill{font-size:5.5px;font-weight:700;padding:1px 4px;border-radius:6px;letter-spacing:.2px}
.ss-kb-av{width:8px;height:8px;border-radius:50%;margin-left:auto;flex-shrink:0;background:linear-gradient(135deg,#a855f7,#ec4899)}

/* Banner color swatches */
.ss-banner-swatches{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
.ss-banner-swatch{width:80px;height:45px;border-radius:8px;cursor:pointer;border:2px solid transparent;transition:all .15s;flex-shrink:0}
.ss-banner-swatch:hover,.ss-banner-swatch.active{border-color:var(--cream);transform:scale(1.05)}
.ss-banner-swatch-img{position:relative}
.ss-banner-swatch-x{position:absolute;top:-6px;right:-6px;width:18px;height:18px;border-radius:50%;border:none;background:var(--color-error,#ef4444);color:#fff;font-size:12px;line-height:1;display:none;align-items:center;justify-content:center;cursor:pointer;padding:0}
.ss-banner-swatch-img:hover .ss-banner-swatch-x{display:inline-flex}

/* Server icon picker */
.ss-icon-picker{display:flex;gap:16px;align-items:center}
.ss-icon-current{width:64px;height:64px;border-radius:50%;background:linear-gradient(135deg,var(--coral),var(--coral-shade));display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#fff;overflow:hidden;flex-shrink:0;border:2px solid var(--border-d)}
.ss-icon-current img{width:100%;height:100%;object-fit:cover}

/* Members list */
.settings-member-row{display:grid;grid-template-columns:36px 1fr 1fr auto auto;gap:12px;align-items:center;padding:10px 0;border-bottom:1px solid var(--border-d)}
.settings-member-row:last-child{border-bottom:none}
.settings-member-av{width:36px;height:36px;border-radius:50%;background:var(--surface);display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;color:var(--cream);overflow:hidden}
.settings-member-av img{width:100%;height:100%;object-fit:cover}
.settings-member-name{font-size:13px;font-weight:600;color:var(--cream)}
.settings-member-email{font-size:11px;color:var(--muted)}
.settings-member-plat-role{font-size:11px;color:var(--muted);text-transform:capitalize}
.role-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;color:#fff;margin:1px 2px;white-space:nowrap}
.role-badges{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
@keyframes saShine{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}
.settings-member-actions{display:flex;gap:4px}
.settings-member-actions button{background:none;border:1px solid var(--border-d);color:var(--muted);font-size:11px;padding:4px 10px;border-radius:6px;cursor:pointer;transition:all .15s}
.settings-member-actions button:hover{color:var(--cream);border-color:var(--cream)}

/* Roles editor — two-panel Discord-style */
.roles-editor{display:grid;grid-template-columns:220px 1fr;gap:1px;background:var(--border-d);border:1px solid var(--border-d);border-radius:12px;overflow:hidden;min-height:400px}
.roles-list{background:var(--bg-main);padding:12px;display:flex;flex-direction:column;gap:2px}
.roles-list-item{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--cream);border:none;background:none;text-align:left;width:100%;transition:background .15s;user-select:none;-webkit-user-select:none;touch-action:none}
.roles-list-item:hover,.roles-list-item.active{background:rgba(255,255,255,.06)}
.roles-list-item .role-dot{width:12px;height:12px;border-radius:50%;flex-shrink:0}
.roles-list-item.rp-dragging{opacity:.2;cursor:grabbing}
.rp-drag-ghost{position:fixed;z-index:9010;pointer-events:none;opacity:.92;box-shadow:0 12px 40px rgba(0,0,0,.5),0 0 12px rgba(124,92,255,.25);transform:scale(.97) rotate(1.5deg);background:var(--bg-dark);border-radius:6px;display:flex;align-items:center;gap:8px;padding:8px 10px;font-size:13px;color:var(--cream)}
.roles-list-item.rp-drop-above{box-shadow:0 -2px 0 var(--coral) inset}
.roles-list-item.rp-drop-below{box-shadow:0 2px 0 var(--coral) inset}
.roles-list-add{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--muted);border:1px dashed var(--border-d);background:none;text-align:left;width:100%;margin-top:auto;transition:all .15s}
.roles-list-add:hover{color:var(--cream);border-color:var(--cream)}
.roles-detail{background:var(--bg-main);padding:20px;overflow-y:auto}
.roles-detail-empty{display:flex;align-items:center;justify-content:center;height:100%;color:var(--muted);font-size:13px}
.roles-field{margin-bottom:16px}
.roles-field label{display:block;font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}
.roles-field input[type="text"]{width:100%;padding:8px 12px;background:var(--surface);border:1px solid var(--border-d);border-radius:8px;color:var(--cream);font-size:13px;outline:none}
.roles-field input[type="text"]:focus{border-color:var(--coral)}
.roles-color-swatches{display:flex;gap:6px;flex-wrap:wrap}
.roles-color-swatch{width:28px;height:28px;border-radius:50%;cursor:pointer;border:2px solid transparent;transition:all .15s}
.roles-color-swatch:hover,.roles-color-swatch.active{border-color:var(--cream);transform:scale(1.15)}
.perm-grid{display:grid;gap:6px;margin-top:8px}
.perm-row{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--surface);border-radius:8px}
.perm-row-label{font-size:12px;color:var(--cream)}
.perm-row-desc{font-size:10px;color:var(--muted)}
.perm-toggle{position:relative;width:36px;height:20px;flex-shrink:0}
.perm-toggle input{opacity:0;width:0;height:0;position:absolute}
.perm-toggle .slider{position:absolute;inset:0;background:var(--border-d);border-radius:10px;cursor:pointer;transition:.2s}
.perm-toggle .slider:before{content:'';position:absolute;left:2px;top:2px;width:16px;height:16px;border-radius:50%;background:var(--muted);transition:.2s}
.perm-toggle input:checked+.slider{background:var(--coral)}
.perm-toggle input:checked+.slider:before{transform:translateX(16px);background:#fff}
.perm-section-header{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);padding:10px 0 4px;border-top:1px solid var(--border-d)}
.perm-section-header:first-child{border-top:none;padding-top:0}
.perm-advanced-toggle{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--muted);cursor:pointer;padding:10px 0 4px;border-top:1px solid var(--border-d)}
.perm-advanced-toggle:hover{color:var(--cream)}
.edit-item-role-row{display:flex;align-items:center;gap:8px;padding:7px 0;border-bottom:1px solid rgba(255,255,255,.04)}
.edit-item-role-row:last-child{border-bottom:none}
.edit-item-role-row .role-badge{flex-shrink:0}
.edit-item-role-row .eirr-remove{margin-left:auto;background:none;border:none;color:var(--muted);cursor:pointer;font-size:14px;padding:2px 6px;border-radius:4px;transition:all .15s}
.edit-item-role-row .eirr-remove:hover{color:var(--danger-text);background:rgba(239,68,68,.1)}
.eim-role-pill{display:inline-flex;align-items:center;gap:5px;padding:5px 10px;border-radius:14px;font-size:12px;font-weight:600;color:var(--cream);background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);cursor:pointer;transition:all .15s;user-select:none}
.eim-role-pill:hover{background:rgba(255,255,255,.1)}
.eim-role-pill.selected{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.25)}
.eim-role-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.eim-access-toggle{display:inline-flex;border:1px solid var(--border-d);border-radius:6px;overflow:hidden;flex-shrink:0}
.eim-access-opt{padding:3px 10px;font-size:11px;font-weight:600;color:var(--muted);cursor:pointer;transition:all .15s;user-select:none}
.eim-access-opt:first-child{border-right:1px solid var(--border-d)}
.eim-access-opt:hover{color:var(--cream)}
.eim-access-opt.active{background:rgba(255,255,255,.1);color:var(--cream)}
.eim-color-swatch{width:28px;height:28px;border-radius:50%;cursor:pointer;border:2px solid transparent;transition:all .15s;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}
.eim-color-swatch:hover{transform:scale(1.15)}
.eim-color-swatch.active{border-color:var(--cream);box-shadow:0 0 0 2px rgba(255,255,255,.15)}
.roles-detail-actions{display:flex;gap:8px;margin-top:20px;padding-top:16px;border-top:1px solid var(--border-d)}
.roles-detail-actions .btn-save{padding:6px 16px;background:var(--coral);color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;transition:opacity .15s}
.roles-detail-actions .btn-save:hover{opacity:.85}
.roles-detail-actions .btn-delete{padding:6px 16px;background:none;color:var(--danger-text);border:1px solid var(--color-error);border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;transition:all .15s}
.roles-detail-actions .btn-delete:hover{background:var(--color-error);color:#fff}

/* Role assignment dropdown */
.role-assign-dropdown{position:absolute;background:var(--bg-main);border:1px solid var(--border-d);border-radius:8px;padding:8px;z-index:100;min-width:200px;box-shadow:0 8px 24px rgba(0,0,0,.4)}
.role-assign-dropdown .rad-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:6px;cursor:pointer;font-size:12px;color:var(--cream);transition:all .12s;user-select:none;border:1px solid transparent}
.role-assign-dropdown .rad-item:hover{background:rgba(255,255,255,.06)}
.role-assign-dropdown .rad-item.selected{background:rgba(255,255,255,.1);border-color:var(--border-d)}
.role-assign-dropdown .rad-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}

/* Template cards */
.ss-template-card{border:1px solid var(--border-d);border-radius:10px;padding:14px;display:flex;align-items:center;gap:12px;transition:background .12s}
.ss-template-card:hover{background:rgba(255,255,255,.02)}
.ss-template-icon{width:40px;height:40px;border-radius:8px;background:rgba(124,92,255,.1);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
.ss-template-info{flex:1;min-width:0}
.ss-template-name{font-size:13px;font-weight:600;color:var(--cream)}
.ss-template-desc{font-size:11px;color:var(--muted);margin-top:2px}
.ss-template-meta{font-size:10px;color:var(--sec);margin-top:4px}
.ss-template-actions{display:flex;gap:6px;flex-shrink:0}

/* Emote grid */
.ss-emote-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(60px,1fr));gap:8px}
.ss-emote-cell{display:flex;flex-direction:column;align-items:center;gap:4px;padding:8px;border-radius:8px;border:1px solid var(--border-d);text-align:center;position:relative}
.ss-emote-cell img{width:32px;height:32px;object-fit:contain}
.ss-emote-cell .name{font-size:9px;color:var(--muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ss-emote-cell .ss-emote-del{position:absolute;top:2px;right:2px;background:rgba(0,0,0,.5);border:none;color:var(--muted);font-size:12px;width:18px;height:18px;border-radius:50%;cursor:pointer;display:none;align-items:center;justify-content:center}
.ss-emote-cell:hover .ss-emote-del{display:flex}


/* Full-bleed pages: cancel .content padding so internal sidebars sit flush */
#page-settings.active{margin:-28px -36px -60px;height:calc(100% + 88px);display:flex!important;flex-direction:column;overflow:hidden}
@media(max-width:900px){#page-settings.active{margin:-20px -16px -60px;height:calc(100% + 80px)}}
@media(max-width:768px){#page-settings.active{margin:-16px -12px -80px;height:calc(100% + 96px)}.ss-nav{display:none}.ss-body{padding:20px 16px}}

/* Watchdog message list table */
.wd-msg-table{width:100%;border-collapse:collapse;font-size:13px}
.wd-msg-table th{text-align:left;padding:8px 12px;color:var(--muted);font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.5px;border-bottom:1px solid var(--border-d);position:sticky;top:0;background:var(--bg)}
.wd-msg-table td{padding:10px 12px;border-bottom:1px solid var(--border-d);vertical-align:top;font-size:13px}
.wd-msg-table tr:hover{background:rgba(255,255,255,.02)}
.wd-msg-table .wd-msg-source{display:inline-flex;align-items:center;gap:5px;font-size:11px;padding:3px 8px;border-radius:6px;font-weight:600;white-space:nowrap}
.wd-msg-table .wd-msg-source.agent{background:rgba(139,92,246,.12);color:#a78bfa}
.wd-msg-table .wd-msg-source.discord{background:rgba(88,101,242,.12);color:#7289da}
.wd-msg-table .wd-msg-source.imessage{background:rgba(52,199,89,.12);color:#34c759}
.wd-msg-table .wd-msg-source.email{background:rgba(94,158,214,.12);color:#5e9ed6}
.wd-msg-table .wd-msg-source.website{background:rgba(231,206,58,.12);color:var(--gold)}
.wd-msg-table .wd-msg-source.slack{background:rgba(124,92,255,.12);color:var(--coral)}
.wd-msg-badge{display:inline-block;font-size:9px;font-weight:700;padding:2px 6px;border-radius:4px;text-transform:uppercase;margin-right:6px}
.wd-msg-badge.critical{background:var(--coral);color:#fff}
.wd-msg-badge.high{background:var(--gold);color:#000}
.wd-msg-badge.medium{background:rgba(94,158,214,.2);color:var(--blue)}
.wd-msg-badge.low{background:rgba(255,255,255,.06);color:var(--muted)}
.wd-msg-table td h1,.wd-msg-table td h2,.wd-msg-table td h3{font-size:13px;font-weight:700;margin:4px 0 2px;color:var(--cream)}
.wd-msg-table td ul{padding-left:16px;margin:4px 0}
.wd-msg-table td li{margin:2px 0}
.wd-msg-table td pre{background:rgba(0,0,0,.2);padding:6px 8px;border-radius:4px;font-size:11px;overflow-x:auto;margin:4px 0}
.wd-msg-table td strong{color:var(--cream);font-weight:600}
/* Scheduler master toggle */
.cc-scheduler-bar{display:flex;align-items:center;gap:10px;padding:8px 16px;border-bottom:1px solid var(--border-d);font-size:11px;color:var(--muted)}
.cc-scheduler-bar .sched-toggle{cursor:pointer;display:flex;align-items:center;gap:4px}
.cc-scheduler-bar .sched-toggle:hover{color:var(--text)}
.cc-scheduler-dot{width:6px;height:6px;border-radius:50%;background:var(--green)}
.cc-scheduler-dot.off{background:var(--mid-gray)}
.item-title{white-space:normal;word-wrap:break-word;padding-right:10px}

/* ── Chat readability improvements ── */
/* More visual separation between author groups */
.cr-msg-row:not(.cr-msg-grouped){margin-top:20px}
/* Tighter compact grouped messages */
.cr-msg-grouped{min-height:20px}
/* Breathing room at the end of message feeds so the last message isn't clipped at the edge */
.chatroom-messages-wrap{padding-bottom:24px}
/* ── Chat readability v2 ── */
/* More vertical breathing per row; flex-shrink:0 prevents rows from collapsing in the column flex container which caused embeds to overflow and overlap */
.cr-msg-row{padding-top:5px;padding-bottom:5px;flex-shrink:0}
/* Clearer hover highlight in dense feeds — was rgba(.02), barely visible */
.cr-msg-row:hover{background:rgba(255,255,255,.045)}
/* Wrap long URLs and unbreakable strings */
.cr-msg-text{overflow-wrap:anywhere}
/* Enable text selection in message areas (app sets user-select:none globally) */
.cr-msg-text,.cr-msg-author,.msg-embed,.msg-link{user-select:text;-webkit-user-select:text}
.chatroom-messages-wrap{user-select:text;-webkit-user-select:text}
/* Ensure embeds are proper blocks that don't overlap surrounding text */
.msg-embed{display:block;overflow:hidden}
/* Hub chat: add visual break when speaker switches so conversations are easier to scan */
/* Hub chat bubble text should also wrap long URLs */
.chat-msg{overflow-wrap:anywhere}

/* Coming Soon — 16-bit pixel art page */
.cs-wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:calc(100vh - 48px);min-height:calc(100dvh - 48px);gap:10px;padding:40px;margin:-28px -36px -60px;user-select:none}
.cs-canvas-box{image-rendering:pixelated;image-rendering:crisp-edges}
.cs-canvas-box canvas{display:block;image-rendering:pixelated;image-rendering:crisp-edges}
.cs-title{font-family:var(--pixel);font-size:14px;letter-spacing:1px;text-transform:uppercase;color:var(--gold);text-shadow:2px 2px 0 rgba(0,0,0,.5)}
.cs-subtitle{font-family:var(--pixel);font-size:8px;color:var(--muted);max-width:360px;text-align:center;line-height:2}
@keyframes csPixelBlink{0%,100%{opacity:1}50%{opacity:.3}}
/* ── Monday.com Import Modal ── */
.import-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:9999;display:flex;align-items:center;justify-content:center}
.import-modal{background:var(--dark);border:1px solid var(--border-d);border-radius:14px;padding:28px;width:500px;max-width:90vw;box-shadow:0 16px 48px rgba(0,0,0,.5)}
.import-modal h3{margin:0 0 6px;font-size:18px;font-family:var(--serif);font-weight:400;color:var(--off-white)}
.import-modal .import-subtitle{font-size:12px;color:var(--muted);margin-bottom:20px}
.import-dropzone{border:2px dashed rgba(255,255,255,.12);border-radius:10px;padding:32px 20px;text-align:center;cursor:pointer;transition:all .2s;margin-bottom:16px}
.import-dropzone:hover,.import-dropzone.dragover{border-color:var(--coral);background:rgba(124,92,255,.04)}
.import-dropzone-icon{font-size:28px;margin-bottom:8px}
.import-dropzone-text{font-size:13px;color:var(--cream)}
.import-dropzone-hint{font-size:11px;color:var(--muted);margin-top:4px}
.import-preview{background:rgba(255,255,255,.04);border-radius:10px;padding:16px;margin-bottom:16px}
.import-preview-title{font-size:13px;font-weight:600;color:var(--off-white);margin-bottom:10px;display:flex;align-items:center;gap:8px}
.import-preview-stat{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--cream);padding:3px 0}
.import-preview-stat .import-stat-num{font-weight:700;color:var(--off-white);min-width:24px}
.import-preview-cols{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.import-preview-col{font-size:11px;padding:3px 10px;border-radius:6px;font-weight:600;background:rgba(255,255,255,.06);color:var(--cream)}
.import-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:20px}
.import-actions button{padding:8px 18px;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .15s}
.import-btn-cancel{background:rgba(255,255,255,.06);color:var(--muted)}
.import-btn-cancel:hover{background:rgba(255,255,255,.1);color:var(--cream)}
.import-btn-go{background:var(--coral);color:white}
.import-btn-go:hover{filter:brightness(1.1)}
.import-btn-go:disabled{opacity:.35;cursor:default;filter:none}
.import-loading{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);padding:8px 0}
.group-create-app-btn{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);color:var(--cream);font-size:11px;font-weight:600;padding:4px 10px;border-radius:6px;cursor:pointer;transition:all .15s;font-family:var(--sans)}
.group-create-app-btn:hover{background:rgba(255,255,255,.12);color:var(--off-white)}

/* ── Popup menu fade animations ── */
@keyframes ctxFadeIn{0%{opacity:0}33%{opacity:.33}66%{opacity:.66}100%{opacity:1}}
@keyframes ctxFadeOut{0%{opacity:1}33%{opacity:.66}66%{opacity:.33}100%{opacity:0}}
.card-ctx-menu.open,.edit-ctx-menu,.sidebar-ctx-menu{animation:ctxFadeIn .2s ease-out}
.ms-dropdown.open .ms-dropdown-menu{animation:ctxFadeIn .2s ease-out}
.ctx-closing{animation:ctxFadeOut .15s ease-in forwards!important;pointer-events:none!important}
.ms-dropdown-menu.ctx-closing{display:block!important}

/* ── Workshop/child-workshop: per-column scrolling layout ── */
#page-workshop.active,#page-custom-workshop.active{margin:-28px -36px -60px;height:calc(100% + 88px);display:flex!important;flex-direction:column;overflow:hidden;padding:0!important;background:var(--bg-canvas)}
/* Automations: match the kanban board background (was the brighter --bg-board).
   Trash is NOT in here any more. That fill was chosen when the page was a card on a
   backdrop; with the card gone it became a darker rectangle inset by the content padding
   — which is to say, one more container. Trash now sits on the app background, like Home
   and Files. */
#page-automations.active{background:var(--dark)}
/* Softer, less-bright containers on those pages (no harsh outlines) to match kanban cards */
#page-trash .auto-card,#page-automations .auto-card,.auto-card{border-color:rgba(255,255,255,.06);background:rgba(255,255,255,.015)}
#page-workshop.active>:first-child,#page-custom-workshop.active>:first-child{margin-top:0!important}
#page-workshop.active .workshop-views,#page-custom-workshop.active .workshop-views{position:relative!important;top:auto!important;flex-shrink:0;padding:6px 16px 4px!important;margin:0 0 6px!important;background:transparent!important;border-bottom:none!important;min-height:0!important;height:auto!important}
/* Tab strip is flush-left so the first tab's background extends all
   the way to the page edge — matches the Airtable mockup where the
   leftmost tab has no gap between it and the viewport. The toolbar
   below keeps its 16px padding for breathing room. */
#page-workshop.active .workshop-tabs,#page-custom-workshop.active .workshop-tabs{padding:0!important}

/* Tab strips live INSIDE the .topbar as flex children (hoisted there
   by JS on init). Default: hidden — each strip is only shown when its
   workshop page is active. Active state: flex into the empty space
   left by the hidden .topbar-left, ending before .topbar-right. The
   tabs align to the BOTTOM of the topbar so the active-tab underline
   sits on the topbar's border-bottom. Negative margin-left cancels
   the topbar's 36px left padding so the first tab sits flush with
   the sidebar edge — no orphan gap on the left of "Main". */
.topbar > .workshop-tabs{display:none;align-items:flex-end;height:100%;flex:1;min-width:0;border-bottom:0;margin:0 0 0 -36px;padding:0;background:transparent;overflow-x:auto;overflow-y:hidden}
body:has(#page-workshop.active) .topbar > #workshopTabs{display:flex}
body:has(#page-custom-workshop.active) .topbar > #cwTabs{display:flex}
/* Defensive: if anything ever ends up positioned between page-workshop's top
   and the workshop-views tab strip, force it to take zero space. The kanban
   view should always start flush with the topbar. */
#page-workshop.active .client-board-header:empty,#page-custom-workshop.active .client-board-header:empty{display:none!important;padding:0!important;margin:0!important;border:0!important;height:0!important}
#page-workshop.active #workshopBoardView,#page-custom-workshop.active #cwBoardView{padding-top:0!important;margin-top:0!important}
#workshopBoardView,#cwBoardView{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden;padding:0 16px 12px}
#workshopCalendarView,#workshopGroupView,#workshopJournalView,#workshopWidgetsView,#cwCalendarView,#cwGroupView,#cwJournalView,#cwWidgetsView{flex:1;min-height:0;overflow-y:auto;padding:14px 36px 28px;display:flex;flex-direction:column}
/* Canvas (widgets) view is edge-to-edge — the iframe carries its own bg + grid */
#workshopWidgetsView,#cwWidgetsView{padding:0!important}
/* Calendar variant: edge-to-edge, no dead space. The tab strip's
   bottom border serves as the divider between tabs and the calendar
   header row. The container pulls up by -8px to absorb .workshop-views'
   margin-bottom (set at 8px in the rule above) AND grows an extra 8px
   downward so the grid stays flush with the bottom of the page. */
#workshopCalendarView,#cwCalendarView{
  padding:0 !important;
  margin-top:-8px;
  /* Extend the height to match the negative top margin so the bottom
     of the calendar pane stays at the bottom of the page. flex:1 alone
     would have shifted everything up 8px and left an 8px black band
     below the grid. */
  height:calc(100% + 8px)
}
/* Unscheduled now lives INSIDE the right sidebar as a third section
   (alongside At a Glance + Upcoming). Override its legacy floating
   drawer styles so it stacks vertically and matches the other sections. */
#workshopCalendarView .cal-sidebar .cal-unscheduled,
#cwCalendarView .cal-sidebar .cal-unscheduled,
#mvCalendarPane .cal-sidebar .cal-unscheduled{
  margin-top:0;border-radius:0;border:0;background:transparent;overflow:visible;
  /* When the drawer is open, share the sidebar 50/50 with Upcoming —
     both sections flex into available space. When closed, the
     unscheduled section collapses to just its header height. */
  display:flex;flex-direction:column;min-height:0
}
#workshopCalendarView .cal-sidebar .cal-unscheduled.open,
#cwCalendarView .cal-sidebar .cal-unscheduled.open,
#mvCalendarPane .cal-sidebar .cal-unscheduled.open{
  flex:1 1 0
}
#workshopCalendarView .cal-sidebar .cal-unscheduled:not(.open),
#cwCalendarView .cal-sidebar .cal-unscheduled:not(.open),
#mvCalendarPane .cal-sidebar .cal-unscheduled:not(.open){
  flex:0 0 auto
}
#workshopCalendarView .cal-sidebar .cal-unscheduled-header,
#cwCalendarView .cal-sidebar .cal-unscheduled-header,
#mvCalendarPane .cal-sidebar .cal-unscheduled-header{
  padding:0;background:transparent;margin-bottom:12px
}
#workshopCalendarView .cal-sidebar .cal-unscheduled-header:hover,
#cwCalendarView .cal-sidebar .cal-unscheduled-header:hover,
#mvCalendarPane .cal-sidebar .cal-unscheduled-header:hover{background:transparent;color:var(--cream)}
#workshopCalendarView .cal-sidebar .cal-unscheduled-body,
#cwCalendarView .cal-sidebar .cal-unscheduled-body,
#mvCalendarPane .cal-sidebar .cal-unscheduled-body{
  padding:0;max-height:none !important;overflow-y:auto;
  /* show the body by default in sidebar context — collapse toggle still
     adds/removes the .open class for animation purposes. */
}
#workshopCalendarView .cal-sidebar .cal-unscheduled:not(.open) .cal-unscheduled-body,
#cwCalendarView .cal-sidebar .cal-unscheduled:not(.open) .cal-unscheduled-body,
#mvCalendarPane .cal-sidebar .cal-unscheduled:not(.open) .cal-unscheduled-body{
  display:none
}
#workshopCalendarView .cal-sidebar .cal-unscheduled.open .cal-unscheduled-body,
#cwCalendarView .cal-sidebar .cal-unscheduled.open .cal-unscheduled-body,
#mvCalendarPane .cal-sidebar .cal-unscheduled.open .cal-unscheduled-body{
  /* Flex into the available height of the unscheduled section so the
     body scrolls internally rather than getting a fixed cap. With the
     parent at flex:1 1 0, this body fills the section. */
  display:flex;flex:1 1 0;min-height:0;max-height:none;overflow-y:auto;flex-direction:column
}
/* Chips stack vertically (single column) in the narrow sidebar rather
   than wrapping into multiple rows like the old horizontal drawer. */
#workshopCalendarView .cal-sidebar .cal-unscheduled-list,
#cwCalendarView .cal-sidebar .cal-unscheduled-list,
#mvCalendarPane .cal-sidebar .cal-unscheduled-list{
  flex-direction:column;flex-wrap:nowrap;gap:6px
}
#workshopCalendarView .cal-sidebar .cal-unscheduled-chip,
#cwCalendarView .cal-sidebar .cal-unscheduled-chip,
#mvCalendarPane .cal-sidebar .cal-unscheduled-chip{
  max-width:100%;width:100%;box-sizing:border-box
}
/* Header count + caret stay aligned with the existing "View all" / link
   pattern from At a Glance and Upcoming. */
#workshopCalendarView .cal-sidebar .cal-unscheduled-header .cu-count,
#cwCalendarView .cal-sidebar .cal-unscheduled-header .cu-count,
#mvCalendarPane .cal-sidebar .cal-unscheduled-header .cu-count{margin-left:auto}
/* Sidebar (workshop + child workshop + Overview) — no internal padding,
   no gap between cards, no card borders or rounded corners. The cards
   become flush sections of one continuous pane. A 1px top border
   between adjacent cards is the only visible divider. The pane itself
   is separated from the calendar grid by border-left only. */
#workshopCalendarView .cal-with-sidebar,
#cwCalendarView .cal-with-sidebar,
#mvCalendarPane .cal-with-sidebar{gap:0}
#workshopCalendarView .cal-sidebar,
#cwCalendarView .cal-sidebar,
#mvCalendarPane .cal-sidebar{
  border-left:1px solid var(--border-d) !important;
  padding:0 !important;
  background:rgba(255,255,255,.015);
  box-sizing:border-box;
  gap:0 !important;
  margin:0 !important
}
/* Cards collapse into the pane: no edges, no background tint, just
   their own internal 14px content padding. */
#workshopCalendarView .cal-sidebar .cal-side-card,
#cwCalendarView .cal-sidebar .cal-side-card,
#mvCalendarPane .cal-sidebar .cal-side-card{
  border:0 !important;
  border-radius:0 !important;
  margin:0 !important;
  background:transparent !important;
  padding:16px 18px !important
}
/* Divider line between adjacent cards. */
#workshopCalendarView .cal-sidebar .cal-side-card + .cal-side-card,
#cwCalendarView .cal-sidebar .cal-side-card + .cal-side-card,
#mvCalendarPane .cal-sidebar .cal-side-card + .cal-side-card{
  border-top:1px solid var(--border-d) !important
}
/* The calendar grid itself has 8px rounded corners that look weird
   when it runs to the page edges. Square it off on workshop calendars. */
#workshopCalendarView .calendar-grid,
#cwCalendarView .calendar-grid{border-radius:0}
.kanban{flex:1;min-height:0;align-items:stretch;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.12) transparent}
.kanban::-webkit-scrollbar{height:4px}
.kanban::-webkit-scrollbar-track{background:transparent}
.kanban::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:999px}
.kanban::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.22)}
.kanban-col-header{flex-shrink:0}
.kanban-col{overflow:hidden}
.kanban-col-body{flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.12) transparent}
.kanban-col-body::-webkit-scrollbar{width:4px}
.kanban-col-body::-webkit-scrollbar-track{background:transparent}
.kanban-col-body::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:999px}
.kanban-col-body::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.22)}
.kanban-add{background:rgba(255,255,255,.04);border:none;border-radius:0;border-bottom:1px solid var(--border-d);padding:10px 14px;margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;flex-shrink:0;text-align:center}
@media(max-width:900px){
  #page-workshop.active,#page-custom-workshop.active{margin:-20px -16px -60px;height:calc(100% + 80px)}
  #page-workshop.active .workshop-views,#page-custom-workshop.active .workshop-views{padding:12px 16px 10px}
  #workshopBoardView,#cwBoardView{padding:0 16px 12px}
  #workshopCalendarView,#workshopGroupView,#workshopJournalView,#workshopWidgetsView,#cwCalendarView,#cwGroupView,#cwJournalView,#cwWidgetsView{padding:10px 16px 20px}
}
@media(max-width:768px){
  #page-workshop.active,#page-custom-workshop.active{margin:-16px -12px -80px;height:calc(100% + 96px)}
  #page-workshop.active .workshop-views,#page-custom-workshop.active .workshop-views{padding:10px 12px 8px}
  #workshopBoardView,#cwBoardView{padding:0 12px 8px}
  #workshopCalendarView,#workshopGroupView,#workshopJournalView,#workshopWidgetsView,#cwCalendarView,#cwGroupView,#cwJournalView,#cwWidgetsView{padding:8px 12px 20px}
}

/* ==================== WIDGET TOOL PAGE ==================== */
.wt-wrap{display:flex;flex-direction:column;height:100%;padding:0;animation:pageFadeIn .3s ease}
.wt-header{display:flex;align-items:center;gap:14px;padding:0 0 18px;border-bottom:1px solid var(--border-d);margin-bottom:20px;flex-shrink:0}
.wt-header-icon{font-size:26px;line-height:1;flex-shrink:0}
.wt-header-info{flex:1;min-width:0}
.wt-header-title{font-family:var(--serif);font-size:22px;color:var(--off-white);font-weight:400;line-height:1.1}
.wt-header-desc{font-size:12px;color:var(--muted);margin-top:2px}
.wt-header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}
.wt-body{flex:1;overflow-y:auto;min-height:0}
.wt-stat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;margin-bottom:20px}
.wt-stat-card{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:12px;padding:18px 20px;transition:background .15s;position:relative;overflow:hidden}
.wt-stat-card:hover{background:rgba(255,255,255,.06)}
.wt-stat-card-accent{position:absolute;top:0;left:0;right:0;height:3px}
.wt-stat-label{font-size:10px;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);font-weight:700;margin-bottom:8px;margin-top:2px}
.wt-stat-value{font-family:var(--serif);font-size:32px;color:var(--off-white);line-height:1.1;margin-bottom:4px}
.wt-stat-sub{font-size:12px;color:var(--muted)}
.wt-section{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:12px;padding:18px 20px;margin-bottom:14px}
.wt-section-title{font-size:11px;font-weight:700;color:var(--cream);margin-bottom:12px;text-transform:uppercase;letter-spacing:.6px;display:flex;align-items:center;gap:8px}
.wt-list-row{display:flex;align-items:center;padding:10px 0;border-bottom:1px solid rgba(255,255,255,.04);gap:10px}
.wt-list-row:last-child{border-bottom:none}
.wt-list-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.wt-list-main{flex:1;min-width:0}
.wt-list-title{font-size:13px;color:var(--cream);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wt-list-sub{font-size:11px;color:var(--muted);margin-top:1px}
.wt-list-right{font-size:11px;color:var(--muted);white-space:nowrap;flex-shrink:0}
.wt-empty{color:var(--muted);font-style:italic;font-size:13px;padding:24px 0;text-align:center}
.wt-goal-item{margin-bottom:16px}
.wt-goal-label{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;font-size:12px}
.wt-goal-name{color:var(--cream);font-weight:600}
.wt-goal-pct{color:var(--muted)}
.wt-goal-bar{height:8px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden}
.wt-goal-fill{height:100%;border-radius:999px;transition:width .5s cubic-bezier(.2,.8,.3,1)}
.wt-notepad{width:100%;background:transparent;border:none;outline:none;resize:none;color:var(--cream);font-family:var(--sans);font-size:13px;line-height:1.7;min-height:280px;display:block;box-sizing:border-box}
.wt-notepad::placeholder{color:var(--muted)}
.wt-site-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid rgba(255,255,255,.04)}
.wt-site-row:last-child{border-bottom:none}
.wt-site-url{font-size:13px;color:var(--cream);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wt-site-latency{font-size:11px;color:var(--muted);min-width:52px;text-align:right;flex-shrink:0}
.wt-cal-mini-days-hdr{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:2px}
.wt-cal-mini-hdr-cell{font-size:9px;text-align:center;color:var(--muted);font-weight:700;padding:2px 0;text-transform:uppercase;letter-spacing:.5px}
.wt-cal-mini-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.wt-cal-mini-day{min-height:50px;background:rgba(255,255,255,.02);border-radius:6px;padding:4px 5px;font-size:10px;color:rgba(255,255,255,.3);cursor:default;box-sizing:border-box}
.wt-cal-mini-day.wt-cal-has-posts{background:rgba(32,123,170,.07);color:var(--cream)}
.wt-cal-mini-day.wt-cal-today{background:rgba(124,92,255,.1);outline:1px solid rgba(124,92,255,.25);color:var(--off-white)}
.wt-cal-mini-day.wt-cal-empty{background:transparent;pointer-events:none}
.wt-cal-mini-dots{display:flex;flex-wrap:wrap;gap:2px;margin-top:3px}
.wt-cal-mini-dot{width:5px;height:5px;border-radius:50%}
.wt-usage-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.04);font-size:12px;gap:8px}
.wt-usage-row:last-child{border-bottom:none}
.wt-usage-label{color:var(--cream);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wt-usage-val{color:var(--muted);font-family:var(--sans);flex-shrink:0}
.wt-add-goal-btn{background:rgba(255,255,255,.03);border:1px dashed rgba(255,255,255,.1);border-radius:8px;color:var(--muted);cursor:pointer;font-size:12px;padding:8px 14px;transition:all .15s;width:100%;text-align:center;margin-top:4px;font-family:var(--sans)}
.wt-add-goal-btn:hover{color:var(--cream);background:rgba(255,255,255,.06)}
.wt-back-btn{background:none;border:1px solid var(--border-d);border-radius:6px;color:var(--muted);font-size:11px;cursor:pointer;padding:5px 10px;transition:all .15s;font-family:var(--sans)}
.wt-back-btn:hover{color:var(--cream);border-color:rgba(255,255,255,.2)}
.wt-connect-box{text-align:center;padding:36px 20px;background:rgba(255,255,255,.02);border:1px dashed var(--border-d);border-radius:12px}
.wt-connect-icon{font-size:36px;margin-bottom:12px}
.wt-connect-title{font-size:15px;color:var(--cream);font-weight:600;margin-bottom:6px}
.wt-connect-desc{font-size:12px;color:var(--muted);line-height:1.5;max-width:320px;margin:0 auto 16px}
.wt-site-input-row{display:flex;gap:8px;margin-bottom:12px}
.wt-site-input{flex:1;padding:7px 10px;border-radius:6px;border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--cream);font-size:12px;font-family:var(--sans);outline:none}
.wt-site-input:focus{border-color:var(--coral)}
.wt-pill-badge{display:inline-block;padding:2px 8px;border-radius:20px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}
.wt-chat-msg{display:flex;gap:8px;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.04)}
.wt-chat-msg:last-child{border-bottom:none}
.wt-chat-avatar{width:26px;height:26px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;color:var(--cream);flex-shrink:0}
.wt-chat-body{flex:1;min-width:0}
.wt-chat-author{font-size:11px;font-weight:600;color:var(--cream);margin-bottom:1px}
.wt-chat-text{font-size:12px;color:var(--muted);line-height:1.4;white-space:pre-wrap;word-break:break-word}
/* ── Card file drag-drop ── */
.kanban-card.file-drag-over{outline:2px solid var(--tdz-col,var(--col-color,var(--purple)));outline-offset:2px;
  background:color-mix(in srgb,var(--tdz-col,var(--col-color,var(--purple))) 10%,var(--surface-raised));transition:none;position:relative}
/* A List row is the same drop target as a tile — same overlay, same three destinations.
   It is a grid row with no positioning of its own, so it has to become the box the
   overlay is measured against; outline-offset goes inward because a row sits flush
   against its neighbours and an outward ring would overlap them. */
.gv-flat-row.file-drag-over{outline:2px solid var(--tdz-col,var(--col-color,var(--purple)));outline-offset:-2px;
  background:color-mix(in srgb,var(--tdz-col,var(--col-color,var(--purple))) 10%,transparent)}
.gv-flat-row.tdz-choosing{position:relative;z-index:30}
.gv-flat-row.file-drag-over.tdz-choosing{outline:none}


.kanban-card.file-attaching{opacity:.55;pointer-events:none;transition:opacity .15s}

/* ── Task drop zone: the hold menu, and the drop landing ────────────────────
   Wears the floating profile card's shell (.cr-profile-popout.mention-profile) because
   it is the same object — a panel that appears beside the thing you are pointing at. */
/* The destinations render INSIDE the tile, and deliberately OUTSIDE the layout. Making
   a short tile grow to fit three rows meant the whole column reflowed under the cursor
   every time the drag crossed a card — with the options now opening on arrival rather
   than after a hold, that was constant. Pinned to the tile's box instead, overhanging
   the tile below when three rows need more room than the tile has.
   --tdz-col is the tile's own status colour, set from JS; the var chain is the fallback
   for a column that has no colour at all. */
.kanban-card.tdz-choosing{z-index:30}
.kanban-card.file-drag-over.tdz-choosing{outline:none}
.tdz-choices{position:absolute;left:0;right:0;top:0;bottom:0;min-height:128px;z-index:6;
  display:flex;flex-direction:column;justify-content:center;gap:4px;padding:8px;
  border:2px solid var(--tdz-col,var(--col-color,var(--purple)));border-radius:14px;
  background:color-mix(in srgb,var(--tdz-col,var(--col-color,var(--purple))) 16%,rgba(0,0,0,.72));
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
/* Near the bottom of a full column the overhang would be clipped by the column's own
   scroll box, so it hangs off the top edge instead. */
.tdz-choices.grows-up{top:auto;bottom:0}
/* One destination fills the tile rather than sitting as a short row with dead space
   under it, which reads like something failed to load. */
.tdz-choices.is-solo{min-height:0}
.tdz-choices.is-solo .tdz-choice{flex:1;justify-content:center}
.tdz-choice{display:flex;align-items:center;gap:9px;width:100%;padding:6px 9px;
  border:1px solid transparent;border-radius:8px;
  background:color-mix(in srgb,var(--bg-shell) 88%,transparent);
  color:var(--ink-solid);font:600 12px var(--sans);text-align:left;cursor:copy;
  animation:sdCascadeIn .2s cubic-bezier(.21,.61,.35,1) backwards;
  transition:background .12s ease,border-color .12s ease,transform .12s ease}
.tdz-choice:nth-child(2){animation-delay:40ms}
.tdz-choice:nth-child(3){animation-delay:80ms}
.tdz-choice-ico{flex:none;width:20px;height:20px;display:grid;place-items:center;
  color:var(--tdz-col,var(--col-color,var(--purple)))}
.tdz-choice-ico svg{width:15px;height:15px}
.tdz-choice-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* is-over, not :hover — during a drag nothing is hovered, so the row the drag is over
   is marked explicitly. */
.tdz-choice.is-over{background:color-mix(in srgb,var(--tdz-col,var(--col-color,var(--purple))) 34%,var(--bg-shell));
  border-color:var(--tdz-col,var(--col-color,var(--purple)));transform:scale(1.02)}
.tdz-choice.is-over .tdz-choice-ico{color:var(--ink-solid)}

/* The landing. The chip arcs from where the file was let go into the middle of the
   task and shrinks as the task takes it; --tdz-dx/--tdz-dy carry that trip, measured
   at drop time. Both sit on <body> so a column's scroll overflow cannot clip them. */
.tdz-fly{position:fixed;z-index:10250;pointer-events:none;
  display:flex;align-items:center;gap:7px;max-width:220px;
  padding:7px 11px 7px 8px;border-radius:9px;
  background:var(--bg-shell);border:1px solid var(--purple);
  box-shadow:0 12px 30px rgba(0,0,0,.5);
  transform:translate(-50%,-50%);transform-origin:50% 50%;
  animation:tdzFly .46s cubic-bezier(.45,0,.7,.15) forwards}
.tdz-fly-ico{flex:none;width:17px;height:17px;color:var(--purple)}
.tdz-fly-ico svg{width:17px;height:17px;display:block}
.tdz-fly-name{font:600 12px var(--sans);color:var(--ink-solid);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@keyframes tdzFly{
  0%{transform:translate(-50%,-50%) scale(1);opacity:1}
  55%{transform:translate(calc(-50% + var(--tdz-dx,0px)*.55),calc(-50% + var(--tdz-dy,0px)*.55 - 24px)) scale(.74);opacity:1}
  100%{transform:translate(calc(-50% + var(--tdz-dx,0px)),calc(-50% + var(--tdz-dy,0px))) scale(.2);opacity:0}}
.tdz-ring{position:fixed;z-index:10249;pointer-events:none;border-radius:12px;
  border:2px solid var(--purple);
  animation:tdzRing .55s cubic-bezier(.22,1,.36,1) .3s forwards;opacity:0}
@keyframes tdzRing{0%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.07)}}
.kanban-card.tdz-recv{animation:tdzRecv .45s cubic-bezier(.22,1,.36,1) .3s}
@keyframes tdzRecv{0%{transform:scale(1)}40%{transform:scale(1.035)}100%{transform:scale(1)}}
@media (prefers-reduced-motion:reduce){
  .tdz-choice{animation:none;transition:none}
  .tdz-choice.is-over{transform:none}
  .tdz-fly,.tdz-ring,.kanban-card.tdz-recv{animation:none;display:none}
}
/* Ghost card shrink-to-title animation.
   These are DIRECT-child selectors, and the title is no longer a direct child of the card —
   it lives inside .kc-stage-title now. Without exempting that row too, dragging would
   collapse the title along with everything else and leave an empty ghost. */
.kanban-card-ghost{min-height:0!important}
.kanban-card-ghost > :not(.kanban-card-text):not(.kc-stage-title){transition:max-height .2s ease,opacity .15s ease,margin .2s ease,padding .2s ease;overflow:hidden;max-height:80px}
.kanban-card-ghost.ghost-shrunk > :not(.kanban-card-text):not(.kc-stage-title){max-height:0;opacity:0;margin-top:0!important;margin-bottom:0!important}
/* Hold-to-drag: slightly more prominent feedback */
.kanban-card.card-hold{box-shadow:0 0 0 2px var(--col-color,var(--coral)),0 4px 24px rgba(0,0,0,.5),0 0 20px color-mix(in srgb,var(--col-color,var(--coral)) 25%,transparent);border-color:var(--col-color,var(--coral));cursor:grab}

/* ── Route-to-board picker ── */
.card-route-btn{background:none;border:1px solid var(--border-d);color:var(--muted);font-size:12px;font-family:var(--sans);cursor:pointer;padding:6px 12px;border-radius:8px;display:flex;align-items:center;gap:6px;transition:all .15s}
.card-route-btn:hover{color:var(--cream);border-color:rgba(255,255,255,.22);background:rgba(255,255,255,.04)}
.card-route-btn svg{flex-shrink:0}
.card-route-picker{position:fixed;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 8px 28px rgba(0,0,0,.55);min-width:200px;max-height:280px;overflow-y:auto;z-index:10001;padding:4px 0}
.card-route-picker-item{display:flex;align-items:center;gap:8px;padding:8px 14px;font-size:12px;font-family:var(--sans);color:var(--cream);cursor:pointer;transition:background .1s;white-space:nowrap}
.card-route-picker-item:hover{background:rgba(255,255,255,.06)}
.card-route-picker-item .route-item-icon{font-size:14px;line-height:1;flex-shrink:0}
.card-route-picker-empty{padding:10px 14px;font-size:12px;color:var(--muted);font-style:italic}
.card-route-routing-badge{display:inline-flex;align-items:center;gap:4px;background:rgba(58,158,165,.15);border:1px solid rgba(58,158,165,.3);color:var(--teal);font-size:11px;font-family:var(--sans);padding:3px 8px;border-radius:6px;font-weight:600;letter-spacing:.3px}

/* ==================== UNIFIED PAGE TABS ==================== */
.page-tabs{display:flex;gap:4px;padding:0 0 10px;margin-bottom:14px;border-bottom:1px solid var(--border-d)}
.page-tab{padding:7px 16px;border:1px solid var(--border-d);border-radius:6px;background:none;font-family:var(--sans);font-size:12px;font-weight:500;color:var(--muted);cursor:pointer;transition:all .15s;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.page-tab:hover{color:var(--cream);border-color:rgba(255,255,255,.2)}
.page-tab.active{background:var(--state-hover);color:var(--cream);border-color:rgba(255,255,255,.15)}
.page-tab svg{width:14px;height:14px;opacity:.6;flex-shrink:0}
.page-tab.active svg{opacity:1}
.page-tab .tab-count{font-size:10px;background:rgba(255,255,255,.08);color:var(--muted);padding:1px 6px;border-radius:10px;font-weight:600;font-family:var(--sans)}
.page-tab.active .tab-count{background:rgba(255,255,255,.12);color:var(--cream)}

/* ==================== AUTOMATIONS CANVAS ==================== */
.cinv-wrap{animation:pageFadeIn .3s ease}
.cinv-split{display:grid;grid-template-columns:1fr 300px;gap:20px;align-items:start}
@media(max-width:900px){.cinv-split{grid-template-columns:1fr}}
.cinv-submit-card{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:12px;padding:24px;margin-bottom:20px}
.cinv-card-title{font-family:var(--serif);font-size:18px;color:var(--cream);margin-bottom:4px}
.cinv-card-sub{font-size:12px;color:var(--muted);margin-bottom:16px;line-height:1.5}
.cinv-mode-tabs{display:flex;gap:6px;margin-bottom:18px}
.cinv-mode-tab{padding:6px 14px;border:1px solid var(--border-d);border-radius:6px;background:none;color:var(--muted);font-size:12px;font-family:var(--sans);cursor:pointer;transition:all .15s}
.cinv-mode-tab.active{background:var(--state-hover);color:var(--cream);border-color:rgba(255,255,255,.2)}
.cinv-upload-zone{border:2px dashed rgba(255,255,255,.12);border-radius:10px;padding:28px 20px;text-align:center;cursor:pointer;transition:all .2s;margin-bottom:14px}
.cinv-upload-zone:hover,.cinv-upload-zone.drag-over{border-color:var(--coral);background:rgba(124,92,255,.06)}
.cinv-upload-preview{display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(115,172,131,.08);border:1px solid rgba(115,172,131,.2);border-radius:8px;margin-bottom:14px;font-size:12px;color:var(--cream)}
.cinv-upload-preview-name{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cinv-pay-card{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:12px;padding:20px;margin-bottom:16px}
.cinv-pay-title{font-size:10px;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);font-weight:700;margin-bottom:12px}
.cinv-pay-methods{display:flex;flex-direction:column;gap:8px}
.cinv-pay-btn{display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:8px;border:1px solid var(--border-d);text-decoration:none;color:var(--cream);font-size:12px;transition:all .15s;font-family:var(--sans)}
.cinv-pay-btn:hover{border-color:rgba(255,255,255,.25);background:rgba(255,255,255,.05)}
.cinv-pay-btn-name{font-size:12px;font-weight:600}
.cinv-pay-btn-desc{font-size:10px;color:var(--muted)}
.cinv-auto-pill{display:inline-flex;align-items:center;gap:4px;background:rgba(115,172,131,.12);border:1px solid rgba(115,172,131,.25);color:var(--green);font-size:10px;font-weight:700;padding:2px 8px;border-radius:10px;letter-spacing:.3px;margin-left:6px}
/* ── Automations ── */
.auto-section{margin-bottom:28px}
.auto-section-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.auto-section-title{font-family:var(--serif);font-size:18px;color:var(--off-white);display:flex;align-items:center;gap:8px}
.auto-add-btn{padding:6px 14px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer;transition:background .12s,border-color .12s}
.auto-add-btn:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2)}
.auto-canvas{background-color:rgba(255,255,255,.02);background-image:radial-gradient(circle,rgba(255,255,255,.07) 1px,transparent 1px);background-size:20px 20px;border:1px solid var(--border-d);border-radius:12px;padding:20px;min-height:80px;overflow:hidden}
.auto-empty{text-align:center;padding:32px 20px;color:var(--muted);font-size:13px;font-style:italic}
/* #2/#3/#4 — automation rule cards: kanban-card look + left bar, IF/THEN pixel font, purple underline */
.auto-canvas{background-image:none;padding:14px;background-color:transparent;border:none}
.auto-rule{position:relative;display:flex;align-items:center;gap:12px;background:var(--dark);border:1px solid color-mix(in srgb, var(--col-color, var(--border-d)) 24%, transparent);border-radius:6px;padding:10px 12px 10px 16px;margin-bottom:12px;color:var(--cream);transition:background .15s,box-shadow .3s ease,border-color .2s ease,opacity .16s linear}
.auto-rule::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;border-radius:6px 0 0 6px;background:var(--col-color,var(--border-d))}
.auto-rule:hover{background:color-mix(in srgb, var(--col-color, var(--state-hover)) 22%, var(--dark));border-color:color-mix(in srgb, var(--col-color, var(--border-d)) 36%, transparent);box-shadow:0 2px 8px rgba(0,0,0,.25)}
.auto-rule-sentence{flex:1;min-width:0;font-family:var(--sans);font-size:14px;color:var(--off-white);line-height:1.55;display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.auto-rule-kw{font-family:var(--pixel);font-size:10px;font-weight:700;letter-spacing:.5px;color:var(--purple);text-transform:uppercase;line-height:1;position:relative;top:1px}
.auto-rule-part{text-decoration:underline;text-decoration-color:var(--purple);text-decoration-thickness:2px;text-underline-offset:3px;color:var(--off-white)}
.auto-rule-part b{color:var(--cream);font-weight:600}
.auto-rule-comma{color:var(--muted);margin-left:-4px}
.auto-rule-disabled{opacity:.45}
.auto-rule-controls{flex-shrink:0;display:flex;align-items:center;gap:2px}
.auto-section-ico{display:inline-flex;align-items:center;color:var(--muted)}
.auto-rule-edit,.auto-rule-delete{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:4px;border-radius:5px;color:var(--muted);cursor:pointer;line-height:0;transition:color .12s,background .12s}
.auto-rule-edit:hover{color:var(--cream);background:var(--state-hover)}
.auto-rule-delete:hover{color:var(--coral);background:rgba(140,114,219,.14)}
.auto-node{background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:10px;padding:12px 16px;min-width:120px;max-width:260px;flex:1 1 0}
.auto-node:hover{background:var(--state-hover)}
.auto-node-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-bottom:4px}
.auto-node-value{font-size:13px;color:var(--cream);line-height:1.3}
.auto-node-value .auto-detail{color:var(--muted);font-size:11px}
.auto-node-trigger{border-left:3px solid var(--gold)}
.auto-node-action{border-left:3px solid var(--green)}
.auto-connector{display:flex;align-items:center;width:48px;flex-shrink:0;justify-content:center}
.auto-connector svg{color:var(--muted)}
.auto-rule-controls{margin-left:auto;display:flex;align-items:center;gap:6px;flex-shrink:0;padding-left:12px;opacity:0;transition:opacity .15s}
.auto-rule:hover .auto-rule-controls{opacity:1}
.auto-rule-toggle{position:relative;display:inline-block;width:32px;height:18px}
.auto-rule-toggle input{opacity:0;width:0;height:0}
.auto-rule-toggle .auto-toggle-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:rgba(255,255,255,.1);border-radius:18px;transition:.2s}
.auto-rule-toggle .auto-toggle-slider:before{position:absolute;content:"";height:12px;width:12px;left:3px;bottom:3px;background:var(--muted);border-radius:50%;transition:.2s}
.auto-rule-toggle input:checked+.auto-toggle-slider{background:rgba(115,172,131,.35)}
.auto-rule-toggle input:checked+.auto-toggle-slider:before{transform:translateX(14px);background:var(--green)}
.auto-rule.disabled .auto-node{opacity:.4}
.auto-rule.disabled .auto-connector{opacity:.4}
.auto-ctrl-btn{background:none;border:none;color:var(--muted);cursor:pointer;padding:4px;border-radius:4px;font-size:12px;line-height:1;transition:color .12s,background .12s}
.auto-ctrl-btn:hover{color:var(--cream);background:var(--state-hover)}
.auto-ctrl-btn.danger:hover{color:var(--danger-text);background:rgba(239,68,68,.12)}
.auto-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:center;justify-content:center;padding:20px}
.auto-modal{background:var(--dark);border:1px solid var(--border-d);border-radius:14px;width:100%;max-width:500px;padding:28px;position:relative}
.auto-modal .ms-dropdown.open{z-index:300}
.auto-modal .ms-dropdown-menu{z-index:300}
.auto-modal h3{font-family:var(--serif);font-size:20px;color:var(--cream);margin:0 0 18px}
.auto-modal label{display:block;font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;color:var(--muted);margin-bottom:5px;margin-top:14px}
.auto-modal label:first-of-type{margin-top:0}
.auto-modal input[type="text"],.auto-modal textarea{width:100%;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:6px;color:var(--cream);font-family:var(--sans);font-size:13px;padding:8px 10px;outline:none;box-sizing:border-box;margin-bottom:4px}
.auto-modal input[type="text"]:focus,.auto-modal textarea:focus{border-color:var(--coral)}
.auto-modal textarea{min-height:60px;resize:vertical;line-height:1.5}
/* #6/#7 — single-line IF/THEN modal: combobox inputs + X/check icon buttons */
.auto-modal-line{max-width:560px}
.auto-modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px}
.auto-modal-head h3{margin:0}
.auto-modal-iconbtns{display:flex;align-items:center;gap:6px}
.auto-modal-x,.auto-modal-check{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:8px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);cursor:pointer;line-height:0;transition:background .12s,border-color .12s,color .12s}
.auto-modal-x{color:var(--muted)}
.auto-modal-x:hover{color:var(--cream);background:rgba(255,255,255,.09)}
.auto-modal-check{color:#fff;background:var(--purple);border-color:var(--purple)}
.auto-modal-check:hover{filter:brightness(1.12)}
.auto-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.auto-line .auto-rule-kw{flex-shrink:0;font-size:12px}
.auto-line-name{flex-direction:column;align-items:stretch;gap:5px;margin-top:6px;border-top:1px solid var(--border-d);padding-top:16px}
.auto-line-name label{font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;color:var(--muted)}
.auto-line-name .auto-opt{font-weight:400;text-transform:none;letter-spacing:0}
.auto-combo{position:relative;flex:1 1 160px;min-width:140px}
.auto-combo-input{width:100%;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:8px;color:var(--cream);font-family:var(--sans);font-size:13px;padding:9px 12px;outline:none;box-sizing:border-box}
.auto-combo-input:focus{border-color:var(--purple);box-shadow:0 0 0 2px var(--purple-soft)}
.auto-combo-input::placeholder{color:var(--muted)}
.auto-combo-menu{display:none;position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:200;max-height:240px;overflow-y:auto;background:var(--surface);border:1px solid var(--border-d);border-radius:8px;padding:4px;box-shadow:0 8px 28px rgba(0,0,0,.45)}
.auto-combo-menu.open{display:block}
.auto-combo-item{padding:8px 10px;border-radius:6px;font-size:13px;color:var(--cream);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.auto-combo-item:hover,.auto-combo-item.hi{background:var(--purple-soft);color:var(--off-white)}
.auto-combo-empty{padding:10px;font-size:12px;color:var(--muted);text-align:center}
.auto-inline-config{margin-top:10px}
.auto-inline-config:empty{margin-top:0}
.auto-config-area{margin-top:6px;margin-bottom:4px}
.auto-config-area .ms-dropdown{margin-bottom:4px}
@media(max-width:768px){.auto-rule{flex-wrap:wrap}.auto-node{min-width:100%;max-width:100%}.auto-connector{width:100%;height:32px;transform:rotate(90deg)}.auto-rule-controls{width:100%;justify-content:flex-end;padding-top:8px;opacity:1}}



/* ── VIDEO GENERATOR ── */
.vg-root{display:flex;flex-direction:column;height:100%;overflow:hidden}
.vg-header{padding:16px 24px;border-bottom:1px solid var(--border-d);display:flex;align-items:center;gap:12px;flex-shrink:0}
.vg-header h2{font-family:var(--serif);font-size:20px;font-weight:400;color:var(--off-white);margin:0}
.vg-body{flex:1;overflow-y:auto;padding:20px 24px 60px}
.vg-steps{display:flex;gap:4px;margin-left:auto}
.vg-steps button{padding:4px 12px;font-size:11px;font-weight:600;border:1px solid var(--border-d);border-radius:6px;background:transparent;color:var(--muted);cursor:pointer;text-transform:uppercase;letter-spacing:.5px}
.vg-steps button.active{background:var(--state-hover);color:var(--off-white);border-color:var(--coral)}
.vg-steps button:hover{background:rgba(255,255,255,.04)}
.vg-section{margin-bottom:24px}
.vg-section-title{font-size:11px;text-transform:uppercase;letter-spacing:.8px;color:var(--muted);margin-bottom:10px;font-weight:700}
.vg-project-list{display:flex;flex-direction:column;gap:8px}
.vg-project-card{padding:12px 16px;background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;cursor:pointer;display:flex;align-items:center;gap:12px}
.vg-project-card:hover{background:rgba(255,255,255,.06)}
.vg-project-card .name{font-size:14px;color:var(--off-white);font-weight:500}
.vg-project-card .meta{font-size:11px;color:var(--muted);margin-left:auto}
.vg-project-card .status{font-size:10px;padding:2px 8px;border-radius:4px;background:rgba(255,255,255,.06);color:var(--muted);text-transform:uppercase;letter-spacing:.5px}
.vg-btn{padding:6px 14px;font-size:12px;font-weight:600;border:1px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.06);color:var(--cream);cursor:pointer;transition:all .15s}
.vg-btn:hover{background:rgba(255,255,255,.1)}
.vg-btn.primary{background:var(--coral);color:#fff;border-color:var(--coral)}
.vg-btn.primary:hover{opacity:.85}
.vg-btn.danger{color:var(--danger-text);border-color:var(--color-error)}
.vg-btn:disabled{opacity:.35;pointer-events:none}
.vg-input{padding:8px 12px;font-size:13px;border:1px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.05);color:var(--off-white);width:100%;font-family:var(--sans)}
.vg-input:focus{border-color:var(--coral);outline:none}
.vg-textarea{min-height:120px;resize:vertical;line-height:1.5;font-family:var(--sans)}
.vg-scene{padding:12px 14px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:8px;margin-bottom:8px;position:relative}
.vg-scene.red-cue{opacity:.4;border-left:3px solid var(--coral)}
.vg-scene.external-ref{border-left:3px solid var(--blue)}
.vg-scene-header{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.vg-scene-num{font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.5px}
.vg-scene-time{font-size:10px;color:var(--teal);font-family:var(--sans)}
.vg-scene-text{font-size:13px;color:var(--cream);line-height:1.5}
.vg-scene-text.editable{cursor:text;padding:4px 6px;border-radius:4px}
.vg-scene-text.editable:focus{background:rgba(255,255,255,.05);outline:1px solid var(--border-d)}
.vg-scene-actions{display:flex;gap:4px;margin-top:8px}
.vg-scene-actions button{padding:2px 8px;font-size:10px;border:1px solid var(--border-d);border-radius:4px;background:transparent;color:var(--muted);cursor:pointer}
.vg-scene-actions button:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.vg-scene-media{margin-top:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.vg-scene-media img,.vg-scene-media video{max-height:80px;border-radius:4px;border:1px solid var(--border-d)}
.vg-scene-media a{font-size:11px;color:var(--blue);text-decoration:underline}
.vg-status{display:inline-block;font-size:10px;padding:2px 6px;border-radius:3px;text-transform:uppercase;letter-spacing:.4px}
.vg-status.done{background:rgba(115,172,131,.15);color:var(--green)}
.vg-status.generating,.vg-status.polling,.vg-status.queued{background:rgba(231,206,58,.15);color:var(--gold)}
.vg-status.failed{background:rgba(239,68,68,.15);color:var(--danger-text)}
.vg-style-prompt{margin-bottom:16px;padding:12px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:8px}
.vg-style-prompt label{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);display:block;margin-bottom:6px;font-weight:700}
.vg-export-checklist{list-style:none;padding:0;margin:0}
.vg-export-checklist li{padding:6px 0;font-size:13px;color:var(--cream);border-bottom:1px solid rgba(255,255,255,.03)}
.vg-export-checklist li::before{content:'✓ ';color:var(--green)}
.vg-back-btn{font-size:12px;color:var(--muted);cursor:pointer;background:none;border:none;padding:0}
.vg-back-btn:hover{color:var(--cream)}
.vg-loading{color:var(--muted);font-size:13px;font-style:italic;padding:20px 0}
.vg-regen-row{display:flex;gap:6px;align-items:center;margin-top:6px}
.vg-regen-row input{flex:1;padding:4px 8px;font-size:11px;border:1px solid var(--border-d);border-radius:4px;background:rgba(255,255,255,.05);color:var(--cream)}
.vg-regen-row input:focus{border-color:var(--coral);outline:none}
.vg-grid-header{display:grid;grid-template-columns:1.2fr 1.2fr .8fr .8fr;gap:14px;padding:8px 14px;margin-bottom:4px}
.vg-grid-header span{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.vg-grid-row{display:grid;grid-template-columns:1.2fr 1.2fr .8fr .8fr;gap:14px;padding:12px 14px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:8px;margin-bottom:6px;align-items:start}
.vg-grid-row .vg-col-script{font-size:12px;color:var(--cream);line-height:1.5}
.vg-grid-row .vg-col-desc{font-size:12px;color:var(--off-white);line-height:1.5}
.vg-grid-row .vg-col-desc .vg-desc-text{margin-bottom:6px;font-style:italic;color:var(--gold);transition:background .15s}
.vg-grid-row .vg-col-desc .vg-desc-text:focus{background:rgba(255,255,255,.06);outline:1px solid var(--border-d)}
.vg-grid-row .vg-col-media{display:flex;flex-direction:column;gap:6px}
.vg-grid-row .vg-col-media img{max-width:100%;border-radius:4px}
.vg-grid-row .vg-col-media video{max-width:100%;border-radius:4px}
.vg-grid-row .vg-col-video{display:flex;flex-direction:column;gap:6px}
.vg-grid-row .vg-col-video video{max-width:100%;border-radius:4px}
.vg-grid-row .vg-col-video img{max-width:100%;border-radius:4px}
.vg-grid-row .vg-scene-num{font-size:10px;font-weight:700;color:var(--muted);letter-spacing:.5px;margin-bottom:4px;display:block}
.vg-grid-row .vg-inline-actions{display:flex;gap:4px;flex-wrap:wrap;margin-top:6px}
.vg-grid-row .vg-inline-actions button{font-size:10px;padding:3px 8px}
/* Video thumb placeholder. Geometry only — it sweeps with the shared skeleton
   shimmer ("Loading skeletons" further down), which also flips in light mode;
   its own hard-coded white gradient never did. */
.vg-loader{width:100%;aspect-ratio:16/9;border-radius:4px;display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--muted)}
.vg-loader .vg-loader-text{display:flex;flex-direction:column;align-items:center;gap:4px}
.vg-loader .vg-spinner{width:20px;height:20px;border:2px solid rgba(255,255,255,.1);border-top-color:var(--gold);border-radius:50%;animation:spin 1s linear infinite}
/* ── Video Generator Preview Tab ── */
.vg-tabs{display:flex;gap:4px;margin-left:auto}
.vg-tab{padding:6px 14px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;border:1px solid var(--border-d);border-radius:6px;background:transparent;color:var(--muted);cursor:pointer;transition:all .15s}
.vg-tab.active{background:var(--state-hover);color:var(--off-white);border-color:var(--coral)}
.vg-tab:hover:not(.active){background:rgba(255,255,255,.04);color:var(--cream)}
.vg-body-preview{display:flex;flex-direction:column;overflow:hidden;padding-bottom:0}
.vg-preview-layout{display:flex;gap:20px;flex:1;overflow:hidden}
.vg-preview-script{width:420px;flex-shrink:0;overflow-y:auto;padding:0 16px 60px 0;scroll-behavior:smooth}
.vg-preview-script .vg-ps-scene{padding:12px 14px;border-radius:8px;margin-bottom:8px;cursor:pointer;transition:background .12s;border:1px solid transparent}
.vg-preview-script .vg-ps-scene:hover{background:rgba(255,255,255,.03)}
.vg-preview-script .vg-ps-scene.active{background:rgba(124,92,255,.06);border-color:rgba(124,92,255,.15)}
.vg-preview-script .vg-ps-num{font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px;display:flex;align-items:center;gap:8px}
.vg-preview-script .vg-ps-num .vg-ps-thumb{width:40px;height:24px;border-radius:3px;object-fit:cover}
.vg-preview-script .vg-ps-text{font-size:14px;color:rgba(255,255,255,.4);line-height:1.6;transition:color .2s}
.vg-preview-script .vg-ps-scene.active .vg-ps-text{color:var(--cream)}
.vg-preview-script .vg-ps-word{transition:color .15s,background .15s;border-radius:2px;padding:0 1px}
.vg-preview-script .vg-ps-word.spoken{color:var(--off-white);background:rgba(124,92,255,.15)}
.vg-preview-right{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}
.vg-preview-player{position:relative;background:#000;border-radius:8px;overflow:hidden;aspect-ratio:16/9;flex-shrink:0}
.vg-preview-player video,.vg-preview-player .vg-preview-placeholder{width:100%;height:100%;object-fit:contain;position:absolute;top:0;left:0}
.vg-preview-placeholder{display:flex;align-items:center;justify-content:center;color:var(--cream);font-size:15px;font-family:var(--sans);text-align:center;padding:24px;background:#111}
.vg-preview-controls{display:flex;align-items:center;gap:10px;padding:12px 0}
.vg-preview-controls button{padding:6px 14px;font-size:12px;font-weight:600;border:1px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.06);color:var(--cream);cursor:pointer}
.vg-preview-controls button:hover{background:rgba(255,255,255,.1)}
.vg-preview-controls .vg-play-btn{background:var(--coral);color:#fff;border-color:var(--coral);min-width:70px}
.vg-preview-controls .vg-play-btn:hover{opacity:.9}
.vg-preview-time{font-size:13px;font-family:var(--sans);color:var(--cream);min-width:100px}
.vg-preview-scrubber{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:rgba(255,255,255,.1);border-radius:3px;outline:none;cursor:pointer}
.vg-preview-scrubber::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;border-radius:50%;background:var(--coral);cursor:pointer}
.vg-preview-scene-info{padding:12px 0;font-size:12px;color:var(--muted);border-top:1px solid var(--border-d);margin-top:8px;flex:1;overflow-y:auto}
.vg-preview-scene-info .vg-psi-title{font-size:13px;color:var(--cream);font-weight:600;margin-bottom:4px}
.vg-preview-scene-info .vg-psi-desc{font-size:12px;color:var(--gold);font-style:italic;line-height:1.5}
.vg-preview-script .vg-ps-scene.red-cue{border-left:3px solid var(--coral);opacity:.6}
.vg-preview-script .vg-ps-scene.red-cue .vg-ps-text{color:var(--coral);font-style:italic;font-size:12px}

/* ==================== UNIFIED PROPERTY SYSTEM ==================== */
/* Property row layout in card modal */
/* Matched to .subtask-inline-row — same padding, gap, radius and row height, so a
   property reads identically whether it sits on a task or on a subtask. */
.card-prop-row{display:flex;align-items:center;gap:9px;margin-top:2px;min-height:34px;
  padding:4px 8px;border-radius:8px}
/* Property rows were ragged — 36 / 40 / 41 / 45px — because every control type had
   its own height (a text input 21px, a person editor 26, a date button 27, a select
   31). One control height makes every row identical, and 26 + 8px of row padding
   lands them on the same 34px as a subtask row. */
.card-prop-value > input,
.card-prop-value > button,
.card-prop-value > .ms-dropdown,
.card-prop-value > .ms-dropdown > .ms-dropdown-trigger,
.card-prop-value > .prop-person-editor,
.card-prop-value > div > input{min-height:26px;box-sizing:border-box}
/* min-height alone leaves a control 26.5px when its own content + padding + borders
   exceed it (the date button did), which shows up as one ragged row. Pin the height. */
.card-prop-value > .ms-dropdown,
.card-prop-value > .ms-dropdown > .ms-dropdown-trigger,
.card-prop-value > button,
.card-prop-value > input,
.card-prop-value > div > input{height:26px}
.card-prop-row[draggable="true"]{cursor:grab}
.card-prop-row.drag-over-top{box-shadow:inset 0 2px 0 var(--coral)}
.card-prop-row.drag-over-bottom{box-shadow:inset 0 -2px 0 var(--coral)}
/* Same type as .subtask-inline-title: 13px, --cream. The label was 11px/--muted,
   which read as a different component sitting next to the subtask rows. */
/* gap:9px matches .subtask-inline-row, so glyph→text spacing is identical in both. */
.card-prop-label{font-size:13px;color:var(--cream);min-width:110px;max-width:110px;display:flex;align-items:center;gap:9px;cursor:pointer;padding:0;border-radius:6px;transition:background .1s;flex-shrink:0;user-select:none;position:relative}
/* Hidden until the ROW is hovered — not the label. Keyed to the label it only
   appeared while pointing directly at the property name, which made it easy to miss.
   visibility rather than display so its column stays reserved: with display:none the
   row's contents shifted sideways the moment it appeared, and the ⋮ would not hold a
   consistent x with the subtask rows'. */
.card-prop-menu-btn{display:inline-flex;visibility:hidden;background:none;border:none;color:var(--muted);font-size:14px;cursor:pointer;padding:0 2px;line-height:1;margin-left:auto;flex-shrink:0;opacity:.5;transition:opacity .1s}
.card-prop-row:hover .card-prop-menu-btn{visibility:visible}
.card-prop-menu-btn:hover{opacity:1;color:var(--cream)}
.card-prop-label:hover{background:rgba(255,255,255,.04)}
/* 20px to match .subtask-inline-check's box, so a property name and a subtask name
   start at the same x. The glyph inside stays its own size and just centres. */
.card-prop-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.5;color:var(--muted)}
.card-prop-icon svg{width:14px;height:14px}
.card-prop-value{flex:1;min-width:0}
/* ---- One control width for every property value ----------------------------
   The value column was ragged: a text input 120px (`.group-inline-edit` carries a
   global max-width:120px from the group view that leaks in here), a date button
   108, a number 100, a URL ~185 — while selects and person editors stretched the
   full 514. Eleven properties meant eleven container widths. Pin every SINGLE-value
   control to one width. Chip-based values (person, multiselect, route, files) are
   left flowing: their width IS their content, and forcing a box around them would
   just reintroduce ragged edges from the other direction. */
.card-modal{--cm-ctl-w:280px}
.card-modal .card-prop-value > input:not([type="checkbox"]),
.card-modal .card-prop-value > button,
.card-modal .card-prop-value > .cm-ctl-wrap{width:var(--cm-ctl-w);max-width:100%}
/* createMsDropdown writes width:100% as an INLINE style, so !important is the only
   lever a stylesheet has here — unlike #cardModalColWrap, which solves the same
   problem by sizing a wrapper, these dropdowns sit directly in the value cell. */
.card-modal .card-prop-value > .ms-dropdown{width:var(--cm-ctl-w)!important;max-width:100%}
.card-modal .card-prop-value > input.group-inline-edit,
.card-modal .card-prop-value > .cm-ctl-wrap > input.group-inline-edit{max-width:none}
.card-modal .card-prop-value > .cm-ctl-wrap{display:flex;align-items:center;gap:4px}
.card-modal .card-prop-value > .cm-ctl-wrap > input{flex:1;min-width:0;max-width:none}
/* ---- Smart string --------------------------------------------------------------
   How the value is being read is reported by the property's ICON, not by a badge next
   to the field — see smartKindIcon(). The badge appeared and disappeared as you typed,
   and each change relaid out a row inside a scrolling modal, which is what made the
   view jump the moment a value became currency. The icon box is a fixed 20px whatever
   it draws, so swapping it costs no layout at all.

   Values stay LEFT-aligned. Right-aligning numerics is the usual spreadsheet cue, but
   here it made a value physically move across the field mid-keystroke the moment the
   parser recognised it — the text running away from the cursor as you typed. */
.smart-val.is-num{font-variant-numeric:tabular-nums}
/* The kind icon reads as a live indicator rather than dead chrome. */
.card-prop-row .card-prop-icon svg{transition:opacity .12s}
.smart-open{flex:none;color:var(--blue);font-size:11px;text-decoration:none;
  padding:0 2px;line-height:1}
.smart-open:hover{text-decoration:underline}
/* ---- Checkbox ---------------------------------------------------------------
   It was a raw native <input type=checkbox>, which macOS Chrome paints as a white
   box no stylesheet can reach — `accent-color` only tints the CHECKED fill, so an
   unchecked box stayed bright white in a black modal. appearance:none takes the
   box back and draws it in the app's own palette. */
.card-modal .card-prop-value input[type="checkbox"]{
  appearance:none;-webkit-appearance:none;
  width:18px;height:18px;min-height:0;margin:0;flex-shrink:0;
  background:rgba(255,255,255,.06);border:1px solid var(--border-d);
  border-radius:5px;cursor:pointer;display:inline-grid;place-content:center;
  transition:background .12s,border-color .12s}
.card-modal .card-prop-value input[type="checkbox"]:hover{border-color:var(--muted)}
.card-modal .card-prop-value input[type="checkbox"]::before{
  content:"";width:10px;height:10px;transform:scale(0);
  transition:transform .12s ease;background:var(--bg-main);
  clip-path:polygon(14% 44%,0 60%,40% 100%,100% 22%,84% 6%,38% 68%)}
.card-modal .card-prop-value input[type="checkbox"]:checked{
  background:var(--green);border-color:var(--green)}
.card-modal .card-prop-value input[type="checkbox"]:checked::before{transform:scale(1)}
.card-modal .card-prop-value input[type="checkbox"]:focus-visible{
  outline:2px solid var(--coral);outline-offset:2px}
.card-modal .card-prop-value input[type="checkbox"]:disabled{opacity:.5;cursor:default}
/* Room below as well as above — the button sat flush against the COMMENTS heading while
   every other section break in the modal breathes ~24px. */
.card-prop-add{margin:10px 0 24px}
.card-prop-empty{opacity:0;transition:opacity .2s;padding:4px 0}
.card-prop-empty:hover{opacity:1}
#cardModalCustomFields:hover .card-prop-empty{opacity:1}

/* Property pills (select/multi-select) */
.prop-pill{display:inline-flex;align-items:center;gap:3px;font-size:10px;font-weight:600;padding:2px 8px;border-radius:999px;white-space:nowrap;line-height:1.4}
.prop-pill+.prop-pill{margin-left:3px}
.prop-pill-remove{width:14px;height:14px;border-radius:50%;border:none;background:rgba(255,255,255,.12);color:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:9px;padding:0;margin-left:2px;transition:background .1s}
.prop-pill-remove:hover{background:rgba(255,255,255,.28)}
.prop-pill-add{width:20px;height:20px;border-radius:50%;border:1px dashed var(--border-d);background:none;color:var(--muted);cursor:pointer;font-size:12px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}
.prop-pill-add:hover{background:rgba(255,255,255,.06);border-color:var(--coral);color:var(--coral)}

/* Multi-select editor */
.multiselect-editor{display:flex;flex-wrap:wrap;gap:4px;align-items:center;min-height:26px;padding:2px}
.multiselect-dropdown{position:fixed;z-index:10001;background:var(--dark);border:1px solid var(--border-d);border-radius:8px;padding:4px 0;min-width:180px;max-height:200px;overflow-y:auto;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.multiselect-dropdown-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:12px;color:var(--cream);transition:background .1s}
.multiselect-dropdown-item:hover{background:rgba(255,255,255,.06)}
.multiselect-dropdown-item .msd-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.multiselect-dropdown-search{width:100%;border:none;background:rgba(255,255,255,.05);color:var(--cream);font-size:12px;padding:6px 12px;outline:none;border-bottom:1px solid var(--border-d)}

/* Person PFP avatars on kanban cards */
.kanban-card-bottom{display:flex;align-items:center;justify-content:space-between;margin-top:6px}
.kanban-card-bottom-right{display:flex;align-items:center;gap:8px;margin-left:auto}
.card-avatars{display:flex;align-items:center}
.card-avatar{width:22px;height:22px;border-radius:50%;overflow:hidden;object-fit:cover;border:2px solid var(--dark);flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:700;color:#fff;background:var(--coral)}
.card-avatar img,.card-avatar svg{width:100%;height:100%;object-fit:cover;display:block}
.card-avatar+.card-avatar{margin-left:-6px}
.card-avatar img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.card-avatar-overflow{width:22px;height:22px;border-radius:50%;border:2px solid var(--dark);background:rgba(255,255,255,.12);display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:var(--muted);margin-left:-6px;flex-shrink:0}
.card-bottom-row{display:flex;align-items:center;justify-content:space-between;margin-top:4px}

/* ═══════════════════ TaskWhiz board theme (henshu) ═══════════════════ */
/* Columns: clean vertical stacks, no card-like container */
.kanban-col{
  /* A board is three levels deep — canvas, the column holding the cards, then the cards. */
  background:var(--surface-container) !important;
  border:none !important;
  border-radius:14px !important;
  padding:8px 10px 10px !important;
  flex:0 0 282px !important;min-width:282px;max-width:282px;
}
/* Drop the full-width colored bar; keep a thin transparent grab/drag strip */
.kanban-col-header-bar{
  background:transparent !important;
  min-height:10px !important;height:10px !important;
  border-radius:0 !important;
  padding-right:0 !important;
}
.kanban-col-menu{position:absolute;top:5px;right:5px;z-index:7}
.kanban-col-header{padding:2px 4px 12px !important;align-items:center}
.kanban-col-title{display:flex;align-items:center;gap:9px;min-width:0}
.kanban-col-title::before{
  content:'';width:11px;height:11px;border-radius:3px;flex-shrink:0;
  background:var(--col-color,var(--muted));
  box-shadow:0 0 0 3px color-mix(in srgb,var(--col-color,var(--muted)) 16%,transparent);
}
.kanban-col-name{
  font-family:var(--sans);font-weight:700;font-size:13px;color:var(--off-white);
  letter-spacing:.2px;text-transform:none;padding:0;
}
.kanban-col-name:hover{background:rgba(255,255,255,.06)}
.kanban-col-count{
  font-family:var(--sans);font-size:11px;font-weight:600;color:var(--muted);
  background:transparent;padding:0 2px;
}
/* Add-card: subtle left-aligned row */
.kanban-add{
  background:transparent !important;border:none !important;border-bottom:none !important;
  color:var(--muted);text-transform:none;letter-spacing:0;
  font-size:12px;font-weight:600;text-align:left;
  padding:9px 8px !important;border-radius:8px;margin:2px 0;
}
.kanban-add:hover{background:rgba(255,255,255,.05) !important;color:var(--white)}

/* Cards: rounded surface, content-sized, soft border + lift on hover */
.kanban-card{
  background:color-mix(in srgb,var(--col-color,var(--purple)) 4%,var(--card,#171719)) !important;
  border:1px solid rgba(255,255,255,.06) !important;
  border-radius:14px !important;
  padding:14px !important;
  margin-bottom:10px;
  min-height:0 !important;
  box-shadow:0 1px 2px rgba(0,0,0,.22);
  transition:transform .14s ease,box-shadow .2s ease,border-color .2s ease;
}
.kanban-card:hover{
  border-color:color-mix(in srgb,var(--col-color,var(--purple)) 55%,transparent) !important;
  box-shadow:0 6px 22px rgba(0,0,0,.4);
}
.kanban-card.card-active{
  border-color:var(--col-color,var(--purple)) !important;
  box-shadow:0 0 0 1px var(--col-color,var(--purple)),0 8px 26px rgba(0,0,0,.45);
}
.kanban-card[data-card-color]{border-left:3px solid var(--card-color,var(--purple)) !important}
.kanban-card-text{
  font-family:var(--sans);font-weight:600;font-size:14px;line-height:1.4;
  color:var(--white);letter-spacing:.1px;
}
.kanban-card-text .card-desc,.kanban-card-text .kanban-card-desc{font-weight:400;color:var(--muted);font-size:12px}
.kanban-card-meta{margin-top:8px;font-size:11px;gap:8px}

/* Progress bars → match the status color, rounded, taller */
.kanban-card-cl-bar{height:6px !important;background:rgba(255,255,255,.08);border-radius:999px}
.kanban-card-cl-fill{background:var(--col-color,var(--purple)) !important;border-radius:999px}
.kanban-card-cl-footer{margin-top:5px;font-size:11px}
.kanban-card-cl-pct{color:var(--col-color,var(--purple));font-weight:700}
.kanban-card-subtask-progress .subtask-bar{height:6px !important;border-radius:999px}
.kanban-card-subtask-progress .subtask-bar-fill{background:var(--col-color,var(--purple)) !important;border-radius:999px}

/* Comment / view counts */
.kanban-card-comments{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--muted);font-family:var(--sans)}
.kanban-card-comments svg{opacity:.6}

/* Avatar stack — overlapping with surface-matched ring */
.card-avatar,.card-avatar-overflow{width:24px;height:24px;border:2px solid var(--card,#171719)}
.card-avatar{background:var(--purple)}
.card-avatar+.card-avatar,.card-avatar-overflow{margin-left:-8px}
.kanban-card-bottom{margin-top:12px}
.kanban-cards{min-height:8px}
/* Idle add-column affordance: same column footprint with only the centered plus.
   No fake colour bar or header is rendered before the user starts the draft. */
.kanban-col-ghost{
  opacity:0;
  display:flex;flex-direction:column;
  transition:opacity .25s ease;
  /* An explicit border. .kanban-col derives one from color-mix(... var(--col-color) ...),
     and a column with no colour yet leaves that custom property SET BUT EMPTY — which makes
     the whole declaration invalid at computed-value time (the var() fallback does not fire
     for an empty value, only for a missing one), so border-color fell back to currentColor:
     a near-white ring that read as the grey-brown flash until a real colour arrived. */
  border-color:var(--hairline-2);
}
.kanban-new-col-input{border-color:var(--hairline-2) !important}
.kanban-new-col-input>.kanban-col-header{padding-top:2px !important}
.kanban-new-col-input .kanban-col-title{width:100%}
.kanban-new-col-title-input{
  min-width:0;width:100%;margin:0;border:0;background:transparent;outline:0;
  box-shadow:none;color:var(--off-white);caret-color:var(--off-white);
}
.kanban-new-col-title-input:focus{
  background:rgba(255,255,255,.06);box-shadow:none;
}
.kanban-col-ghost:hover{opacity:.6}
.kanban-col-ghost.kanban-col-ghost-empty{opacity:.42}
.kanban-col-ghost.kanban-col-ghost-empty:hover{opacity:.62}
.kanban-col-ghost-label{display:inline-flex;align-items:center;justify-content:center}
.kanban-col-ghost-plus{font-size:40px;font-weight:300;line-height:1;color:var(--muted);opacity:.7;transition:color .15s ease,opacity .15s ease,transform .15s ease}
.kanban-col-ghost:hover .kanban-col-ghost-plus{color:var(--off-white);opacity:1;transform:scale(1.06)}
/* Calendar Upcoming rail is RESTORED and moved to the LEFT per the mockup —
   see the CALENDAR override block at the end of this file. */

/* ─── Polish batch ─── */
/* A. Slight drop shadow cast by the left sidebar */
/* No cast shadow. It made sense when the sidebar and the canvas were different
   colours — it read as a soft separation. They are one ground now, so all the
   shadow does is smear a dark band down the join: the "black gap between the
   sidebar and the project area". Same plane, no seam. */
/* Restored at the owner's request, but as a WIDE soft falloff rather than the tight band
   that was removed here before — a tight shadow between two surfaces of the same colour
   reads as a black gap in the join, which is what made the old one wrong. */
.sidebar{box-shadow:18px 0 30px -18px rgba(0,0,0,.9)}
/* B. Kanban cards = same dark as the sidebar, no outlines */
.kanban-card{background:var(--surface-raised) !important;border:none !important;border-radius:12px !important;box-shadow:0 1px 3px rgba(0,0,0,.2) !important;transition:background var(--dur-press) var(--ease-std),box-shadow var(--dur-press) var(--ease-std),transform var(--dur-press) var(--ease-std) !important}
/* Subtle hover: keep the 1px border and only shift its COLOR (never border:none — that
   snaps the border to currentColor on mouse-leave and flashes white). Gentle lift + soft shadow. */
.kanban-card:hover{background:#1d1d20 !important;box-shadow:0 3px 11px rgba(0,0,0,.24) !important}
.kanban-card.card-active{border:none !important;box-shadow:0 0 0 2px color-mix(in srgb,var(--col-color,var(--purple)) 70%,transparent) !important}
.kanban-card[data-card-color]{border-left:none !important}
/* C. Top bar restored as the mockup's breadcrumb + search field (2026 redesign). */
/* D. "+ Add item" → a single centered + */
.kanban-add{font-size:0 !important;display:flex !important;align-items:center;justify-content:center}
.kanban-add::before{content:'+';font-size:22px;font-weight:400;line-height:1;color:var(--muted)}
.kanban-add:hover::before{color:var(--text-1)}
/* E. Column ⋮ menu — always visible + vertical */
.kanban-col-menu-btn{opacity:1 !important;font-size:0 !important;letter-spacing:0 !important}
.kanban-col-menu-btn::before{content:'\22EE';font-size:17px;letter-spacing:0;line-height:1}
.kanban-col-header-bar:hover .kanban-col-menu-btn{opacity:1}
/* ─── end Polish batch ─── */
/* ═════════════════ end TaskWhiz board theme ═════════════════ */

/* ═══════════ Sauce Media agency brand — saucemedia.henshu.app ═══════════ */
/* White-label override: the henshu platform is purple, but the Sauce Media
   tenant carries its own identity (pulled from Henshu) — coral var(--coral),
   warm dark surfaces, Libre Franklin, the signature rainbow gradient. The
   TaskWhiz layout stays; only the palette + type change. Higher specificity
   than :root so it wins regardless of source order. */
/* ═══════════ BASE PALETTE ═══════════
   These used to exist ONLY inside html[data-brand="saucemedia"] below, which meant any
   host not stamped with that attribute had no --purple, --dark, --card, --surface,
   --white, --muted or --sans at all. Not a cosmetic gap: those are load-bearing, and
   every color-mix() referencing one becomes invalid at computed-value time, which drops
   the whole declaration rather than falling back.

   index.html only stamps data-brand for a KNOWN agency, so the hosts without it are: any
   new self-serve agency subdomain, any custom domain, and localhost. The product we just
   built per-seat signup for would have rendered unstyled for the second agency that ever
   signed up — and it is why local test harnesses kept reporting these vars undefined.

   Promoting the values to :root fixes all of those and changes nothing for Sauce Media,
   whose block still follows and still wins. A future brand overriding one token now
   inherits the rest instead of starting from nothing.
   ═══════════════════════════════════════ */
:root{
  --coral:#7c5cff;
  --purple:#7c5cff;
  --purple-soft:rgba(124,92,255,.16);
  --coral-shade:#5d3fe0;
  --blue:#5E9CFF;--green:#5BCF8E;
  --bg-main:#0a0a0b;--bg-dark:#161618;--dark:#141416;--black:#070708;
  --card:#141416;--surface:#131315;
  --white:#fff;--muted:#999990;
  --sans:var(--font-sans);
}

html[data-brand="saucemedia"]{
  --coral:#7c5cff;
  --purple:#7c5cff;
  --purple-soft:rgba(124,92,255,.16);
  --coral-shade:#5d3fe0;
  --orange:#df8a83;
  --gold:#e7ce3a;--pink:#de3f7f;--blue:#5E9CFF;--green:#5BCF8E;--teal:#3a9ea5;--lavender:#c7abc4;--peach:#df8a83;
  --bg-main:#0a0a0b;--bg-dark:#161618;--dark:#141416;--black:#070708;
  --card:#141416;--surface:#131315;
  --white:#fff;--off-white:#fafaf8;--cream:#e6ded6;--muted:#999990;
  --sans:var(--font-sans);
  --rainbow:linear-gradient(90deg,#e7ce3a 0%,#e7ce3a 12%,#e6ded6 12%,#e6ded6 22%,#de3f7f 22%,#de3f7f 34%,#207baa 34%,#207baa 46%,#73ac83 46%,#73ac83 58%,#c7abc4 58%,#c7abc4 70%,#df8a83 70%,#df8a83 78%,var(--coral) 78%,var(--coral) 90%,#3a9ea5 90%,#3a9ea5 100%);
}
/* ═══════════ end Sauce Media agency brand ═══════════ */

/* ─── Sidebar Clients dropdown (on the agency label; replaces Productions page) ─── */
.sidebar-clients-wrap{position:relative}
/* Board switcher: a small icon button overlaid on the right of the "Sauce Media" home/agency row. */
.sidebar-clients-trigger{position:absolute;top:0;bottom:0;right:34px;display:flex;align-items:center;padding:0 6px;background:none;border:none;cursor:pointer;z-index:3;pointer-events:none}
.sidebar-clients-switch{width:15px;height:15px;color:var(--muted);opacity:0;transition:opacity .15s;flex-shrink:0}
/* Only agency staff can see/use the switcher; clients never do (icon stays invisible + non-interactive). */
body.agency-staff .sidebar-clients-trigger,
body[data-shuttle-mode="internal"] .sidebar-clients-trigger{pointer-events:auto}
body.agency-staff .sidebar-clients-wrap:hover .sidebar-clients-switch,
body[data-shuttle-mode="internal"] .sidebar-clients-wrap:hover .sidebar-clients-switch,
body.agency-staff .sidebar-clients-wrap.open .sidebar-clients-switch,
body[data-shuttle-mode="internal"] .sidebar-clients-wrap.open .sidebar-clients-switch{opacity:.9}
.sidebar-clients-menu{position:absolute;left:10px;right:8px;top:100%;margin-top:5px;z-index:60;background:#121211;border:1px solid rgba(255,255,255,.075);border-radius:10px;box-shadow:0 16px 36px rgba(0,0,0,.58),inset 0 1px 0 rgba(255,255,255,.025);padding:5px;max-height:320px;overflow-y:auto}
.sidebar-client-item,.sidebar-client-add{display:flex;align-items:center;gap:8px;width:100%;background:none;border:none;cursor:pointer;padding:8px 10px;border-radius:7px;font-family:var(--sans);font-size:13px;color:var(--cream);text-align:left;transition:background .12s}
.sidebar-client-item:hover,.sidebar-client-add:hover{background:rgba(255,255,255,.07)}
.sidebar-client-item.current{background:color-mix(in srgb,var(--coral) 13%,transparent);font-weight:600;color:var(--white)}
.sidebar-client-dot{width:8px;height:8px;border-radius:50%;background:var(--coral);flex-shrink:0;opacity:.85}
.sidebar-client-avatar{width:22px;height:22px;border-radius:50%;overflow:hidden;background:color-mix(in srgb,var(--coral) 16%,transparent);color:var(--coral);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;flex-shrink:0;letter-spacing:.3px}
.sidebar-client-avatar img,.sidebar-client-avatar svg{width:100%;height:100%;object-fit:cover;border-radius:50%;display:block}
.sidebar-client-name{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidebar-client-agency-tag{margin-left:6px;font-size:11px;font-style:italic;font-weight:400;color:var(--muted);opacity:.7}
.sidebar-client-edit{opacity:0;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--muted);cursor:pointer;padding:3px;border-radius:5px;transition:opacity .12s,color .12s,background .12s}
.sidebar-client-item:hover .sidebar-client-edit{opacity:.6}
.sidebar-client-edit:hover{opacity:1;color:var(--white);background:rgba(255,255,255,.1)}
.sidebar-client-edit svg{width:13px;height:13px}
.sidebar-client-check{width:13px;height:13px;color:var(--coral);flex-shrink:0}
.sidebar-clients-empty{padding:11px 10px;font-size:12px;color:var(--muted);font-style:italic;text-align:center}
.sidebar-client-add{color:var(--coral);font-weight:600;border-top:1px solid var(--border-d);margin-top:4px}
.sidebar-client-add svg{width:14px;height:14px;flex-shrink:0}
/* ─── end Sidebar Clients dropdown ─── */

/* ─── Board view tabs (Kanban / List View / Calendar) — TaskWhiz-style ─── */
.ws-view-tabs{display:inline-flex;align-items:center;gap:2px}
/* #25 — on mobile the view-switcher (Board/List/Calendar/Canvas/Automations) overflowed the
   header width, so the last tab (Automations) sat off-screen and was unreachable. Let the
   pill row scroll horizontally so every view is tappable. */
body[data-mobile-mode="app"] .ws-view-tabs{overflow-x:auto;max-width:100%;flex-wrap:nowrap;scrollbar-width:none;-webkit-overflow-scrolling:touch;touch-action:pan-x}
body[data-mobile-mode="app"] .ws-view-tabs::-webkit-scrollbar{display:none}
.ws-view-tab{display:inline-flex;align-items:center;gap:8px;background:none;border:none;cursor:pointer;
  padding:9px 16px 13px;font-family:var(--sans);font-size:15px;font-style:normal;font-weight:600;
  color:var(--muted);position:relative;transition:color .15s;white-space:nowrap;letter-spacing:.1px}
.ws-view-tab svg{width:18px;height:18px;opacity:.65;flex-shrink:0;transition:opacity .15s}
.ws-view-tab:hover{color:var(--cream)}
.ws-view-tab:hover svg{opacity:.9}
.ws-view-tab.active{color:var(--white)}
.ws-view-tab.active svg{opacity:1}
.ws-view-tab.active::after{content:'';position:absolute;left:10px;right:10px;bottom:0;height:3px;
  border-radius:3px 3px 0 0;background:var(--purple)}
/* View tabs: icon-only with a hover tooltip (text label hidden). */
.ws-view-tab-label{display:none}
.ws-view-tab{padding:11px 13px}
.ws-view-tab svg{width:20px;height:20px}
/* Hover tooltip removed — the tabs already show their label, so it was a redundant pop-up. */
.ws-view-tab::before{content:none !important}
.ws-view-tab:hover::before{opacity:0}
.ws-view-filter svg{opacity:.7}
.ws-view-filter:hover svg,.ws-view-filter.has-filters svg,.ws-view-filter.is-active svg{opacity:1}
.ws-view-filter.has-filters,.ws-view-filter.is-active{color:var(--purple)}
/* Filter button fades out on Canvas / Automations (nothing to filter there). Toggled
   by the view switcher; these two rules were collateral in the dash-canvas CSS removal
   and are restored here, beside the rest of .ws-view-filter rather than back among the
   deleted block. */
.ws-view-filter{transition:opacity .25s ease}
.ws-view-filter.filter-hidden{opacity:0;pointer-events:none}
.ws-filter-count{position:absolute;top:3px;right:2px;min-width:14px;height:14px;background:var(--purple);color:#fff;font-size:9px;font-weight:700;line-height:1;border-radius:7px;display:flex;align-items:center;justify-content:center;padding:0 3px}

/* ─── Board header banner + breadcrumb + title ─── */
/* Board-header banner removed (owner: too big). JS also strips the node; this keeps it gone. */
.ws-banner{display:none !important}
.ws-banner::after{content:'';position:absolute;bottom:0;left:0;right:0;height:60px;background:linear-gradient(to bottom,transparent,var(--dark));pointer-events:none;z-index:1}
/* ─── Board header: file-tree breadcrumb + big italic title ─── */
/* ---- Page title: ONE definition ----------------------------------------------
   Every page heading (a project, Trash, Home, Files, Settings…) is a .ws-page-title in
   a .ws-title-row. These numbers used to be written out several times over — the type
   duplicated between the title and its rename INPUT, the box duplicated between the
   editable and non-editable variants, the row gap set twice — so "make headings a bit
   smaller" meant finding all of them and the rename input silently drifted out of step.

   Change a value HERE and every page heading follows, the rename input included.
   Breakpoints override the TOKENS below, not the rules, so a responsive tweak is also
   a one-line change. */
:root{
  --page-title-font: var(--display);
  --page-title-size: 34px;
  --page-title-weight: 800;
  --page-title-tracking: -.02em;
  --page-title-leading: 1.05;
  --page-title-color: var(--white);
  /* The box behind an editable title — also applied (transparent) to a non-editable one
     so the TEXT lands in the same place on every page. */
  --page-title-pad: 6px 14px;
  --page-title-radius: 12px;
  --page-title-gap: 12px;      /* title ↔ icon */
  --page-title-icon: 34px;     /* the icon's hit box */
  --page-title-glyph: 30px;    /* the glyph drawn inside it */
  --page-header-pad: 18px 16px 6px 24px;
}
.ws-header{padding:var(--page-header-pad);display:flex;flex-direction:column;gap:8px}
.ws-breadcrumb{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-family:var(--sans);
  font-size:14px;font-style:italic;font-weight:600;color:var(--muted)}
.ws-crumb{color:var(--muted);transition:color .15s}
.ws-crumb.clickable{cursor:pointer}
.ws-crumb.clickable:hover{color:var(--cream)}
.ws-crumb-last{color:var(--white)}
/* Project titles match the Home greeting (.hh-greet): display font, 34px, same weight/tracking. */
/* One line, always. text-wrap:balance was actively working against this -- it exists to
   split a heading into even lines, so a long project name became two. A title that grows
   downward moves the tab strip and the whole board with it; an ellipsis costs a few
   characters and moves nothing. min-width:0 is what lets it actually shrink inside its
   flex row (a flex item defaults to min-width:auto and refuses to go below its text). */
.ws-page-title{margin:0;font-family:var(--page-title-font);font-size:var(--page-title-size);font-style:normal;font-weight:var(--page-title-weight);color:var(--page-title-color);line-height:var(--page-title-leading);letter-spacing:var(--page-title-tracking);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%}
.ws-page-title[onclick]:hover{opacity:.85}
/* The rename input must occupy EXACTLY the space the <h2> text did, or the whole
   page below the header jumps when you click to rename. Two things caused that:
   a 2px border-bottom (which takes layout height) and width:100% (which stretched
   the title's container out to 520px regardless of the name). The underline is now
   a box-shadow — painted, not laid out — and the width is set from the measured
   text by _sizeWsTitleInput(), so the container hugs the name and grows only as
   the user types. */
.ws-page-title-input{font-family:var(--page-title-font);font-size:var(--page-title-size);font-weight:var(--page-title-weight);letter-spacing:var(--page-title-tracking);color:var(--page-title-color);background:transparent;border:none;outline:none;padding:0;margin:0;line-height:var(--page-title-leading);display:block;width:auto;min-width:1ch;max-width:min(52vw,640px);box-shadow:0 2px 0 0 var(--ws-title-underline,var(--purple))}
.ws-title-row{display:flex;align-items:center;gap:var(--page-title-gap)}
/* Edit Project modal — icon button to the left of the Name input */
.edit-item-icon-btn{width:40px;height:40px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;color:var(--white);cursor:pointer;transition:background .15s,border-color .15s}
.edit-item-icon-btn:hover{background:var(--state-hover);border-color:rgba(255,255,255,.22)}
.ws-title-icon{display:inline-flex;align-items:center;justify-content:center;width:var(--page-title-icon);height:var(--page-title-icon);color:var(--white);flex-shrink:0;opacity:.95}
/* Project header affordances: a filled container behind the title says "you can
   edit this", matching the task card title. The icon is a real control when the
   user's role allows changing it. */
.ws-page-title.is-editable{padding:var(--page-title-pad);border-radius:var(--page-title-radius);cursor:text;
  /* Nothing at rest. A permanent fill made the title read as a control sitting in a
     grey slab — one more surface on a page that already had too many. The affordance
     belongs to approaching it, so the fill arrives on hover and focus (below).
     NO negative margin: .ws-title-row's 12px gap is the breathing room from the
     icon, and -12px cancelled it exactly, leaving the container hugging it. */
  background:transparent;
  border:1px solid transparent;
  transition:background var(--dur-short,.15s) var(--ease-std,ease),border-color var(--dur-short,.15s) var(--ease-std,ease)}
.ws-page-title.is-editable:hover,.ws-page-title.is-editable:focus-within{background:var(--surface-inset);border-color:var(--hairline-2)}
.ws-title-icon.is-editable{cursor:pointer;border-radius:10px;
  transition:background var(--dur-short,.15s) var(--ease-std,ease),transform var(--dur-press,.12s) var(--ease-std,ease)}
.ws-title-icon.is-editable:hover{background:var(--bg-inset);opacity:1}
.ws-title-icon.is-editable:active{transform:scale(.93)}
.ws-title-icon svg,.ws-title-icon img{width:var(--page-title-glyph);height:var(--page-title-glyph)}
.ws-title-icon img{border-radius:7px;object-fit:cover}
.proj-icon-picker{position:fixed;z-index:100010;background:var(--dark);border:1px solid var(--border-d);border-radius:12px;box-shadow:0 14px 44px rgba(0,0,0,.55);padding:8px;width:268px;max-width:268px;max-height:340px;overflow-y:auto} /* above .field-modal-overlay (10100) — was rendering BEHIND the edit modal */
.proj-icon-picker .pip-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:2px}
.proj-icon-picker .pip-colors{display:flex;flex-wrap:wrap;gap:7px;justify-content:flex-end;align-items:center;padding-top:9px;margin-top:8px;border-top:1px solid var(--border-d)}
.proj-icon-picker .pip-colors-label{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:600;margin-right:auto}
.proj-icon-picker .pip-swatch{width:20px;height:20px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;transition:transform .1s ease,border-color .1s ease;box-shadow:0 0 0 1px rgba(0,0,0,.3) inset}
.proj-icon-picker .pip-swatch:hover{transform:scale(1.18)}
.proj-icon-picker .pip-swatch.on{border-color:var(--cream)}
.proj-icon-picker .pip-swatch-default{background:conic-gradient(#df8a83,#e7ce3a,#86c06c,#72a2da,#8c72db,#de3f7f,#df8a83)}
.proj-icon-picker .pip-btn{width:36px;height:36px;border:none;background:none;border-radius:8px;color:var(--cream);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .12s,color .12s}
.proj-icon-picker .pip-btn:hover{background:rgba(255,255,255,.1);color:var(--white)}
.proj-icon-picker .pip-btn.on{background:color-mix(in srgb,var(--purple) 22%,transparent);color:var(--white)}
.proj-icon-picker .pip-btn svg{width:19px;height:19px}
/* ── Review tab — Frame.io-style player + comments ── */
.rev-drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;min-height:280px;border:2px dashed var(--border-d);border-radius:14px;color:var(--muted);text-align:center;padding:32px;transition:border-color .15s,background .15s}
.rev-drop.drag{border-color:var(--purple);background:color-mix(in srgb,var(--purple) 8%,transparent)}
.rev-drop svg{width:46px;height:46px;opacity:.6}
.rev-drop-title{font-size:16px;font-weight:600;color:var(--cream)}
.rev-drop-sub{font-size:13px}
.rev-link{background:none;border:none;color:var(--modal-col-color,var(--purple));font:inherit;cursor:pointer;padding:0;text-decoration:underline}
.rev-uploading{display:flex;align-items:center;justify-content:center;min-height:280px;color:var(--muted);font-size:14px;text-align:center;padding:24px}
.rev-wrap{display:flex;gap:16px;align-items:flex-start}
.rev-main{flex:1;min-width:0}
.rev-replace{margin-top:8px;font-size:12px}
/* Player */
.rev-player{position:relative;width:auto;max-width:100%;margin:0 auto;background:#000;border-radius:12px;overflow:hidden;aspect-ratio:16/9;max-height:50vh;user-select:none;-webkit-user-select:none}
.rev-video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#000;display:block}
/* True Review fullscreen. The Fullscreen API targets .rev-main so the custom
   transport and annotation UI remain available; iOS may fullscreen the native
   video instead. Both paths explicitly shed normal-stage sizing constraints. */
.rev-main:fullscreen,.rev-main:-webkit-full-screen{
  width:100vw!important;height:100vh!important;max-width:none!important;max-height:none!important;
  margin:0!important;padding:0!important;display:flex!important;flex-direction:column!important;
  overflow:hidden!important;background:#000!important
}
.rev-main:fullscreen .rev-stage,.rev-main:-webkit-full-screen .rev-stage,
.rev-stage:fullscreen,.rev-stage:-webkit-full-screen{
  width:100vw!important;height:auto!important;min-height:0!important;max-height:none!important;
  flex:1 1 auto!important;margin:0!important;padding:0!important;background:#000!important;
  display:flex!important;align-items:stretch!important;justify-content:stretch!important;overflow:hidden!important
}
.rev-main:fullscreen .rev-player,.rev-main:-webkit-full-screen .rev-player,
.rev-stage:fullscreen .rev-player,.rev-stage:-webkit-full-screen .rev-player{
  width:100%!important;height:100%!important;min-width:0!important;min-height:0!important;
  max-width:none!important;max-height:none!important;aspect-ratio:auto!important;
  margin:0!important;border-radius:0!important;box-shadow:none!important;background:#000!important
}
.rev-main:fullscreen .rev-video,.rev-main:-webkit-full-screen .rev-video,
.rev-stage:fullscreen .rev-video,.rev-stage:-webkit-full-screen .rev-video{
  width:100%!important;height:100%!important;max-width:none!important;max-height:none!important;
  object-fit:contain!important;background:#000!important
}
.rev-video:fullscreen,.rev-video:-webkit-full-screen{
  width:100vw!important;height:100vh!important;max-width:none!important;max-height:none!important;
  object-fit:contain!important;background:#000!important
}
.rev-main:fullscreen .rev-transport,.rev-main:-webkit-full-screen .rev-transport{
  width:100%!important;flex:0 0 auto!important;box-sizing:border-box;background:#000
}
.rev-buffer-indicator{position:absolute;top:50%;left:50%;z-index:6;display:flex;align-items:center;gap:9px;transform:translate(-50%,-50%);padding:9px 13px;border:1px solid rgba(255,255,255,.16);border-radius:999px;background:rgba(8,8,10,.78);box-shadow:0 7px 24px rgba(0,0,0,.35);color:#fff;font-size:12px;font-weight:650;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .15s,visibility 0s linear .15s;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.rev-player.is-buffering .rev-buffer-indicator{opacity:1;visibility:visible;transition-delay:0s}
.rev-buffer-spinner{width:15px;height:15px;flex:0 0 auto;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:revBufferSpin .72s linear infinite}
@keyframes revBufferSpin{to{transform:rotate(360deg)}}
.rev-tapzone{position:absolute;top:0;bottom:44px;width:50%;z-index:2;cursor:pointer;touch-action:manipulation}
.rev-tapzone-l{left:0}.rev-tapzone-r{right:0}
.rev-ic-pause{display:none}
.rev-player.rev-playing .rev-ic-play{display:none}
.rev-player.rev-playing .rev-ic-pause{display:block}
.rev-cm-seekable{cursor:pointer}
.card-modal.card-modal-maxed{max-width:none !important;width:100vw;height:100vh;max-height:100vh;border-radius:0}
.card-modal-overlay-maxed{padding:0 !important}
.rev-seekflash{position:absolute;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;align-items:center;gap:4px;color:#fff;opacity:0;pointer-events:none;z-index:3;background:rgba(0,0,0,.4);border-radius:50%;width:96px;height:96px;justify-content:center;transition:opacity .2s}
.rev-seekflash svg{width:30px;height:30px}.rev-seekflash span{font:600 12px var(--mono);font-variant-numeric:tabular-nums}
.rev-seekflash-l{left:9%}.rev-seekflash-r{right:9%}
.rev-seekflash.show{animation:revSeekFlash .55s ease}
@keyframes revSeekFlash{0%{opacity:0;transform:translateY(-50%) scale(.85)}25%{opacity:1;transform:translateY(-50%) scale(1)}100%{opacity:0;transform:translateY(-50%) scale(1)}}
.rev-bigplay{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:64px;height:64px;border-radius:50%;border:none;background:rgba(0,0,0,.55);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:4;transition:opacity .15s,transform .12s}
.rev-bigplay svg{width:30px;height:30px;margin-left:3px}
.rev-bigplay:active{transform:translate(-50%,-50%) scale(.93)}
.rev-player.rev-playing .rev-bigplay{opacity:0;pointer-events:none}
.rev-ctrlbar{position:absolute;left:0;right:0;bottom:0;z-index:5;display:flex;align-items:center;gap:10px;padding:8px 12px 9px;background:linear-gradient(to top,rgba(0,0,0,.75),rgba(0,0,0,0))}
.rev-cbtn{flex-shrink:0;width:30px;height:30px;border:none;background:none;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:7px;-webkit-tap-highlight-color:transparent}
.rev-cbtn:hover{background:rgba(255,255,255,.14)}
.rev-cbtn svg{width:18px;height:18px}
.rev-scrub{position:relative;flex:1;min-width:0;height:30px;display:flex;align-items:center;cursor:pointer;touch-action:none}
.rev-scrub-track{position:absolute;left:0;right:0;height:4px;border-radius:3px;background:rgba(255,255,255,.22);overflow:hidden}
.rev-scrub-buffer{position:absolute;inset:0;z-index:1}
.rev-scrub-buffer span{position:absolute;top:0;bottom:0;background:rgba(255,255,255,.42)}
.rev-scrub-fill{position:relative;z-index:2;height:100%;border-radius:3px;background:var(--modal-col-color,var(--purple));width:0}
.rev-markers{position:absolute;left:0;right:0;top:0;bottom:0;pointer-events:none}
.rev-marker{position:absolute;top:-7px;width:10px;height:13px;margin-left:-5px;transform:none;background:var(--mk,var(--gold));border:0;
  clip-path:polygon(50% 100%, 0 68%, 0 18%, 18% 0, 82% 0, 100% 18%, 100% 68%);border-radius:50%;pointer-events:auto;cursor:pointer;z-index:2;transition:transform .1s}
.rev-marker:hover{transform:translateY(-50%) scale(1.3)}
.rev-marker.resolved{background:var(--green)}
.rev-knob{position:absolute;top:50%;width:13px;height:13px;margin-left:-6.5px;transform:translateY(-50%);background:#fff;border-radius:50%;box-shadow:0 1px 4px rgba(0,0,0,.5);pointer-events:none;z-index:3;left:0}
.rev-tc{flex-shrink:0;font:700 12px var(--mono);font-variant-numeric:tabular-nums;color:#fff;cursor:pointer;padding:2px 4px;border-radius:5px;letter-spacing:.2px}
.rev-tc:hover{background:rgba(255,255,255,.14)}
.rev-media-err{position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;background:rgba(0,0,0,.85);color:var(--cream);font-size:14px}
/* Comments column */
/* No fill of its own — the rail sits on the wrap's ground; a second surface one shade
   lighter read as a panel pasted on top of the tab. Border went in the outline sweep. */
.rev-side{width:300px;flex-shrink:0;background:transparent;border:none;border-radius:12px;display:flex;flex-direction:column;max-height:62vh}
.rev-side-head{flex-shrink:0;font-size:13px;font-weight:700;color:var(--white);padding:12px 12px 8px}
.rev-count{color:var(--muted);font-weight:600}
.rev-list{flex:1;min-height:0;overflow-y:auto;padding:0 8px}
.rev-empty{font-size:13px;color:var(--muted);font-style:italic;line-height:1.5;padding:8px 4px 16px}
.rev-cm{position:relative;display:flex;gap:9px;padding:9px 8px;border-radius:9px;transition:background .12s}
.rev-cm:hover{background:rgba(255,255,255,.04)}
.rev-cm.flash{background:color-mix(in srgb,var(--gold) 18%,transparent);animation:revCmFlash 1.4s ease}
@keyframes revCmFlash{0%{background:color-mix(in srgb,var(--gold) 32%,transparent)}100%{background:transparent}}
.rev-cm-av{flex-shrink:0;width:28px;height:28px;border-radius:50%;background:var(--purple-soft);color:var(--purple);font:700 10px var(--sans);display:flex;align-items:center;justify-content:center;overflow:hidden}
.rev-cm-body{flex:1;min-width:0}
.rev-cm-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:3px}
.rev-cm-author{font-size:12px;font-weight:600;color:var(--cream)}
.rev-cm-time{font-size:11px;color:var(--muted)}
.rev-cm-idx{font:600 10px var(--mono);color:var(--muted)}
.rev-cm-scope{display:inline-flex;color:var(--muted)}.rev-cm-scope svg{width:12px;height:12px}
.rev-cm-chip{font:700 10px var(--mono);font-variant-numeric:tabular-nums;color:#1b1b1b;background:var(--gold);border:none;border-radius:5px;padding:2px 6px;cursor:pointer;letter-spacing:.2px}
.rev-cm-chip:hover{filter:brightness(1.08)}
.rev-cm-text{font-size:13px;color:var(--off-white);line-height:1.42;word-break:break-word}
.rev-cm.resolved{opacity:.55}.rev-cm.resolved .rev-cm-text{text-decoration:line-through}
.rev-cm-acts{display:flex;gap:6px;margin-top:6px;opacity:0;transition:opacity .12s}
.rev-cm:hover .rev-cm-acts{opacity:1}
.rev-cm-act{font:600 11px var(--sans);color:var(--muted);background:none;border:none;cursor:pointer;padding:0}
.rev-cm-act:hover{color:var(--cream)}
.rev-cm-resolve{display:inline-flex;align-items:center;gap:4px}
.rev-cm-resolve svg{width:14px;height:14px}
.rev-cm-resolve.on{color:var(--green)}
.rev-cm-del:hover{color:var(--danger-text)}
/* Input bar */
.rev-inputbar{flex-shrink:0;border-top:none;padding:8px 10px 10px}
.rev-anchor-row{margin-bottom:7px}
.rev-anchor-toggle{display:inline-flex;align-items:center;gap:6px;font:600 11px var(--sans);color:var(--muted);background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:999px;padding:4px 10px;cursor:pointer}
.rev-anchor-toggle b{font:700 11px var(--mono);font-variant-numeric:tabular-nums}
.rev-anchor-toggle.on{color:var(--modal-col-color,var(--purple));border-color:color-mix(in srgb,var(--modal-col-color,var(--purple)) 45%,transparent);background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 12%,transparent)}
.rev-anchor-dot{width:7px;height:7px;border-radius:50%;background:currentColor;opacity:.4}
.rev-anchor-toggle.on .rev-anchor-dot{opacity:1}
.rev-input-row{display:flex;align-items:center;gap:8px}
.rev-input{flex:1;min-width:0;background:#1c1c20;border:1px solid var(--border-d);border-radius:9px;color:var(--white);padding:9px 11px;font:inherit;font-size:13px;outline:none}
/* The review composer is a contenteditable now (it has to hold @mention chips),
   so it needs the box behaviour an <input> gave for free: a floor height when
   empty, wrapping, and a ceiling before it scrolls. */
.rev-input[contenteditable]{min-height:19px;max-height:120px;overflow-y:auto;white-space:pre-wrap;word-break:break-word;line-height:1.45}
.rev-input[contenteditable]:focus{border-color:var(--hairline)}
.rev-input .mention{vertical-align:baseline}
/* File preview: the column is rebuilt on every refresh, so the <img>/<video> is
   recreated and re-fetched — that was the flashing. Fade in on load instead of
   painting a half-decoded frame. */
.fm-previmg,.fm-prevvid{opacity:0;transition:opacity .22s var(--ease-std,ease)}
.fm-previmg.is-loaded,.fm-prevvid.is-loaded{opacity:1}
@media(prefers-reduced-motion:reduce){.fm-previmg,.fm-prevvid{transition:none;opacity:1}}
.rev-input:focus{border-color:color-mix(in srgb,var(--purple) 55%,transparent)}
.rev-send{flex-shrink:0;width:36px;height:36px;background:var(--modal-col-color,var(--purple));color:#fff;border:none;border-radius:9px;display:flex;align-items:center;justify-content:center;cursor:pointer}
.rev-send svg{width:17px;height:17px}
/* Player settings slide-up sheet */
.rev-sheet-ov{position:fixed;inset:0;z-index:99998;background:rgba(0,0,0,.5);opacity:0;transition:opacity .25s;display:flex;align-items:flex-end;justify-content:center}
.rev-sheet-ov.open{opacity:1}
.rev-sheet{width:100%;max-width:520px;background:var(--bg-dark);border-radius:18px 18px 0 0;border:1px solid var(--border-d);border-bottom:none;transform:translateY(100%);transition:transform .28s cubic-bezier(.22,1,.36,1);max-height:84vh;display:flex;flex-direction:column;padding-bottom:env(safe-area-inset-bottom,0px)}
.rev-sheet-ov.open .rev-sheet{transform:translateY(0)}
.rev-sheet-grip{width:38px;height:4px;border-radius:3px;background:color-mix(in srgb,var(--text-1) 20%,transparent);margin:9px auto 4px}
/* #7 — Calendar month/year picker sheet (mobile). Year stepper + 12-month grid + jump-to-today. */
.cmp-sheet{padding:0 16px 16px}
.cmp-yearrow{display:flex;align-items:center;justify-content:center;gap:18px;padding:4px 0 14px}
.cmp-yarrow{width:40px;height:40px;border:0;background:rgba(255,255,255,.06);color:var(--cream);border-radius:12px;font-size:22px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;-webkit-tap-highlight-color:transparent}
.cmp-yarrow:active{background:rgba(255,255,255,.12)}
.cmp-year{font-size:18px;font-weight:700;color:var(--off-white);min-width:72px;text-align:center;font-variant-numeric:tabular-nums}
.cmp-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.cmp-m{padding:14px 0;border:1px solid var(--border-d);background:rgba(255,255,255,.03);color:var(--cream);border-radius:12px;font-size:14px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,color .15s;-webkit-tap-highlight-color:transparent}
.cmp-m:active{background:var(--state-hover)}
.cmp-m.is-today{border-color:color-mix(in srgb,var(--purple) 55%,transparent);color:var(--purple)}
.cmp-m.is-sel{background:var(--purple);border-color:var(--purple);color:#fff}
.cmp-today{margin-top:14px;width:100%;padding:13px;border:0;border-radius:12px;background:rgba(255,255,255,.06);color:var(--cream);font-size:14px;font-weight:600;cursor:pointer;-webkit-tap-highlight-color:transparent}
.cmp-today:active{background:rgba(255,255,255,.12)}
html[data-theme="light"] .cmp-yarrow,html[data-theme="light"] .cmp-today{background:rgba(0,0,0,.05)}
html[data-theme="light"] .cmp-m{background:rgba(0,0,0,.02)}
html[data-theme="light"] .cmp-m:active,html[data-theme="light"] .cmp-yarrow:active,html[data-theme="light"] .cmp-today:active{background:rgba(0,0,0,.08)}
html[data-theme="light"] .cmp-m.is-sel{background:var(--purple);color:#fff}
.rev-sheet-head{display:flex;align-items:center;justify-content:space-between;padding:6px 18px 12px;font-family:var(--sans);font-size:17px;font-weight:600;color:var(--off-white)}
.rev-sheet-done{background:none;border:none;color:var(--purple);font:600 15px var(--sans);cursor:pointer}
.rev-sheet-body{overflow-y:auto;padding:0 16px 18px}
.rev-set-group{background:rgba(255,255,255,.05);border:none;border-radius:13px;margin-bottom:14px;overflow:hidden}
.rev-set-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 14px}
.rev-set-row+.rev-set-row{border-top:1px solid var(--hairline)}
.rev-set-label{font-size:14px;color:var(--cream);font-weight:500}
.rev-seg-group{display:flex;flex-wrap:wrap;gap:4px;background:rgba(0,0,0,.25);border-radius:9px;padding:3px;justify-content:flex-end}
@media(max-width:560px){.rev-set-row{flex-wrap:wrap}.rev-seg-group{flex-basis:100%;justify-content:flex-start;margin-top:2px}}
.rev-seg{font:600 12px var(--sans);color:var(--muted);background:none;border:none;border-radius:7px;padding:5px 9px;cursor:pointer;white-space:nowrap}
.rev-seg.on{background:var(--modal-col-color,var(--purple));color:#fff}
.rev-switch{flex-shrink:0;width:44px;height:26px;border-radius:999px;border:none;background:color-mix(in srgb,var(--text-1) 16%,transparent);cursor:pointer;position:relative;transition:background .18s}
.rev-switch.on{background:var(--modal-col-color,var(--purple))}
.rev-switch-knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;transition:left .18s}
.rev-switch.on .rev-switch-knob{left:21px}
/* Comments — sub-tabs, filter bar, threads, reactions, voice, attachments */
.rev-subtabs{flex-shrink:0;display:flex;gap:4px;padding:10px 12px 4px}
.rev-subtab{font:600 13px var(--sans);color:var(--muted);background:none;border:none;border-bottom:2px solid transparent;padding:5px 4px;margin-right:8px;cursor:pointer}
.rev-subtab.on{color:var(--off-white);border-bottom-color:var(--modal-col-color,var(--purple))}
.rev-filterbar{flex-shrink:0;display:flex;align-items:center;gap:8px;padding:4px 12px 8px}
.rev-filter-btn{display:inline-flex;align-items:center;gap:5px;font:600 12px var(--sans);color:var(--cream);background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:8px;padding:5px 9px;cursor:pointer}
.rev-filter-btn svg{width:13px;height:13px}
.rev-icon-btn{flex-shrink:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:8px;color:var(--muted);cursor:pointer;margin-left:auto}
.rev-icon-btn:hover{color:var(--cream)}.rev-icon-btn svg{width:16px;height:16px}
.rev-cm-more{font-size:15px;line-height:.6}
.rev-replies{margin:2px 0 4px 37px;border-left:2px solid var(--border-d);padding-left:6px}
.rev-cm-reply{padding:6px 8px}.rev-cm-reply .rev-cm-av{width:22px;height:22px;font-size:9px}
.rev-reply-composer{display:flex;align-items:center;gap:6px;margin:4px 0 8px 37px;padding-left:6px}
.rev-send-sm{width:32px;height:32px}.rev-send-sm svg{width:15px;height:15px}
.rev-cm-reax{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.rev-reax-pill{font:600 11px var(--sans);color:var(--cream);background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:999px;padding:2px 8px;cursor:pointer}
.rev-reax-pill.mine{background:var(--purple-soft);border-color:color-mix(in srgb,var(--purple) 45%,transparent);color:var(--purple)}
.rev-cm-audio{display:block;margin-top:7px;width:100%;max-width:240px;height:34px}
.rev-cm-atts{display:flex;flex-direction:column;gap:6px;margin-top:7px}
.rev-cm-att{font:600 12px var(--sans);color:var(--blue);text-decoration:none}
.rev-cm-att-img{max-width:200px;max-height:140px;border-radius:8px;display:block}
.rev-edit-box{margin:4px 0}
.rev-edit-acts{display:flex;gap:8px;margin-top:6px}
.rev-fields{padding:6px 4px 16px}
.rev-field{display:flex;justify-content:space-between;gap:12px;padding:11px 8px;border-bottom:1px solid rgba(255,255,255,.05)}
.rev-field-k{font-size:12px;color:var(--muted);font-weight:500}
.rev-field-v{font-size:13px;color:var(--off-white);text-align:right;word-break:break-word}
.rev-field-empty{color:var(--muted)}
/* Input bar mic / attach */
.rev-mic,.rev-attach{flex-shrink:0;width:36px;height:36px;background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:9px;color:var(--cream);display:flex;align-items:center;justify-content:center;cursor:pointer}
.rev-mic:hover,.rev-attach:hover{background:rgba(255,255,255,.1)}
.rev-mic svg,.rev-attach svg{width:17px;height:17px}
.rev-mic.recording{background:var(--color-error);border-color:var(--color-error);color:#fff;animation:revRecPulse 1.2s ease-in-out infinite}
@keyframes revRecPulse{0%,100%{opacity:1}50%{opacity:.55}}
.rev-rec-bar{margin-top:7px;font:600 12px var(--sans);color:var(--danger-text);display:flex;align-items:center;gap:8px}
.rev-comment-upload-tray{display:flex;flex-direction:column;gap:6px;margin:0 0 7px}
.rev-comment-upload{display:flex;align-items:center;gap:9px;min-width:0;padding:8px 9px;border-radius:10px;
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.08);color:var(--cream)}
.rev-comment-upload.is-failed{border-color:color-mix(in srgb,var(--color-error,#ff6b6b) 42%,transparent);background:color-mix(in srgb,var(--color-error,#ff6b6b) 9%,transparent)}
.rev-comment-upload-thumb,.rev-comment-upload-glyph{width:34px;height:34px;border-radius:8px;flex:none;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.07);object-fit:cover;color:var(--muted)}
.rev-comment-upload-glyph svg{width:17px;height:17px}
.rev-comment-upload-copy{display:flex;flex:1;min-width:0;flex-direction:column;gap:2px}
.rev-comment-upload-copy strong{font:600 11px var(--sans);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rev-comment-upload-state{font:500 10px var(--sans);color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rev-comment-upload.is-failed .rev-comment-upload-state{color:var(--danger-text)}
.rev-comment-upload-track{display:block;height:3px;border-radius:999px;overflow:hidden;background:rgba(255,255,255,.1);margin-top:2px}
.rev-comment-upload-track i{display:block;height:100%;border-radius:inherit;background:var(--modal-col-color,var(--purple));transition:width .12s linear}
.rev-comment-upload.is-failed .rev-comment-upload-track i{background:var(--color-error,#ff6b6b)}
.rev-comment-upload-action,.rev-comment-upload-x{border:0;background:none;color:var(--muted);cursor:pointer;flex:none;font:600 10px var(--sans);padding:5px}
.rev-comment-upload-action{color:var(--modal-col-color,var(--purple))}
.rev-comment-upload-x{font-size:18px;line-height:1}
.rev-comment-upload-action:hover,.rev-comment-upload-x:hover{color:var(--off-white)}
@media (prefers-reduced-motion:reduce){.rev-comment-upload-track i{transition:none}}
/* Popover (react / menu / filter / sort) */
.rev-popover{position:fixed;z-index:99999;background:var(--dark);border:1px solid var(--border-d);border-radius:11px;box-shadow:0 8px 28px rgba(0,0,0,.5);padding:5px;min-width:120px}
.rev-menu-pop{display:flex;flex-direction:column}
.rev-menu-item{font:500 13px var(--sans);color:var(--cream);background:none;border:none;text-align:left;padding:9px 12px;border-radius:7px;cursor:pointer;white-space:nowrap}
.rev-menu-item:hover{background:rgba(255,255,255,.07)}
.rev-menu-item.on{color:var(--purple)}
.rev-menu-head{font:700 9px var(--sans);text-transform:uppercase;letter-spacing:.5px;color:var(--muted);padding:9px 12px 4px}
.rev-menu-sep{height:1px;background:var(--border-d);margin:4px 6px}
.rev-guides-pop{min-width:178px}
.rev-guide-item{display:flex;align-items:center;gap:7px}
.rev-guide-check{width:14px;height:14px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--purple)}
.rev-guides{position:absolute;inset:0;pointer-events:none;z-index:3}
.rev-guide-svg{width:100%;height:100%;display:block}
.rev-guide-lines line{stroke:rgba(255,255,255,.5);stroke-width:1;vector-effect:non-scaling-stroke}
.rev-guide-rects rect{fill:none;stroke:rgba(231,206,58,.78);stroke-width:1;vector-effect:non-scaling-stroke;stroke-dasharray:5 4}
.rev-guide-vframe{fill:none;stroke:rgba(140,114,219,.95);stroke-width:1.5;vector-effect:non-scaling-stroke}
.rev-guide-mask{fill:rgba(0,0,0,.4)}
.rev-guide-ui{fill:rgba(140,114,219,.2);stroke:rgba(140,114,219,.55);stroke-width:1;vector-effect:non-scaling-stroke}
.rev-menu-del{color:var(--danger-text)}
@media(max-width:768px){.rev-wrap{flex-direction:column;align-items:stretch}.rev-main{width:100%}.rev-side{width:100%;max-height:none}.rev-list{max-height:46vh}.rev-player{max-height:none}.rev-cm-acts{opacity:1}}
@media(hover:none){.rev-cm-acts{opacity:1}}
/* ===== Review tab — Frame.io-style overhaul (matches the design mockup) ===== */
/* Widen the card modal on the Review tab so the 2-column player + comments fits. */
/* No :has() — the width must not wait for the review content to mount, or the modal
   opens narrow and widens a frame later. */
/* Sizing moved to .cm-wide-tab, which Review and Schedule both carry — two !important
   width declarations for the same box is how one of them ends up a mystery. */
/* Size the wrap so the whole modal (header ~186px + 32px bottom pad) fits within
   the modal's 90vh cap — no internal scroll. */
.rev-wrap.rev2{gap:0;align-items:stretch;height:min(calc(86vh - 252px),640px);border:none;border-radius:16px;overflow:hidden;background:var(--surf-1,var(--dark))}
/* The viewer column is a DARK ROOM in BOTH themes. Video is letterboxed against black and
   judged against a neutral surround, so .rev-main (stage + player + transport + transcript)
   deliberately does not flip. Rather than hardcode a colour at every usage site inside it —
   which the Design Rules forbid — redeclare the token aliases once, here: every descendant
   then inherits the dark voice in light mode too.
   These MUST be the leaf aliases, not the --color-* semantics: --border-d:var(--color-
   hairline-2) is substituted at :root, so redefining the semantic token on a descendant
   would never reach it. If anyone later "tidies" these into --color-* names the whole
   transport silently goes white-on-white again in light mode.
   Values are the EFFECTIVE dark values under html[data-brand="saucemedia"] (line 9246), not
   the bare :root ones — --off-white is #fafaf8 there, and #f3f3f4 would visibly dull the
   transcript in DARK mode.
   .rev-side is a SIBLING of this element so the comments column still flips; popovers and
   sheets are appended to <body>, so they are outside the island too. */
/* Rounded on ALL corners — the rail beside it is transparent now, so the dark room's
   right edge is exposed and square corners read as a cropped screenshot. */
.rev2 .rev-main{flex:1;min-width:0;display:flex;flex-direction:column;border-radius:16px;overflow:hidden;background:#08080a;
  color-scheme:dark;
  /* Redeclaring the aliases is not enough on its own: .rev-transcript, .rev-vt-line,
     .rev-stage and .rev-tcwrap set no colour of their own and inherit it from <body>,
     which in light theme is near-black — so the transcript rendered black-on-#08080a.
     The island owns a base colour too, or "dark room" only holds for the elements that
     happen to name a token. */
  color:var(--off-white);
  --white:#ffffff;--off-white:#fafaf8;--cream:#e6ded6;--sec:#a3a3ab;--muted:#999990;
  --text-1:#ffffff;--text-2:rgba(235,235,245,.6);--text-3:rgba(235,235,245,.45);
  --hairline:rgba(255,255,255,.06);--hairline-2:rgba(255,255,255,.08);--hairline-3:rgba(255,255,255,.12);
  --border-d:rgba(255,255,255,.08);--bg-inset:rgba(255,255,255,.07);
  --surf-1:#0e0e10;--surf-2:#131315;--surf-3:#161618;--dark:#141416;
  --purple:#7c5cff;--purple-soft:rgba(124,92,255,.16);
  --gold:#e7ce3a;--green:#5BCF8E;--blue:#5E9CFF;--danger-text:#ff8585}
/* file / version strip */
.rev2 .rev-verbar{flex:none;display:flex;align-items:center;gap:11px;padding:14px 26px 12px;border-bottom:1px solid rgba(255,255,255,.05);margin:0}
.rev2 .rev-verbar-ico{width:26px;height:26px;border-radius:7px;background:linear-gradient(150deg,#3a2a4a,#1c1428);display:flex;align-items:center;justify-content:center;flex:none}
.rev2 .rev-verbar-file{font:600 14px var(--sans);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:300px}
.rev2 .rev-verbar-proj{font:700 10px var(--pixel);color:rgba(235,235,245,.5);background:rgba(255,255,255,.06);border-radius:6px;padding:3px 7px;text-transform:uppercase;letter-spacing:.3px}
.rev2 .rev-verbar-dot{display:none}
.rev2 .rev-verbar-nav{margin-left:auto;display:flex;align-items:center;gap:3px}
.rev2 .rev-verbar-arrow{width:30px;height:30px;border:none;background:none;color:rgba(235,235,245,.6);border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer}
.rev2 .rev-verbar-arrow:hover:not([disabled]){background:rgba(255,255,255,.06);color:#fff}
.rev2 .rev-verbar-arrow[disabled]{opacity:.3;cursor:default}
.rev2 .rev-verbar-arrow svg{width:15px;height:15px}
.rev2 .rev-verbar-count{font:700 11px var(--pixel);color:rgba(235,235,245,.8);padding:0 6px}
/* stage */
.rev2 .rev-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;padding:14px;background:radial-gradient(80% 60% at 50% 40%,#141418,#08080a 82%);position:relative;container-type:size}
.rev2 .rev-player{width:min(100%,calc(100cqh * var(--rev-ar,1.77778)));height:auto;max-height:none;aspect-ratio:var(--rev-ar,16/9);border-radius:12px;box-shadow:0 24px 70px rgba(0,0,0,.6);background:#000}
.rev2-corner{position:absolute;left:12px;top:12px;font:600 10px var(--pixel);color:rgba(255,255,255,.9);background:rgba(0,0,0,.55);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border-radius:6px;padding:3px 8px;pointer-events:none;z-index:4;letter-spacing:.3px}
/* Video title + version selector, top-right of the player (moved here from the
   corner overlay + the comments sidebar header). */
/* Sits in the top-right CORNER OF THE STAGE (the playback area), not on the video. */
.rev2 .rev-stage>.rev-topright{position:absolute;right:18px;top:16px;z-index:9;display:flex;align-items:center;gap:8px;background:rgba(0,0,0,.55);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.1);border-radius:9px;padding:5px 6px 5px 10px;max-width:calc(100% - 36px)}
.rev-topright{position:absolute;right:18px;top:16px;z-index:9;display:flex;align-items:center;gap:8px;background:rgba(0,0,0,.55);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.1);border-radius:9px;padding:5px 6px 5px 10px;max-width:calc(100% - 36px)}
.rev-tr-name{font:600 12px var(--sans);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:180px;cursor:default;border-radius:6px;padding:2px 5px;margin:-2px -1px -2px -5px;transition:background .14s}
.rev-tr-name[onclick]{cursor:pointer}
.rev-tr-name[onclick]:hover{background:rgba(124,92,255,.28)}
.rev-tr-nav{display:flex;align-items:center;gap:1px;flex:none}
.rev-tr-arrow{width:24px;height:24px;border:none;background:none;color:rgba(255,255,255,.65);border-radius:7px;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0}
.rev-tr-arrow:hover:not([disabled]){background:rgba(255,255,255,.12);color:#fff}
.rev-tr-arrow[disabled]{opacity:.3;cursor:default}
.rev-tr-arrow svg{width:14px;height:14px}
.rev-tr-count{font:700 12px var(--sans);font-variant-numeric:tabular-nums;color:rgba(255,255,255,.85);padding:0 4px;white-space:nowrap}
.rev2 .rev-bigplay{width:66px;height:66px;background:rgba(10,10,14,.5);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.22)}
.rev-dropping .rev-stage{outline:2px dashed var(--purple);outline-offset:-10px;background:rgba(124,92,255,.06)}
/* Hover the file strip → the player tints purple + shows a clickable "Upload new
   version" overlay (opens the picker → the existing uploading animation). */
.rev2 .rev-verbar{cursor:pointer}
.rev-upload-overlay{position:absolute;inset:0;z-index:8;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:11px;background:rgba(124,92,255,.28);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);border:2px dashed rgba(124,92,255,.65);border-radius:12px;color:#fff;font:700 15px var(--sans);opacity:0;pointer-events:none;transition:opacity .16s ease}
.rev-upload-overlay svg{width:32px;height:32px;stroke:#fff}
/* Overlay is a pure hint (pointer-events:none) shown while hovering the sidebar
   file name (.rev-show-upload); clicking that file name opens the version picker. */
.rev-wrap.rev-show-upload .rev-upload-overlay{opacity:1}
.rev-wrap.rev-show-upload .rev-player{box-shadow:0 24px 70px rgba(0,0,0,.6),0 0 0 2px rgba(124,92,255,.5)}
/* transport (below the stage) */
/* Transparent, so the transport sits on .rev-main's own #08080a — the dark room the
   player lives in. Its surf-1 fill was one shade lighter and read as a separate tray. */
.rev2 .rev-transport{flex:none;padding:10px 18px 10px;background:transparent;border-top:none}
.rev2 .rev-transport .rev-scrub{height:24px;flex:none}
.rev2 .rev-transport .rev-scrub-track{height:5px;background:rgba(255,255,255,.16)}
.rev2 .rev-transport .rev-scrub-fill{background:var(--modal-col-color,var(--purple))}
.rev2 .rev-transport .rev-marker{width:11px;height:14px;top:-16px;margin-left:-5.5px;border:0;border-radius:0;
  background:var(--mk,#FFD766);clip-path:polygon(0 0,100% 0,100% 58%,50% 100%,0 58%);transform-origin:50% 100%}
.rev2 .rev-transport .rev-marker:hover{transform:scale(1.2)}
.rev2 .rev-transport .rev-marker.resolved{background:var(--green,#5BCF8E)}
.rev2 .rev-transport .rev-knob{width:14px;height:14px;margin-left:-7px}
.rev-ctrlrow{display:flex;align-items:center;gap:14px;margin-top:13px}
.rev2 .rev-ctrlrow .rev-cbtn{width:32px;height:32px;color:rgba(235,235,245,.82);border-radius:8px}
.rev2 .rev-ctrlrow .rev-cbtn:hover{background:var(--state-hover);color:#fff}
.rev2 .rev-cbtn-play{width:40px !important;height:40px !important;background:var(--modal-col-color,var(--purple)) !important;color:#fff !important;border-radius:50% !important}
.rev2 .rev-cbtn-play:hover{background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 82%,#000) !important}
.rev2 .rev-cbtn-play svg{width:17px;height:17px}
.rev-tcwrap{display:flex;align-items:baseline;gap:7px;margin-left:2px;white-space:nowrap}
.rev2 .rev-tcwrap .rev-tc{font:700 16px var(--sans);font-variant-numeric:tabular-nums;color:#fff;background:none !important;padding:0}
.rev-tc-dur{font:600 16px var(--sans);font-variant-numeric:tabular-nums;color:rgba(235,235,245,.4)}
.rev-ctrl-spacer{flex:1;min-width:8px}
.rev-wrap.rev-playing .rev-ic-play{display:none}
.rev-wrap.rev-playing .rev-ic-pause{display:block}
.rev2 .rev-replace{margin:12px 0 0;font-size:13px}
.rev-upload-link{display:inline-flex;align-items:center;gap:8px;font:600 13px var(--sans);color:var(--modal-col-color,var(--purple));cursor:pointer;background:none;border:none;padding:6px 8px;margin-left:-8px;border-radius:8px}
.rev-delete-link{display:inline-flex;align-items:center;justify-content:center;color:rgba(235,235,245,.55);cursor:pointer;background:none;border:none;padding:6px 8px;border-radius:8px;margin-left:2px}
.rev-delete-link:hover{background:rgba(255,107,107,.12);color:#ff6b6b}
.rev-delete-link svg{width:15px;height:15px}
.rev-upload-link:hover{background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 14%,transparent)}
.rev-upload-link svg{width:15px;height:15px}
/* right sidebar */
.rev2 .rev-side{width:392px;flex:none;background:transparent;border:none;border-radius:0;max-height:none;height:100%}
.rev2 .rev-subtabs{gap:16px;justify-content:space-between;align-items:flex-start;border-bottom:1px solid var(--hairline-2);padding:16px 20px 0}
.rev2 .rev-subtab-static{cursor:default;color:var(--text-1);border-bottom-color:var(--modal-col-color,var(--purple))}
/* File name + format/size + version nav, top-right of the sidebar header. */
.rev-fileinfo{display:flex;align-items:center;gap:10px;padding-bottom:9px;min-width:0}
.rev-fileinfo-main{display:flex;flex-direction:column;align-items:flex-end;gap:1px;min-width:0;border-radius:8px;padding:3px 6px;margin:-3px -6px;transition:background .14s}
.rev-fileinfo-main[onclick]{cursor:pointer}
.rev-fileinfo-main[onclick]:hover{background:rgba(124,92,255,.16)}
.rev-fileinfo-name{font:600 13px var(--sans);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:150px}
.rev-fileinfo-meta{font:700 9px var(--pixel);color:rgba(235,235,245,.5);letter-spacing:.3px}
.rev-fileinfo-nav{display:flex;align-items:center;gap:1px;flex:none}
.rev-fileinfo-nav .rev-verbar-arrow{width:26px;height:26px}
.rev-fileinfo-nav .rev-verbar-arrow svg{width:14px;height:14px}
.rev2 .rev-subtab{font:700 15px var(--sans);color:var(--text-3);padding-bottom:13px;margin:0 0 -1px;border-bottom:2px solid transparent}
.rev2 .rev-subtab.on{color:var(--text-1);border-bottom-color:var(--modal-col-color,var(--purple))}
.rev2 .rev-filterbar{padding:12px 20px 10px;gap:8px}
.rev2 .rev-filter-btn{height:32px;padding:0 12px;border-radius:9px;background:var(--bg-inset);border:none;font:600 13px var(--sans);color:var(--text-1)}
.rev2 .rev-icon-btn{width:32px;height:32px;background:none;border:none;color:var(--text-2);border-radius:8px}
.rev2 .rev-icon-btn:hover{background:var(--bg-inset);color:var(--text-1)}
.rev2 .rev-list{padding:2px 20px 8px;display:flex;flex-direction:column;gap:16px}
/* comment card */
.rev2 .rev-cm{gap:11px;padding:6px;margin:-6px;border-radius:10px}
.rev2 .rev-cm:hover{background:none}
.rev2 .rev-cm-av{width:34px;height:34px;background:var(--purple-soft);overflow:hidden}
.rev-cm-av svg,.rev-cm-av img{width:100%;height:100%;display:block;object-fit:cover;border-radius:inherit}
.rev2 .rev-cm-author{font:600 14px var(--sans);color:var(--text-1)}
.rev2 .rev-cm-time{font:400 12px var(--sans);color:var(--text-3)}
.rev2 .rev-cm-idx{display:none}
.rev2 .rev-cm-chip{margin-left:auto;font:600 11px var(--sans);color:#fff;background:rgba(255,255,255,.08)}
.rev2 .rev-cm-text{font:400 14px/1.5 var(--sans);color:color-mix(in srgb,var(--text-1) 85%,transparent);margin-top:6px}
.rev2 .rev-cm.resolved .rev-cm-text{color:var(--text-3)}
.rev2 .rev-cm-acts{opacity:1;margin-top:9px;align-items:center;gap:14px}
.rev2 .rev-cm-act{font:600 12px var(--sans);color:var(--text-3)}
.rev2 .rev-cm-act:hover{color:var(--text-1)}
.rev2 .rev-cm-resolve.on{color:var(--green)}
.rev2 .rev-replies{margin:12px 0 0 0;border-left:none;padding-left:0}
.rev2 .rev-cm-reply{padding:0;margin-top:10px}
.rev2 .rev-cm-reply .rev-cm-av{width:28px;height:28px;background:var(--purple-soft);overflow:hidden}
/* composer */
.rev2 .rev-inputbar{padding:10px 14px 12px;border-top:none}
.rev2 .rev-anchor-toggle{height:30px;padding:0 11px;border-radius:8px;font:600 12px var(--sans)}
.rev2 .rev-input{min-height:44px;border-radius:12px;background:transparent;border:none;padding:12px 14px}
.rev2 .rev-send{width:44px;height:44px;border-radius:12px}
.rev2 .rev-mic,.rev2 .rev-attach{width:38px;height:38px;border-radius:10px;background:none;border:none;color:var(--text-2)}
.rev2 .rev-mic:hover,.rev2 .rev-attach:hover{background:var(--bg-inset);color:var(--text-1)}
/* In the composer the mic is a .cmt-btn like emoji / annotate / attach, but the standalone
   .rev-mic control rules above outrank .cmt-btn and were forcing it to a 38px box with a
   hard-coded near-white glyph: visibly larger than its three neighbours in dark, and
   invisible against the white sidebar in light. Re-assert the .cmt-btn treatment here.
   .recording is split out because .rev2 .rev-mic was also swallowing the record colour,
   leaving the pulse animation as the only sign the mic is live. :not(.recording) is on the
   colour rules only, never the box, so starting a recording cannot resize the button. */
.rev2 .cmt-actions .rev-mic{width:30px;height:30px;border-radius:8px}
.rev2 .cmt-actions .rev-mic:not(.recording){color:var(--text-3)}
.rev2 .cmt-actions .rev-mic.recording{color:var(--danger-text)}
@media(max-width:900px){.card-modal.cm-review-active{width:96vw !important;max-width:none !important}.rev-wrap.rev2{flex-direction:column;height:auto}.rev2 .rev-side{width:100%;border-left:none;border-top:1px solid var(--hairline-2);height:auto}.rev2 .rev-player{aspect-ratio:var(--rev-ar,16/9);height:auto;width:min(100%,calc(52vh * var(--rev-ar,1.77778)));max-height:none}.rev2 .rev-stage{padding:0;container-type:normal}}
/* rev2 comment rows are flush cards (padding:0) and take no hover fill in either theme.
   Without this the generic html[data-theme="light"] .rev-cm:hover (line 10549, specificity
   0,3,1) outranks .rev2 .rev-cm:hover{background:none} (line 9674, 0,3,0) and paints a
   full-bleed grey slab behind every comment — light mode only. */
html[data-theme="light"] .rev2 .rev-cm:hover{background:none}
/* Share sheet */
.rev-share-body{padding:4px 0 8px}
.rev-share-link{display:flex;gap:8px;margin-bottom:14px}
#revShareUrl{flex:1;min-width:0;background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:10px;color:var(--off-white);font:600 13px var(--mono);padding:11px 12px;outline:none}
.rev-share-copy{flex-shrink:0;background:var(--purple);color:#fff;border:none;border-radius:10px;font:600 14px var(--sans);padding:0 18px;cursor:pointer}
.rev-share-actions{margin-bottom:14px}
.rev-share-row{display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:none;color:var(--cream);font:500 14px var(--sans);padding:13px 14px;cursor:pointer}
.rev-share-row+.rev-share-row{border-top:1px solid var(--hairline)}
.rev-share-row svg{width:18px;height:18px;color:var(--muted)}
/* Destructive rows read RED, not brand purple. --coral is a legacy alias of the
   brand purple in this theme, so it made "Revoke link" / "Delete video" look like
   a primary action (design rule: reference the semantic token). */
.rev-share-revoke{color:var(--danger-text)}.rev-share-revoke svg{color:var(--danger-text)}
.rev-share-note{font-size:12px;color:var(--muted);line-height:1.5;padding:0 4px}
/* Public review view (/r/<slug>) */
html.public-review-mode #app{display:none!important}
html.public-review-mode #loginGate{display:none!important}
.pub-rev-root{position:fixed;inset:0;z-index:50;background:var(--bg-main);display:flex;flex-direction:column;overflow:auto}
.pub-rev-head{flex-shrink:0;display:flex;align-items:baseline;gap:10px;padding:16px 20px;border-bottom:1px solid var(--border-d)}
.pub-rev-brand{font-family:var(--serif);font-size:22px;font-weight:700;color:var(--off-white);letter-spacing:-.5px}
.pub-rev-sub{font-size:14px;color:var(--muted)}
.pub-rev-body{flex:1;min-height:0;padding:0;max-width:none;width:100%;margin:0}
.pub-rev-panel{width:100%;height:100%}
/* Public review fills the screen (no modal, so size the wrap to the page). */
.pub-rev-panel .rev-wrap.rev2{height:100%;max-height:none;border:none;border-radius:0}
.pub-rev-root .rev-replace,.pub-rev-root .rev-cm-acts,.pub-rev-root .rev-subtabs,.pub-rev-root .rev-mic,.pub-rev-root .rev-attach{display:none!important}
.pub-rev-root .rev-cbtn[aria-label="Share"]{display:none}
/* Public password gate */
.pub-rev-gate{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;min-height:48vh;text-align:center;padding:32px}
.pub-rev-gate-icon{display:flex;color:var(--muted)}
.pub-rev-gate-title{font-family:var(--serif);font-size:21px;color:var(--off-white)}
.pub-rev-gate-sub{font-size:14px;color:var(--muted)}
.pub-rev-gate-row{display:flex;gap:8px;margin-top:8px;width:100%;max-width:320px}
.pub-rev-gate-row .rev-input{flex:1}
/* Share-sheet protection controls */
.rev-share-protect{padding:2px 0}
.rev-share-pw{background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:8px;color:var(--off-white);font:inherit;font-size:14px;padding:8px 10px;outline:none;max-width:170px;text-align:right}
.rev-share-pw:focus{border-color:color-mix(in srgb,var(--purple) 55%,transparent)}
.rev-share-apply{width:100%;background:var(--purple);color:#fff;border:none;border-radius:9px;font:600 14px var(--sans);padding:10px;cursor:pointer}
.pub-rev-404{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-height:50vh;text-align:center;padding:32px}
.pub-rev-404-emoji{display:flex;color:var(--muted)}
.pub-rev-404-title{font-family:var(--serif);font-size:22px;color:var(--off-white)}
.pub-rev-404-sub{font-size:14px;color:var(--muted);max-width:340px;line-height:1.5}
/* ── Schedule tab (post composer) ── */
.sch-wrap{display:flex;flex-direction:column;gap:14px}
.sch-head{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.sch-profile-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.sch-profile-select{min-width:210px;flex:1}
.sch-setup{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 14px;border:1px solid color-mix(in srgb,var(--purple) 35%,var(--border-d));border-radius:12px;background:color-mix(in srgb,var(--purple) 8%,transparent)}
.sch-setup>div{display:flex;flex-direction:column;gap:3px;min-width:0}
.sch-setup b{font-size:13px;color:var(--cream)}
.sch-setup span{font-size:11px;line-height:1.4;color:var(--muted)}
.sch-accounts{display:flex;align-items:stretch;gap:9px;flex-wrap:wrap}
.sch-account-chip{position:relative;min-width:150px;max-width:240px;min-height:52px;padding:7px 34px 7px 8px;border-radius:13px;border:1px solid var(--border-d);background:#1c1c20;color:var(--cream);cursor:pointer;display:flex;align-items:center;gap:9px;text-align:left;transition:border-color .15s,background .15s,box-shadow .15s}
.sch-account-chip:hover{border-color:color-mix(in srgb,var(--pc) 60%,var(--border-d))}
.sch-account-chip.on{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 11%,#1c1c20);box-shadow:0 0 0 1px color-mix(in srgb,var(--pc) 68%,transparent)}
.sch-account-chip:disabled{cursor:default;opacity:.72}
.sch-account-chip>img,.sch-manager-account>img{width:32px;height:32px;border-radius:10px;object-fit:cover;background:rgba(255,255,255,.06);flex:none}
.sch-account-icon,.sch-manager-icon{width:32px;height:32px;border-radius:10px;display:flex;align-items:center;justify-content:center;flex:none;color:var(--pc);background:color-mix(in srgb,var(--pc) 12%,transparent)}
.sch-account-icon svg,.sch-manager-icon svg{width:18px;height:18px}
.sch-account-copy{display:flex;flex-direction:column;min-width:0;line-height:1.2}
.sch-account-copy b{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-account-copy small{font-size:10px;color:var(--muted);margin-top:3px}
.sch-account-check{position:absolute;right:10px;top:50%;transform:translateY(-50%);width:16px;height:16px;border:1px solid var(--border-d);border-radius:50%;display:flex;align-items:center;justify-content:center;color:transparent;font-size:10px;background:rgba(255,255,255,.025)}
.sch-account-chip.on .sch-account-check{border-color:var(--pc);background:var(--pc);color:#fff}
.sch-account-add{width:52px;height:52px;border-radius:13px;border:1px dashed color-mix(in srgb,var(--modal-col-color,var(--purple)) 55%,var(--border-d));background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 7%,transparent);color:var(--cream);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s}
.sch-account-add span{font-size:28px;font-weight:300;line-height:1;margin-top:-2px}
.sch-account-add:hover{border-style:solid;border-color:var(--modal-col-color,var(--purple));background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 14%,transparent)}
.sch-account-empty{min-height:52px;display:flex;flex-direction:column;justify-content:center;gap:3px;color:var(--muted)}
.sch-account-empty b{font-size:12px;color:var(--cream)}
.sch-account-empty span{font-size:10px}
.sch-manager{display:flex;flex-direction:column;gap:12px;min-width:min(480px,78vw)}
.sch-manager-note,.sch-platform-chooser>p{margin:0;color:var(--muted);font-size:12px;line-height:1.5}
.sch-manager-list{display:flex;flex-direction:column;gap:7px;max-height:42vh;overflow:auto}
.sch-manager-account{display:flex;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--border-d);border-radius:11px;background:rgba(255,255,255,.025);cursor:pointer;transition:border-color .15s,background .15s}
.sch-manager-account:hover{border-color:color-mix(in srgb,var(--purple) 45%,var(--border-d))}
.sch-manager-account.selected{border-color:color-mix(in srgb,var(--purple) 62%,var(--border-d));background:color-mix(in srgb,var(--purple) 9%,transparent)}
.sch-manager-account.disabled{cursor:default;opacity:.65}
.sch-manager-account>span:nth-child(2){display:flex;flex:1;min-width:0;flex-direction:column;gap:3px}
.sch-manager-account b{font-size:12px;color:var(--cream);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-manager-account small,.sch-manager-privacy{font-size:10px;color:var(--muted);line-height:1.4}
.sch-manager-account input{accent-color:var(--purple);width:16px;height:16px;flex:none}
.sch-manager-empty{display:flex;flex-direction:column;gap:3px;padding:18px;border:1px dashed var(--border-d);border-radius:11px;text-align:center}
.sch-manager-empty b{font-size:12px;color:var(--cream)}
.sch-manager-empty span,.sch-manager-permission{font-size:10px;color:var(--muted)}
.sch-manager-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;width:100%}
.sch-manager-footer .sch-manager-permission{margin-right:auto}
.sch-platform-chooser{display:flex;flex-direction:column;gap:14px;min-width:min(500px,80vw)}
.sch-platform-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.sch-platform-choice{display:grid;grid-template-columns:36px minmax(0,1fr);grid-template-rows:auto auto;column-gap:10px;align-items:center;text-align:left;padding:11px;border:1px solid var(--border-d);border-radius:12px;background:rgba(255,255,255,.025);color:var(--cream);cursor:pointer}
.sch-platform-choice:hover{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 8%,transparent)}
.sch-platform-choice>span{grid-row:1/3;width:36px;height:36px;border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--pc);background:color-mix(in srgb,var(--pc) 12%,transparent)}
.sch-platform-choice svg{width:20px;height:20px}
.sch-platform-choice b{font-size:12px}
.sch-platform-choice small{font-size:10px;color:var(--muted)}
.sch-option-card{display:flex;gap:10px;padding:10px 11px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.025)}
.sch-option-card b{font-size:12px;color:var(--cream)}
.sch-option-card small{display:block;margin-top:2px;font-size:10px;line-height:1.4;color:var(--muted)}
.sch-confirm{align-items:flex-start;cursor:pointer}
.sch-confirm input{margin:2px 0 0;accent-color:var(--purple);flex:none}
.sch-confirm span{min-width:0}
.sch-page{align-items:center;justify-content:space-between;flex-wrap:wrap}
.sch-page label{font-size:12px;font-weight:650;color:var(--cream)}
.sch-page label span{font-size:10px;font-weight:500;color:var(--muted)}
.sch-page .sch-in{min-width:200px;flex:1}
.sch-outcome>small{flex:1 0 100%;margin-top:-2px}
.sch-outcome .sch-in{border-color:color-mix(in srgb,var(--gold) 24%,var(--border-d))}
.sch-option-warning{flex-direction:column;border-color:color-mix(in srgb,var(--gold) 34%,var(--border-d))}
.sch-loading,.sch-error{padding:9px 11px;border-radius:9px;font-size:12px;line-height:1.45}
.sch-loading{color:var(--muted);background:rgba(255,255,255,.035)}
.sch-error{color:var(--danger-text);background:color-mix(in srgb,var(--danger-text) 9%,transparent);border:1px solid color-mix(in srgb,var(--danger-text) 28%,transparent)}
.sch-caption{width:100%;min-height:120px;resize:vertical;background:#1c1c20;border:1px solid var(--border-d);border-radius:12px;color:var(--white);padding:12px 14px;font:inherit;font-size:14px;outline:none;line-height:1.5;box-sizing:border-box}
.sch-caption:focus{border-color:color-mix(in srgb,var(--purple) 55%,transparent)}
.sch-drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-height:120px;border:2px dashed var(--border-d);border-radius:12px;color:var(--muted);font-size:13px;text-align:center;transition:border-color .15s,background .15s}
.sch-drop.drag{border-color:var(--purple);background:color-mix(in srgb,var(--purple) 8%,transparent)}
.sch-drop svg{width:30px;height:30px;opacity:.6}
.sch-drop-note{font-size:10px;color:var(--muted);opacity:.8}
.sch-drop-locked{min-height:74px;border-style:solid;background:rgba(255,255,255,.02)}
.sch-media{position:relative;display:inline-block;border-radius:12px;overflow:hidden;max-width:240px}
.sch-media-el{display:block;width:100%;max-height:240px;object-fit:cover;background:#000}
.sch-media-meta{padding:7px 9px;background:#161619;color:var(--muted);font-size:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sch-media-x{position:absolute;top:6px;right:6px;width:24px;height:24px;border-radius:50%;border:none;background:rgba(0,0,0,.6);color:#fff;cursor:pointer;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center}
.sch-row{display:flex;flex-direction:column;gap:5px}
.sch-row label{font-size:12px;font-weight:600;color:var(--muted)}
.sch-label-note{font-size:10px;font-weight:500;opacity:.75}
.sch-in{background:#1c1c20;border:1px solid var(--border-d);border-radius:9px;color:var(--white);padding:9px 12px;font:inherit;font-size:14px;outline:none;box-sizing:border-box}
.sch-in:focus{border-color:color-mix(in srgb,var(--purple) 55%,transparent)}
.sch-desc{min-height:70px;resize:vertical;line-height:1.45}
.sch-foot{display:flex;align-items:center;justify-content:flex-end;border-top:none}
.sch-status{font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:8px}
.sch-status-ring{width:14px;height:14px;flex:none;border-radius:50%;border:2px solid var(--color-hairline-3);border-top-color:currentColor;box-sizing:border-box;animation:bsoSpin var(--dur-complex,500ms) linear infinite}
@media(prefers-reduced-motion:reduce){.sch-status-ring{animation:none}}
.sch-foot{flex-wrap:wrap;gap:10px;justify-content:space-between!important}
.sch-status-draft{color:var(--muted)}
.sch-status-ready{color:var(--gold)}
.sch-status-posted{color:var(--green)}
.sch-status-draft-created{color:var(--gold)}
.sch-status-failed{color:var(--danger-text)}
.sch-batch{display:flex;flex-direction:column;gap:6px}
.sch-batch-label{font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--muted)}
.sch-batch-tabs{display:flex;gap:6px;overflow-x:auto;overscroll-behavior-x:contain;padding:1px 1px 4px;scrollbar-width:thin}
.sch-batch-tab{flex:0 0 auto;min-width:116px;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 10px;border:1px solid var(--border-d);border-radius:9px;background:rgba(255,255,255,.025);color:var(--cream);font:inherit;text-align:left;cursor:pointer}
.sch-batch-tab:hover{background:var(--state-hover)}
.sch-batch-tab.on{border-color:color-mix(in srgb,var(--modal-col-color,var(--purple)) 64%,var(--border-d));background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 10%,transparent)}
.sch-batch-tab b{font-size:11px;white-space:nowrap}
.sch-batch-tab small{font-size:9px;color:var(--muted);white-space:nowrap}
.sch-job-list{display:flex;flex-direction:column;border:1px solid var(--border-d);border-radius:12px;overflow:hidden}
.sch-job{display:flex;align-items:center;gap:10px;padding:10px 11px;background:rgba(255,255,255,.02);border-bottom:1px solid var(--border-d)}
.sch-job:last-child{border-bottom:0}
.sch-job-icon{width:28px;height:28px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:8px;color:var(--pc);background:color-mix(in srgb,var(--pc) 10%,transparent)}
.sch-job-icon svg{width:16px;height:16px}
.sch-job-main{flex:1;min-width:0;display:grid;grid-template-columns:minmax(76px,auto) minmax(90px,1fr);gap:2px 8px;align-items:center}
.sch-job-main b{font-size:12px;color:var(--cream)}
.sch-job-main small{grid-column:1/-1;font-size:10px;line-height:1.35;color:var(--danger-text);overflow-wrap:anywhere}
.sch-job-state{font-size:10px;color:var(--muted)}
.sch-job-published{color:var(--green)}
.sch-job-draft_created{color:var(--gold)}
.sch-job-failed{color:var(--danger-text)}
.sch-job-scheduled,.sch-job-queued{color:var(--gold)}
.sch-job-actions{display:flex;align-items:center;gap:5px;flex:none}
.sch-actions{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.sch-act{font-size:11px;font-weight:600;font-family:var(--sans);padding:6px 11px;border-radius:8px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;transition:background .12s}
.sch-act:hover{background:var(--state-hover)}
.sch-act.is-disabled,.sch-act[disabled]{opacity:.4;cursor:not-allowed}
.sch-act-primary{border:none;background:var(--modal-col-color,var(--purple));color:#fff;padding:7px 14px;border-radius:9px;font-size:12px}
.sch-act-primary:hover{background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 86%,#fff);filter:none}
.sch-act-primary.is-disabled,.sch-act-primary:disabled{opacity:.45;cursor:default}
.sch-act-primary.is-disabled:hover,.sch-act-primary:disabled:hover{background:var(--modal-col-color,var(--purple))}
.sch-act-primary:hover{background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 28%,transparent)}
.sch-act-danger{border-color:color-mix(in srgb,var(--danger-text) 34%,transparent);color:var(--danger-text)}
.sch-act-posted{border-color:color-mix(in srgb,var(--green) 40%,transparent);color:var(--green)}
@media(max-width:600px){.sch-profile-row{align-items:stretch}.sch-profile-select{flex-basis:100%;min-width:0}.sch-setup{align-items:flex-start;flex-direction:column}.sch-account-chip{min-width:calc(100% - 61px);max-width:none;flex:1}.sch-manager,.sch-platform-chooser{min-width:0}.sch-platform-grid{grid-template-columns:1fr}.sch-manager-footer{flex-wrap:wrap}.sch-manager-footer .sch-manager-permission{flex-basis:100%}.sch-page{align-items:stretch;flex-direction:column}.sch-page .sch-in{min-width:0;width:100%}.sch-foot{align-items:flex-start}.sch-actions{width:100%}.sch-job{align-items:flex-start;flex-wrap:wrap}.sch-job-main{min-width:150px}.sch-job-actions{width:100%;padding-left:38px}}
.ws-crumb-sep{color:var(--faint,rgba(255,255,255,.32));font-style:normal;font-weight:400}
.ws-board-title{display:inline-flex;align-items:center;gap:14px;background:none;border:none;cursor:pointer;
  padding:0;font-family:var(--sans);font-style:italic;font-weight:800;font-size:38px;line-height:1.04;
  letter-spacing:-.02em;color:var(--white);text-align:left}
.ws-board-title-caret{width:26px;height:26px;color:var(--purple);flex-shrink:0;transition:transform .15s}
#page-workshop.ws-tabs-shown .ws-board-title-caret,#page-custom-workshop.ws-tabs-shown .ws-board-title-caret{transform:rotate(180deg)}
/* When the title caret is toggled, reveal the underlying tab strip as a switcher */
#page-workshop:not(.ws-tabs-shown) > #workshopTabs,#page-custom-workshop:not(.ws-tabs-shown) > #cwTabs{display:none}
@media(max-width:760px){.ws-board-title{font-size:28px}
  :root{--page-title-size:22px;--page-title-icon:24px;--page-title-glyph:22px;
        --page-header-pad:14px 2px 4px 16px}}
/* ─── end board header ─── */

/* ═══════════════ Home — Attention Inbox ═══════════════ */
#page-dashboard.home-inbox-active #dashCanvasViewport{display:none}
.home-inbox{padding:30px 16px 60px 24px;overflow-y:auto;height:100%;font-family:var(--sans)}
/* Home header reuses the board's .ws-header (breadcrumb + title) but without its extra padding so it lines up with the inbox content. */
.hi-ws-header{padding:0 !important;gap:6px}
/* Centered AI prompt box + per-user AI recap placeholder. */
.hi-ai{max-width:760px;margin:8px auto 22px;display:flex;flex-direction:column;gap:14px}
.hi-ai-prompt{display:flex;align-items:center;gap:11px;background:#1c1c20;border:1px solid var(--border-d);border-radius:14px;padding:12px 14px;transition:border-color .15s,box-shadow .15s}
.hi-ai-prompt:focus-within{border-color:color-mix(in srgb,var(--purple) 60%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--purple) 14%,transparent)}
.hi-ai-spark{width:20px;height:20px;color:var(--purple);flex-shrink:0}
.hi-ai-input{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--white);font-family:var(--sans);font-size:15px}
.hi-ai-input::placeholder{color:var(--muted)}
.hi-ai-send{flex-shrink:0;width:32px;height:32px;border-radius:9px;border:none;background:var(--purple);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:filter .15s}
.hi-ai-send:hover{filter:brightness(1.12)}
.hi-ai-send svg{width:15px;height:15px}
.hi-ai-recap{background:#161619;border:1px solid var(--border-d);border-radius:14px;padding:16px 18px}
.hi-ai-recap-head{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:700;color:var(--white)}
.hi-ai-recap-head svg{width:16px;height:16px;color:var(--purple);flex-shrink:0}
.hi-ai-soon{margin-left:auto;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--purple);background:color-mix(in srgb,var(--purple) 15%,transparent);padding:3px 8px;border-radius:999px}
.hi-ai-recap-body{margin-top:9px;font-size:13px;color:var(--muted);line-height:1.55}
/* When the user types (and nothing matches), the box silently switches to AI mode — only an icon/badge changes. */
.hi-ai-mode{display:none;font-size:10px;font-weight:700;letter-spacing:.5px;color:var(--purple);background:color-mix(in srgb,var(--purple) 16%,transparent);padding:3px 7px;border-radius:999px;flex-shrink:0;align-items:center}
.hi-ai-prompt.ai-on .hi-ai-mode{display:inline-flex}
.hi-ai-prompt.ai-on .hi-ai-spark{color:var(--purple);filter:drop-shadow(0 0 6px color-mix(in srgb,var(--purple) 50%,transparent))}
.hi-loading{padding:60px;text-align:center;color:var(--muted);font-style:italic}
.hi-sync-note{margin:-6px 0 16px;padding:10px 12px;border:1px solid rgba(240,196,75,.2);background:rgba(240,196,75,.06);border-radius:10px;color:var(--muted);font-size:12px;line-height:1.45}
.hi-sync-note strong{color:var(--gold);font-weight:700}
.hi-top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:24px;flex-wrap:wrap}
.hi-title-wrap{min-width:0}
.hi-title{font-family:var(--display);font-style:normal;font-weight:800;font-size:34px;letter-spacing:-.02em;color:var(--white);margin:7px 0 0;line-height:1.05;text-wrap:balance}
.hi-sub{font-size:14px;font-weight:500;color:rgba(235,235,245,0.5);margin-top:5px}
.hi-controls{display:flex;align-items:center;gap:10px}
.hi-seg{display:inline-flex;background:var(--surface-container);border-radius:10px;padding:4px;gap:3px}
.hi-seg button{background:none;border:none;color:rgba(235,235,245,0.6);font-family:var(--sans);font-size:13px;font-weight:600;padding:6px 15px;border-radius:7px;cursor:pointer;transition:all .15s}
.hi-seg button.on{background:var(--purple);color:#fff}
.hi-refresh{display:flex;align-items:center;justify-content:center;background:none;border:1px solid rgba(255,255,255,.1);color:rgba(235,235,245,0.6);width:38px;height:38px;border-radius:10px;cursor:pointer;transition:all .15s}
.hi-refresh svg{width:16px;height:16px}
.hi-refresh:hover{color:var(--white);border-color:rgba(255,255,255,.2)}
.hi-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:24px 0 26px}
.hi-stat{display:flex;align-items:center;gap:16px;background:var(--card);border:1px solid var(--hairline);border-radius:14px;padding:17px 20px;position:relative;overflow:hidden}
.hi-stat::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px}
.hi-stat-red::before{background:var(--purple)}.hi-stat-amber::before{background:var(--gold)}.hi-stat-green::before{background:var(--green)}.hi-stat-blue::before{background:var(--blue)}
.hi-stat-n{font-family:var(--display);font-size:30px;font-weight:800;color:var(--white);line-height:1;min-width:42px}
.hi-stat-l{font-size:14px;font-weight:700;color:var(--white)}
.hi-stat-s{font-size:12px;color:rgba(235,235,245,0.45);margin-top:2px}
.hi-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;align-items:start}
.hi-col{display:flex;flex-direction:column;gap:20px;min-width:0}
/* A Home widget CONTAINS a list of items — the same role a board column plays, so it
   wears the same surface. (--surf-modal existed for this one rule and resolved to
   rgb(15,15,18), a private sixth neutral.) */
.hi-card{background:var(--surface-container);border:0;border-radius:16px;overflow:hidden}
.hi-card-head{display:flex;align-items:center;justify-content:space-between;padding:20px 22px 8px;font-size:16px;font-weight:700;color:var(--white)}
.hi-count{font-size:11px;font-weight:700;color:var(--text-2);background:rgba(255,255,255,.07);border-radius:7px;padding:2px 8px;margin-left:5px}
.hi-card-body{padding:2px 12px 14px}
/* The tick was an inline svg on a text baseline, so it rode low against the sentence.
   A centred flex row puts the two on the same optical line whatever the font metrics. */
.hi-empty{padding:44px 10px;color:rgba(235,235,245,0.4);font-size:14px;font-weight:500;
  display:flex;align-items:center;justify-content:center;gap:8px;text-align:center}
.hi-empty-ico{flex:none;display:block}
.hi-group{margin-bottom:4px}
.hi-group-head{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--text-3);padding:9px 8px 5px;display:flex;align-items:center;gap:6px}
.hi-caret{font-size:9px;opacity:.6}
.hi-row{display:flex;align-items:center;gap:13px;padding:11px 8px;border-radius:9px;cursor:pointer;transition:background .12s;font-size:13px}
.hi-row:hover{background:rgba(255,255,255,.04)}
.hi-prod{color:#9a8fd6;font-weight:600;font-size:13px;flex:0 0 26%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hi-task{color:var(--white);font-size:14px;font-weight:500;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hi-cell{flex-shrink:0}
.hi-pill{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;padding:3px 8px;border-radius:6px;display:inline-block}
.hi-pill.done{background:color-mix(in srgb,var(--green) 16%,transparent);color:var(--green)}
.hi-pill.prog{background:var(--purple-tint-strong);color:var(--purple-text)}
.hi-pill.todo{background:rgba(255,255,255,.08);color:#b8b8c0}
.hi-pill.overdue{background:color-mix(in srgb,var(--danger) 18%,transparent);color:var(--danger-text)}
.hi-date{font-size:13px;color:var(--muted);min-width:64px;text-align:right;display:inline-block}
.hi-date.overdue{color:var(--danger-text);font-weight:600}
.hi-owner{display:inline-flex;align-items:center;gap:5px;font-size:13px;color:var(--text-2)}
/* Home list — mark-complete fade-out + green strikethrough (cosmetic; state writes immediately). */
.hi-row-completing{animation:hiRowComplete .64s ease forwards;pointer-events:none}
@keyframes hiRowComplete{0%{opacity:1}72%{opacity:1}100%{opacity:0;transform:translateX(8px)}}
.hi-row-completing{animation-duration:1.8s !important} /* linger with the strikethrough before the row leaves (was gone in .64s — "goes away way too fast") */
.hi-row-completing .hi-task,.hi-row-completing .ht-title{text-decoration:line-through;text-decoration-color:var(--green,#7ccf84);text-decoration-thickness:2px;color:var(--muted);transition:color .15s}
/* Home list — mobile spreadsheet density (Linear/Notion list feel): dense rows, hairline
   dividers, tight columns (check · title · status · date). */
body[data-mobile-mode="app"] .hi-row{gap:9px;padding:9px 12px;border-radius:0;font-size:13px;border-bottom:1px solid rgba(255,255,255,.05)}
body[data-mobile-mode="app"] .hi-row:hover,body[data-mobile-mode="app"] .hi-row:active{background:rgba(255,255,255,.04)}
body[data-mobile-mode="app"] .hi-group .hi-row:last-of-type{border-bottom:none}
body[data-mobile-mode="app"] .hi-prod,body[data-mobile-mode="app"] .hi-owner{display:none}
body[data-mobile-mode="app"] .hi-task{font-size:14px;font-weight:500}
body[data-mobile-mode="app"] .hi-pill{font-size:10px;padding:1px 7px}
body[data-mobile-mode="app"] .hi-date{font-size:11px;min-width:50px}
body[data-mobile-mode="app"] .hi-check{margin-right:7px !important}
body[data-mobile-mode="app"] .hi-group-head{padding:15px 12px 7px;font-size:11px}
.hi-mention{display:flex;gap:11px;padding:12px 10px;border-bottom:1px solid rgba(255,255,255,.04)}
.hi-mention:last-child{border-bottom:none}
.hi-mention-av .card-avatar,.hi-mention-av img{width:30px;height:30px;border-radius:50%}
.hi-mention-body{flex:1;min-width:0}
.hi-mention-top{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted)}
.hi-mention-top b{color:var(--white);font-weight:700}
.hi-mention-prod{color:var(--muted)}
.hi-mention-when{margin-left:auto;font-size:11px;opacity:.7}
.hi-mention-title{font-size:14px;font-weight:600;color:var(--white);margin:3px 0 2px}
.hi-mention-text{font-size:13px;color:var(--muted);line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hi-mention-actions{display:flex;flex-direction:column;gap:6px;flex-shrink:0;justify-content:center}
.hi-open{background:rgba(255,255,255,.06);border:1px solid var(--border-d);color:var(--white);font-size:12px;font-weight:600;padding:6px 14px;border-radius:8px;cursor:pointer;font-family:var(--sans)}
.hi-open:hover{background:rgba(255,255,255,.12)}
.hi-markread{background:none;border:none;color:var(--green);font-size:12px;font-weight:600;cursor:pointer;font-family:var(--sans);white-space:nowrap}
.hi-read{font-size:11px;color:var(--muted)}
@media(max-width:1000px){.hi-stats{grid-template-columns:repeat(2,1fr)}.hi-grid{grid-template-columns:1fr}}
/* ═══════════════ end Home Attention Inbox ═══════════════ */

/* ═══════════════ Home — "Good morning" redesign ═══════════════ */
.hh-top{align-items:flex-start;margin-bottom:26px}
.hh-greet-wrap{min-width:0}
.hh-greet{font-family:var(--display);font-weight:800;font-size:34px;letter-spacing:-.02em;line-height:1.05;color:var(--white);margin:2px 0 0;text-wrap:balance}
.hh-sub{font-size:14px;font-weight:500;color:var(--text-2);margin-top:6px}
.hh-sub .hh-overdue{color:var(--prio-high);font-weight:600}
.hh-grid{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(300px,1fr);gap:20px;align-items:start}
.hh-main{min-width:0;display:flex;flex-direction:column;gap:20px}
.hh-rail{display:flex;flex-direction:column;gap:20px;min-width:0}
.hh-card-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:18px 22px 12px}
.hh-card-title{font-size:17px;font-weight:700;color:var(--white);display:flex;align-items:center;gap:9px}
.hh-card-title .hi-count{font-size:11px;font-weight:700;color:var(--text-2);background:rgba(255,255,255,.07);border-radius:7px;padding:2px 8px;margin:0}
.hh-open{display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:600;color:var(--purple-text);cursor:pointer;transition:color .14s ease}
.hh-open:hover{color:#fff}
.hh-open svg{width:13px;height:13px}
.hh-badge{font-size:11px;font-weight:700;color:var(--purple-text);background:var(--purple-tint-strong);border-radius:999px;padding:3px 9px}
.hh-card-body{padding:0 12px 12px}
.hh-tasks .hh-card-body{padding:0 14px 14px}
/* My Tasks groups */
.ht-group{margin-bottom:6px}
.ht-group:last-child{margin-bottom:0}
.ht-group-head{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--text-3);padding:12px 8px 6px}
.ht-gdot{width:7px;height:7px;border-radius:50%;flex:none}
.ht-gcount{color:var(--text-3);font-weight:700}
.ht-row{display:flex;align-items:center;gap:13px;padding:11px 8px;border-radius:10px;cursor:pointer;transition:background .12s ease;border-bottom:1px solid rgba(255,255,255,.04)}
.ht-group .ht-row:last-of-type{border-bottom:none}
.ht-row:hover{background:rgba(255,255,255,.04)}
.ht-check{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;background:none;border:none;cursor:pointer}
.ht-check svg{width:18px;height:18px}
.ht-main{flex:1;min-width:0}
.ht-title{font-size:14px;font-weight:600;color:var(--white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ht-proj{display:flex;align-items:center;gap:6px;margin-top:3px;font-size:13px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ht-dot{width:7px;height:7px;border-radius:50%;flex:none}
.ht-stagecell{flex:none}
.ht-stage{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;padding:3px 9px;border-radius:6px;white-space:nowrap}
.ht-due{flex:none;width:74px;text-align:right;font-size:13px;font-weight:600;color:var(--text-2)}
.ht-due.overdue{color:var(--danger-text)}
.ht-due.today{color:var(--gold)}
.ht-more{font-size:12px;color:var(--text-3);padding:8px 8px 4px;cursor:pointer}
.ht-more:hover{color:var(--text-2)}
/* Mentions (rail) */
.hh-mentions .hh-card-body,.hh-activity .hh-card-body{padding:0 10px 10px}
.hm-item{display:flex;gap:11px;padding:12px 10px;border-radius:10px;cursor:pointer;transition:background .12s ease;border-bottom:1px solid rgba(255,255,255,.04)}
.hm-item:last-child{border-bottom:none}
.hm-item:hover{background:rgba(255,255,255,.04)}
.hm-av{flex:none}
.hm-av-tag{width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:rgba(124,92,255,.16);color:#a78bfa}
.hm-av .card-avatar,.hm-av img,.hm-av .profile-avatar{width:30px;height:30px;border-radius:50%}
.hm-body{flex:1;min-width:0}
.hm-top{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-2)}
.hm-top b{color:var(--white);font-weight:700}
.hm-verb{color:var(--text-3)}
.hm-time{margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-3);white-space:nowrap}
.hm-unread{width:7px;height:7px;border-radius:50%;background:var(--purple);flex:none}
.hm-text{font-size:13px;color:rgba(235,235,245,.82);line-height:1.45;margin-top:4px}
.hm-at{color:var(--purple-text);font-weight:600}
.hm-ctx{display:inline-flex;align-items:center;gap:6px;margin-top:8px;font-size:12px;font-weight:600;color:var(--text-3);background:rgba(255,255,255,.05);border:1px solid var(--hairline);border-radius:7px;padding:3px 9px;max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.hm-ctx svg{flex:none;opacity:.8}
/* Recent Activity (rail) */
.ha-item{display:flex;align-items:flex-start;gap:11px;padding:11px 10px;border-radius:10px;cursor:pointer;transition:background .12s ease;border-bottom:1px solid rgba(255,255,255,.04)}
.ha-item:last-child{border-bottom:none}
.ha-item:hover{background:rgba(255,255,255,.04)}
.ha-ic{flex:none;width:30px;height:30px;border-radius:9px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.05);border:1px solid var(--hairline)}
.ha-dot{width:9px;height:9px;border-radius:50%;display:block}
.ha-body{flex:1;min-width:0}
.ha-title{font-size:13px;font-weight:600;color:var(--white);line-height:1.35}
.ha-text{font-size:12px;color:var(--text-2);line-height:1.4;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ha-time{flex:none;font-size:12px;color:var(--text-3);white-space:nowrap}
@media(max-width:1080px){.hh-grid{grid-template-columns:1fr}}
/* ═══════════════ end Home redesign ═══════════════ */

/* Remove the workshop tab strip ("Main" + "+") from the top — the breadcrumb/title replaces it */
#workshopTabs,#cwTabs{display:none !important}

/* ─── Collapsible left sidebar ─── */
.sidebar{transition:transform .22s ease}
.main{transition:margin-left .22s ease}
/* Collapsed = narrow ICON-ONLY rail (labels hidden, icons centered) */
.app.sidebar-collapsed .sidebar{width:72px;min-width:72px}
.app.sidebar-collapsed .main{margin-left:72px !important}
.app.sidebar-collapsed .sidebar-label,
.app.sidebar-collapsed .sidebar-section-name,
.app.sidebar-collapsed .sidebar-server-name,
.app.sidebar-collapsed #sidebarServerName,
.app.sidebar-collapsed .sidebar-server-caret,
.app.sidebar-collapsed .sidebar-home-flip,
.app.sidebar-collapsed .sidebar-home-add,
.app.sidebar-collapsed .sidebar-clients-trigger,
.app.sidebar-collapsed .sidebar-clients-menu,
.app.sidebar-collapsed .sidebar-banner,
.app.sidebar-collapsed .sidebar-profile-info{display:none !important}
.app.sidebar-collapsed #sidebarServerBar{flex-direction:column;gap:10px;justify-content:center}
.app.sidebar-collapsed .sidebar-server-trigger{justify-content:center;padding:0;width:auto;flex:0 0 auto}
.app.sidebar-collapsed .sidebar-collapse-btn svg{transform:rotate(180deg)}
.app.sidebar-collapsed .sidebar-nav a,
.app.sidebar-collapsed #sidebarUnifiedItems a,
.app.sidebar-collapsed .sidebar-section-nav a{justify-content:center;padding-left:0;padding-right:0;gap:0;font-size:0}
.app.sidebar-collapsed .sidebar-nav a svg,
.app.sidebar-collapsed #sidebarUnifiedItems a svg,
.app.sidebar-collapsed .sidebar-section-nav a svg{width:20px;height:20px;flex-shrink:0;font-size:initial}
.app.sidebar-collapsed .sidebar-profile{justify-content:center;padding-left:6px;padding-right:6px;gap:0}
#sidebarServerBar{display:flex;align-items:center;gap:5px}
#sidebarServerBar .sidebar-server-trigger{flex:1;min-width:0}
.sidebar-collapse-btn{flex-shrink:0;background:rgba(255,255,255,.06);border:1px solid var(--border-d);color:var(--muted);width:28px;height:28px;border-radius:7px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:color .15s,background .15s}
.sidebar-collapse-btn:hover{color:var(--white);background:rgba(255,255,255,.12)}
.sidebar-expand-btn{position:fixed;top:13px;left:12px;z-index:1200;background:var(--card,#262628);border:1px solid var(--border-d);color:var(--white);width:34px;height:34px;border-radius:9px;cursor:pointer;display:none;align-items:center;justify-content:center;box-shadow:0 4px 16px rgba(0,0,0,.45)}
.sidebar-expand-btn:hover{border-color:rgba(255,255,255,.25)}
.app.sidebar-collapsed .sidebar-expand-btn{display:none}
.sidebar-collapse-btn svg,.sidebar-expand-btn svg{width:16px;height:16px}
/* Workspace identity restored as the glass workspace card (#sidebarServerBar, 2026 redesign). */
.sidebar-expand-btn{display:none !important}
/* Clean collapse/expand toggle at the top of the sidebar — no box, no emoji, no outline. */
.sb-collapse{position:absolute;top:11px;right:11px;z-index:30;background:none;border:none;color:var(--muted);cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s,color .15s,top .2s,left .2s,right .2s}
.sb-collapse:hover{opacity:1;color:var(--white)}
.sb-collapse svg{width:18px;height:18px}
.app.sidebar-collapsed .sb-collapse{left:0;right:0;margin:0 auto;top:14px}
.app.sidebar-collapsed .sb-collapse svg{transform:rotate(180deg)}
/* Trash link visibility is governed by permissions (canAccessTrash / _updateShuttleTrashVisibility), not force-hidden. */
/* "+ New Workshop" affordance (replaces the old hardcoded Studio item); hidden from client users. */
.sidebar-new-workshop{color:var(--muted) !important}
.sidebar-new-workshop:hover{color:var(--white) !important}
body[data-shuttle-mode="client"] .sidebar-new-workshop{display:none !important}
.sidebar-nav a[data-page="dashboard"]{font-weight:700}
.sidebar-nav a[data-page="dashboard"] .sidebar-server-icon{width:26px;height:26px;font-size:11px}
.sidebar-home-name{font-size:15px;font-weight:700;color:var(--white)}
/* Home item flips "Sauce Media" up to reveal "Home" on hover or when selected. */
.sidebar-home-flip{position:relative;display:inline-block;height:1.25em;line-height:1.25em;overflow:hidden;vertical-align:bottom}
.sidebar-home-flip .shf-face{display:block;height:1.25em;transition:transform .3s cubic-bezier(.22,1,.36,1)}
.sidebar-home-flip .shf-back{position:absolute;left:0;top:0;transform:translateY(105%)}
.sidebar-nav a[data-page="dashboard"]:hover .shf-front{transform:translateY(-105%)}
.sidebar-nav a[data-page="dashboard"]:hover .shf-back{transform:translateY(0)}
/* Make every sidebar nav item match the "Sauce Media" home item: 15px, bold, white. */
.sidebar-nav a{font-size:15px;font-weight:700;color:var(--white)}
.sidebar-nav a:hover{color:var(--white)}
.sidebar-nav a svg{width:24px;height:24px;opacity:.95}
/* Person pills in card modal */
.prop-person-pill{display:inline-flex;align-items:center;gap:5px;padding:2px 8px 2px 2px;background:rgba(255,255,255,.08);border-radius:999px;font-size:11px;color:var(--cream)}
.prop-person-pill img{width:20px;height:20px;border-radius:50%;object-fit:cover}
.prop-person-pill .prop-person-initials{width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:8px;font-weight:700;color:#fff;flex-shrink:0}
/* Agency Home -> Manage Workspaces member roster. The table uses the same person
   pills as tasks; the dialog expands them into a complete, searchable roster. */
.hwm-people-cell{overflow:visible;min-width:0}
.hwm-workspace-row .gv-flat-cell{height:auto;min-height:42px}
.hwm-pills{display:flex;align-items:center;flex-wrap:wrap;gap:5px;min-width:0;max-width:100%;padding-block:3px}
.hwm-person-pill{height:26px;max-width:150px;padding:2px 9px 2px 3px;flex:0 1 auto;border:1px solid transparent;gap:6px}
.hwm-person-pill .card-avatar,.hwm-menu .card-avatar{border:none;flex:0 0 auto}
/* A real picture fills the circle; the purple fallback fill only belongs behind the emoji avatar. */
.hwm-person-pill .card-avatar:has(img),.hwm-menu .card-avatar:has(img){background:transparent}
.hwm-person-pill .card-avatar img,.hwm-menu .card-avatar img{display:block;width:100%;height:100%;object-fit:cover;border-radius:50%}
.hwm-more-pill{cursor:pointer;font-family:var(--sans);color:var(--muted);padding:2px 9px}
.hwm-more-pill:hover{color:var(--cream);background:rgba(255,255,255,.12)}
.hwm-pill-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.hwm-add-pill{height:26px;min-width:26px;border:1px dashed var(--border-d);border-radius:999px;background:transparent;color:var(--muted);cursor:pointer;font:600 11px var(--sans);padding:0 7px;white-space:nowrap}
.hwm-add-pill:hover{border-color:var(--purple);color:var(--cream);background:color-mix(in srgb,var(--purple) 10%,transparent)}
.hwm-more{color:var(--muted);font-size:11px;white-space:nowrap}
.hwm-count-fallback{color:var(--muted);font-size:12px}
.hwm-menu{position:fixed;z-index:10200;border-radius:10px;padding:5px;min-width:220px;max-width:300px;max-height:320px;overflow-y:auto;font-family:var(--sans);animation:gvEditPopIn .14s ease-out both}
.hwm-menu .hwm-candidate{display:flex;align-items:center;gap:9px;width:100%;padding:8px 11px;border:0;border-radius:6px;background:none;color:var(--cream);font:500 13px var(--sans);text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .12s}
.hwm-menu .hwm-candidate:hover,.hwm-menu .hwm-candidate:focus-visible{background:rgba(255,255,255,.06);outline:none}
.hwm-menu .hwm-candidate[disabled]{opacity:.5;cursor:default}
.hwm-menu .hwm-candidate.is-member{background:color-mix(in srgb,var(--purple) 12%,transparent)}
.hwm-menu .hwm-candidate.is-member:hover{background:color-mix(in srgb,var(--purple) 18%,transparent)}
.hwm-menu .hwm-candidate.is-locked{cursor:default;color:var(--muted)}
.hwm-menu .hwm-candidate.is-locked:hover{background:color-mix(in srgb,var(--purple) 12%,transparent)}
.hwm-check{width:14px;height:14px;margin-left:auto;flex:0 0 auto;color:var(--purple)}
.hwm-check.hwm-lock{color:var(--muted)}
.hwm-candidate-name small{display:block;font-size:10px;font-weight:500;color:var(--muted);line-height:1.2}
.hwm-menu .hwm-candidate .card-avatar{flex:0 0 auto}
.hwm-candidate-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hwm-menu-avatar{width:20px;height:20px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center}
.hwm-menu-avatar img,.hwm-menu-avatar .prop-person-initials{width:20px;height:20px;border-radius:50%;object-fit:cover;font-size:8px}
.hwm-invite-circle{border-radius:50%;border:1px dashed var(--border-d);color:var(--muted);font:600 13px/1 var(--sans);transition:border-color .12s,color .12s}
.hwm-invite-row:hover .hwm-invite-circle,.hwm-invite-row:focus-visible .hwm-invite-circle{border-color:var(--purple);color:var(--cream)}
.hwm-menu.is-invite{padding:8px;min-width:380px;max-width:440px}
.hwm-invite{display:grid;grid-template-columns:minmax(160px,1fr) auto auto;gap:6px;align-items:center}
.hwm-invite .ss-btn{height:32px;padding:0 12px;white-space:nowrap}
.hwm-tier-btn{display:inline-flex;align-items:center;gap:6px;height:32px;min-width:96px;padding:0 8px 0 10px;border:1.5px solid var(--border-d);border-radius:6px;background:rgba(255,255,255,.06);color:var(--cream);font:500 12px var(--sans);cursor:pointer;white-space:nowrap;transition:border-color .12s,background .12s}
.hwm-tier-btn:hover{background:rgba(255,255,255,.09)}
.hwm-tier-btn:focus-visible{outline:none;border-color:var(--purple)}
.hwm-tier-btn .hwm-tier-label{flex:1;text-align:left}
.hwm-tier-btn svg{width:13px;height:13px;color:var(--muted);flex:0 0 auto}
.hwm-tier-btn .rad-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
.hwm-tier-dd .rad-head{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;padding:4px 8px;margin-bottom:4px}
.hwm-invite .kanban-input{width:100%;height:32px;box-sizing:border-box;margin:0;padding:6px 9px;font-size:12px}
.hwm-invite-back{margin-top:6px;border:0;background:none;color:var(--muted);font:11px var(--sans);cursor:pointer;padding:2px 3px}
.hwm-invite-back:hover{color:var(--cream)}
.hwm-empty{color:var(--muted);font-size:12px;padding:8px 11px}
@media(max-width:760px){
  .hwm-menu.is-invite{min-width:min(92vw,320px)}
  .hwm-invite{grid-template-columns:1fr auto}
  .hwm-invite .ss-btn{grid-column:1/-1}
}
/* Scoped to a task: a kanban card's pills stay small on purpose (a card is a dense
   preview, and 13px pills would double its height). Inside the task, where the
   property IS the content, they all match the @mention chip. */
.card-modal .prop-pill,
.card-modal .prop-person-pill,
.card-modal .router-pill{
  height:var(--pill-h);padding:0 var(--pill-pad-x);border-radius:var(--pill-radius);
  font-size:var(--pill-font-size);font-weight:var(--pill-font-weight);
  gap:var(--pill-gap);color:var(--pill-ink);line-height:1;
  display:inline-flex;align-items:center;box-sizing:border-box}
/* An avatar or glyph rides flush to the leading edge, like the chip's does. */
.card-modal .prop-person-pill{padding-left:2px}
.card-modal .router-pill{padding-left:var(--pill-pad-lead)}
.card-modal .prop-pill-remove{width:var(--pill-remove);height:var(--pill-remove)}

/* One row for every chip-based value — people, files, routes. Each of the three used to
   build its own flex wrapper (two of them inline, with the numbers written out by hand),
   which is why their spacing and their [+] never quite agreed. Spacing is --pill-gap in
   BOTH axes, so a wrapped second line sits as far from the first as the pills do from each
   other, instead of the 4px that made the [+] look stuck to the row above it. */
.prop-chip-row{display:flex;flex-wrap:wrap;gap:var(--pill-gap);align-items:center;min-height:26px}
.prop-chip-row.is-inline{display:inline-flex;min-height:0;vertical-align:middle}
.prop-person-editor{display:flex;flex-wrap:wrap;gap:var(--pill-gap);align-items:center;min-height:26px}
.prop-person-dropdown{position:fixed;z-index:10001;background:var(--dark);border:1px solid var(--border-d);border-radius:8px;padding:4px 0;min-width:220px;max-height:220px;overflow-y:auto;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.prop-person-dropdown-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:12px;color:var(--cream);transition:background .1s}
.prop-person-dropdown-item:hover{background:rgba(255,255,255,.06)}
.prop-person-dropdown-item img{width:22px;height:22px;border-radius:50%;object-fit:cover}
.prop-person-dropdown-item .ppd-initials{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;flex-shrink:0}
.prop-person-dropdown-search{width:100%;border:none;background:rgba(255,255,255,.05);color:var(--cream);font-size:12px;padding:6px 12px;outline:none;border-bottom:1px solid var(--border-d)}

/* Property option editor */
.prop-options-editor{margin-top:8px;padding:12px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:10px}
.prop-opt-row{display:flex;align-items:center;gap:6px;padding:4px 0}
.prop-opt-color{width:14px;height:14px;border-radius:50%;cursor:pointer;border:1.5px solid var(--border-d);flex-shrink:0}
.prop-opt-color:hover{border-color:var(--coral)}
.prop-opt-label{flex:1;min-width:0}
.prop-opt-label input{background:transparent;border:none;color:var(--cream);font-size:12px;width:100%;outline:none;padding:2px 4px;border-radius:4px}
.prop-opt-label input:focus{background:rgba(255,255,255,.06)}
.prop-opt-remove{opacity:.4;cursor:pointer;font-size:12px;padding:2px 4px}
.prop-opt-remove:hover{opacity:1;color:var(--coral)}

/* Color picker mini */
.prop-color-picker{display:flex;gap:4px;flex-wrap:wrap;padding:8px;background:var(--dark);border:1px solid var(--border-d);border-radius:8px;position:fixed;z-index:10002;box-shadow:0 8px 24px rgba(0,0,0,.5);max-width:140px}
.prop-color-swatch{width:20px;height:20px;border-radius:50%;cursor:pointer;border:2px solid transparent;transition:border-color .1s}
.prop-color-swatch:hover,.prop-color-swatch.active{border-color:var(--off-white)}

/* ─── Add Property slide-out popover ──────────────────────────────────
   Replaces the centered "Add Property" modal. Anchored to the + button
   it was opened from; scales out from that corner so it reads like a
   menu unfurl rather than a takeover modal. */
.add-prop-popover{
  position:fixed;z-index:10100;
  width:340px;
  background:#15151a;
  border:1px solid var(--border-d);border-radius:14px;
  box-shadow:0 24px 60px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.04);
  display:flex;flex-direction:column;
  overflow:hidden;
  animation:appPopIn .22s cubic-bezier(.22,1,.36,1) both
}
@keyframes appPopIn{
  from{opacity:0;transform:scale(.9) translateY(-4px)}
  to{opacity:1;transform:none}
}
.add-prop-popover.is-closing{animation:appPopOut var(--dur-toggle) var(--ease-exit) forwards}
@keyframes appPopOut{
  from{opacity:1;transform:none}
  to{opacity:0;transform:scale(.95) translateY(-4px)}
}
.add-prop-popover .app-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:14px 16px 10px;
  border-bottom:1px solid var(--border-d);flex-shrink:0
}
.add-prop-popover .app-head-title{font-size:14px;font-weight:700;color:var(--cream);letter-spacing:-.1px}
.add-prop-popover .app-close{
  appearance:none;background:none;border:0;color:var(--muted);cursor:pointer;
  width:28px;height:28px;border-radius:7px;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .12s,color .12s
}
.add-prop-popover .app-close svg{width:14px;height:14px}
.add-prop-popover .app-close:hover{background:rgba(255,255,255,.06);color:var(--cream)}
.add-prop-popover .app-body{
  padding:14px 16px 8px;display:flex;flex-direction:column;gap:10px;
  max-height:60vh;overflow-y:auto
}
.add-prop-popover .app-label{
  font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;
  color:var(--muted);margin-bottom:-3px
}
.add-prop-popover .app-name-input{
  width:100%;font-size:14px;color:var(--cream);
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:9px;
  padding:10px 12px;outline:none;
  transition:border-color .12s,background .12s
}
.add-prop-popover .app-name-input:focus{border-color:var(--coral);background:rgba(255,255,255,.06)}
.add-prop-popover .app-name-input::placeholder{color:var(--muted)}
.add-prop-popover .app-type-grid{
  display:grid;grid-template-columns:repeat(2,1fr);gap:6px
}
.add-prop-popover .app-type-btn{
  display:flex;align-items:center;gap:10px;
  padding:10px 12px;border-radius:8px;
  background:none;border:1px solid var(--border-d);
  color:rgba(255,255,255,.7);font-size:13px;font-family:var(--sans);font-weight:500;
  cursor:pointer;text-align:left;
  transition:background .12s,border-color .12s,color .12s;
  -webkit-tap-highlight-color:transparent
}
.add-prop-popover .app-type-btn:hover{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.15);color:rgba(255,255,255,.95)}
.add-prop-popover .app-type-btn.is-active{
  background:rgba(124,92,255,.10);border-color:var(--coral);color:var(--coral)
}
.add-prop-popover .app-type-icon{
  width:18px;height:18px;flex-shrink:0;
  display:inline-flex;align-items:center;justify-content:center;
  color:var(--cream);opacity:.6;
  transition:opacity .12s,color .12s
}
.add-prop-popover .app-type-icon svg{width:16px;height:16px;display:block}
.add-prop-popover .app-type-btn:hover .app-type-icon{opacity:.95}
.add-prop-popover .app-type-btn.is-active .app-type-icon{color:var(--coral);opacity:1}
.add-prop-popover .app-show-row{
  display:flex;align-items:center;gap:8px;
  font-size:13px;color:var(--off-white);
  padding:4px 0;cursor:pointer;user-select:none
}
.add-prop-popover .app-show-row input{margin:0;cursor:pointer;accent-color:var(--coral)}
.add-prop-popover .app-opts-wrap{display:flex;flex-direction:column;gap:6px;border-top:1px solid var(--border-d);padding-top:10px;margin-top:2px}
.add-prop-popover .app-opts-list{display:flex;flex-direction:column;gap:5px;max-height:200px;overflow-y:auto}
.add-prop-popover .app-opts-empty{font-size:12px;color:var(--muted);padding:6px 2px}
.add-prop-popover .app-opt-row{
  display:flex;align-items:center;gap:8px;
  padding:5px 6px;border-radius:8px;
  transition:background .12s
}
.add-prop-popover .app-opt-row:hover{background:rgba(255,255,255,.03)}
.add-prop-popover .app-opt-color{
  width:18px;height:18px;border-radius:50%;flex-shrink:0;
  border:0;cursor:pointer;padding:0;
  transition:transform .1s
}
.add-prop-popover .app-opt-color:hover{transform:scale(1.12)}
.add-prop-popover .app-opt-pill{
  flex:1;min-width:0;
  display:inline-flex;align-items:center;justify-content:flex-start;
  padding:4px 9px;border-radius:6px;
  font-size:12px;font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.add-prop-popover .app-opt-remove{
  width:22px;height:22px;flex-shrink:0;
  background:none;border:0;color:var(--muted);cursor:pointer;
  border-radius:6px;
  display:inline-flex;align-items:center;justify-content:center;
  transition:background .12s,color .12s
}
.add-prop-popover .app-opt-remove:hover{background:rgba(239,68,68,.14);color:#f87171}
.add-prop-popover .app-opts-add input{
  width:100%;font-size:13px;color:var(--cream);
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:8px;
  padding:8px 10px;outline:none;transition:border-color .12s
}
.add-prop-popover .app-opts-add input:focus{border-color:var(--coral)}
.add-prop-popover .app-opts-add input::placeholder{color:var(--muted)}
.add-prop-popover .app-foot{
  display:flex;align-items:center;justify-content:flex-end;gap:8px;
  padding:10px 16px 14px;border-top:1px solid var(--border-d);
  background:rgba(255,255,255,.015);flex-shrink:0
}
.add-prop-popover .app-cancel{
  appearance:none;background:none;border:1px solid var(--border-d);
  color:var(--muted);cursor:pointer;
  padding:7px 14px;border-radius:8px;font-size:13px;font-weight:500;
  transition:background .12s,color .12s
}
.add-prop-popover .app-cancel:hover{background:rgba(255,255,255,.04);color:var(--cream)}
.add-prop-popover .app-save{
  appearance:none;border:0;
  background:var(--coral);color:#fff;
  cursor:pointer;
  padding:8px 16px;border-radius:8px;font-size:13px;font-weight:700;
  box-shadow:0 1px 0 rgba(255,255,255,.1) inset;
  transition:background .12s,transform .08s
}
.add-prop-popover .app-save:hover{background:#d44e2a}
.add-prop-popover .app-save:active{transform:scale(.98)}
/* Mobile: bottom-sheet variant */
.add-prop-popover.is-mobile{
  left:8px !important;right:8px !important;
  width:auto !important;max-width:none !important;
  bottom:calc(20px + env(safe-area-inset-bottom,0px)) !important;
  top:auto !important;
  border-radius:16px;
  transform-origin:bottom center !important;
  animation:appPopInMobile .22s cubic-bezier(.22,1,.36,1) both
}
@keyframes appPopInMobile{
  from{opacity:0;transform:translateY(20px)}
  to{opacity:1;transform:none}
}
.add-prop-popover.is-mobile.is-closing{animation:appPopOutMobile var(--dur-toggle) var(--ease-exit) forwards}
@keyframes appPopOutMobile{
  from{opacity:1;transform:none}
  to{opacity:0;transform:translateY(20px)}
}
.add-prop-popover.is-mobile .app-name-input,
.add-prop-popover.is-mobile .app-opts-add input{font-size:16px}
.add-prop-popover.is-mobile .app-type-btn{padding:11px 12px;font-size:14px}
.add-prop-popover.is-mobile .app-body{max-height:calc(70vh - 100px)}
/* Property type picker */
.prop-type-picker{position:fixed;z-index:10001;padding:8px;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 8px 32px rgba(0,0,0,.5);width:320px;max-height:400px;overflow-y:auto}
.prop-type-picker-title{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;padding:4px 8px 6px;font-weight:600}
.prop-type-picker-sep{height:1px;background:var(--border-d);margin:4px 0}
.prop-type-picker-grid{display:grid;grid-template-columns:1fr 1fr;gap:2px}
.prop-type-item{display:flex;align-items:center;gap:8px;padding:7px 10px;cursor:pointer;transition:background .1s;border-radius:6px}
.prop-type-item:hover{background:rgba(255,255,255,.06)}
.prop-type-item-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--muted)}
.prop-type-item-icon svg{width:16px;height:16px}
.prop-type-item-label{font-size:12px;color:var(--cream);font-weight:500}

/* Property context menu */
.prop-ctx-menu{position:fixed;z-index:10001;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;padding:4px 0;min-width:180px;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.prop-ctx-menu button{display:flex;align-items:center;gap:8px;width:100%;background:none;border:none;color:var(--cream);padding:7px 14px;font-size:12px;cursor:pointer;text-align:left;transition:background .1s}
.prop-ctx-menu button:hover{background:rgba(255,255,255,.06)}
/* --danger-text like every other context menu's danger action. --coral is the brand
   purple here, which both mis-signalled 'destructive' and, at low contrast against
   the near-black menu, made the text read as smaller than its neighbours. */
.prop-ctx-menu button.ctx-danger{color:var(--danger-text)}
.prop-ctx-menu button.ctx-danger:hover{background:rgba(239,68,68,.12)}
.prop-ctx-menu .ctx-sep{height:1px;background:var(--border-d);margin:4px 0}
.prop-ctx-menu .ctx-header{padding:6px 14px;font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px}

/* #16 Home-task modal: originating-client chip next to status (agency page only) */
/* The workspace chip takes the CARD's own colour, not a fixed purple. It sits beside the
   status pill, which is already tinted by --modal-col-color, so a hardcoded purple was the
   one thing in that row ignoring the task it belongs to. color-mix keeps the same weight as
   the old rgba(...,.14) tint while following whatever colour the column is.
   Falls back to --coral (the brand purple) for any card whose column has no colour set. */
.cm-client-chip{display:inline-flex;align-items:center;gap:6px;margin-left:10px;padding:2px 9px 2px 2px;border-radius:999px;
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 14%,transparent);
  color:var(--modal-col-color,var(--coral));
  font-size:11px;font-weight:600;line-height:1.6;vertical-align:middle;white-space:nowrap}
/* Workspace icon, circular, on the leading edge. object-fit:cover so a non-square source
   crops rather than distorting; the initials span is the fallback when a workspace has no
   icon uploaded, so the chip keeps its shape either way. */
.cm-client-chip .cm-client-chip-ico{width:16px;height:16px;border-radius:50%;flex:none;object-fit:cover;display:block}
.cm-client-chip .cm-client-chip-fallback{width:16px;height:16px;border-radius:50%;flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 30%,transparent);
  color:var(--modal-col-color,var(--coral));font-size:8px;font-weight:700;line-height:1}

/* #2/#19 In-place client switcher inside the gear menu (scrollable, wheel-scrolls) */
.scm-switch-back{display:flex;align-items:center;gap:7px;width:100%;padding:9px 12px;background:none;border:none;border-bottom:1px solid var(--border-d,rgba(255,255,255,.06));color:var(--muted);font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer;text-align:left}
.scm-switch-back:hover{color:var(--white,#fff)}
.scm-client-scroll{max-height:300px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:4px 0}

/* #8 Per-board freeform sticky-note Canvas */
.board-canvas-wrap{display:flex;flex-direction:column;height:100%;min-height:0}
.board-canvas-toolbar{display:flex;align-items:center;gap:12px;padding:8px 4px 10px}
.bc-add-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border-radius:8px;background:var(--purple,#8c72db);border:none;color:#fff;font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer}
.bc-add-btn:hover{filter:brightness(1.08)}
.bc-hint{font-size:11px;color:var(--muted)}
.board-canvas{position:relative;flex:1;min-height:440px;overflow:auto;border-radius:12px;background-color:rgba(255,255,255,.012);background-image:radial-gradient(rgba(255,255,255,.05) 1px,transparent 1px);background-size:22px 22px;border:1px solid rgba(255,255,255,.05)}
.bc-empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--muted);font-size:13px;pointer-events:none}
.bc-note{position:absolute;min-width:140px;min-height:90px;border-radius:10px;background:var(--bc-color,#e7ce3a);box-shadow:0 6px 18px rgba(0,0,0,.28);display:flex;flex-direction:column;overflow:hidden}
.bc-note.bc-dragging{opacity:.92;cursor:grabbing;z-index:6}
.bc-note.bc-resizing{z-index:6;box-shadow:0 12px 32px rgba(0,0,0,.4)}
.bc-note-bar{display:flex;align-items:center;gap:6px;padding:5px 7px;cursor:grab;background:rgba(0,0,0,.12);touch-action:none}
.bc-note-colors{display:flex;gap:4px;margin-right:auto}
.bc-color{width:13px;height:13px;border-radius:50%;border:1.5px solid rgba(0,0,0,.25);cursor:pointer;padding:0}
.bc-color.on{box-shadow:0 0 0 2px rgba(255,255,255,.85)}
.bc-note-del{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:none;color:rgba(0,0,0,.55);cursor:pointer;border-radius:4px}
.bc-note-del:hover{background:rgba(0,0,0,.15);color:#000}
.bc-note-body{flex:1;padding:8px 10px;font-family:var(--sans);font-size:13px;line-height:1.45;color:#1a1a1a;outline:none;white-space:pre-wrap;word-break:break-word;overflow:auto}
.bc-note-body:empty:before{content:attr(data-ph);color:rgba(0,0,0,.4)}
.bc-resize{position:absolute;right:0;bottom:0;width:18px;height:18px;cursor:nwse-resize;touch-action:none;z-index:3;opacity:0;transition:opacity .15s}
.bc-note:hover .bc-resize{opacity:.55}
.bc-resize:hover{opacity:1}
.bc-resize::after{content:'';position:absolute;right:3px;bottom:3px;width:8px;height:8px;border-right:2px solid rgba(0,0,0,.45);border-bottom:2px solid rgba(0,0,0,.45);border-bottom-right-radius:2px}

/* App-update toast (Henshu updated — Refresh) */

/* Forgot-password link on the login gate */
.login-forgot-link{display:block;width:100%;margin-top:2px;background:none;border:none;color:var(--muted);font-family:var(--sans);font-size:12px;cursor:pointer;text-align:center;padding:4px;transition:color .15s}
.login-forgot-link:hover{color:var(--purple,#8c72db)}
.login-forgot-link:disabled{opacity:.6;cursor:default}

/* Board-switch transition overlay (instant feedback on client/agency switch; bridges the reload) */
.board-switch-overlay{position:fixed;inset:0;z-index:100001;display:flex;align-items:center;justify-content:center;background:var(--dark,#1b1b1b);opacity:0;transition:opacity .1s ease}
.board-switch-overlay.show{opacity:1}
.bso-inner{display:flex;flex-direction:column;align-items:center;gap:18px}
/* Circle, not a rounded square: every other workspace icon in the app is a
   circle (.sd-ws-ic, .cw-av, .ws-member-stack) — the switch screen's tile was
   the one holdout (owner request, 2026-08-13). */
.bso-icon{width:64px;height:64px;border-radius:50%;overflow:hidden;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center}
.bso-icon img{width:100%;height:100%;object-fit:cover}
.bso-initials{font-family:var(--sans);font-size:24px;font-weight:700;color:var(--purple,#8c72db)}
.bso-name{font-family:var(--sans);font-size:17px;font-weight:600;color:var(--cream,#fafaf8)}
/* Rounding clamped via 9999px (circle on any square box, never a squircle),
   1:1 aspect + flex:none against stretch, and will-change:transform so Chrome
   rasterizes the ring on its own layer instead of re-tessellating the rotating
   border (the classic "spinner looks like a rounded rectangle" artifact). */
.bso-spinner{width:22px;height:22px;flex:none;aspect-ratio:1;box-sizing:border-box;border-radius:9999px;border:2.5px solid rgba(255,255,255,.12);border-top-color:var(--purple,#8c72db);animation:bsoSpin .7s linear infinite;will-change:transform}
@media (prefers-reduced-motion:reduce){
  .board-switch-overlay{transition:none}
  .bso-spinner{animation:none}
  .rev-buffer-spinner{animation:none}
}
@keyframes bsoSpin{to{transform:rotate(360deg)}}
/* ── Item E — Automations modal: desktop unchanged; mobile = full-screen task-style
   layout (sticky header + When/Then tabs + scrollable content). ── */
.auto-flow-part{display:contents}          /* desktop: IF/THEN flow inline exactly as before */
.auto-modal-tabs{display:none}             /* desktop hides the tab strip */
body[data-mobile-mode="app"] #autoModal.auto-modal-overlay{padding:0;align-items:stretch;justify-content:stretch}
body[data-mobile-mode="app"] #autoModal .auto-modal{
  max-width:100%;width:100%;border-radius:0;border:0;
  display:block;padding:0 0 calc(24px + env(safe-area-inset-bottom,0px));
  height:100dvh;max-height:100dvh;overflow-y:auto;-webkit-overflow-scrolling:touch
}
body[data-mobile-mode="app"] #autoModal .auto-modal-head{
  position:sticky;top:0;z-index:3;flex-shrink:0;margin:0;
  padding:calc(12px + env(safe-area-inset-top,0px)) 16px 12px;
  border-bottom:1px solid var(--border-d);background:var(--dark)
}
body[data-mobile-mode="app"] #autoModal .auto-modal-head h3{font-size:18px}
body[data-mobile-mode="app"] #autoModal .auto-modal-tabs{
  display:flex;flex-shrink:0;gap:8px;padding:12px 16px;border-bottom:1px solid var(--border-d);background:var(--dark)
}
body[data-mobile-mode="app"] #autoModal .auto-modal-tab{
  flex:1;border:1px solid var(--border-d);background:rgba(255,255,255,.04);color:var(--cream);
  font-family:var(--sans);font-size:14px;font-weight:600;padding:9px 0;border-radius:999px;cursor:pointer;
  -webkit-tap-highlight-color:transparent
}
body[data-mobile-mode="app"] #autoModal .auto-modal-tab.is-active{
  background:color-mix(in srgb,var(--purple) 18%,transparent);border-color:color-mix(in srgb,var(--purple) 45%,transparent);color:var(--off-white)
}
/* Scrollable content region below the sticky header + tabs */
body[data-mobile-mode="app"] #autoModal .auto-modal > .auto-line,
body[data-mobile-mode="app"] #autoModal .auto-modal > .auto-inline-config{padding-left:16px;padding-right:16px}
body[data-mobile-mode="app"] #autoModal .auto-modal > .auto-line:first-of-type{margin-top:16px}
body[data-mobile-mode="app"] #autoModal .auto-flow-part{display:flex;align-items:center;gap:8px;width:100%;margin-bottom:6px}
body[data-mobile-mode="app"] #autoModal .auto-rule-comma{display:none}
/* Tab show/hide: only the active panel's parts + config render on mobile */
body[data-mobile-mode="app"] #autoModal[data-atab="when"] .auto-flow-part[data-apanel="then"],
body[data-mobile-mode="app"] #autoModal[data-atab="when"] .auto-inline-config[data-apanel="then"],
body[data-mobile-mode="app"] #autoModal[data-atab="then"] .auto-flow-part[data-apanel="when"],
body[data-mobile-mode="app"] #autoModal[data-atab="then"] .auto-inline-config[data-apanel="when"]{display:none}
/* ── Item F — Members tab: Discord-mobile grouped-card rows + Member detail sheet ── */
.settings-member-chev{display:none}   /* desktop: no chevron, inline actions stay */
body[data-mobile-mode="app"] #ssMembersList{
  display:flex;flex-direction:column;gap:0;
  background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:14px;overflow:hidden
}
body[data-mobile-mode="app"] .settings-member-row{
  display:flex;align-items:center;gap:12px;padding:12px 14px;grid-template-columns:none;
  border-bottom:1px solid var(--border-d);cursor:pointer;-webkit-tap-highlight-color:transparent
}
body[data-mobile-mode="app"] .settings-member-row:active{background:rgba(255,255,255,.05)}
body[data-mobile-mode="app"] .settings-member-row:last-child{border-bottom:none}
body[data-mobile-mode="app"] .settings-member-av{width:42px;height:42px;font-size:16px;flex-shrink:0}
body[data-mobile-mode="app"] .settings-member-idwrap{flex:1;min-width:0}
body[data-mobile-mode="app"] .settings-member-name{font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body[data-mobile-mode="app"] .settings-member-email{font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body[data-mobile-mode="app"] .settings-member-row .role-badges{flex-shrink:0;max-width:34vw;justify-content:flex-end}
body[data-mobile-mode="app"] .settings-member-row .role-badges .cr-profile-role:not(:first-child){display:none}  /* one chip on mobile */
body[data-mobile-mode="app"] .settings-member-plat-role,
body[data-mobile-mode="app"] .settings-member-actions{display:none}
body[data-mobile-mode="app"] .settings-member-chev{display:block;width:18px;height:18px;color:var(--muted);flex-shrink:0}
/* Member detail sheet */
.ssms-sheet{display:none}
body[data-mobile-mode="app"] .ssms-sheet.open{display:flex;flex-direction:column;position:fixed;inset:0;z-index:10070;background:var(--black);overflow-y:auto;-webkit-overflow-scrolling:touch}
.ssms-head{position:sticky;top:0;flex-shrink:0;padding:calc(12px + env(safe-area-inset-top,0px)) 14px 12px;border-bottom:1px solid var(--border-d);background:var(--black);z-index:2}
.ssms-back{display:inline-flex;align-items:center;gap:6px;background:none;border:0;color:var(--off-white);font-family:var(--sans);font-size:16px;font-weight:600;cursor:pointer;-webkit-tap-highlight-color:transparent}
.ssms-back svg{width:22px;height:22px}
.ssms-hero{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;padding:28px 20px 22px;border-bottom:1px solid var(--border-d)}
.ssms-av{width:88px;height:88px;border-radius:50%;overflow:hidden;background:var(--surface);display:flex;align-items:center;justify-content:center;font-size:34px;font-weight:700;color:var(--cream);margin-bottom:4px}
.ssms-av img{width:100%;height:100%;object-fit:cover}
.ssms-name{font-size:21px;font-weight:700;color:var(--off-white)}
.ssms-email{font-size:13px;color:var(--muted)}
.ssms-plat{font-size:12px;color:var(--cream);text-transform:capitalize;background:rgba(255,255,255,.06);border-radius:999px;padding:3px 12px;margin-top:4px}
.ssms-roles{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:8px}
.ssms-actions{display:flex;flex-direction:column;gap:0;padding:0;margin:16px;background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:14px;overflow:hidden}
.ssms-act{display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:0;border-bottom:1px solid var(--border-d);color:var(--off-white);font-family:var(--sans);font-size:16px;padding:15px 16px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.ssms-act:last-child{border-bottom:none}
.ssms-act:active{background:rgba(255,255,255,.05)}
.ssms-act svg{width:18px;height:18px;color:var(--muted)}
.ssms-danger{color:#ff453a}
.ssms-noact{padding:18px;text-align:center;color:var(--muted);font-size:13px;font-style:italic}
/* ── Item G — full-page filter view (desktop) + named saved-filters strip ──
   Mobile already full-screens via its own #workshopFilterPanel rule; .wf-fp brings the
   same full-page treatment to desktop (no longer an anchored dropdown). */
.workshop-filter-panel.wf-fp{
  position:fixed;inset:0;left:0;top:0;width:100%;max-width:100%;
  height:100dvh;max-height:100dvh;border:0;border-radius:0;box-shadow:none;
  background:var(--dark);z-index:9600
}
.workshop-filter-panel.wf-fp .wf-msheet-head,
.workshop-filter-panel.wf-fp .wf-saved-strip,
.workshop-filter-panel.wf-fp .wf-header,
.workshop-filter-panel.wf-fp .wf-body,
.workshop-filter-panel.wf-fp .wf-footer{width:100%;max-width:780px;margin-left:auto;margin-right:auto;box-sizing:border-box}
.wf-saved-strip{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:12px 16px;border-bottom:1px solid var(--border-d)}
.wf-saved-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.wf-saved-empty{font-size:12px;color:var(--muted);font-style:italic}
.wf-saved-pill{display:inline-flex;align-items:center;gap:6px;background:color-mix(in srgb,var(--purple) 16%,transparent);border:1px solid color-mix(in srgb,var(--purple) 40%,transparent);color:var(--off-white);font-family:var(--sans);font-size:13px;font-weight:600;padding:6px 10px 6px 12px;border-radius:999px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.wf-saved-x{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;color:var(--muted);font-size:15px;line-height:1}
.wf-saved-x:hover{color:var(--coral)}
.wf-saved-add{margin-left:auto;background:none;border:1px dashed var(--border-d);color:var(--cream);font-family:var(--sans);font-size:13px;font-weight:600;padding:6px 12px;border-radius:999px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.wf-saved-add:hover{border-color:var(--purple);color:var(--off-white)}
/* ── Item H — Board Settings: desktop unchanged dropdown; mobile = full-page iOS-grouped
   settings sheet. ws-dd-body is display:contents on desktop so the menu renders exactly as
   before; the header is hidden on desktop. ── */
.ws-dd-head{display:none}
.ws-dd-body{display:contents}
body[data-mobile-mode="app"] .cw-dropdown.open{
  position:fixed !important;inset:0 !important;left:0 !important;top:0 !important;right:0 !important;bottom:0 !important;
  width:100% !important;max-width:100% !important;max-height:100dvh !important;min-width:0 !important;
  margin:0 !important;border:0 !important;border-radius:0 !important;box-shadow:none !important;
  background:var(--black) !important;
  display:flex !important;flex-direction:column !important;justify-content:flex-start !important;
  padding:0 0 calc(24px + env(safe-area-inset-bottom,0px)) !important;z-index:10050 !important;overflow-y:auto !important
}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-head{
  display:flex;align-items:center;justify-content:space-between;flex-shrink:0;
  padding:calc(14px + env(safe-area-inset-top,0px)) 16px 12px;background:var(--black);border-bottom:1px solid var(--border-d)
}
body[data-mobile-mode="app"] .cw-dropdown .ws-dd-title{font-family:var(--serif);font-size:20px;color:var(--off-white)}
body[data-mobile-mode="app"] .cw-dropdown .ws-dd-title{flex-shrink:0;white-space:nowrap}
body[data-mobile-mode="app"] .cw-dropdown .ws-dd-done{width:auto;flex:0 0 auto;border:0;background:var(--coral);color:#fff;font-weight:600;font-size:14px;font-family:var(--sans);padding:8px 18px;border-radius:999px;cursor:pointer;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body{
  display:flex;flex-direction:column;gap:0;margin:18px 16px;
  background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:14px;overflow:hidden
}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > button{
  display:flex;align-items:center;gap:13px;width:100%;justify-content:flex-start;
  padding:15px 16px;font-size:16px;color:var(--off-white);border:0;border-bottom:1px solid var(--border-d);
  background:none;border-radius:0;white-space:normal
}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > button:last-child{border-bottom:0}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > button svg{width:19px;height:19px;flex-shrink:0;color:var(--muted)}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > button::after{
  content:'';margin-left:auto;width:8px;height:8px;border-right:2px solid var(--muted);border-top:2px solid var(--muted);transform:rotate(45deg);flex-shrink:0
}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > button:active{background:rgba(255,255,255,.05)}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > div[style]{display:none}
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > .cw-dropdown-danger,
body[data-mobile-mode="app"] .cw-dropdown.open .ws-dd-body > .cw-dropdown-danger svg{color:#ff453a !important}
/* ── Item K — History sub-sections (Activity / Comments / Reviews / Publishing) ──
   mobile + desktop. A pill sub-tab bar above the log filters which source is shown. */
.card-hist-subtabs{display:flex;gap:6px;flex-wrap:wrap;margin:2px 0 14px;position:relative}
.card-hist-subtab{flex:0 0 auto;position:relative;z-index:1;background:transparent;border:none;color:var(--muted);font-family:var(--sans);font-size:12px;font-weight:600;padding:6px 13px;border-radius:999px;cursor:pointer;transition:color .15s;-webkit-tap-highlight-color:transparent}
.card-hist-subtab:hover{color:var(--cream)}
/* The sliding pill IS the selection highlight, tinted by the task's status. */
.card-hist-subtabs .m-pill-thumb{background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 18%,transparent);border:0;border-radius:999px}
.card-hist-subtab.is-active{background:transparent;border:none;color:var(--off-white)}
.card-hist-subtab-ct{margin-left:6px;font-size:10px;font-weight:700;color:var(--muted);background:rgba(255,255,255,.08);border-radius:9px;padding:1px 6px;vertical-align:middle}
.card-hist-subtab.is-active .card-hist-subtab-ct{color:var(--cream);background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 26%,transparent)}
.card-hist-section{display:flex;flex-direction:column;gap:0}
.hist-resolved{font-size:10px;color:var(--green);text-transform:uppercase;letter-spacing:.4px;margin-left:4px;font-weight:700}
body[data-mobile-mode="app"] .card-hist-subtabs{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
body[data-mobile-mode="app"] .card-hist-subtabs::-webkit-scrollbar{display:none}
/* ── Blocking "new version" overlay — unmissable, non-dismissable (no X). Mobile + desktop. ── */
.app-update-overlay{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(0,0,0,.66);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);opacity:0;transition:opacity .2s ease}
.app-update-overlay.show{opacity:1}
.app-update-card{width:100%;max-width:340px;background:var(--dark,#111110);border:1px solid var(--border-d);border-radius:18px;padding:30px 24px;text-align:center;box-shadow:0 24px 60px rgba(0,0,0,.6)}
.app-update-icon{width:54px;height:54px;border-radius:50%;margin:0 auto 16px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--purple,#8c72db) 18%,transparent);color:var(--purple,#8c72db)}
.app-update-icon svg{width:26px;height:26px}
.app-update-title{font-family:var(--serif);font-size:22px;color:var(--off-white);margin-bottom:8px}
.app-update-desc{font-size:14px;color:var(--muted);line-height:1.5;margin-bottom:22px}
.app-update-btn{width:100%;border:0;border-radius:999px;padding:14px;font-family:var(--sans);font-size:16px;font-weight:600;color:#fff;background:linear-gradient(135deg,#7c3aed,#a78bfa);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:transform .12s}
.app-update-btn:active{transform:scale(.98)}

/* ==================== LIGHT THEME ==================== */
/* Soft off-white surfaces, near-black text, brand purple accent. Built from the
   variable foundation (flips every var-driven surface) + targeted overrides for the
   hardcoded white-alpha elevation/borders the dark UI uses. */
html[data-theme="light"]{
  color-scheme:light;
  --white:#ffffff;
  --off-white:#1c1c1e;          /* primary text → near-black */
  --cream:#3a3a42;              /* secondary text */
  --sec:#55555e;
  --muted:#76767e;              /* tertiary / placeholders */
  --light:#f4f4f0;--mid-gray:#d9d9d4;
  --dark:#ffffff;               /* sidebar / panels / modals / dropdowns */
  --black:#e9ebee;
  --bg-main:#f5f6f8;            /* main content (iOS system-gray-6 vibe) */
  --bg-dark:#eceef1;
  --bg-board:#eef0f3;           /* kanban board */
  /* App canvas / page shells / elevated surfaces — these dark tokens were left
     un-overridden and kept the Home dashboard (.main/#page-dashboard/.hi-card),
     the workshop canvas, and kanban cards dark-on-light. */
  --bg-app:#f5f6f8;             /* .main + #page-dashboard + workshop page canvas */
  --bg-deep:#eceef1;
  --surf-1:#ffffff;--surf-2:#ffffff;--surf-3:#ffffff;--surf-4:#ffffff;
  --surf-modal:#ffffff;         /* Home dashboard cards (.hi-card) */
  --card:#ffffff;--surface:#ffffff;
  --bg-card:#f0f0f3;/* social-pub avatar/well surface on light — inset, not white-on-white */
  --border:rgba(0,0,0,.08);
  --border-d:rgba(0,0,0,.12);   /* "border on dark" → hairline dark on light */
  /* Hairline dividers were white-alpha (invisible on white surfaces). */
  --hairline:rgba(0,0,0,.08);--hairline-2:rgba(0,0,0,.11);--hairline-3:rgba(0,0,0,.14);
  /* Semantic text tokens were near-white (invisible on light surfaces): the Home
     dashboard, comments, and many panels read secondary/tertiary text via these. */
  --text-1:#17171c;--text-2:#5f5f6b;--text-3:#7d7d89;
  --purple:#7a5fd6;--purple-soft:rgba(122,95,214,.12);
  --coral:#7a5fd6;--coral-shade:#5f48c0;
  --green:#3f9d54;--blue:#2f6fb0;--gold:#b48f10;--pink:#cf2a6c;--teal:#2c8088;--peach:#cf5e54;--lavender:#9a7d96;--orange:#bf6618;
  --bg-inset:rgba(0,0,0,.06);/* recessed well on light surfaces */
  --skel-hi:rgba(0,0,0,.11);/* skeleton shimmer highlight on light surfaces */
;
  /* Glass menus (dropdowns/ctx menus/pickers) — light recipe. The component rules use
     var(--glass-*) !important, so overriding the VARS here flips them all at once. */
  --glass-bg:rgba(255,255,255,.88);--glass-border:rgba(0,0,0,.10);
  /* Light-theme liquid glass also lives in tokens.css. */
  --glass-shadow:0 24px 60px rgba(0,0,0,.14),inset 0 1px 0 rgba(255,255,255,.6);
  --modal-bg:#ffffff;
  /* Pill bars, Home cards and stat tiles are built on these two; they were never
     remapped, so every one of them stayed near-black on the light canvas. */
  --bg-shell:#ffffff;--surface-container:#ffffff;
}
html[data-theme="light"] body{background:var(--bg-board);color:var(--off-white)}
html[data-theme="light"] ::-webkit-scrollbar-thumb{background:rgba(0,0,0,.18)}
html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.30)}
html[data-theme="light"] .board-bottom-fade{background:linear-gradient(to bottom,rgba(238,240,243,0) 0%,rgba(238,240,243,.72) 68%,rgba(238,240,243,1) 100%)}
/* Elevated surfaces / hover / active — flip white-alpha overlays to dark-alpha */
html[data-theme="light"] .panel,
html[data-theme="light"] .stat-card,
html[data-theme="light"] .kanban-column,
html[data-theme="light"] .co-panel,
html[data-theme="light"] .asset-card{background:#ffffff;border-color:var(--border-d);box-shadow:0 1px 3px rgba(0,0,0,.05)}
html[data-theme="light"] .kanban-card,
html[data-theme="light"] .card,
html[data-theme="light"] .ms-dropdown-menu,
html[data-theme="light"] .context-menu,
html[data-theme="light"] .card-ctx-menu,
html[data-theme="light"] .edit-ctx-menu,
html[data-theme="light"] .sidebar-ctx-menu,
html[data-theme="light"] .popover,
html[data-theme="light"] .rev-popover{background:#ffffff;border-color:var(--border-d);box-shadow:0 4px 16px rgba(0,0,0,.12)}
/* Inputs */
html[data-theme="light"] input[type="text"],
html[data-theme="light"] input[type="email"],
html[data-theme="light"] input[type="password"],
html[data-theme="light"] input[type="search"],
html[data-theme="light"] input[type="number"],
html[data-theme="light"] input[type="datetime-local"],
html[data-theme="light"] textarea,
html[data-theme="light"] .ms-dropdown-trigger,
html[data-theme="light"] .rev-input,
html[data-theme="light"] .sch-in,
html[data-theme="light"] .sch-caption{background:#ffffff;border-color:rgba(0,0,0,.14);color:var(--off-white)}
html[data-theme="light"] input::placeholder,
html[data-theme="light"] textarea::placeholder{color:#9a9aa2}
html[data-theme="light"] input:focus,
html[data-theme="light"] textarea:focus,
html[data-theme="light"] .rev-input:focus{border-color:var(--purple)}
/* Generic hover/active overlays (white-alpha → subtle dark) on common rows/buttons */
html[data-theme="light"] .sidebar-nav .nav-item:hover,
html[data-theme="light"] .sidebar-channel:hover,
html[data-theme="light"] .ms-dropdown-item:hover,
html[data-theme="light"] .context-menu-item:hover,
html[data-theme="light"] .rev-cm:hover,
html[data-theme="light"] .rev-menu-item:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] .sidebar-nav .nav-item.active,
html[data-theme="light"] .sidebar-channel.active{background:rgba(122,95,214,.12);color:var(--off-white)}
/* Sidebar footer nav links (HDrive / Trash) are bare <a> colored white-alpha →
   invisible on the now-white sidebar. Remap to dark text + dark-alpha hover/active. */
html[data-theme="light"] .sidebar-nav a,
html[data-theme="light"] #sidebarFooterNav a{color:var(--sec)}
html[data-theme="light"] .sidebar-nav a:hover,
html[data-theme="light"] #sidebarFooterNav a:hover{color:var(--off-white);background:rgba(0,0,0,.04)}
html[data-theme="light"] .sidebar-nav a.active{color:var(--off-white);background:rgba(122,95,214,.12)}
html[data-theme="light"] .sidebar-nav a svg{opacity:.85}
/* HANDOFF 4.5 — light mode needs DARK text in the sidebar (owner confirmed). The
   favourites, folders and their children were still painting --muted, which is tuned
   for the dark sidebar and is unreadable on a light one. --text-1/--text-2 are
   theme-aware, so this reads correctly in both. */
html[data-theme="light"] .sidebar-fav-nav a,
html[data-theme="light"] .sidebar-section-nav a,
html[data-theme="light"] .sidebar-cat-item,
html[data-theme="light"] #sidebarFooterNav a,
html[data-theme="light"] .sidebar-channel-name{color:var(--text-1)}
html[data-theme="light"] .sidebar-fav-nav a svg,
html[data-theme="light"] .sidebar-section-nav a svg,
html[data-theme="light"] .sidebar-cat-item svg,
html[data-theme="light"] #sidebarFooterNav a svg{opacity:.9}
html[data-theme="light"] .sidebar-fav-nav a.active,
html[data-theme="light"] .sidebar-section-nav a.active,
html[data-theme="light"] #sidebarFooterNav a.active,
html[data-theme="light"] .sidebar-cat-item.active{color:var(--text-1)}
/* Workspace switcher pill (over the gradient header): white-alpha card + white text
   → near-invisible on a white sidebar. Make it a solid white pill with dark text,
   per the mockup ("white workspace pill"). */
html[data-theme="light"] .sidebar-ws-card{background:#ffffff;border:1px solid var(--border-d);box-shadow:0 1px 3px rgba(0,0,0,.06)}
html[data-theme="light"] .sidebar-ws-card .sidebar-ws-main,
html[data-theme="light"] .sidebar-ws-id strong{color:var(--off-white)}
/* Sidebar banner fades to near-black (#0c0c0e) for the dark theme — on a white
   sidebar that reads as a dark smudge under the workspace pill. Fade to the light
   sidebar surface instead so the gradient header dissolves cleanly. */
html[data-theme="light"] .sidebar-banner-fade,
html[data-theme="light"] .sidebar-banner-gradient{background:linear-gradient(to bottom,transparent,#ffffff)}
/* Top bar + sidebar chrome */
html[data-theme="light"] .sidebar,
html[data-theme="light"] .global-right-sidebar{background:#ffffff;border-color:var(--border-d);color:var(--off-white)}
html[data-theme="light"] .topbar{background:var(--bg-canvas);border-color:var(--border-d);color:var(--off-white)}
html[data-theme="light"] .topbar-btn,
html[data-theme="light"] .ss-btn,
html[data-theme="light"] .admin-btn{background:#ffffff;border-color:rgba(0,0,0,.12);color:var(--cream)}
html[data-theme="light"] .topbar-btn:hover,
html[data-theme="light"] .ss-btn:hover{background:rgba(0,0,0,.04)}
/* Modal */
html[data-theme="light"] .card-modal,
html[data-theme="light"] .modal,
html[data-theme="light"] .ss-modal,
html[data-theme="light"] .rev-sheet{background:#ffffff;color:var(--off-white)}
html[data-theme="light"] .card-modal-overlay,
html[data-theme="light"] .modal-overlay{background:rgba(0,0,0,.35)}
/* Toast */
html[data-theme="light"] .kanban-col-name:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] .kanban-col-name:focus{background:rgba(0,0,0,.07)}
html[data-theme="light"] .kanban-add:hover{background:rgba(0,0,0,.04) !important}
/* Native form widgets (selects/date pickers) declare color-scheme:dark for the dark
   theme; flip them in light mode so the OS renders them light. */
html[data-theme="light"] .auto-sel,html[data-theme="light"] .auto-val-input,
html[data-theme="light"] .trash-purge-select,
html[data-theme="light"] .subtask-popup .card-prop-value input,
html[data-theme="light"] .subtask-popup .card-prop-value select,
html[data-theme="light"] .col-select,html[data-theme="light"] .wf-in,
html[data-theme="light"] .due-date-input{color-scheme:light;background:var(--bg-inset);color:var(--off-white)}
html[data-theme="light"] .toast{background:#ffffff;color:var(--off-white);box-shadow:0 8px 32px rgba(0,0,0,.18);border:1px solid var(--border-d)}
/* Settings panes */
html[data-theme="light"] .us-section{background:#ffffff;border-color:var(--border-d)}
html[data-theme="light"] .ss-section{background:transparent}
html[data-theme="light"][class] .ss-pane input,
html[data-theme="light"] .ss-pane textarea{background:#ffffff}
/* Mobile bottom nav */
html[data-theme="light"] .mobile-bottom-nav,
html[data-theme="light"] .m-tabbar{background:#ffffff;border-color:var(--border-d)}
/* #6 Liquid Glass (light) — translucent white-frosted hotbar + cal controls bar. */
html[data-theme="light"] body[data-mobile-mode="app"] .m-bottom-nav,
html[data-theme="light"] body[data-mobile-mode="app"] [data-cal-tab-nav]{
  background:rgba(248,249,251,.62);
  border-color:rgba(0,0,0,.08);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.55),0 -6px 24px rgba(0,0,0,.10);
}
/* No static background on the active item — the sliding .m-pill-thumb is the SOLE highlight
   (a bg here painted a second, static purple under the thumb = the "double purple" flash). */
html[data-theme="light"] .m-bottom-nav .is-active,
html[data-theme="light"] .m-tab.is-active{color:var(--purple)}
/* Review tab in light */
html[data-theme="light"] .rev-side,
html[data-theme="light"] .pub-rev-root{background:var(--bg-main)}
html[data-theme="light"] .rev-input,
html[data-theme="light"] #revShareUrl{background:#ffffff}
html[data-theme="light"] .rev-set-group,
html[data-theme="light"] .rev-anchor-toggle{background:#ffffff;border-color:var(--border-d)}
html[data-theme="light"] .rev-seg-group{background:rgba(0,0,0,.05)}
html[data-theme="light"] .rev-cm-chip,
html[data-theme="light"] .rev-marker{color:#1b1b1b}
/* Status pills / badges keep contrast (deeper saturation handled by var overrides) */
html[data-theme="light"] .rainbow-strip,
html[data-theme="light"] .strip-t,
html[data-theme="light"] .strip-b{opacity:.95}
/* Theme toggle (System / Dark / Light) — neutral surface works in both themes */
.theme-toggle{display:inline-flex;gap:4px;background:rgba(127,127,131,.14);border:0;border-radius:11px;padding:4px}
.theme-seg{font:600 13px var(--sans);color:var(--muted);background:none;border:none;border-radius:8px;padding:8px 18px;cursor:pointer;transition:background .15s,color .15s;-webkit-tap-highlight-color:transparent}
.theme-seg:hover{color:var(--cream)}
/* The sliding thumb is the highlight. The segment paints its own block only when the
   thumb is absent (reduced motion, or before the pill bar is wired). */
.theme-toggle:not(:has(.m-pill-thumb.show)) .theme-seg.on{background:var(--purple);color:#fff}
.theme-toggle:has(.m-pill-thumb.show) .theme-seg.on{background:transparent;color:#fff}
.theme-toggle .m-pill-thumb{background:var(--purple)}
.theme-toggle-note{font-size:12px;color:var(--muted);margin-top:10px;line-height:1.5}
/* ── Mobile Client Management (iOS rows, no spreadsheet) ── */
body[data-mobile-mode="app"] .cm-m{display:flex;flex-direction:column;gap:14px;padding:4px 2px 24px}
.cm-m-summary{display:flex;align-items:center;gap:14px;background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:14px;padding:16px 18px}
.cm-m-sum-big{font-family:var(--serif);font-size:34px;font-weight:700;color:var(--off-white);line-height:1}
.cm-m-sum-label{font-size:14px;color:var(--cream);font-weight:600}
.cm-m-sum-sub{font-size:12px;color:var(--muted);margin-top:2px}
.cm-m-search{display:flex;align-items:center;gap:8px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:11px;padding:0 12px}
.cm-m-search svg{width:17px;height:17px;color:var(--muted);flex-shrink:0}
.cm-m-search input{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--off-white);font:inherit;font-size:16px;padding:11px 0}
.cm-m-pills{display:flex;gap:8px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px}
.cm-m-pills::-webkit-scrollbar{display:none}
.cm-m-pill{flex-shrink:0;font:600 13px var(--sans);color:var(--muted);background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:999px;padding:7px 14px;cursor:pointer;-webkit-tap-highlight-color:transparent}
.cm-m-pill.on{background:var(--purple);color:#fff;border-color:var(--purple)}
.cm-m-sechead{display:flex;align-items:center;justify-content:space-between;padding:4px 6px 0}
.cm-m-sechead span{font-size:12px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.cm-m-onboard{font:600 13px var(--sans);color:var(--purple);background:var(--purple-soft);border:1px solid color-mix(in srgb,var(--purple) 40%,transparent);border-radius:999px;padding:6px 13px;cursor:pointer}
.cm-m-list{background:rgba(255,255,255,.04);border:1px solid var(--border-d);border-radius:14px;overflow:hidden}
.cm-m-row{display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;background:none;border:none;cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent}
.cm-m-row+.cm-m-row{border-top:1px solid rgba(255,255,255,.06)}
.cm-m-row:active{background:rgba(255,255,255,.04)}
.cm-m-av{flex-shrink:0;width:40px;height:40px;border-radius:50%;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;background:var(--purple-soft)}
.cm-m-av img{width:100%;height:100%;object-fit:cover}
.cm-m-av-emoji{font-size:20px;background:rgba(255,255,255,.06)}
.cm-m-row-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cm-m-row-name{font-size:15px;font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cm-m-row-sub{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cm-m-row-right{flex-shrink:0;display:flex;flex-direction:column;align-items:flex-end;gap:3px}
.cm-m-pkg{font:700 10px var(--sans);text-transform:uppercase;letter-spacing:.4px;color:var(--pk,var(--muted));background:color-mix(in srgb,var(--pk,var(--muted)) 14%,transparent);border-radius:5px;padding:2px 7px}
.cm-m-ret{font:600 12px var(--mono);color:var(--green)}
.cm-m-chev{flex-shrink:0;width:18px;height:18px;color:var(--muted)}
.cm-m-empty{padding:32px 16px;text-align:center;color:var(--muted);font-size:13px;font-style:italic}
/* ==================== Automations — Zapier-style flow builder ==================== */
.azp-pixlabel{font-family:var(--pixel);text-transform:uppercase;letter-spacing:.5px;color:var(--purple);font-size:10px;line-height:1.4}
.azp-pixlabel-sm{font-size:9px;margin:16px 0 8px;color:var(--muted)}
.azp-head{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.azp-head-title{font-family:var(--pixel);font-size:15px;letter-spacing:.5px;color:var(--off-white);text-shadow:2px 2px 0 rgba(0,0,0,.4)}
.auto-builder{max-width:680px}
.azp-editor{position:relative;margin-top:16px;border:1px solid var(--border-d);border-radius:14px;padding:22px 18px;background-color:rgba(255,255,255,.015);background-image:radial-gradient(rgba(255,255,255,.05) 1px,transparent 1px);background-size:22px 22px;background-position:-1px -1px}
.azp-chain{display:flex;flex-direction:column;align-items:center;gap:0;max-width:460px;margin:0 auto}
.azp-stepwrap{width:100%}
.azp-step-label{margin:0 0 6px 2px}
.azp-lbl-trigger{color:var(--gold)}
.azp-lbl-action{color:var(--purple)}
.azp-step{position:relative;display:flex;align-items:stretch;width:100%;border:1px solid var(--border-d);border-radius:12px;background:var(--dark);box-shadow:0 2px 8px rgba(0,0,0,.3);overflow:hidden;transition:border-color .15s,box-shadow .15s,transform .12s}
.azp-step:hover{border-color:rgba(140,114,219,.45);box-shadow:0 4px 16px rgba(0,0,0,.4)}
.azp-step-trigger:hover{border-color:rgba(231,206,58,.45)}
.azp-step-empty{border-style:dashed;background:rgba(255,255,255,.02)}
.azp-grip{display:flex;align-items:center;justify-content:center;width:24px;flex-shrink:0;color:var(--muted);cursor:grab;opacity:.5;transition:opacity .15s}
.azp-step:hover .azp-grip{opacity:.9}
.azp-grip:active{cursor:grabbing}
.azp-step-pick{flex:1;min-width:0;display:flex;align-items:center;gap:12px;padding:13px 12px;background:none;border:none;color:var(--cream);cursor:pointer;text-align:left;font-family:var(--sans)}
.azp-step-ico{flex-shrink:0;width:38px;height:38px;border-radius:9px;background:rgba(140,114,219,.12);display:flex;align-items:center;justify-content:center;font-size:19px;line-height:1}
.azp-step-trigger .azp-step-ico{background:rgba(231,206,58,.12)}
.azp-step-textwrap{min-width:0;display:flex;flex-direction:column;gap:2px}
.azp-step-title{font-size:14px;font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.azp-step-summary{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.azp-step-chev{flex-shrink:0;color:var(--muted);display:flex;align-items:center;padding-right:4px}
.azp-step-tools{display:flex;align-items:center;gap:1px;padding:0 6px;flex-shrink:0}
.azp-step-mv{width:22px;height:22px;border-radius:5px;border:none;background:none;color:var(--muted);cursor:pointer;font-size:12px;line-height:1;transition:background .12s,color .12s}
.azp-step-mv:hover:not([disabled]){background:var(--state-hover);color:var(--cream)}
.azp-step-mv[disabled]{opacity:.25;cursor:default}
.azp-step-del{width:24px;height:24px;border-radius:6px;border:none;background:none;color:var(--muted);cursor:pointer;font-size:17px;line-height:1;transition:background .12s,color .12s}
.azp-step-del:hover{background:rgba(239,68,68,.14);color:var(--danger-text)}
.azp-conn{display:flex;align-items:center;gap:8px;width:100%;max-width:200px;padding:8px 0}
.azp-conn-line{flex:1;height:0;border-top:2px dotted rgba(140,114,219,.4)}
.azp-conn-kw{font-family:var(--pixel);font-size:9px;letter-spacing:.5px;color:var(--purple);opacity:.9}
.azp-conn-and .azp-conn-line{border-color:rgba(255,255,255,.14)}
.azp-conn-and .azp-conn-kw{color:var(--muted)}
.azp-step-config{margin:8px 0 2px;padding:12px 14px;border:1px solid var(--border-d);border-left:2px solid rgba(140,114,219,.5);border-radius:0 10px 10px 0;background:rgba(255,255,255,.025);display:flex;flex-direction:column;gap:9px}
.azp-cfg-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.azp-cfg-lbl{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);min-width:78px}
.azp-cfg-ctl{flex:1;min-width:140px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.azp-cfg-note{font-size:11px;color:var(--muted);font-style:italic;line-height:1.5}
.azp-num{max-width:72px}
.azp-wide{flex:1;min-width:160px;max-width:none}
.azp-textarea{min-height:64px;resize:vertical;font-family:var(--sans);line-height:1.5}
.azp-varwrap{flex:1;display:flex;align-items:flex-start;gap:6px;min-width:160px}
.azp-var-btn{flex-shrink:0;font-family:var(--mono);font-size:12px;font-weight:700;padding:6px 9px;border-radius:7px;border:1px solid var(--border-d);background:rgba(140,114,219,.12);color:var(--purple);cursor:pointer;transition:background .12s}
.azp-var-btn:hover{background:rgba(140,114,219,.24)}
.azp-var-menu{position:fixed;z-index:10095;background:var(--dark);border:1px solid var(--border-d);border-radius:10px;box-shadow:0 12px 32px rgba(0,0,0,.55);padding:5px;max-height:280px;overflow-y:auto;min-width:230px}
.azp-var-item{display:flex;flex-direction:column;gap:1px;width:100%;padding:7px 10px;background:none;border:none;border-radius:6px;cursor:pointer;text-align:left}
.azp-var-item:hover{background:rgba(255,255,255,.06)}
.azp-var-item code{font-family:var(--mono);font-size:12px;color:var(--purple)}
.azp-var-item span{font-size:11px;color:var(--muted)}
.azp-add-step{margin-top:14px;padding:9px 16px;border:1px dashed rgba(140,114,219,.5);border-radius:9px;background:rgba(140,114,219,.06);color:var(--purple);cursor:pointer;transition:background .15s,border-color .15s}
.azp-add-step:hover{background:rgba(140,114,219,.16);border-color:var(--purple)}
.azp-picker-overlay{position:fixed;inset:0;z-index:10060;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px}
.azp-picker-sheet{width:100%;max-width:440px;max-height:80vh;display:flex;flex-direction:column;background:var(--dark);border:1px solid var(--border-d);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);overflow:hidden;animation:toastIn var(--dur-press) var(--ease-std)}
.azp-picker-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;border-bottom:1px solid var(--border-d)}
.azp-picker-title{font-size:11px}
.azp-picker-x{width:28px;height:28px;border-radius:7px;border:1px solid var(--border-d);background:none;color:var(--muted);cursor:pointer;font-size:18px;line-height:1}
.azp-picker-x:hover{color:var(--cream)}
.azp-picker-list{overflow-y:auto;padding:8px}
.azp-picker-item{display:flex;align-items:center;gap:12px;width:100%;padding:11px 12px;background:none;border:none;border-radius:10px;cursor:pointer;text-align:left;transition:background .12s}
.azp-picker-item:hover{background:rgba(140,114,219,.12)}
.azp-picker-ico{flex-shrink:0;width:36px;height:36px;border-radius:9px;background:rgba(255,255,255,.05);display:flex;align-items:center;justify-content:center;font-size:18px}
.azp-picker-txt{min-width:0;display:flex;flex-direction:column;gap:2px}
.azp-picker-name{font-size:14px;font-weight:600;color:var(--off-white);display:flex;align-items:center;gap:7px}
.azp-picker-desc{font-size:12px;color:var(--muted);line-height:1.4}
.azp-picker-badge{font-family:var(--pixel);font-size:7px;text-transform:uppercase;letter-spacing:.5px;color:var(--gold);background:rgba(231,206,58,.14);border-radius:4px;padding:2px 5px}
/* Page title: regular bold sans (matches Projects/Settings) — the pixel typeface is
   reserved for the small inline TRIGGER/ACTION/+ADD STEP labels (.azp-pixlabel) only. */
.azp-page-title{font-family:var(--sans);font-size:22px;font-weight:700;letter-spacing:-.2px;color:var(--off-white);text-shadow:none;margin:0}
.azp-empty-pix{font-family:var(--pixel);font-size:13px;letter-spacing:.5px;color:var(--purple);line-height:1.8}
/* ── Automations page — iOS-grouped, mobile-friendly chrome (.azp-page wraps the page
   whether it renders on the standalone tab or inside a project tab) ── */
.azp-head-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.azp-head-titles{display:flex;flex-direction:column;gap:2px;min-width:0}
.azp-head-sub{font-size:12px;color:var(--muted);line-height:1.4}
.azp-head-actions{display:flex;align-items:center;gap:8px;margin-left:auto;flex-wrap:wrap}
.azp-search{width:200px;padding:9px 12px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.04);color:var(--cream);font-size:13px;font-family:var(--sans)}
.azp-search:focus{outline:none;border-color:var(--coral)}
.azp-head-btn{display:inline-flex;align-items:center;gap:6px;padding:9px 14px;border-radius:10px;font-size:13px;font-weight:600;white-space:nowrap}
.azp-head-btn svg{width:15px;height:15px}
.azp-tab-body{padding:0 2px 24px}
/* Empty state */
.azp-empty-icon{width:56px;height:56px;margin:8px auto 4px;border-radius:16px;display:flex;align-items:center;justify-content:center;background:rgba(140,114,219,.12);color:var(--purple,#8c72db)}
.azp-empty-icon svg{width:28px;height:28px}
.azp-empty-title{font-family:var(--sans);font-size:17px;font-weight:700;color:var(--off-white);margin:10px 0 6px}
.azp-empty-hint{font-size:13px;color:var(--muted);max-width:420px;margin:0 auto 18px;line-height:1.6}
.azp-empty-actions{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
/* Mobile: stack the header, full-width search, scrolling pill tabs (matches the rest of
   the app's mobile pill bars). Applies on BOTH the standalone page and the project tab. */
body[data-mobile-mode="app"] .azp-page{padding:4px 14px 0}
body[data-mobile-mode="app"] .azp-head-bar{flex-direction:column;align-items:stretch;gap:10px}
body[data-mobile-mode="app"] .azp-head-actions{margin-left:0;gap:8px}
body[data-mobile-mode="app"] .azp-search{flex:1;width:auto;order:-1}
body[data-mobile-mode="app"] .azp-head-actions .azp-head-btn{flex:1;justify-content:center}
body[data-mobile-mode="app"] .azp-tabs{display:flex;gap:8px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;border-bottom:0;padding:4px 0 14px;margin:0}
body[data-mobile-mode="app"] .azp-tabs::-webkit-scrollbar{height:0}
body[data-mobile-mode="app"] .azp-tabs .page-tab{flex:0 0 auto;white-space:nowrap;border-radius:999px;padding:8px 16px;font-size:13px;font-weight:600}
html[data-theme="light"] .azp-empty-icon{background:rgba(140,114,219,.12)}
@media (max-width:600px){
  .azp-picker-overlay{align-items:flex-end;padding:0}
  .azp-picker-sheet{max-width:100%;max-height:88vh;border-radius:16px 16px 0 0}
  .azp-chain{max-width:100%}
  .azp-cfg-lbl{min-width:64px}
}
/* ── Automation templates: sheet + cards + tag pills ── */
.azp-tmpl-controls{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}
.azp-tmpl-search{width:100%;padding:10px 14px;border:1px solid var(--border-d);border-radius:10px;background:rgba(255,255,255,.04);color:var(--cream);font-size:13px;font-family:var(--sans);box-sizing:border-box}
.azp-tmpl-search:focus{outline:none;border-color:var(--purple)}
.azp-tmpl-pills{display:flex;gap:7px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none}
.azp-tmpl-pills::-webkit-scrollbar{display:none}
.azp-tmpl-pill{flex-shrink:0;padding:6px 13px;border-radius:999px;border:1px solid var(--border-d);background:rgba(255,255,255,.03);color:var(--muted);font-size:12px;font-family:var(--sans);cursor:pointer;white-space:nowrap;transition:background .12s,color .12s,border-color .12s}
.azp-tmpl-pill:hover{color:var(--cream);border-color:rgba(140,114,219,.4)}
.azp-tmpl-pill.active{background:rgba(140,114,219,.18);border-color:var(--purple);color:var(--off-white)}
.azp-tmpl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}
.azp-tmpl-card{border:1px solid var(--border-d);border-radius:12px;padding:15px 16px;background:rgba(255,255,255,.02);cursor:pointer;transition:border-color .15s,background .15s,transform .12s;display:flex;flex-direction:column;gap:8px}
.azp-tmpl-card:hover{border-color:rgba(140,114,219,.5);background:rgba(140,114,219,.06);transform:translateY(-2px)}
.azp-tmpl-top{display:flex;align-items:center;gap:10px}
.azp-tmpl-ico{flex-shrink:0;width:34px;height:34px;border-radius:9px;background:rgba(140,114,219,.12);display:flex;align-items:center;justify-content:center;font-size:17px}
.azp-tmpl-name{font-family:var(--pixel);font-size:10px;letter-spacing:.3px;line-height:1.5;color:var(--off-white)}
.azp-tmpl-desc{font-size:12px;color:var(--muted);line-height:1.5;flex:1}
.azp-tmpl-tags{display:flex;flex-wrap:wrap;gap:5px}
.azp-tmpl-tag{font-family:var(--pixel);font-size:7px;text-transform:uppercase;letter-spacing:.4px;color:var(--purple);background:rgba(140,114,219,.13);border-radius:4px;padding:3px 6px;line-height:1.4}
.azp-tmpl-tag-custom{color:var(--gold);background:rgba(231,206,58,.14)}
.azp-tmpl-sheet{width:100%;max-width:760px;max-height:85vh;display:flex;flex-direction:column;background:var(--dark);border:1px solid var(--border-d);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);overflow:hidden;animation:toastIn var(--dur-press) var(--ease-std)}
.azp-tmpl-sheet-body{overflow-y:auto;padding:18px}
@media (max-width:600px){
  .azp-tmpl-overlay{align-items:flex-end;padding:0}
  .azp-tmpl-sheet{max-width:100%;max-height:90vh;border-radius:16px 16px 0 0}
  .azp-tmpl-grid{grid-template-columns:1fr}
}
/* ── Save-as-template + import + template menu ── */
.azp-tmpl-menu-btn{margin-left:auto;flex-shrink:0;width:24px;height:24px;border-radius:6px;border:none;background:none;color:var(--muted);cursor:pointer;font-size:16px;line-height:1;transition:background .12s,color .12s}
.azp-tmpl-menu-btn:hover{background:var(--state-hover);color:var(--cream)}
.azp-tmpl-menu-item{display:block;width:100%;padding:8px 12px;background:none;border:none;border-radius:6px;cursor:pointer;text-align:left;font-size:13px;color:var(--cream);font-family:var(--sans)}
.azp-tmpl-menu-item:hover{background:rgba(255,255,255,.06)}
.azp-tmpl-menu-item.danger{color:var(--peach,#df8a83)}
.azp-tmpl-menu-item.danger:hover{background:rgba(223,138,131,.12)}
.azp-menu-ico{display:flex !important;align-items:center;gap:9px}
.azp-menu-ico svg{flex:none;opacity:.8}
.azp-savetmpl{width:100%;max-width:440px;display:flex;flex-direction:column;background:var(--dark);border:1px solid var(--border-d);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);overflow:hidden;animation:toastIn var(--dur-press) var(--ease-std)}
.azp-savetmpl-body{padding:18px;display:flex;flex-direction:column;gap:10px}
.azp-savetmpl-lbl{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin-top:4px}
.azp-savetmpl-foot{display:flex;justify-content:flex-end;gap:8px;margin-top:8px}
.azp-import-card{border:1px solid var(--border-d);border-radius:12px;padding:15px 16px;background:rgba(140,114,219,.06);display:flex;flex-direction:column;gap:8px}
@media (max-width:600px){
  .azp-savetmpl{max-width:100%;border-radius:16px 16px 0 0}
}
/* property context-menu subheader (visibility section) */
.prop-ctx-menu .ctx-subhead{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);padding:5px 12px 3px}
/* ── Automation trigger tag picker (Card tagged) ── */
.azp-tagpick{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.azp-tagpick-any{font-size:12px;color:var(--muted);font-style:italic}
.azp-tagchip{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--cream);background:rgba(140,114,219,.14);border:1px solid rgba(140,114,219,.3);padding:3px 5px 3px 9px;border-radius:8px}
.azp-tagchip-x{background:none;border:none;color:var(--muted);cursor:pointer;font-size:14px;line-height:1;padding:0 1px;border-radius:4px}
.azp-tagchip-x:hover{color:var(--peach,#df8a83)}
.azp-tagchip-add{background:none;border:1px dashed var(--border-d);color:var(--muted);font-family:var(--sans);font-size:12px;padding:4px 10px;border-radius:8px;cursor:pointer;transition:border-color .15s,color .15s}
.azp-tagchip-add:hover{border-color:var(--purple,#8c72db);color:var(--purple,#8c72db)}
.azp-tag-menu{min-width:210px}
.azp-tag-input{width:100%;box-sizing:border-box;padding:7px 10px;margin-bottom:4px;border:1px solid var(--border-d);border-radius:7px;background:rgba(255,255,255,.05);color:var(--cream);font-family:var(--sans);font-size:13px}
.azp-tag-input:focus{outline:none;border-color:var(--purple,#8c72db)}
/* ── Automation row ⋯ options menu ── */
.azp-rule-menu{min-width:172px;z-index:10070}
.auto-rule-more svg{display:block}
/* ── Reusable shimmer skeleton rows ──
   Geometry only. The shimmer itself comes from the shared design-rules loader
   block ("Loading skeletons") further down — .skl-c is listed in its selector. */
.skl-list{display:flex;flex-direction:column}
.skl-row{display:flex;align-items:center;gap:12px;padding:14px 16px;border-bottom:1px solid var(--border-d)}
.skl-row:last-child{border-bottom:none}
.skl-row-comment{align-items:flex-start}
.skl-c{display:block;border-radius:6px}
.skl-avatar{width:34px;height:34px;border-radius:9px;flex-shrink:0}
.skl-row-comment .skl-avatar{border-radius:50%}
.skl-bar{height:13px}
.skl-bar-sm{height:10px;margin-top:7px}
.skl-chev{width:7px;height:12px;margin-left:auto;flex-shrink:0;border-radius:3px}
.skl-lines{flex:1;display:flex;flex-direction:column}
/* Staggered fade-in when real rows replace the skeleton */
@keyframes mProjFadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.m-proj-fadein .m-project-swipe{animation:mProjFadeIn .2s ease both}
.m-proj-fadein .m-project-swipe:nth-child(1){animation-delay:0ms}
.m-proj-fadein .m-project-swipe:nth-child(2){animation-delay:30ms}
.m-proj-fadein .m-project-swipe:nth-child(3){animation-delay:60ms}
.m-proj-fadein .m-project-swipe:nth-child(4){animation-delay:90ms}
.m-proj-fadein .m-project-swipe:nth-child(5){animation-delay:120ms}
.m-proj-fadein .m-project-swipe:nth-child(6){animation-delay:150ms}
.m-proj-fadein .m-project-swipe:nth-child(7){animation-delay:180ms}
.m-proj-fadein .m-project-swipe:nth-child(n+8){animation-delay:210ms}
@media(prefers-reduced-motion:reduce){.skl-row{animation:none;opacity:.45}.m-proj-fadein .m-project-swipe{animation:none}}
/* ── Modify Project sheet (mobile): project info + column editing ── */
.mpc-sheet .rev-sheet-body{padding:14px 16px 28px}
.mpc-label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin:16px 2px 7px}
.mpc-label:first-child{margin-top:2px}
.mpc-group{background:rgba(255,255,255,.03);border:1px solid var(--border-d);border-radius:12px;overflow:hidden}
.mpc-info-row{display:flex;align-items:center;gap:10px;padding:10px 12px}
.mpc-icon-btn{flex-shrink:0;width:38px;height:38px;border-radius:9px;border:1px solid var(--border-d);background:rgba(255,255,255,.04);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;padding:0;overflow:hidden}
.mpc-icon-btn img,.mpc-icon-btn svg{width:30px;height:30px;border-radius:7px}
.mpc-name-input{flex:1;min-width:0;background:none;border:0;color:var(--off-white);font-size:15px;font-weight:600;font-family:var(--sans);outline:none;padding:6px 0}
.mpc-swatches{display:flex;flex-wrap:wrap;gap:8px;padding:4px 12px 12px}
.mpc-swatch{width:24px;height:24px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;transition:transform .1s}
.mpc-swatch.on{border-color:#fff;transform:scale(1.08)}
.mpc-swatch:active{transform:scale(.92)}
.mpc-cols{display:flex;flex-direction:column}
.mpc-col-row{display:flex;align-items:center;gap:6px;padding:7px 10px;border-bottom:1px solid var(--border-d)}
.mpc-col-row:last-child{border-bottom:none}
.mpc-grip{flex-shrink:0;width:20px;display:flex;align-items:center;justify-content:center;color:var(--muted);cursor:grab;opacity:.6}
.mpc-col-dot{flex-shrink:0;width:20px;height:20px;border-radius:50%;border:1px solid rgba(255,255,255,.18);cursor:pointer;padding:0}
.mpc-col-name{flex:1;min-width:0;background:none;border:0;border-bottom:1px solid transparent;color:var(--cream);font-size:14px;font-family:var(--sans);outline:none;padding:6px 2px}
.mpc-col-name:focus{border-bottom-color:var(--purple)}
.mpc-col-mv{flex-shrink:0;width:26px;height:30px;border:0;background:none;color:var(--muted);font-size:13px;cursor:pointer;border-radius:6px}
.mpc-col-mv:active:not([disabled]){background:var(--state-hover)}
.mpc-col-mv[disabled]{opacity:.25}
.mpc-col-del{flex-shrink:0;width:30px;height:30px;border:0;background:none;color:var(--muted);font-size:19px;line-height:1;cursor:pointer;border-radius:6px}
.mpc-col-del:active{background:rgba(239,68,68,.16);color:var(--danger-text)}
.mpc-add-col{width:100%;margin-top:8px;padding:11px;border:1px dashed var(--border-d);border-radius:10px;background:none;color:var(--purple);font-size:14px;font-weight:600;font-family:var(--sans);cursor:pointer}
.mpc-add-col:active{background:rgba(140,114,219,.1)}
/* ════════ Light theme: kill remaining dark-residue surfaces (mobile header, cards,
   status pills, switcher, Modify-Project sheet). These beat hardcoded !important darks. ════════ */
/* Mobile top bar — was a hardcoded near-black gradient with no light override. */
html[data-theme="light"] body[data-mobile-mode="app"] .m-app-header{
  /* #6 Liquid Glass (light) — white-frosted, translucent so content shows through. */
  background:rgba(255,255,255,.62) !important;
  border-bottom-color:rgba(0,0,0,.08) !important;
  /* #27 — flat in light mode: drop the 0 6px 24px outer shadow, keep only the hairline. */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.55) !important;
}
html[data-theme="light"] .m-app-header-title{color:var(--off-white)}
html[data-theme="light"] .m-app-brand-chev,
html[data-theme="light"] .m-header-search-btn{color:var(--cream)}
/* Kanban cards — the "polish batch" forced background:#141417 !important; flip to white. */
html[data-theme="light"] .kanban-card{
  background:#ffffff !important;
  border:1px solid var(--border-d) !important;
  box-shadow:0 1px 3px rgba(0,0,0,.08) !important;
  color:var(--off-white) !important;
}
html[data-theme="light"] .kanban-card:hover{box-shadow:0 4px 14px rgba(0,0,0,.12) !important}
html[data-theme="light"] .kanban-card-text{color:var(--off-white) !important}
html[data-theme="light"] .kanban-card-text .card-desc,
html[data-theme="light"] .kanban-card-text .kanban-card-desc,
html[data-theme="light"] .kanban-card-comments,
html[data-theme="light"] .kanban-card-meta{color:var(--muted) !important}
html[data-theme="light"] .card-avatar,
html[data-theme="light"] .card-avatar-overflow{border-color:#ffffff !important}
html[data-theme="light"] .kanban-card-cl-bar,
html[data-theme="light"] .kanban-card-subtask-progress .subtask-bar{background:rgba(0,0,0,.08) !important}
/* Status pills inside cards / calendar — white-alpha bg vanishes on white; use dark-alpha. */
html[data-theme="light"] .kanban-card .cdc-status,
html[data-theme="light"] .cdc-status,
html[data-theme="light"] .status-badge{background:rgba(0,0,0,.06);color:var(--cream)}
/* Workspace switcher menu + client picker. */
html[data-theme="light"] .client-switch-menu,
html[data-theme="light"] .board-switch-overlay .board-switch-sheet,
html[data-theme="light"] .cw-dropdown,
html[data-theme="light"] .prop-ctx-menu{background:#ffffff;border-color:var(--border-d);box-shadow:0 8px 28px rgba(0,0,0,.14)}
/* Spotlight overlay + its input. */
html[data-theme="light"] #spotlightOverlay{background:rgba(0,0,0,.32)}
html[data-theme="light"] #spotlightOverlay .spotlight-box,
html[data-theme="light"] #spotlightOverlay input{background:#ffffff;color:var(--off-white)}
/* Mobile confirm alert. */
html[data-theme="light"] .m-alert-overlay .m-alert-card{background:#ffffff;color:var(--off-white)}
/* Modify Project sheet content (mpc-*) — flip white-alpha surfaces to hairline-on-white. */
html[data-theme="light"] .mpc-group{background:#ffffff;border-color:var(--border-d)}
html[data-theme="light"] .mpc-icon-btn{background:rgba(0,0,0,.03)}
html[data-theme="light"] .mpc-name-input,
html[data-theme="light"] .mpc-col-name{color:var(--off-white)}
/* Mobile pill tabs (home / stage) — sticky bar bg + pills read on a light page. */
/* #11 — home tab bar matches the page canvas (no off-white band); stage bar keeps board bg. */
html[data-theme="light"] .m-home-tabs{background:var(--bg-main);border-bottom-color:var(--border-d)}
html[data-theme="light"] .m-stage-bar{background:var(--bg-board);border-bottom-color:var(--border-d)}
/* #23 — in light mode the soft-purple (#a78bfa) sliding pill washed out against the light
   board surface, so the active-tab indicator was nearly invisible. Use the solid brand
   purple for the pill + white active-tab text so the sliding selection clearly reads. */
html[data-theme="light"] body[data-mobile-mode="app"] .m-home-tabs .m-pill-thumb,
html[data-theme="light"] body[data-mobile-mode="app"] .m-stage-bar .m-pill-thumb,
html[data-theme="light"] body[data-mobile-mode="app"] #mTaskTabs .m-pill-thumb{background:var(--m-accent,#7c5cff)}
html[data-theme="light"] body[data-mobile-mode="app"] .m-home-tab.is-active,
html[data-theme="light"] body[data-mobile-mode="app"] .m-stage-pill.is-active,
html[data-theme="light"] body[data-mobile-mode="app"] .m-task-tab.is-active{color:#fff}
html[data-theme="light"] body[data-mobile-mode="app"] .m-home-tab.is-active .m-home-tab-ct,
html[data-theme="light"] body[data-mobile-mode="app"] .m-stage-pill.is-active .m-stage-ct{background:rgba(255,255,255,.22);color:#fff}
/* ── Light theme: project list rows (were hardcoded #141312 opaque → black on a light page) ── */
html[data-theme="light"] body[data-mobile-mode="app"] .m-projects-list{background:var(--bg2);border-color:rgba(0,0,0,.09)}
html[data-theme="light"] body[data-mobile-mode="app"] .m-project-swipe:not(:last-child){border-bottom-color:rgba(0,0,0,.06)}
html[data-theme="light"] body[data-mobile-mode="app"] .m-projects-list .m-project-row{background:var(--bg2);color:var(--ink-solid)}
/* Same layered-press rule as dark (see the note by the dark :active): the tint
   goes ON TOP of the opaque fill so the swipe drawer can't show through. */
html[data-theme="light"] body[data-mobile-mode="app"] .m-projects-list .m-project-row:active{
  background:linear-gradient(rgba(0,0,0,.04),rgba(0,0,0,.04)),var(--bg2);
}
html[data-theme="light"] .m-project-row{background:#ffffff;color:var(--off-white)}
html[data-theme="light"] .m-project-icon{background:rgba(0,0,0,.05);color:var(--cream)}
/* Light mode used to fall to the neutral grey tile above (equal specificity, later in the
   file, so it won on mobile too) — the accent disappeared entirely. Keep the same accent
   here, with a denser glyph so it holds contrast against a white row. */
html[data-theme="light"] body[data-mobile-mode="app"] .m-project-icon{
  background:color-mix(in srgb,var(--proj-accent,var(--m-accent)) 14%,#ffffff);
  color:color-mix(in srgb,var(--proj-accent,var(--m-accent)) 80%,#000000)
}
html[data-theme="light"] .m-project-chev{color:var(--muted)}
/* ── Drag-to-dismiss handles: take over the gesture (no native scroll / pull-to-refresh) ── */
body[data-mobile-mode="app"] .rev-sheet-grip,
body[data-mobile-mode="app"] .rev-sheet-head,
body[data-mobile-mode="app"] [data-sheet-handle]{touch-action:none}
/* Beefier invisible grab target around the grip pill */
body[data-mobile-mode="app"] .rev-sheet-grip{position:relative;cursor:grab}
body[data-mobile-mode="app"] .rev-sheet-grip::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:120px;height:26px}
/* ════════ Light theme — round 7 dark-residue sweep ════════
   ~20 components still painted with hardcoded near-black surfaces (no light override),
   so they stayed black boxes on a white page. Scoped overrides only — DARK mode untouched.
   Grouped: floating menus/popovers → A; panels/cards/inputs → B; mobile full-screen
   surfaces (#0a0a09, !important base) → C; misc (drop target, spotlight rows) → D. */
/* A — floating menus / popovers / dropdowns / pickers (#111110/#15151a/#1a1a19/#121211 → white) */
html[data-theme="light"] .server-dropdown,
html[data-theme="light"] .mv-filter-panel,
html[data-theme="light"] .voice-rec-indicator,
html[data-theme="light"] .cal-day-popover,
html[data-theme="light"] .sidebar-clients-menu,
html[data-theme="light"] .add-prop-popover{background:#ffffff;border-color:var(--border-d);box-shadow:0 8px 28px rgba(0,0,0,.14);color:var(--off-white)}
/* mobile property bottom-sheets (base sets #15151a !important) */
html[data-theme="light"] body[data-mobile-mode="app"] .prop-person-dropdown,
html[data-theme="light"] body[data-mobile-mode="app"] .prop-multi-dropdown,
html[data-theme="light"] body[data-mobile-mode="app"] .prop-color-picker,
html[data-theme="light"] body[data-mobile-mode="app"] .prop-type-picker,
html[data-theme="light"] body[data-mobile-mode="app"] .prop-ctx-menu{background:#ffffff !important;border-color:var(--border-d) !important;color:var(--off-white)}
/* B — panels / cards / form inputs */
html[data-theme="light"] .gv-flat-table{background:#ffffff}
html[data-theme="light"] .gv-flat-header{background:#ffffff !important;border-bottom-color:var(--hairline-2) !important}
/* List-view STATUS pill (.gv-status-text) hardcodes a dark #1c1c20 blend → reads as a
   dark column on a light page. Re-blend the status color into a LIGHT base, and darken
   the text so the label AND any glyph/icon inside the pill stay legible (the icon inherits
   currentColor). Mirrors the user's fix: dark icon/text on the active light pill. */
html[data-theme="light"] .gv-status-text{
  background:color-mix(in srgb, var(--gv-status-color, #888) 16%, #ffffff);
  color:color-mix(in srgb, var(--gv-status-color, #888) 70%, #1a1a1a)
}
html[data-theme="light"] .gv-flat-cell-status:hover .gv-status-text{
  background:color-mix(in srgb, var(--gv-status-color, #888) 26%, #ffffff)
}
html[data-theme="light"] .gv-status-text svg{color:currentColor;stroke:currentColor;fill:none}
/* Status picker popover: keep the active row's label + bullseye dot legible on the
   white light-theme popover (active color was the raw status hue, low-contrast on white). */
html[data-theme="light"] .gv-edit-popover .gv-sp-row.is-active{
  color:color-mix(in srgb, var(--gv-row-color, #888) 70%, #1a1a1a)
}
html[data-theme="light"] .gv-edit-popover .gv-sp-row svg{color:currentColor;stroke:currentColor}
/* Generic select/status value pill inside a list cell — ensure any inline icon inherits
   the pill's (dark, on light) text color rather than staying white/invisible. */
html[data-theme="light"] .gv-flat-cell .prop-pill svg{color:currentColor;stroke:currentColor}
html[data-theme="light"] .rev-side{background:#ffffff;border-color:var(--border-d)}
html[data-theme="light"] .hi-ai-prompt,
html[data-theme="light"] .hi-ai-recap{background:#ffffff;border-color:var(--border-d)}
html[data-theme="light"] .sch-account-chip{background:#ffffff;border-color:var(--border-d);color:var(--cream)}
html[data-theme="light"] .sch-account-chip.on{background:color-mix(in srgb,var(--pc) 8%,#ffffff)}
html[data-theme="light"] .sch-account-add,
html[data-theme="light"] .sch-manager-account,
html[data-theme="light"] .sch-platform-choice,
html[data-theme="light"] .sch-option-card,
html[data-theme="light"] .sch-loading,
html[data-theme="light"] .sch-drop-locked,
html[data-theme="light"] .sch-job{background:rgba(0,0,0,.025)}
html[data-theme="light"] .sch-media-meta{background:#f1f1f4}
html[data-theme="light"] .feature-req-form input,
html[data-theme="light"] .feature-req-form textarea,
html[data-theme="light"] .feature-req-form select{background:#ffffff;border-color:rgba(0,0,0,.14);color:var(--off-white)}
/* C — mobile full-screen task card + comments sheet + property full-sheet (#0a0a09, !important base) */
html[data-theme="light"] body[data-mobile-mode="app"] .card-modal{background:#ffffff !important}
html[data-theme="light"] body[data-mobile-mode="app"] .card-modal-overlay{background:rgba(0,0,0,.35) !important}
html[data-theme="light"] #mCommentsSheet{background:#ffffff}
/* Comments slide-up sheet was pure black (#0a0a09 panel) on a light page. Light-theme the
   panel surface, the drag grip, the sticky input bar, and the inner comment labels/empty/
   icons (currentColor) so the whole sheet reads light. Mobile only. */
html[data-theme="light"] #mCommentsSheet .m-csheet-panel{background:#ffffff;border-top-color:var(--border-d)}
html[data-theme="light"] #mCommentsSheet .m-csheet-grip{background:rgba(0,0,0,.2)}
html[data-theme="light"] #mCommentsSheet .m-csheet-head{border-bottom-color:var(--border-d)}
html[data-theme="light"] #mCommentsSheet .m-csheet-title,
html[data-theme="light"] #mCommentsSheet .m-csheet-x{color:var(--off-white)}
html[data-theme="light"] body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput{background:#ffffff}
html[data-theme="light"] #mCommentsSheet .m-csheet-body{color:var(--off-white)}
html[data-theme="light"] #mCommentsSheet .m-csheet-body svg{color:currentColor;stroke:currentColor}
html[data-theme="light"] .m-fsheet{background:#ffffff}
/* Mobile property-picker bottom-sheet hardcodes background:#15151a !important
   (L6095) with white-alpha button hovers → dark sheet on a light mobile app. */
html[data-theme="light"] body[data-mobile-mode="app"] .prop-ctx-menu{background:#ffffff !important;box-shadow:0 -8px 32px rgba(0,0,0,.18),0 0 0 1px rgba(0,0,0,.06) !important}
html[data-theme="light"] body[data-mobile-mode="app"] .prop-ctx-menu button:active{background:rgba(0,0,0,.06)}
/* Kanban columns + List-view table hardcode background:#0e0e10 !important (the
   "TaskWhiz board theme" block, L8646 / L10952) which beats the --dark token in
   light mode → dark columns/table on a light board. Override with !important. */
html[data-theme="light"] .kanban-col{background:#ffffff !important;border:1px solid var(--border-d) !important}
html[data-theme="light"] .kanban-col-ghost{background:transparent !important;border:1px dashed rgba(0,0,0,.18) !important}
html[data-theme="light"] .gv-flat-table{background:#ffffff !important;box-shadow:0 1px 3px rgba(0,0,0,.06)}
/* D — misc: kanban column drop-target highlight + Spotlight result rows */
html[data-theme="light"] .kanban-col.drop-target{background:rgba(122,95,214,.10) !important}
html[data-theme="light"] .spotlight-item:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] body[data-mobile-mode="app"] .spotlight-item{background:rgba(0,0,0,.03)}
html[data-theme="light"] body[data-mobile-mode="app"] .spotlight-item+.spotlight-item{border-top-color:rgba(0,0,0,.07)}
/* Desktop spotlight: item icon was white-on-white; footer/esc keys had white-alpha chrome */
html[data-theme="light"] .spotlight-item-icon{background:rgba(0,0,0,.05);color:var(--muted)}
html[data-theme="light"] .spotlight-esc-kbd,
html[data-theme="light"] .spotlight-footer-key{background:rgba(0,0,0,.05);border-color:var(--border-d)}
html[data-theme="light"] .spotlight-footer{border-top-color:var(--border-d)}
/* Notifications panel: container + text are tokenized; only the white-alpha hover needs flipping */
html[data-theme="light"] .notif-item:hover{background:rgba(0,0,0,.04)}
html[data-theme="light"] .global-right-sidebar-header button:hover{background:rgba(0,0,0,.05);color:var(--off-white)}
/* ════════ Light theme — round 2 sweep (task-nav bar, view tooltip, status pills) ════════ */
/* Mobile task-detail bottom nav (Sub-tasks / Back / Properties) — hardcoded near-black. */
html[data-theme="light"] body[data-mobile-mode="app"] #mTaskNav.open{
  background:rgba(255,255,255,.92) !important;border-top-color:rgba(0,0,0,.08) !important;
}
/* View-switcher hover tooltip (was #0c0c0e) — flip to a light chip with dark text. */
html[data-theme="light"] .ws-view-tab::before{background:#ffffff;color:var(--off-white);box-shadow:0 6px 18px rgba(0,0,0,.16)}
/* Status pill (home/mention task rows): white-alpha bg vanishes on a white page → dark-alpha. */
html[data-theme="light"] .mv-task-status{background:rgba(0,0,0,.06);color:var(--off-white)}
/* Calendar bottom controls: the month-nav/view-toggle pill group reads on a light page. */
html[data-theme="light"] .cal-month-nav{border-color:var(--border-d)}
html[data-theme="light"] .cal-month-nav .workshop-view-btn:hover{background:rgba(0,0,0,.05) !important}

/* ── Project folders (mobile Projects list grouping) ── */
.m-projects-head{position:relative}
.m-projects-newfolder{
  position:absolute;right:12px;top:6px;display:inline-flex;align-items:center;gap:5px;
  padding:6px 11px;border-radius:999px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.05);color:var(--cream);font-family:var(--sans);
  font-size:12px;font-weight:600;cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.m-projects-newfolder:active{background:rgba(255,255,255,.1)}
.m-projects-newfolder svg{width:15px;height:15px}
body[data-mobile-mode="app"] .m-folder-row{
  position:relative;display:flex;align-items:center;background:#1b1916;
  border-bottom:1px solid var(--border-d);
}
body[data-mobile-mode="app"] .m-folder-toggle{
  flex:1;min-width:0;display:flex;align-items:center;gap:12px;
  padding:11px 4px 11px 14px;background:none;border:0;cursor:pointer;
  color:var(--off-white);font-family:var(--sans);font-size:15px;font-weight:600;text-align:left;
  -webkit-tap-highlight-color:transparent;
}
body[data-mobile-mode="app"] .m-folder-toggle:active{background:rgba(255,255,255,.05)}
.m-folder-caret{width:16px;height:16px;flex-shrink:0;color:var(--muted);display:inline-flex;align-items:center;justify-content:center}
.m-folder-caret svg{width:16px;height:16px}
.m-folder-ico{color:var(--gold)}
.m-folder-emoji{font-size:18px;line-height:1}
.m-folder-count{
  margin-left:auto;flex-shrink:0;min-width:20px;text-align:center;
  font-size:12px;font-weight:700;color:var(--muted);
  background:rgba(255,255,255,.07);border-radius:999px;padding:1px 7px;
}
.m-folder-opts{
  flex-shrink:0;width:40px;align-self:stretch;display:flex;align-items:center;justify-content:center;
  background:none;border:0;color:var(--muted);cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.m-folder-opts svg{width:18px;height:18px}
.m-folder-opts:active{color:var(--off-white)}
/* Nested project row — indent the content; the swipe area + action pills stay full width. */
body[data-mobile-mode="app"] .m-proj-nested .m-project-row{padding-left:34px}
body[data-mobile-mode="app"] .m-proj-nested .m-project-icon{transform:scale(.92)}
.m-folder-name-input{
  width:100%;box-sizing:border-box;padding:11px 13px;border-radius:10px;
  border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--off-white);
  font-family:var(--sans);font-size:15px;outline:none;
}
.m-folder-name-input:focus{border-color:var(--coral)}
.m-folder-check{margin-left:auto;color:var(--green);font-weight:700}
/* Light theme */
html[data-theme="light"] body[data-mobile-mode="app"] .m-folder-row{background:#efece6;border-bottom-color:rgba(0,0,0,.08)}
html[data-theme="light"] body[data-mobile-mode="app"] .m-folder-toggle{color:#1a1a17}
html[data-theme="light"] body[data-mobile-mode="app"] .m-folder-toggle:active{background:rgba(0,0,0,.04)}
html[data-theme="light"] .m-folder-count{background:rgba(0,0,0,.07);color:#55504a}
html[data-theme="light"] .m-projects-newfolder{background:rgba(0,0,0,.04);color:#33302b;border-color:rgba(0,0,0,.12)}
html[data-theme="light"] .m-folder-name-input{background:#fff;color:#1a1a17}
/* Light theme: text that hardcodes color:var(--white) (which stays #fff in light) and sits
   on a now-LIGHT surface was rendering invisible — the board/Home project title vanished
   (#2) and the Home Unscheduled rows showed empty check-circles with no titles (#3). Remap
   those text elements to the theme-aware primary text. Dark mode is untouched (scoped). */
html[data-theme="light"] .ws-page-title,
html[data-theme="light"] .ws-page-title-input,
html[data-theme="light"] .ws-crumb-last,
html[data-theme="light"] .ws-title-icon,
html[data-theme="light"] .hi-task{color:var(--off-white)}
/* Home "Good morning" dashboard — greeting + card titles + stat numbers + task/mention
   rows all render primary text via color:var(--white), which stays #fff in light mode →
   white-on-white. Remap the primary-text elements to near-black. Secondary text already
   flows through --text-2/3 (now dark). Dark mode untouched (scoped selector). */
html[data-theme="light"] .hh-greet,
html[data-theme="light"] .hh-card-title,
html[data-theme="light"] .hi-title,
html[data-theme="light"] .hi-card-head,
html[data-theme="light"] .hi-stat-n,
html[data-theme="light"] .hi-stat-l,
html[data-theme="light"] .hi-ai-recap-head,
html[data-theme="light"] .ht-title,
html[data-theme="light"] .hi-mention-title,
html[data-theme="light"] .hi-mention-top b,
html[data-theme="light"] .hm-top b{color:var(--off-white)}
/* .hi-count pill + row/hover fills used white-alpha (invisible / no contrast on white) */
html[data-theme="light"] .hh-card-title .hi-count{background:rgba(0,0,0,.05)}
html[data-theme="light"] .ht-row,
html[data-theme="light"] .hm-item{border-bottom-color:rgba(0,0,0,.06)}
html[data-theme="light"] .ht-row:hover,
html[data-theme="light"] .hm-item:hover{background:rgba(0,0,0,.04)}
html[data-theme="light"] .hh-open:hover,
html[data-theme="light"] .hi-refresh:hover{color:var(--purple)}
/* Home empty-states + Unread/All segmented control hardcode white-alpha text/track */
html[data-theme="light"] .hi-empty{color:var(--text-3)}
html[data-theme="light"] .hi-seg{background:rgba(0,0,0,.05)}
html[data-theme="light"] .hi-seg button{color:var(--sec)}
html[data-theme="light"] .hi-seg button.on{color:#fff}
/* #9 — Light-mode dark-residue sweep. These app-wide popups/menus hardcode a dark rgba
   background (not the theme-aware var(--dark)), so they stayed dark — with var(--cream) text
   going near-black in light, that's dark-on-dark. Convert to white surfaces + dark hairline +
   dark-alpha hovers. (Review-tab .rev-* surfaces are intentionally left to that feature branch.) */
html[data-theme="light"] .emote-input-picker,
html[data-theme="light"] .emote-picker{background:#ffffff;border-color:rgba(0,0,0,.12);box-shadow:0 6px 20px rgba(0,0,0,.14)}
/* #4 — Tab-swap cross-fade. The board view switch now runs its full re-render inside a
   document.startViewTransition (see _wsCrossfadeSwitch); tune the root cross-fade to a quick
   ~100ms dissolve with a slight upward drift on the incoming frame. Kept short so the swap
   still feels instant, just without the blank flash. */
::view-transition-old(root),
::view-transition-new(root){animation-duration:.1s;animation-timing-function:cubic-bezier(.4,0,.2,1)}
::view-transition-new(root){animation-name:vtFadeInUp}
@keyframes vtFadeInUp{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}
/* Kill the root cross-fade entirely — the incoming frame fading up from opacity:0 exposed the
   un-themed html canvas for a frame = the "swap between tabs flashes black" bug (mobile/narrow VT
   path only; desktop navigate() already swaps instantly). An instant cut matches the workshop
   view-tab switch, which abandoned startViewTransition for this same flash. */
::view-transition-old(root),::view-transition-new(root){animation:none !important}
/* Fix A — mobile tab-switch cross-fade holds the CHROME still. Earlier startViewTransition
   attempts flashed because the whole document (incl. the backdrop-filter header + hotbar) went
   into the `root` snapshot and cross-faded — snapshotting a backdrop-filter element renders it
   blank for a frame = the full-screen flash. Giving the chrome its own view-transition-name
   pulls it OUT of `root` (only page content cross-fades), and pinning its group to no animation
   keeps it perfectly static (old==new position) so it never flickers. */
body[data-mobile-mode="app"] .m-app-header{view-transition-name:m-app-header}
body[data-mobile-mode="app"] #mBottomNav{view-transition-name:m-bottom-nav}
::view-transition-group(m-app-header),::view-transition-group(m-bottom-nav){animation:none}
::view-transition-old(m-app-header),::view-transition-new(m-app-header),
::view-transition-old(m-bottom-nav),::view-transition-new(m-bottom-nav){animation:none;mix-blend-mode:normal}
@media (prefers-reduced-motion: reduce){
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}
}

/* ── Cluster: annotation drawing + transcript + quality (items 4, 9) ── */
/* Quality control-bar button: icon + tiny label */
.rev-cbtn-q{width:auto;gap:4px;padding:0 7px}
.rev-q-lbl{font:700 11px var(--mono);font-variant-numeric:tabular-nums;letter-spacing:.2px}
.rev-cbtn.on{background:var(--purple);color:#fff}
.rev-q-na{font:600 10px var(--sans);color:var(--muted);margin-left:6px}
.rev-menu-foot{font:600 10px var(--mono);color:var(--muted);padding:6px 12px 8px;border-top:1px solid var(--border-d);margin-top:4px}
.rev-menu-item.is-disabled{opacity:.45;cursor:default}
.rev-menu-item.is-disabled:hover{background:none}
/* Annotation layer (draw mode) */
.rev-player.rev-annotating .rev-tapzone,.rev-player.rev-annotating .rev-bigplay{pointer-events:none}
.rev-annot-layer{position:absolute;inset:0;z-index:7}
.rev-annot-canvas{position:absolute;inset:0;width:100%;height:100%;touch-action:none;cursor:crosshair}
.rev-annot-tools{position:absolute;left:50%;top:16px;transform:translateX(-50%);z-index:11;display:flex;align-items:center;gap:8px;background:rgba(0,0,0,.62);border:1px solid rgba(255,255,255,.14);border-radius:11px;padding:6px 8px;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);max-width:calc(100% - 24px);flex-wrap:wrap;justify-content:center;box-shadow:0 8px 24px rgba(0,0,0,.4)}
/* while annotating, the file/version pill would collide with the centered toolbar */
.rev-stage-annotating>.rev-topright{opacity:0;pointer-events:none}
.rev-annot-swatches{display:flex;gap:5px;align-items:center}
.rev-annot-sw{width:18px;height:18px;border-radius:50%;border:2px solid rgba(255,255,255,.55);background:var(--sw);cursor:pointer;padding:0}
.rev-annot-sw.on{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,.35)}
.rev-annot-tbtn{width:30px;height:30px;display:flex;align-items:center;justify-content:center;border:none;background:rgba(255,255,255,.1);color:#fff;border-radius:8px;cursor:pointer}
.rev-annot-tbtn:hover{background:rgba(255,255,255,.2)}
.rev-annot-tbtn svg{width:16px;height:16px}
.rev-annot-done{width:auto;padding:0 12px;font:700 12px var(--sans)}
.rev-annot-composer.on,.rev-cbtn#revAnnotBtn.on{background:var(--purple);border-color:var(--purple);color:#fff}
/* Annotation viewer overlay (read-only replay over paused frame) */
.rev-annot-view{position:absolute;inset:0;z-index:7;cursor:pointer}
.rev-annot-view-img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;pointer-events:none}
.rev-annot-toggle{display:inline-flex;align-items:center;gap:6px;font:600 12px var(--sans);color:var(--text-2);background:var(--bg-inset);border:1px solid var(--hairline-3);border-radius:8px;padding:5px 9px;cursor:pointer;line-height:1}
.rev-annot-toggle:hover{color:var(--text-1);background:var(--hairline-3)}
.rev-annot-toggle svg{width:15px;height:15px}
/* Comment annotation thumbnail / badge */
.rev-cm-annot{display:inline-flex;align-items:center;gap:7px;margin-top:8px;padding:5px 7px;background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:9px;cursor:pointer;max-width:100%}
.rev-cm-annot:hover{border-color:color-mix(in srgb,var(--purple) 45%,transparent)}
.rev-cm-annot-thumb{width:46px;height:30px;object-fit:cover;border-radius:5px;background:rgba(0,0,0,.3);flex-shrink:0}
.rev-cm-annot-lbl{display:inline-flex;align-items:center;gap:5px;font:600 11px var(--sans);color:var(--purple)}
.rev-cm-annot-lbl svg{flex-shrink:0}
/* Transcript panel (under the player, in .rev-main) */
.rev-transcript{margin-top:10px;background:#161619;border:1px solid var(--border-d);border-radius:12px;overflow:hidden;max-height:34vh;display:flex;flex-direction:column}
.rev-transcript-head{flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:10px 12px 8px;font:700 13px var(--sans);color:var(--off-white);border-bottom:1px solid var(--border-d)}
.rev-transcript-head-actions{display:flex;align-items:center;gap:6px}
.rev-transcript-edit,.rev-transcript-empty-add,.rev-transcript-import,.rev-transcript-cancel,.rev-transcript-save,.rev-transcript-remove{border:0;border-radius:7px;padding:6px 9px;font:700 11px var(--sans);cursor:pointer}
.rev-transcript-edit,.rev-transcript-empty-add,.rev-transcript-import{background:rgba(255,255,255,.08);color:var(--off-white)}
.rev-transcript-edit:hover,.rev-transcript-empty-add:hover,.rev-transcript-import:hover{background:rgba(255,255,255,.14)}
.rev-transcript-x{width:26px;height:26px;display:flex;align-items:center;justify-content:center;background:none;border:none;color:var(--muted);cursor:pointer;border-radius:6px}
.rev-transcript-x:hover{background:var(--state-hover);color:var(--cream)}
.rev-transcript-body{overflow-y:auto;padding:6px 6px 10px}
.rev-transcript-cue{display:flex;gap:9px;padding:6px 6px;border-radius:7px}
.rev-transcript-cue:hover{background:rgba(255,255,255,.04)}
.rev-transcript-tc{flex-shrink:0;font:700 10px var(--mono);font-variant-numeric:tabular-nums;color:#1b1b1b;background:var(--gold);border:none;border-radius:5px;padding:2px 6px;cursor:pointer;height:fit-content}
.rev-transcript-tc:hover{filter:brightness(1.08)}
.rev-transcript-text{font-size:13px;color:var(--off-white);line-height:1.45;word-break:break-word}
.rev-transcript-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;padding:26px 18px}
.rev-transcript-empty svg{width:28px;height:28px;color:var(--muted);opacity:.7}
.rev-transcript-empty-t{font:700 13px var(--sans);color:var(--cream)}
.rev-transcript-empty-s{font-size:12px;color:var(--muted);line-height:1.5}
.rev-transcript-empty-add{margin-top:4px;background:var(--modal-col-color,var(--purple));color:#fff}
.rev-transcript-editor{display:flex;flex-direction:column;gap:8px;padding:10px 12px 12px;min-height:190px}
.rev-transcript-editor textarea{width:100%;min-height:150px;resize:vertical;box-sizing:border-box;border:1px solid var(--border-d);border-radius:8px;background:#0d0d0f;color:var(--off-white);font:12px/1.5 var(--mono);padding:10px;outline:none}
.rev-transcript-editor textarea:focus{border-color:var(--modal-col-color,var(--purple));box-shadow:0 0 0 2px color-mix(in srgb,var(--modal-col-color,var(--purple)) 22%,transparent)}
.rev-transcript-editor-hint{font:11px/1.4 var(--sans);color:var(--muted)}
.rev-transcript-editor-actions{display:grid;grid-template-columns:auto auto 1fr auto auto;align-items:center;gap:6px}
.rev-transcript-cancel{background:transparent;color:var(--muted)}
.rev-transcript-save{background:var(--modal-col-color,var(--purple));color:#fff}
.rev-transcript-remove{background:rgba(255,107,107,.12);color:#ff8a8a}
/* .rev-transcript is appended INTO .rev-main (the always-dark viewer column, line 9582),
   so it must not flip. Removed: html[data-theme="light"] .rev-transcript{background:
   rgba(0,0,0,.02)} — it painted the panel near-transparent black under near-black text. */
html[data-theme="light"] .rev-cm-annot{background:rgba(0,0,0,.03)}

/* ── Review: file-version bar (item 13) + Frame.io-style upload progress (item 2) ── */
.rev-verbar{display:flex;align-items:center;gap:8px;margin-bottom:10px;padding:7px 10px;border:1px solid var(--border-d);border-radius:9px;background:rgba(255,255,255,.03);font-size:12px;color:var(--cream)}
.rev-verbar-proj{color:var(--muted);white-space:nowrap}
.rev-verbar-dot{color:var(--muted);opacity:.6}
.rev-verbar-file{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex:0 1 auto}
.rev-verbar-nav{margin-left:auto;display:flex;align-items:center;gap:4px;flex-shrink:0}
.rev-verbar-count{font-size:11px;color:var(--muted);min-width:42px;text-align:center;font-variant-numeric:tabular-nums}
.rev-verbar-arrow{width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:6px;border:1px solid var(--border-d);background:none;color:var(--cream);cursor:pointer;padding:0;transition:border-color .15s,color .15s,opacity .15s}
.rev-verbar-arrow svg{width:14px;height:14px}
.rev-verbar-arrow:hover:not(:disabled){border-color:var(--purple);color:var(--purple)}
.rev-verbar-arrow:disabled{opacity:.35;cursor:default}
.pub-rev-root .rev-verbar{display:none!important}
.rev-upl{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-3);min-height:280px;padding:var(--sp-6);text-align:center}
.rev-upl-ringbox{position:relative;display:block;width:120px;height:120px;border-radius:var(--r-round);overflow:hidden}
.rev-upl-ring{display:block}
.rev-upl-ring-bg{stroke:var(--border-d)}
/* The meter wears the STATUS colour, not brand purple: on a task in "EDIT IN REVIEW"
   the surface is already that colour and a purple arc read as a different system.
   --modal-col-color is set on #cardModal from the task's column. */
.rev-upl-ring-fg{stroke:var(--modal-col-color,var(--color-primary));transition:stroke-dashoffset var(--dur-press) var(--ease-std),opacity var(--dur-press) var(--ease-std)}
.rev-upl-ring-pct{fill:var(--color-text-1);font-family:var(--sans);font-size:var(--text-2xl);font-weight:var(--fw-bold);font-variant-numeric:tabular-nums;transition:opacity var(--dur-press) var(--ease-std)}
.rev-upl-ringbox.is-phase .rev-upl-ring-fg,.rev-upl-ringbox.is-phase .rev-upl-ring-pct{opacity:0}
.rev-upl-ringbox.is-phase::after{content:'';position:absolute;inset:var(--sp-2);border-radius:var(--r-round);pointer-events:none;
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi) 50%,var(--bg-inset) 75%);background-size:200% 100%;
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - var(--sp-2)),var(--color-text-1) 0);
  mask:radial-gradient(farthest-side,transparent calc(100% - var(--sp-2)),var(--color-text-1) 0);
  animation:skelShimmer 1.4s linear infinite}
.rev-upl-name{font-size:var(--text-base);font-weight:var(--fw-medium);color:var(--color-text-1);max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rev-upl-line{font-size:var(--text-xs);color:var(--color-text-2);font-variant-numeric:tabular-nums}
/* Peer upload / new-version notice in the Review side rail. Deliberately non-destructive:
   it never re-renders the player, so a teammate already watching the current version keeps
   playing while someone else uploads. Static text only, so no motion-ladder entry needed. */
.rev-remote-upl{flex-shrink:0;display:flex;align-items:center;gap:var(--sp-2);margin:var(--sp-2) var(--sp-4) 0;padding:var(--sp-2) var(--sp-3);border:1px solid var(--border-d);border-radius:8px;background:var(--purple-soft);font:500 12px var(--sans);color:var(--cream)}
.rev-remote-upl-txt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rev-remote-upl-pct{flex-shrink:0;font-weight:700;color:var(--purple);font-variant-numeric:tabular-nums}
.rev-remote-upl-btn{flex-shrink:0;background:none;border:none;padding:0;font:700 12px var(--sans);color:var(--purple);cursor:pointer}
.rev-remote-upl-btn:hover{text-decoration:underline}
.pub-rev-root .rev-remote-upl{display:none!important}


/* ============================================================================
   DESKTOP LIGHT MODE — residue fixes (white-alpha overlays + hardcoded text)
   Root TEXT vars already flip in the html[data-theme="light"]{} block above.
   Below = hardcoded-color residue the root flip can't reach. Scoped to
   html[data-theme="light"] only — dark mode + mobile (data-mobile-mode) untouched.
   ============================================================================ */
/* --- KANBAN: white-alpha overlays on column headers, cards, inputs, add-rows --- */
html[data-theme="light"] .kanban-col-name:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] .kanban-col-name:focus{background:rgba(0,0,0,.04)}
html[data-theme="light"] .kanban-col-count{background:rgba(0,0,0,.06)}
html[data-theme="light"] .kanban-card:hover{background:rgba(0,0,0,.03)}
html[data-theme="light"] .kanban-add{background:rgba(0,0,0,.02)}
html[data-theme="light"] .kanban-add:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] .kanban-input{background:rgba(0,0,0,.04)}
html[data-theme="light"] .kanban-card-subtask-progress{background:rgba(0,0,0,.04)}
html[data-theme="light"] .kanban-card-subtask-progress .subtask-bar{background:rgba(0,0,0,.08)}
html[data-theme="light"] .kanban-col-dropdown-actions button:hover{background:rgba(0,0,0,.08);border-color:rgba(0,0,0,.15)}
html[data-theme="light"] .kanban-col-sort-option:hover{background:rgba(0,0,0,.06)}
html[data-theme="light"] .kanban-add-col-btn{background:rgba(0,0,0,.04)}
html[data-theme="light"] .kanban-add-col-btn:hover{background:rgba(0,0,0,.08)}
html[data-theme="light"] .kanban-col-ghost{border-color:rgba(0,0,0,.15)}
html[data-theme="light"] .kanban{scrollbar-color:rgba(0,0,0,.20) transparent}
html[data-theme="light"] .kanban::-webkit-scrollbar-thumb{background:rgba(0,0,0,.20)}
html[data-theme="light"] .kanban::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.35)}
html[data-theme="light"] .kanban-col-body{scrollbar-color:rgba(0,0,0,.20) transparent}
html[data-theme="light"] .kanban-col-body::-webkit-scrollbar-thumb{background:rgba(0,0,0,.20)}
html[data-theme="light"] .kanban-col-body::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.35)}
/* --- LIST / GROUP VIEW --- */
html[data-theme="light"] .group-header:hover{background:rgba(0,0,0,.03)}
html[data-theme="light"] .group-table-header{background:rgba(0,0,0,.02)}
html[data-theme="light"] .group-table-row{border-bottom:1px solid var(--border-d)}
html[data-theme="light"] .group-table-row:hover{background:rgba(0,0,0,.04)}
html[data-theme="light"] .group-inline-edit{background:#ffffff;border-color:var(--border-d);color:var(--off-white);color-scheme:light}
html[data-theme="light"] .gv-flat-row:hover{background:rgba(0,0,0,.04)}
/* #24 — light-mode list view + view tabs text was invisible: list cells used --cream and
   flat-cell titles used #fff (light on the white list surface); the active view tab used
   --white (always #fff). Map them to theme-aware / accent colors so they read in light. */
html[data-theme="light"] .group-table-cell{color:var(--off-white)}
html[data-theme="light"] .gv-flat-cell-title{color:var(--off-white)}
html[data-theme="light"] .ws-view-tab.active{color:var(--purple)}
html[data-theme="light"] .ws-view-tab.active svg{color:var(--purple)}
/* --- TOASTS: dark gradient tails + white-alpha cancel button --- */
html[data-theme="light"] .toast-btn.cancel{background:rgba(0,0,0,.06);color:var(--cream);border:1px solid var(--border-d)}
html[data-theme="light"] .toast-btn.cancel:hover{background:rgba(0,0,0,.10);color:var(--off-white)}
/* --- DROPDOWNS / CONTEXT MENUS --- */
html[data-theme="light"] .server-dropdown-item{color:var(--off-white)}
html[data-theme="light"] .server-dropdown-item:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] .ms-dropdown-item{color:var(--off-white)}
html[data-theme="light"] .ms-dropdown-item.selected{background:rgba(0,0,0,.07);color:var(--off-white)}
html[data-theme="light"] .ms-dropdown-item.selected:hover{background:rgba(0,0,0,.10)}
html[data-theme="light"] .card-ctx-menu button,
html[data-theme="light"] .edit-ctx-menu button,
html[data-theme="light"] .sidebar-ctx-menu button,
html[data-theme="light"] .cw-dropdown button{color:var(--off-white)}
html[data-theme="light"] .card-ctx-menu button:hover,
html[data-theme="light"] .edit-ctx-menu button:hover,
html[data-theme="light"] .sidebar-ctx-menu button:hover,
html[data-theme="light"] .cw-dropdown button:hover{background:rgba(0,0,0,.06)}
html[data-theme="light"] .card-ctx-menu .ctx-submenu,
html[data-theme="light"] .sidebar-ctx-menu .ctx-submenu{background:#ffffff;border-color:var(--border-d);box-shadow:0 8px 24px rgba(0,0,0,.12)}
html[data-theme="light"] .card-ctx-menu .ctx-submenu button,
html[data-theme="light"] .sidebar-ctx-menu .ctx-submenu button{color:var(--off-white)}
html[data-theme="light"] .edit-ctx-menu .ctx-kbd,
html[data-theme="light"] .edit-ctx-menu .ctx-shortcut{color:var(--muted)}

/* ═══════════ Desktop sliding selection — one pill glides + resizes under the
   active item. Reuses the .m-pill-thumb engine on the view tabs, the Home
   Unread/All segment, and the sidebar nav. ═══════════ */
.ws-view-tabs .ws-view-tab,
.hi-seg button,
.sidebar-nav-scroll .sidebar-fav-nav a,
.sidebar-nav-scroll .sidebar-section-nav a,
.sidebar-nav-scroll .sidebar-cat-item,
.sidebar-nav-scroll .sidebar-nav a,
.sidebar-nav-scroll .sidebar-section-label{position:relative;z-index:1}
/* view tabs: the pill replaces the static underline */
.ws-view-tabs .ws-view-tab{border-radius:10px}
.ws-view-tab.active::after{content:none}
/* 16%, NOT 22% — this must be the same mix as the sidebar's active pill
   (.sidebar-nav-scroll .m-pill-thumb). Both tint from the SAME project colour
   (--ws-accent here, --pill-accent there, both the project's icon colour), so the
   alpha was the entire reason a pink project read as two different pinks: the tab
   pill came out visibly hotter than the sidebar row selecting it. Keep the two in
   step — if one changes, change both. */
.ws-view-tabs .m-pill-thumb{background:color-mix(in srgb,var(--ws-accent,var(--purple)) 16%,transparent);border-color:transparent;border-radius:10px}
/* Home Unread/All: solid purple pill (was a static .on background) */
.hi-seg button.on{background:none}
.hi-seg .m-pill-thumb{background:var(--purple);border-color:transparent;border-radius:7px}
/* sidebar: the sliding pill is the primary active highlight, but the active item keeps a SUBTLE
   persistent tint so it's never left un-highlighted in the brief moment the pill repaints after a
   click (the "highlight disappears until you move the cursor" bug). */
/* NO background on an active row. The sliding pill is the selection, full stop — a tint
   underneath it is a second highlight stacked on the first, which is what read as two
   selections. The pill is what has to keep up on a click; a row painting its own
   backup highlight is not the way to fix that. */
.sidebar-nav-scroll .sidebar-fav-nav a.active,
.sidebar-nav-scroll .sidebar-section-nav a.active,
.sidebar-nav-scroll .sidebar-cat-item.active,
.sidebar-nav-scroll .sidebar-nav a.active{background:transparent}
.sidebar-nav-scroll .m-pill-thumb,
#sidebarFooterNav .m-pill-thumb{background:color-mix(in srgb,var(--pill-accent,var(--purple)) 16%,transparent);border-color:transparent;border-radius:9px}
/* Footer nav (Files / Direct Messages / Help / Feedback) is its own pill bar — it
   sits outside .sidebar-nav-scroll, so it needs position:relative to anchor the
   absolutely-positioned thumb, and the same slide timing as everything else. */
#sidebarFooterNav{position:relative}
#sidebarFooterNav .m-pill-thumb,
#sidebarFooterNav .m-pill-rail{transition:transform var(--tab-slide-dur) var(--tab-slide-ease),width var(--tab-slide-dur) var(--tab-slide-ease),height var(--tab-slide-dur) var(--tab-slide-ease),opacity .15s ease}
/* The static fill is the sliding thumb's job — otherwise the active row paints its
   own background and the pill appears to sit on top of a second highlight. */
#sidebarFooterNav a.active{background:transparent}
/* reference slide easing on desktop */
.ws-view-tabs .m-pill-thumb,
.hi-seg .m-pill-thumb,
.sidebar-nav-scroll .m-pill-thumb{transition:transform var(--tab-slide-dur) var(--tab-slide-ease),width var(--tab-slide-dur) var(--tab-slide-ease),height var(--tab-slide-dur) var(--tab-slide-ease),opacity .15s ease}
@media(prefers-reduced-motion:reduce){.ws-view-tabs .m-pill-thumb,.hi-seg .m-pill-thumb,.sidebar-nav-scroll .m-pill-thumb{transition:opacity .18s ease}}
/* Sidebar leading "rail": a thin accent at the very left that slides FASTER than the soft pill
   (.2s vs .36s) so it selects the item quickly and the pill follows. Replaces the static ::before. */
.sidebar-nav-scroll .sidebar-fav-nav a.active::before,
.sidebar-nav-scroll .sidebar-section-nav a.active::before,
.sidebar-nav-scroll .sidebar-nav a.active::before,
.sidebar-nav-scroll .sidebar-cat-item.active::before{content:none}
.sidebar-nav-scroll .m-pill-rail{position:absolute;left:0;top:0;width:3px;z-index:2;background:var(--purple);border-radius:0 3px 3px 0;pointer-events:none;opacity:0;
  transition:transform .2s cubic-bezier(.5,0,.2,1),height .2s cubic-bezier(.5,0,.2,1),opacity .14s ease}
.sidebar-nav-scroll .m-pill-rail.show{opacity:1}
@media(prefers-reduced-motion:reduce){.sidebar-nav-scroll .m-pill-rail{transition:opacity .14s ease}}

/* ═══════════ Board (project) redesign — match mockup ═══════════ */
/* View switcher → a segmented pill with icon + LABEL + the sliding indicator */
.ws-view-tabs{background:var(--surface-container);border-radius:11px;padding:4px;gap:2px}
.ws-view-tabs .ws-view-tab{height:36px;padding:0 14px;border-radius:9px;gap:7px;font:600 13px var(--sans);color:rgba(235,235,245,.7)}
.ws-view-tabs .ws-view-tab svg{width:15px;height:15px;opacity:1}
.ws-view-tabs .ws-view-tab.active{color:#fff}
.ws-view-tabs .ws-view-tab-label{display:inline}
/* Filter now sits OUTSIDE the pill, to its right */
/* Filter and Settings sit side by side, so they are ONE control shape. Previously
   Settings set font:600 13px and Filter inherited whatever was around it, and Filter's
   glyph carried an opacity:.7 that Settings' did not — hence the mismatched sizes. */
.ws-view-filter,.ws-view-settings{height:36px;padding:0 13px;border-radius:10px;gap:7px;
  color:rgba(235,235,245,.7);background:none;border:none;display:inline-flex;align-items:center;
  cursor:pointer;font:600 13px var(--sans)}
.ws-view-filter{margin-left:9px}
.ws-view-filter:hover,.ws-view-settings:hover{background:rgba(255,255,255,.06);color:#fff}
/* :not(.caret) matches .ws-toolbar-btn's specificity — Settings also carries that
   class, whose 14px rule otherwise outranked this and left the two icons unequal. */
.ws-view-filter svg:not(.caret),.ws-view-settings svg:not(.caret){width:15px;height:15px;opacity:1}
.ws-view-filter .ws-view-tab-label{display:none}
/* Board surfaces → mockup (column/card bg + radius set on the !important rules above) */
.kanban{gap:16px}
.kanban-card-text{font-size:14px !important;font-weight:600 !important}

/* ── Workspace card menu: client switcher + "flows from the card" dropdown ── */
/* Client switcher — just a bare icon (no label, no container), shown when the menu is open */
/* It used to swap display:none ↔ inline-flex, and `display` cannot be transitioned, so the
   button popped in and out. It now stays in the box model and animates instead: width and
   scale carry the motion, opacity the fade. Collapsed it is width:0 with margin-left:-4px,
   which cancels the card's own 4px flex gap — so it occupies EXACTLY nothing and the name
   and caret never shift. `visibility` is what still removes it from the tab order when
   collapsed (0 opacity alone stays focusable); it flips instantly on the way in and is
   delayed by the full duration on the way out so the fade is actually seen. Easing matches
   the dropdown's own sdMenuOpen curve so the icon and the menu read as one motion. */
.sidebar-ws-switch{display:inline-flex;align-items:center;justify-content:center;width:0;height:28px;flex:none;padding:0;overflow:hidden;border:none;border-radius:8px;background:none;color:rgba(235,235,245,0.7);cursor:pointer;opacity:0;visibility:hidden;transform:scale(.72);margin-left:-4px;transition:width .2s cubic-bezier(.22,1,.36,1),margin-left .2s cubic-bezier(.22,1,.36,1),transform .2s cubic-bezier(.22,1,.36,1),opacity .16s ease,visibility 0s linear .2s,background .14s ease,color .14s ease}
.sidebar-ws-switch:hover{background:rgba(255,255,255,0.1);color:#fff}
.sidebar-ws-switch svg{width:16px;height:16px;flex:none}
.sidebar-ws-card.ws-open .sidebar-ws-switch{width:28px;margin-left:0;opacity:1;visibility:visible;transform:scale(1);transition:width .2s cubic-bezier(.22,1,.36,1),margin-left .2s cubic-bezier(.22,1,.36,1),transform .2s cubic-bezier(.22,1,.36,1),opacity .18s ease .04s,visibility 0s,background .14s ease,color .14s ease}
/* Reduced motion: keep the fade (so the button doesn't just blink) but drop the travel. */
@media(prefers-reduced-motion:reduce){
.sidebar-ws-switch{transform:none;transition:opacity .12s ease,visibility 0s linear .12s,background .14s ease,color .14s ease}
.sidebar-ws-card.ws-open .sidebar-ws-switch{transform:none;transition:opacity .12s ease,visibility 0s,background .14s ease,color .14s ease}}
/* While the menu is open, the card shows the WORKSPACE identity even on Home */
.sidebar-ws-card.ws-open .ws-layer-space > *{transform:translateY(0) !important;opacity:1 !important}
.sidebar-ws-card.ws-open .ws-layer-home > *{transform:translateY(135%) !important;opacity:0 !important}
/* ...and the SETTINGS layer leaves on the same beat. Opening the menu forces the
   workspace identity back with !important above, which the body.is-settings rules
   cannot outrank -- so without this the settings identity stayed put and the two
   printed on top of each other ("SettingsNe..."). Same translateY(135%), same opacity,
   same per-child cascade: it drops away exactly as home does when the workspace
   identity returns. */
.sidebar-ws-card.ws-open .ws-layer-settings > *{transform:translateY(135%) !important;opacity:0 !important}
/* Card keeps its OWN liquid glass when open (the same translucent glass the closed button
   already has) — just square the bottom corners + drop the bottom shadow so it merges with
   the dropdown, which uses the identical glass recipe (NOT the flat dark --glass-bg). */
/* Drop the CARD's own backdrop-filter while open: a parent backdrop-filter neutralises a
   child's, so with it on, the dropdown couldn't blur the sidebar behind it (content showed
   through sharp). Off → the dropdown's own backdrop-filter actually frosts what's behind. */
/* ONE backdrop-filter for the WHOLE open container: the dropdown starts at the card's TOP
   (top:0) and extends down, so a single frosted-glass layer covers the identity row AND the
   menu — no seam / harsh cut-off. The card is transparent; its identity sits ABOVE the glass. */
/* The identity card is added to each of these three rules rather than given copies of
   them: when the dropdown is open the card goes transparent, its content lifts above
   the glass, and the panel starts at the card's TOP and pads past it — which is what
   makes the workspace menu look like one frosted container instead of a card with a
   box hanging under it. Sharing the declaration is the only way the two stay equal. */
.sidebar-ws-card.ws-open,.cr-profile-idcard.acct-open{border-radius:14px;background:transparent !important;border-color:transparent !important;box-shadow:none !important;backdrop-filter:none !important;-webkit-backdrop-filter:none !important}
.sidebar-ws-card.ws-open > nav,.sidebar-ws-card.ws-open > .sidebar-ws-switch,.sidebar-ws-card.ws-open > .sidebar-ws-caret,.cr-profile-idcard.acct-open > .cr-profile-avatar-wrap,.cr-profile-idcard.acct-open > .cr-profile-idtext,.cr-profile-idcard.acct-open > .cr-profile-idcaret{position:relative;z-index:201}
.server-dropdown{transform-origin:top center}
.sidebar-ws-card.ws-open .server-dropdown.open,.cr-profile-idcard.acct-open .server-dropdown.open{top:0;left:-1px;right:-1px;margin:0;padding-top:52px;background:rgba(255,255,255,0.08);backdrop-filter:blur(20px) saturate(180%);-webkit-backdrop-filter:blur(20px) saturate(180%);border:1px solid rgba(255,255,255,0.2);border-radius:14px;box-shadow:0 18px 36px rgba(0,0,0,0.4);z-index:200;animation:sdMenuOpen .24s cubic-bezier(.22,1,.36,1)}
@keyframes sdFlow{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}

/* ── Drag ghost: a FULL outline in the source column's colour that fades to the
   target column's colour while dragging. The drag JS already swaps --col-color on
   drag-over (app-shell …:35452); the transition does the fade. Overrides the faded
   70%-transparent card-active ring (…:8439) that made the dragged outline look broken. */
.kanban-card-ghost,
.kanban-card-ghost.card-active{
  border:none !important;
  box-shadow:0 0 0 2px var(--col-color,var(--coral)),0 16px 34px rgba(0,0,0,.5) !important;
  transition:box-shadow .25s ease !important;
  /* The base ghost rules clip with overflow:hidden + clip-path:inset(0 round 6px), which
     chopped the 2px outline ring down to just the corners. Let it show the FULL outline. */
  overflow:visible !important;clip-path:none !important;
}

/* ── Sidebar: clean staggered cascade as items first appear (triggered once by JS). */
@keyframes sbCascadeIn{from{opacity:0;transform:translateY(8px);filter:blur(7px)}to{opacity:1;transform:none;filter:blur(0)}}
.sb-cascade-item{animation:sbCascadeIn .42s cubic-bezier(.22,1,.36,1) both}
/* While waiting for real board data, keep the items hidden so they cascade in
   exactly once (instead of painting plainly first, then re-animating). */
#sidebarUnifiedItems.sb-cascade-pending > *{opacity:0}

/* ── Board header actions: overlapping member-avatar stack + Share (mockup). */
/* (row gap now comes from --page-title-gap; this second declaration is gone) */
.ws-header-actions{margin-left:auto;display:flex;align-items:center;gap:14px;flex-shrink:0}
.ws-member-stack{display:flex;align-items:center}
.ws-member-stack > *{margin-left:-9px;border-radius:50%}
.ws-member-stack > *:first-child{margin-left:0}
.ws-member-more{margin-left:-9px;width:28px;height:28px;border-radius:50%;background:#2a2a2e;display:inline-flex;align-items:center;justify-content:center;font:600 11px var(--sans);color:var(--cream)}
.ws-share-btn{height:34px;padding:0 17px;border-radius:9px;background:rgba(255,255,255,.08);color:var(--white,#fff);font:600 13px var(--sans);border:none;cursor:pointer;transition:background .14s,transform .14s}
.ws-share-btn:hover{background:rgba(255,255,255,.14)}
.ws-share-btn:active{transform:scale(.97)}
/* Header access avatars: clickable → profile, hover → name tooltip. */
.ws-member-av{position:relative;display:inline-flex;cursor:pointer;border-radius:50%;margin-left:-9px;box-shadow:0 0 0 2px var(--bg-app,#0a0a0b)}
.ws-member-stack .ws-member-av:first-child{margin-left:0}
/* The same acknowledgement a dropdown row gives: it lifts and lights slightly under the
   pointer instead of only showing a tooltip. Transform rather than a size change so the
   neighbours in the stack do not shuffle. */
.ws-member-av{transition:transform .14s cubic-bezier(.22,1,.36,1),box-shadow .14s ease,filter .14s ease}
.ws-member-av:hover{z-index:6;transform:translateY(-2px) scale(1.08);filter:brightness(1.12);
  box-shadow:0 0 0 2px var(--bg-app,#0a0a0b),0 4px 12px rgba(0,0,0,.45)}
.ws-member-av:active{transform:translateY(0) scale(1.02)}
@media(prefers-reduced-motion:reduce){.ws-member-av{transition:none}.ws-member-av:hover{transform:none}}
.ws-member-av::after{content:attr(data-name);position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);background:#0c0c0e;color:#fff;font:600 11px var(--sans);padding:4px 9px;border-radius:6px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;box-shadow:0 6px 18px rgba(0,0,0,.5);z-index:60}
.ws-member-av:hover::after{opacity:1}

/* ── Board toolbar → mockup: view tabs LEFT, Filter + Settings pushed RIGHT. */
.workshop-views .ws-view-tabs{order:1;margin-right:auto}
.workshop-views .cc-schedule-pill{order:1}
/* Calendar Day/Week/Month toggle + month-nav sit BETWEEN the tabs and Filter (mockup). */
.workshop-views .cal-view-toggle{order:2}
.workshop-views [data-cal-tab-nav],.workshop-views .cal-month-nav{order:3}
.workshop-views .ws-view-filter{order:4;margin-left:0 !important}
.workshop-views [id$="MenuWrap"]{order:5}
.workshop-views .presence-bar{order:6;margin-left:8px !important}
.ws-view-filter .ws-view-tab-label{display:inline !important}
/* .ws-view-settings shares the .ws-view-filter rule above — one shape, one type. */
.ws-view-settings{padding:0 13px !important;border:none !important;min-width:0}
.ws-view-settings .ws-view-tab-label{display:inline}
/* Calendar Day/Week/Month toggle restyled to match the view-tab pill (no boxed border). */
.workshop-views .cal-view-toggle{border:none !important;background:rgba(255,255,255,.05) !important;border-radius:11px !important;padding:4px !important;height:auto !important;gap:2px;overflow:visible !important}
.workshop-views .cal-view-toggle button{border:none !important;border-radius:8px !important;height:30px;padding:0 13px !important;font-size:13px !important;font-weight:600 !important;color:rgba(235,235,245,.6) !important;text-transform:none}
.workshop-views .cal-view-toggle button:hover{background:rgba(255,255,255,.07) !important;color:#fff !important}
.workshop-views .cal-view-toggle button.is-active{background:rgba(255,255,255,.12) !important;color:#fff !important}

/* Switching boards used to snap every accent-derived colour at once, which read as a
   flash. A bare custom property can't animate — the browser has no idea it holds a
   colour — so registering it with @property makes --ws-accent interpolable, and one
   transition on the surface that carries it fades the pill, the tabs, the icons and
   every color-mix() built on it together. */
@property --ws-accent{syntax:'<color>';inherits:true;initial-value:#7c5cff}
#page-workshop,#page-custom-workshop,.has-ws-accent{transition:--ws-accent var(--ws-accent-dur,300ms) var(--tab-slide-ease,ease)}
@media(prefers-reduced-motion:reduce){#page-workshop,#page-custom-workshop,.has-ws-accent{transition:none}}

/* ── DESIGN RULE: every floating menu / dropdown / popover uses the liquid-glass + blur recipe
   (--glass-bg + --glass-blur + --glass-border + --glass-shadow). New menus MUST use it too. ── */
.cw-dropdown,.card-ctx-menu,.col-ctx-menu,.edit-ctx-menu,.prop-ctx-menu,.prop-type-picker,
.ws-toolbar-menu,.ws-view-menu,.workshop-filter-panel,.workshop-sort-dropdown,.sidebar-create-menu,
.add-prop-popover{
  background:var(--glass-bg) !important;
  backdrop-filter:var(--glass-blur) !important;-webkit-backdrop-filter:var(--glass-blur) !important;
  border:1px solid var(--glass-border) !important;
  box-shadow:var(--glass-shadow) !important;
}
/* Selected kanban cards get the SAME colour outline as a card being dragged. */
.kanban-card.card-selected{box-shadow:0 0 0 2px var(--col-color,var(--purple)) !important;overflow:visible !important}
/* A little breathing room above the first sidebar project item. */
#sidebarUnifiedItems{margin-top:8px}

/* Topbar options (⋮) button removed per request. */
#topbarOptionsBtn{display:none !important}

/* Undo toast → compact, single-line, PURPLE (was a wide green card that wrapped to 2 lines). */
.toast.toast-undo{max-width:none;width:auto;padding:6px 7px 6px 16px;gap:12px;text-align:left;border-radius:14px}
.toast.toast-undo .toast-msg{flex:none;white-space:nowrap;font-size:13px}
.toast.toast-undo .toast-actions{gap:6px}
.toast.toast-undo .toast-btn{padding:5px 13px;font-size:12px}
.toast.toast-undo .toast-btn.primary{background:var(--purple);color:#fff}
.toast.toast-undo .toast-btn.primary:hover{background:#6b4ef0}

/* ── List view → mockup: a rounded, INSET table CARD (its own container, not full-bleed) on the
   board bg; clean rows with thin separators; Task + checkbox, Stage = dot + name, Owner avatar. ── */
.group-view{gap:0}
.gv-flat-table{
  background:var(--surface-container) !important;  /* same as the kanban columns — now by
                                                     token, so it stays that way */
  border:none !important;                    /* no outer outline (per mockup) */
  border-radius:14px !important;
  margin:14px 16px 22px 16px !important;      /* top padding; left edge lines up with the view-tabs bar */
  overflow:auto;
  /* Fit the content (header + rows + add-row) — don't stretch to fill the page, which left a
     big empty box below the rows. Caps at the available height + scrolls only when it overflows. */
  flex:0 1 auto !important;
  max-height:calc(100% - 36px);
}
/* Header row → same colour as the view-tab bar above it. */
/* The header row matches the table it sits in (and so the kanban columns), in
   both themes. It is position:sticky, so the fill MUST be opaque — the old 5%
   white tint let rows scroll through underneath it. */
.gv-flat-header{background:var(--surface-container) !important;border-bottom:1px solid var(--hairline-2) !important}
.gv-flat-header .gv-flat-col{border-right:none !important;color:var(--text-2) !important;font-size:11px;letter-spacing:.7px;padding:13px 22px}
.gv-flat-header .gv-flat-col:hover{background:transparent !important;color:var(--text-1) !important}
.gv-flat-row{border-bottom:1px solid var(--hairline)}
.gv-flat-row:last-of-type{border-bottom:none}
.gv-flat-row:hover{background:rgba(255,255,255,.022)}
.gv-flat-cell{border-right:none !important;padding:15px 22px}
.gv-flat-cell-title{font-size:14px;font-weight:600;color:#fff}
.gv-complete-toggle{opacity:.5}
.gv-flat-row:hover .gv-complete-toggle{opacity:.9}
/* Stage → colour dot + plain name (kill the pill background). */
.gv-flat-cell-status .gv-status-text,
.gv-flat-cell-status:hover .gv-status-text{background:transparent !important;color:var(--cream) !important;border-radius:0 !important;padding:0 0 0 16px !important;font-weight:500 !important;position:relative}
.gv-flat-cell-status .gv-status-text::before{content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);width:8px;height:8px;border-radius:50%;background:var(--gv-status-color,#888)}
/* Owner cell — a single avatar */
.gv-flat-cell-owner{display:flex;align-items:center;padding:15px 22px}
.gv-flat-cell-owner .card-avatar,.gv-flat-cell-owner .person-avatar,.gv-flat-cell-owner img{width:26px !important;height:26px !important;border-radius:50%}
.gv-owner-empty{color:var(--muted)}
/* Priority cell → compact coloured pill (the field already carries the option colour). */
.gv-flat-cell .prop-pill,.gv-flat-cell .kanban-priority-badge{font-size:11px;padding:3px 10px;border-radius:6px;font-weight:600}
.gv-flat-add-row{border-top:1px solid var(--hairline);color:var(--muted)}

/* ── Grouped list view: one rounded container per status, stacked + scrolling.
   The Status column drops out of the rows; the container header carries it.
   Side padding lives on the PANE (16px — same as the kanban pane), so the group
   containers run edge-to-edge inside it and line up with the board columns. ── */
/* Grouped List: ONE scroll envelope for every group, so a table wider than the pane
   scrolls inside the view instead of pushing the page off the side of the viewport —
   and so the groups scroll together and stay column-for-column aligned. Each table
   sizes to its content (min-content) inside that shared scroller; giving them their
   own overflow:auto would let them drift out of step with each other. */
.group-view-grouped{display:block !important;overflow:auto;height:auto;flex:1;min-height:0;
  padding-bottom:0;max-width:100%}
.group-view-grouped .gv-flat-table{
  flex:none !important;
  max-height:none !important;
  margin:0 0 12px 0 !important;
  overflow:visible;
  min-width:min-content;
}
.group-view-grouped .gv-flat-table:first-child{margin-top:0}
.group-view-grouped .gv-flat-table:last-child{margin-bottom:0}
.gv-group-header{
  display:flex;align-items:center;gap:9px;
  padding:11px 16px 10px;
  font-size:13px;font-weight:600;color:var(--cream);
  border-bottom:1px solid var(--hairline);
}
.gv-group-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex:none;padding:0;border:0;border-radius:7px;background:transparent;color:var(--gv-group-color,#888);cursor:pointer}
.gv-group-icon:hover,.gv-group-icon:focus-visible{background:color-mix(in srgb,var(--gv-group-color,#888) 16%,transparent);outline:none}
.gv-group-icon.is-readonly{cursor:default}
.gv-group-icon.is-readonly:hover,.gv-group-icon.is-readonly:focus-visible{background:transparent;outline:none}
.gv-group-icon .kanban-col-glyph{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;flex:none;color:inherit}
.gv-group-icon .kanban-col-glyph svg{width:16px;height:16px}
.gv-group-icon .kanban-col-dot{width:10px;height:10px;border-radius:3px;background:var(--gv-group-color,#888)}
.gv-group-name{letter-spacing:.1px;min-width:1ch;border-radius:5px;padding:2px 4px;margin-left:-4px;outline:none}
.gv-group-name[contenteditable="true"]{cursor:text}
.gv-group-name[contenteditable="true"]:hover{background:rgba(255,255,255,.055)}
.gv-group-name[contenteditable="true"]:focus{background:var(--bg-inset);box-shadow:0 0 0 1px color-mix(in srgb,var(--gv-group-color,#888) 70%,transparent)}
.gv-group-count{font-size:11px;color:var(--muted);font-weight:600;background:var(--bg-inset);border-radius:10px;padding:1px 8px;margin-left:1px}

/* ══════════════════════════════════════════════════════════════════════
   CALENDAR → exact match to the owner's Henshu Desktop mockup.
   Upcoming sidebar on the LEFT (Upcoming-only, no card chrome); clean
   borderless month grid, 114px rows; day number in a circle (today =
   purple filled); events = solid stage-coloured pills.
   ══════════════════════════════════════════════════════════════════════ */
/* Upcoming rail removed entirely per owner — the calendar is just the month grid. */
#cwCalendarView .cal-sidebar,#workshopCalendarView .cal-sidebar,#mvCalendarPane .cal-sidebar{display:none !important}
#cwCalendarView .cal-with-sidebar,#workshopCalendarView .cal-with-sidebar,#mvCalendarPane .cal-with-sidebar{gap:0 !important}

/* Month grid → borderless, transparent, fixed 114px rows. */
.calendar-grid{gap:0 !important;background:transparent !important;border-radius:0 !important;grid-template-rows:28px !important;grid-auto-rows:114px !important}
.calendar-day-label{
  background:transparent !important;color:rgba(235,235,245,.38) !important;
  font:700 11px -apple-system,system-ui !important;letter-spacing:.4px !important;padding:6px 0 !important;
  border-bottom:1px solid rgba(255,255,255,.06)
}
/* Very subtle separator lines between the days. */
.calendar-day{
  background:transparent !important;min-height:0 !important;
  padding:7px 9px !important;border-radius:0;gap:5px !important;overflow:hidden;box-sizing:border-box;
  border-right:1px solid rgba(255,255,255,.05);border-bottom:1px solid rgba(255,255,255,.05)
}
.calendar-day:hover{background:rgba(255,255,255,.03) !important}
.calendar-day.today{background:rgba(124,92,255,.12) !important}
.calendar-day.other-month{opacity:.32 !important;background:transparent !important}
/* Day number → always a 24px circle; today filled purple. */
.calendar-day-num{
  font:700 13px -apple-system,system-ui !important;color:rgba(235,235,245,.7) !important;
  width:24px;height:24px;display:flex;align-items:center;justify-content:center;
  border-radius:50%;margin-bottom:0 !important
}
.calendar-day.today .calendar-day-num{background:#7c5cff !important;color:#c9b8ff !important}
/* Keep the "Jun 1" month-start marker legible without breaking the circle. */
.calendar-day-num.is-month-start{width:auto;border-radius:11px;padding:0 8px;gap:3px}
/* Events → pills in the EXACT column colour, muted toward the dark bg so the
   solid fill reads as the stage colour without the neon glow on pure black. */
.calendar-day-card:not([data-workshop-id="__master__"]){
  background:color-mix(in srgb, var(--cal-dot-color,#7c5cff) 68%, #0c0c0f) !important;color:#fff !important;
  padding:3px 6px !important;border-radius:5px !important;min-height:0 !important;gap:0 !important;line-height:1.3
}
.calendar-day-card:not([data-workshop-id="__master__"]):hover{background:color-mix(in srgb, var(--cal-dot-color,#7c5cff) 80%, #0c0c0f) !important}
.calendar-day-card:not([data-workshop-id="__master__"]) .cdc-dot,
.calendar-day-card:not([data-workshop-id="__master__"]) .cdc-status{display:none !important}
.calendar-day-card:not([data-workshop-id="__master__"]) .cdc-line{gap:0 !important}
.calendar-day-card:not([data-workshop-id="__master__"]) .cdc-text{font:600 11px -apple-system,system-ui !important;color:#fff !important}
.calendar-day-overflow{color:rgba(235,235,245,.5) !important;padding:1px 6px !important;text-align:left !important}

/* ── Calendar toolbar: Day/Week/Month + ‹ month › styled EXACTLY like the view-tab
   pill bar (grey container, 44px tall), with a sliding GREY selection thumb. ── */
.workshop-views .cal-view-toggle,
.workshop-views .cal-month-nav{
  position:relative;background:rgba(255,255,255,.05) !important;border:none !important;
  border-radius:11px !important;padding:4px !important;gap:2px !important;height:auto !important;overflow:visible !important
}
.workshop-views .cal-view-toggle button,
.workshop-views .cal-month-nav .workshop-view-btn{
  position:relative;z-index:1;border:none !important;border-radius:9px !important;
  height:36px !important;min-height:36px !important;padding:0 14px !important;
  font-size:13px !important;font-weight:600 !important;color:rgba(235,235,245,.55) !important;
  background:none !important;text-transform:none;transition:color .15s
}
.workshop-views .cal-view-toggle button:hover,
.workshop-views .cal-month-nav .workshop-view-btn:hover{background:rgba(255,255,255,.07) !important;color:#fff !important}
.workshop-views .cal-view-toggle button.is-active{background:none !important;color:#fff !important}
/* The sliding thumb IS the selection highlight (grey, not purple). */
.workshop-views .cal-view-toggle .m-pill-thumb{background:rgba(255,255,255,.12) !important;border-color:transparent !important}
/* Month stepper: arrows hover-highlight; the "June 2026" label is flush (no hover box). */
.workshop-views .cal-month-nav .cal-nav-arrow{padding:0 10px !important}
/* Fixed width (fits the widest cross-month week label ~210px) so the label never
   resizes between Day/Week/Month and pushes the toggle around. */
.workshop-views .cal-month-nav [data-cal-tab-nav-label]{color:#fff !important;width:220px !important;min-width:220px !important;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}
.workshop-views .cal-month-nav [data-cal-tab-nav-label]:hover{background:rgba(255,255,255,.06) !important;color:#fff !important}

/* A bit more breathing room above the toolbar row (view tabs + calendar nav).
   Beats the ID+!important padding rule at ~7702 (padding:6px 16px 4px). */
#page-workshop.active .workshop-views,#page-custom-workshop.active .workshop-views{padding-top:16px !important}

/* ── Calendar DAY view → matches the List view: rounded inset container, clean
   rows with hairline separators, purple (not coral) accents. ── */
.cal-day-view{border:none !important;background:rgba(255,255,255,.018) !important;border-radius:14px !important;margin:14px 16px 22px 16px}
.cal-day-view-head{padding:16px 20px 14px !important;border-bottom:1px solid rgba(255,255,255,.06) !important}
.cal-day-view-head .cdv-date{font-size:19px !important}
.cal-day-view-head .cdv-today-pill{color:var(--purple) !important;background:rgba(124,92,255,.16) !important}
.cal-day-view-body{padding:4px 10px !important;gap:0 !important}
.cal-day-view-body .cdm-item{border:none !important;background:none !important;border-radius:0 !important;border-bottom:1px solid rgba(255,255,255,.05) !important;padding:13px 12px !important}
.cal-day-view-body .cdm-item:last-child{border-bottom:none !important}
.cal-day-view-body .cdm-item:hover{background:rgba(255,255,255,.03) !important}
.cdm-item .cdm-stripe{background:var(--cdm-color,var(--muted)) !important}
.cdm-item .cdm-status{background:color-mix(in srgb,var(--cdm-color) 16%,transparent) !important;color:var(--cdm-color) !important}

/* ── Calendar WEEK view → a "long" version of the month grid: borderless,
   transparent cells (no gridlines/outlines), purple today, event pills inherited. ── */
.cal-week-grid{gap:0 !important;background:transparent !important;border:none !important;border-radius:0 !important}
.cal-week-day{background:transparent !important;padding:8px 9px !important}
.cal-week-day.today{background:rgba(124,92,255,.10) !important;border-radius:10px}
.cal-week-day-head{border-bottom:1px solid rgba(255,255,255,.06) !important;padding-bottom:8px !important;margin-bottom:6px !important}
.cal-week-day-name{color:rgba(235,235,245,.4) !important;font-size:10px !important}
.cal-week-day-num{color:rgba(235,235,245,.75) !important;font-size:16px !important}
.cal-week-day.today .cal-week-day-num{color:#c9b8ff !important}

/* ── New-automation builder: the trigger/action tiles FLOAT (no card background,
   border or shadow); the backdrop blurs + darkens; emoji icon boxes are gone.
   Layout is unchanged — just the chrome removed. ── */
.card-modal-overlay:has(.auto-builder){background:rgba(0,0,0,.74) !important;backdrop-filter:blur(11px) saturate(120%);-webkit-backdrop-filter:blur(11px) saturate(120%)}
.auto-builder .azp-step{background:none !important;border:none !important;box-shadow:none !important}
.auto-builder .azp-step-empty{border:1.5px dashed var(--border-d) !important;background:none !important}
.auto-builder .azp-step-ico{background:none !important}
.auto-builder .azp-step-ico:empty{display:none}
.auto-builder .azp-step-empty .azp-step-ico{display:flex;background:rgba(255,255,255,.05) !important}
.auto-builder .azp-step-config{background:none !important;border:none !important;border-left:none !important;border-radius:0;padding-left:16px}

/* Task pop-up (card modal) → same background as the sidebar. */
.card-modal{background:#0c0c0e}

/* ── Automations LIST → mockup: gridded page bg + retro recipe cards (pixel
   font names, when/then/and keyword chips, purple toggle). ── */
.azp-page{background-color:var(--bg-app);background-image:linear-gradient(var(--hairline-2) 1px,transparent 1px),linear-gradient(90deg,var(--hairline-2) 1px,transparent 1px);background-size:24px 24px}
.azp-recipes-count{margin:16px 0 12px !important;font-size:11px !important;letter-spacing:.6px;color:rgba(235,235,245,.35) !important}
.azp-recipes-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;max-width:980px}
.azp-recipe{background:var(--dark);border:1px solid var(--hairline-2);border-radius:14px;padding:16px 17px;cursor:pointer;box-shadow:0 10px 26px rgba(0,0,0,.3);transition:border-color .15s,opacity .2s}
.azp-recipe:hover{border-color:rgba(255,255,255,.16)}
.azp-recipe-off{opacity:.62}
.azp-recipe-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.azp-recipe-name{font-family:var(--sans);font-size:14px;font-weight:600;color:var(--text-1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.azp-recipe-lines{margin-top:14px;display:flex;flex-direction:column;gap:9px}
.azp-recipe-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.azp-recipe-txt{font-family:var(--sans);font-size:13px;color:rgba(235,235,245,.8);line-height:1.45}
.azp-kw{font-family:var(--pixel);font-size:10px;font-weight:700;border-radius:5px;padding:3px 8px;letter-spacing:.3px;flex:none}
.azp-kw-when{color:#5E9CFF;background:rgba(94,156,255,.14)}
.azp-kw-then{color:#c4b0ff;background:rgba(167,139,250,.16)}
.azp-kw-and{color:rgba(196,176,255,.6);background:rgba(167,139,250,.08)}
.azp-recipe-switch{width:40px;height:23px;flex:none;margin-top:0}
.azp-recipe-switch .auto-switch-slider:before{width:19px;height:19px;left:2px;top:2px}
.azp-recipe-switch input:checked+.auto-switch-slider{background:#7c5cff !important}
.azp-recipe-switch input:checked+.auto-switch-slider:before{transform:translateX(17px)}
/* Template cards: drop the emoji icon slot (removed in render). */
.azp-tmpl-ico{display:none}

/* Automations page header + tabs → mockup: code-comment title, purple New button, pill tabs. */
.azp-topbar{display:flex;align-items:center;gap:14px}
.azp-comment{font-family:var(--pixel);font-size:11px;color:rgba(235,235,245,.4);letter-spacing:.4px}
.azp-new-btn{margin-left:auto;display:inline-flex;align-items:center;gap:8px;height:38px;padding:0 16px;border-radius:11px;background:#7c5cff;border:none;cursor:pointer;font:600 14px var(--sans);color:#fff;box-shadow:0 8px 22px rgba(124,92,255,.32)}
.azp-new-btn:hover{background:#6b4ef0}
.azp-tabpills{display:flex;gap:8px;margin-top:18px;align-items:center}
.azp-tabpill{height:32px;display:flex;align-items:center;padding:0 14px;border-radius:16px;background:var(--bg-inset);border:none;color:var(--text-2);font:600 13px var(--sans);cursor:pointer;transition:background .15s,color .15s}
.azp-tabpill:hover{background:#26262c;color:#fff}
.azp-tabpill.active{background:color-mix(in srgb,var(--ws-accent,var(--purple)) 22%,transparent);color:color-mix(in srgb,var(--ws-accent,var(--purple)) 45%,var(--text-1))}
/* Small round + beside the tab pills (replaces the big right-side New buttons) */
/* + matches the neighboring tab pills (was solid purple with a glow) */
.azp-plus-sm{width:32px;height:32px;flex:none;display:inline-flex;align-items:center;justify-content:center;border-radius:16px;background:#1d1d22;border:none;color:rgba(235,235,245,.7);cursor:pointer;transition:background .15s,color .15s,transform .12s}
.azp-plus-sm:hover{background:#26262c;color:#fff}
.azp-plus-sm:hover{background:color-mix(in srgb,var(--ws-accent,var(--purple)) 32%,transparent);color:var(--text-1)}
.azp-plus-sm:active{transform:scale(.94)}
/* Canvas header + Notes list view */
/* Match the Automations header EXACTLY (same left + top offset, same pixel caption + pill
   spacing) so switching Canvas ⇄ Automations doesn't shift the caption or the pills. The
   ws-canvas-topbar padding compensates for #cwWidgetsView (padding:0) vs the automations
   .azp-page wrapper so both captions land at the same left; caption font inherits the base
   pixel .azp-comment (the sans override is removed). */
.ws-canvas-topbar{padding:0 16px 0}
/* Owner wants "a canvas for your project" in our regular sans, not the pixel face. */
.ws-canvas-topbar .azp-comment{font-family:var(--sans);font-size:13px;font-weight:500;letter-spacing:normal;text-transform:none}
.ws-canvas-tabs{padding:0 16px;margin-top:18px}
.ws-canvas-notes{flex:1 1 auto;min-height:480px;overflow-y:auto;padding:16px 22px 40px}
.ws-cnotes-list{display:flex;flex-direction:column;gap:8px;max-width:680px}
.ws-cnotes-row{display:flex;align-items:flex-start;gap:11px;padding:12px 15px;border-radius:12px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);cursor:pointer;transition:background .15s,border-color .15s}
.ws-cnotes-row:hover{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.13)}
.ws-cnotes-dot{width:10px;height:10px;border-radius:3px;flex:none;margin-top:4px}
.ws-cnotes-main{display:flex;flex-direction:column;gap:3px;min-width:0}
.ws-cnotes-title{font:600 14px var(--sans);color:var(--off-white);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-cnotes-prev{font:400 12px var(--sans);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ws-cnotes-empty{padding:36px 0;color:var(--muted);font:500 13px var(--sans)}
/* Claude MCP connect modal */
.mcp-row-label{font:700 11px var(--sans);text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin:14px 0 5px}
.mcp-hint{font-weight:500;text-transform:none;letter-spacing:0;opacity:.8}
.mcp-code-row{display:flex;align-items:stretch;gap:6px;min-width:0}
.mcp-code{flex:1;min-width:0;font:500 12px var(--mono);color:var(--off-white);background:rgba(255,255,255,.05);border:1px solid var(--border-d);border-radius:8px;padding:7px 9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mcp-code-wrap{white-space:normal;word-break:break-all;text-overflow:clip}
.mcp-copy-btn{flex:none;padding:0 12px;border-radius:8px;border:none;background:#7c5cff;color:#fff;font:600 12px var(--sans);cursor:pointer}
.mcp-copy-btn:hover{background:#6b4ef0}
/* Home — Team Clocks card */
.hh-clocks .hh-card-body{display:flex;flex-direction:column;gap:2px}
.hc-row{display:flex;align-items:center;gap:9px;padding:6px 4px;border-radius:8px}
.hc-row.hc-me{background:rgba(124,92,255,.08)}
.hc-av{width:24px;height:24px;border-radius:50%;overflow:hidden;flex:none}
.hc-name{font:600 13px var(--sans);color:var(--off-white);display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hc-dot{width:7px;height:7px;border-radius:50%;background:#7ccf84;flex:none}
.hc-city{font:500 11px var(--sans);color:var(--muted);margin-left:auto;white-space:nowrap}
.hc-time{font:700 13px var(--sans);color:var(--cream);font-variant-numeric:tabular-nums;min-width:62px;text-align:right}
/* Home → Team Members (right rail): clickable member rows w/ online / last-seen. */
.hh-team .hh-card-body{display:flex;flex-direction:column;gap:2px}
.tm-row{display:flex;align-items:center;gap:10px;padding:8px;border-radius:9px;cursor:pointer;transition:background .12s}
.tm-row:hover{background:rgba(255,255,255,.05)}
.tm-row.tm-me{background:rgba(124,92,255,.08)}
.tm-row.tm-me:hover{background:rgba(124,92,255,.14)}
.tm-av{width:30px;height:30px;border-radius:50%;overflow:hidden;flex:none}
/* ── Coming up ──────────────────────────────────────────────────────────────────
   Bars, not a number. The question is distribution — four deliveries on Thursday and
   nothing either side is a different week from four spread out. Every day keeps a
   visible floor so an empty day reads as a day rather than a gap in the row. */
.hh-load{margin-bottom:16px}
.hh-load .hh-card-body{padding-top:10px}
.hl-strip{display:flex;align-items:flex-end;gap:6px;height:118px}
.hl-day{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:5px;height:100%;
  border-radius:9px;padding:6px 2px 4px;transition:background .12s ease}
.hl-day:hover{background:var(--state-hover)}
.hl-col{flex:1;width:100%;display:flex;align-items:flex-end;justify-content:center;min-height:0}
.hl-bar{display:block;width:min(100%,34px);border-radius:6px 6px 3px 3px;
  background:color-mix(in srgb,var(--purple) 55%,transparent);transition:height .22s var(--ease-std,ease)}
.hl-day.is-empty .hl-bar{background:var(--state-hover)}
.hl-day.is-today .hl-bar{background:var(--purple)}
.hl-day.is-weekend .hl-bar{background:color-mix(in srgb,var(--purple) 26%,transparent)}
.hl-n{font:700 11px var(--sans);color:var(--cream);line-height:1;min-height:11px;font-variant-numeric:tabular-nums}
.hl-lbl{font:600 10px var(--sans);color:var(--text-3);white-space:nowrap;letter-spacing:.2px}
.hl-day.is-today .hl-lbl{color:var(--cream)}
.hl-strip.hl-dense{gap:3px}
.hl-strip.hl-dense .hl-bar{width:min(100%,18px)}
.hl-strip.hl-dense .hl-lbl{font-size:9px}
.hl-range{flex:none}

/* ── Needs attention / Overdue ─────────────────────────────────────────────────── */
.na-row{display:flex;align-items:center;gap:10px;padding:8px;border-radius:9px;transition:background .12s}
.na-task{cursor:pointer}
.na-row:hover{background:var(--state-hover)}
.na-idcol{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.na-name{font:600 13px var(--sans);color:var(--off-white);min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.na-sub{font:500 11px var(--sans);color:var(--text-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.na-counts{display:inline-flex;align-items:center;gap:6px;flex:none}
.na-pill{display:inline-flex;align-items:center;height:var(--pill-h);padding:0 var(--pill-pad-x);
  border-radius:var(--pill-radius);font-size:11px;font-weight:var(--pill-font-weight);line-height:1;flex:none;white-space:nowrap}
.na-over{background:color-mix(in srgb,var(--prio-high,#ff6b6b) 18%,transparent);color:var(--prio-high,#ff6b6b)}
.na-soon{background:color-mix(in srgb,var(--gold,#e7ce3a) 18%,transparent);color:var(--gold,#e7ce3a)}
.tm-idcol{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.tm-name{font:600 14px var(--sans);color:var(--off-white);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tm-sub{font:500 11px var(--sans);color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tm-sub .hc-time{font:500 11px var(--sans);color:var(--text-3);min-width:0;text-align:left}
/* margin-left:auto is for the old .tm-row flex layout, where status floated to the right
   edge. In the roster's grid it pushed the value away from its own column heading while
   every other cell sat at its left padding — reset below. */
.tm-status{margin-left:auto;font:600 12px var(--sans);white-space:nowrap;display:inline-flex;align-items:center;gap:6px;flex:none}
.tm-online{color:#7ccf84}
.tm-offline{color:var(--muted)}
/* Un-activated invite: whole row reads muted, status pill says "Pending invite". */
.tm-pending{color:var(--muted);font-weight:600;opacity:.9;padding:2px 8px;border:1px solid var(--line);border-radius:20px;font-size:11px}
.tm-row.tm-pending-row{opacity:.55}
.tm-row.tm-pending-row:hover{opacity:.8}
.tm-dot{width:7px;height:7px;border-radius:50%;background:#7ccf84;flex:none;box-shadow:0 0 0 3px rgba(124,207,132,.18)}
html[data-theme="light"] .tm-row:hover{background:rgba(0,0,0,.04)}
/* ── henshu brand lockup: [gradient pixel-H mark] + wordmark (+ optional sub-brand) ── */
.henshu-logo{display:flex;align-items:center;justify-content:center;gap:13px}
.henshu-logo-mark{width:auto;height:40px;display:block;flex:none;border-radius:10px}
.henshu-logo .login-title{margin:0}
.login-logo{margin-bottom:26px}
.henshu-logo-sub{font:700 11px var(--pixel);color:#a78bfa;letter-spacing:2px;text-transform:uppercase;align-self:center;margin-left:2px}
.pub-rev-mark{width:26px;height:26px;border-radius:7px;display:block;margin-right:10px;box-shadow:0 4px 14px rgba(124,92,255,.3)}

/* ── Automations background: dark base + line grid + vignette, painted on a
   pseudo-element so it FADES in/out on every tab switch (opacity transition),
   softened at the top with a gradient mask so the grid doesn't clash with the
   header/tabs. Grid spans the ENTIRE page (behind header + toolbar + content). */
/* isolation:isolate makes the page a stacking context so the z-index:-1 grid
   pseudo paints ABOVE the page's own opaque background (it was hiding behind it). */
#page-custom-workshop.active,#page-workshop.active{position:relative;isolation:isolate}
#page-custom-workshop.active::before,#page-workshop.active::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  opacity:0;transition:opacity .45s ease;
}
body.view-automations #page-custom-workshop.active,
body.view-automations #page-workshop.active{background-color:var(--bg-canvas) !important}
body.view-automations #page-custom-workshop.active::before,
body.view-automations #page-workshop.active::before{
  opacity:1;
  background-image:
    radial-gradient(ellipse 125% 130% at 50% 42%,transparent 62%,rgba(0,0,0,.3) 100%),
    linear-gradient(rgba(255,255,255,.04) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.04) 1px,transparent 1px);
  background-size:100% 100%,24px 24px,24px 24px;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 118px);
  mask-image:linear-gradient(to bottom,transparent 0,#000 118px);
}
/* Canvas grid — same page-level treatment as automations (full-screen, same 24px spacing,
   vignette, top mask, opacity fade-in) but DOTTED instead of ruled lines. The canvas iframe
   is transparent so this one page grid shows through behind the notes (the iframe's own grid
   is display:none), so nothing double-draws or shifts. */
body.view-widgets #page-custom-workshop.active,
body.view-widgets #page-workshop.active{background-color:var(--bg-canvas) !important}
body.view-widgets #page-custom-workshop.active::before,
body.view-widgets #page-workshop.active::before{
  opacity:1;
  /* Vignette only. The dot lattice moved into the board itself so it pans and zooms with
     the content; a second, screen-fixed copy here would slide against it. */
  background-image:
    radial-gradient(ellipse 125% 130% at 50% 42%,transparent 68%,rgba(0,0,0,.22) 100%);
  background-size:100% 100%;
  /* Dots default to the CELL CENTRE (12,12); the automations ruled lines sit on the cell
     EDGES (0,24,48). Shift the dot layer by half a cell so a dot lands on every line
     intersection — the two grids now share one lattice and don't jump when you switch tabs. */
  background-position:0 0,12px 12px;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 118px);
  mask-image:linear-gradient(to bottom,transparent 0,#000 118px);
}
/* Canvas "+ new widget" button — positioned to sit in the EXACT same spot as the
   automations "+ New automation" button (below the toolbar / Settings), and styled
   identically (.azp-new-btn: 38px tall, 0 16px pad, 14px/600, soft purple glow). */
.ws-canvas-add{position:fixed;top:180px;right:16px;z-index:40;display:inline-flex;align-items:center;gap:8px;height:38px;padding:0 16px;border:none;border-radius:11px;background:#7c5cff;color:#fff;font:600 14px var(--sans);cursor:pointer;box-shadow:0 8px 22px rgba(124,92,255,.32);transition:background .18s ease}
.ws-canvas-add:hover{background:#6b4ef0}
.ws-canvas-add svg{width:16px;height:16px}
.ws-canvas-add:active{transform:translateY(0) scale(.97)}
.ws-canvas-add svg{width:16px;height:16px}
/* .azp-page no longer needs its own grid; align its content left with the view tabs. */
.azp-page{background:none !important;background-image:none !important;padding:0 16px 16px !important}
/* New-automation popup: no modal container — just the floating IF / THEN / AND on the blurred backdrop. */
.auto-builder{background:none !important;border:none !important;box-shadow:none !important}
.auto-builder .azp-editor{border:none !important;background-color:transparent !important;padding:14px 0 !important;margin-top:6px}
.auto-builder .auto-builder-foot{border-top:none !important;background:none !important}
/* Automation (recipe) cards: no outline, our purple at 30%. */
.azp-recipe{background:rgba(124,92,255,.3) !important;border:none !important;box-shadow:none !important}
/* ============================================================================
   MOBILE UI REBUILD — Automations (turn 3 'auto'). Reference: graph-paper grid
   canvas, surface recipe cards, Silkscreen names / Pixelify labels, keyword
   tokens, soft-purple filter pills. Restores the grid on mobile (a global rule
   above flattens it) and fixes hardcoded-light text. Mobile-scoped.
   ============================================================================ */
body[data-mobile-mode="app"] .azp-page{
  background-color:var(--bg2) !important;
  background-image:linear-gradient(rgba(var(--line),0.045) 1px,transparent 1px),linear-gradient(90deg,rgba(var(--line),0.045) 1px,transparent 1px) !important;
  background-size:24px 24px !important;padding:4px 14px 16px !important
}
body[data-mobile-mode="app"] .azp-recipe{
  background:var(--surface) !important;border:0 !important;border-radius:14px !important;
  padding:14px 15px !important;box-shadow:0 1px 3px rgba(0,0,0,.06) !important
}
body[data-mobile-mode="app"] .azp-recipes-grid{grid-template-columns:1fr !important;gap:12px}
body[data-mobile-mode="app"] .azp-recipe-name{font-family:var(--pixel);font-size:15px;font-weight:400;color:var(--ink-solid)}
body[data-mobile-mode="app"] .azp-recipe-txt{font-family:var(--pixel);font-size:12px;color:rgba(var(--ink),0.78)}
body[data-mobile-mode="app"] .azp-kw{font-family:var(--pixel);font-size:9px}
body[data-mobile-mode="app"] .azp-pixlabel,
body[data-mobile-mode="app"] .azp-comment{font-family:var(--pixel-id);color:rgba(var(--ink),0.45)}
body[data-mobile-mode="app"] .azp-new-btn{background:var(--m-accent) !important;border-radius:14px;color:#fff}

/* ── @mention chips: people = lighter purple + PFP, tasks = light-grey rounded
   box (no outline) + status square. Page tagging is gone. ── */
/* One metric for EVERY chip variant. Without a fixed height, a person chip (15px
   avatar) rendered taller than a task chip (8px status square) on the same line —
   the inconsistency the owner flagged. Height + line-height are now locked, so the
   leading glyph only changes what is INSIDE the chip, never its box. */
.mention,.mention-chip{display:inline-flex;align-items:center;gap:var(--pill-gap);vertical-align:middle;height:var(--pill-h);padding:0 var(--pill-pad-x) 0 var(--pill-pad-lead) !important;border-radius:var(--pill-radius) !important;line-height:1;box-sizing:border-box;max-width:100%;min-width:0}
.mention-person,.mention-chip[data-type="person"],.mention-chip[data-type="bot"]{color:#cbbdff !important;background:rgba(124,92,255,.24) !important;border:none !important}
.mention-person:hover,.mention-chip[data-type="person"]:hover,.mention-chip[data-type="bot"]:hover{background:rgba(124,92,255,.34) !important}
.mention-task,.mention-chip[data-type="task"]{color:var(--cream) !important;background:rgba(255,255,255,.07) !important;border:none !important;border-radius:8px !important}
.mention-task:hover,.mention-chip[data-type="task"]:hover{background:rgba(255,255,255,.12) !important}
.mention-project,.mention-chip[data-type="project"]{color:#cbbdff !important;background:rgba(124,92,255,.18) !important;border:none !important;border-radius:8px !important}
.mention-project:hover,.mention-chip[data-type="project"]:hover{background:rgba(124,92,255,.28) !important}
/* Task status square (rounded) to the left of the name. */
.mention-chip-status{width:8px;height:8px;border-radius:2px;background:var(--muted,#9a9aa2);flex:none;display:inline-block}
/* C4: person PFP avatar inside the chip — centered, no outline. The base .card-avatar carries a
   2px border meant for overlapping avatar stacks; inside a mention chip it read as an ugly ring,
   so drop it and center the inner img/svg. */
.mention .card-avatar,.mention .person-avatar,
.mention-chip .card-avatar,.mention-chip .person-avatar{width:15px !important;height:15px !important;min-width:15px;border:none !important;border-radius:50% !important;flex:none;overflow:hidden;display:inline-flex !important;align-items:center;justify-content:center;padding:0 !important}
/* Sizing applies to every glyph in a chip; the CIRCLE does not. border-radius:50% plus
   overflow:hidden is an AVATAR treatment — cropping a square photo to a round one. Applied
   to a folder or file glyph it clipped the corners off the drawing, which is why those
   icons looked cut in half. Circle only where there is a face. */
.mention .card-avatar img,.mention .card-avatar svg,.mention img,.mention svg,
.mention-chip .card-avatar img,.mention-chip .card-avatar svg,.mention-chip img,.mention-chip svg{
  width:15px !important;height:15px !important;min-width:15px;flex:none;display:block}
.mention .card-avatar img,.mention .card-avatar svg,
.mention-chip .card-avatar img,.mention-chip .card-avatar svg,
.mention-person > img,.mention-chip[data-type="person"] > img{
  border-radius:50% !important;object-fit:cover}
/* A drawn glyph keeps its own geometry and is never cropped. */
.mention-chip[data-type="file"] > svg,.mention-chip[data-type="folder"] > svg,
.mention-chip[data-type="project"] > svg,.mention-chip[data-type="task"] > svg,
.mention-file > svg,.mention-folder > svg,.mention-project > svg,.mention-task > svg{
  border-radius:0 !important;overflow:visible;object-fit:contain}
/* An emote in a chip is a picture, not an avatar — never crop it round either. */
.mention img.inline-emote,.mention-chip img.inline-emote{border-radius:2px !important;object-fit:contain}
.mention-task-ico{width:12px !important;height:12px !important;min-width:12px;
  color:var(--mn-color,var(--muted));opacity:.9}
.mention-chip-label{line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
/* C4: popup row avatar — center it, no border. */
.mention-item .mention-avatar{border:none !important}
.mention-item .mention-avatar img,.mention-item .mention-avatar svg{width:100% !important;height:100% !important;object-fit:cover;display:block;border-radius:50%}
/* Hard cap the @mention popup + its avatar so a real photo can never blow up to full size
   or inherit a hue-rotate filter ("users pop up green and massive"). */
.mention-popup{width:300px !important;max-width:320px !important}
.mention-popup .mention-avatar{width:22px !important;height:22px !important;min-width:22px !important;max-width:22px !important;flex:none !important;border-radius:50% !important;overflow:hidden !important;filter:none !important}
.mention-popup .mention-avatar img,.mention-popup .mention-avatar svg{width:22px !important;height:22px !important;max-width:22px !important;max-height:22px !important;object-fit:cover !important;filter:none !important}

/* New-automation popup: "Name this automation" the same width as the IF/THEN tiles,
   the whole floating column tightened + centered. */
.card-modal.auto-builder{max-width:560px !important;margin:0 auto !important}
.auto-builder .auto-name-input{width:100% !important;box-sizing:border-box;margin-bottom:18px}
.auto-builder .azp-chain{width:100%}
/* ===== Files — Dropbox-style file manager (Miller columns) ===== */
.content:has(#page-files.active){padding:0 !important;overflow:hidden !important}
#page-files.active{height:100%}
.fm-wrap{height:100%;display:flex;flex-direction:column;min-height:0;background:var(--bg-canvas)}

/* ============================================================================
   #5 — MOBILE FILES (Google-Drive-style). Search + quick-filter chips + grid⇄list
   tiles + long-press action sheet + preview overlay + FAB. Mobile-scoped; the
   desktop Miller-column layout (.fm-*) is untouched.
   ============================================================================ */
body[data-mobile-mode="app"] #page-files.active{position:fixed;inset:0;height:auto;background:var(--bg-main);z-index:1}
body[data-mobile-mode="app"] .hdm-wrap{position:absolute;inset:0;overflow-y:auto;-webkit-overflow-scrolling:touch;background:var(--bg-main);
  padding:var(--m-app-header-h, calc(74px + env(safe-area-inset-top,0px))) 0 calc(120px + env(safe-area-inset-bottom,0px))}
body[data-mobile-mode="app"] .hdm-title{font-family:var(--sans);font-size:30px;font-weight:700;letter-spacing:.3px;line-height:1.2;color:var(--ink-solid);padding:14px 16px 8px;margin:0}
/* Toolbar — search + layout toggle */
body[data-mobile-mode="app"] .hdm-toolbar{display:flex;align-items:center;gap:10px;padding:4px 16px 10px}
body[data-mobile-mode="app"] .hdm-search{flex:1;min-width:0;display:flex;align-items:center;gap:8px;background:rgba(var(--line),0.07);border-radius:12px;padding:9px 12px;color:rgba(var(--ink),0.6)}
body[data-mobile-mode="app"] .hdm-search svg{flex:none}
body[data-mobile-mode="app"] .hdm-search input{flex:1;min-width:0;background:none;border:0;outline:0;color:var(--ink-solid);font-family:var(--sans);font-size:16px}
body[data-mobile-mode="app"] .hdm-search-x{flex:none;display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:0;background:none;color:rgba(var(--ink),0.55);cursor:pointer;padding:0}
body[data-mobile-mode="app"] .hdm-viewtog{flex:none;width:42px;height:42px;border-radius:12px;background:rgba(var(--line),0.07);border:0;display:flex;align-items:center;justify-content:center;color:var(--ink-solid);cursor:pointer;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .hdm-viewtog:active{background:rgba(var(--line),0.12)}
/* Breadcrumb (inside a folder) */
body[data-mobile-mode="app"] .hdm-crumb{display:flex;align-items:center;gap:6px;padding:0 16px 10px;min-width:0}
body[data-mobile-mode="app"] .hdm-back{flex:none;display:inline-flex;align-items:center;gap:2px;border:0;background:none;color:var(--m-accent);font-family:var(--sans);font-size:15px;font-weight:600;cursor:pointer;padding:0;max-width:55%}
body[data-mobile-mode="app"] .hdm-back span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-crumb-cur{flex:1;min-width:0;font-size:15px;font-weight:600;color:rgba(var(--ink),0.5);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-crumb-cur::before{content:"/ ";opacity:.5}
/* Chips */
body[data-mobile-mode="app"] .hdm-chips{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;padding:2px 16px 12px}
body[data-mobile-mode="app"] .hdm-chips::-webkit-scrollbar{display:none}
body[data-mobile-mode="app"] .hdm-chip{flex:none;border:0;background:rgba(var(--line),0.07);color:rgba(var(--ink),0.7);font-family:var(--sans);font-size:14px;font-weight:600;height:34px;padding:0 15px;border-radius:17px;cursor:pointer;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .hdm-chip.on{background:var(--m-accent-soft);color:#16121f}
body[data-mobile-mode="app"] .hdm-reslbl{padding:0 18px 10px;font-size:13px;font-weight:600;color:rgba(var(--ink),0.5)}
/* Items — grid + list */
body[data-mobile-mode="app"] .hdm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px;padding:0 16px}
body[data-mobile-mode="app"] .hdm-tile{position:relative;background:var(--surface);border:1px solid var(--border-d);border-radius:14px;padding:10px;display:flex;flex-direction:column;gap:6px;cursor:pointer;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .hdm-tile:active{background:rgba(var(--line),0.05)}
body[data-mobile-mode="app"] .hdm-thumb{position:relative;aspect-ratio:1/1;border-radius:10px;overflow:hidden;background:rgba(var(--line),0.06);display:flex;align-items:center;justify-content:center}
body[data-mobile-mode="app"] .hdm-thumb-img{width:100%;height:100%;object-fit:cover;display:block}
body[data-mobile-mode="app"] .hdm-badge{font-family:var(--mono,monospace);font-size:14px;font-weight:700;letter-spacing:.5px;padding:8px 12px;border-radius:8px;text-align:center;line-height:1}
body[data-mobile-mode="app"] .hdm-tname{font-size:14px;font-weight:600;color:var(--ink-solid);line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-tmeta{font-size:12px;color:rgba(var(--ink),0.45);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-tkebab{position:absolute;top:6px;right:6px;width:28px;height:28px;border:0;background:rgba(0,0,0,.34);border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
body[data-mobile-mode="app"] .hdm-list{display:flex;flex-direction:column;padding:0 16px}
body[data-mobile-mode="app"] .hdm-row{display:flex;align-items:center;gap:12px;padding:11px 4px;border-bottom:0.5px solid rgba(var(--line),0.08);cursor:pointer;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .hdm-row:active{background:rgba(var(--line),0.04)}
body[data-mobile-mode="app"] .hdm-rthumb{position:relative;flex:none;width:44px;height:44px;border-radius:9px;overflow:hidden;background:rgba(var(--line),0.06);display:flex;align-items:center;justify-content:center}
/* Folder / project / task tiles tint from the row's own accent (--proj-accent, set by
   _hdmFolderRow / _hdmFolderTile from _hdFolderAccent), so the container matches the
   glyph inside it. Rows with no colour of their own keep the neutral fill. */
body[data-mobile-mode="app"] .hdm-rthumb-folder,
body[data-mobile-mode="app"] .hdm-thumb-folder{
  background:color-mix(in srgb,var(--proj-accent,transparent) 16%,rgba(var(--line),0.05))
}
body[data-mobile-mode="app"] .hdm-rthumb-img{width:100%;height:100%;object-fit:cover;display:block}
body[data-mobile-mode="app"] .hdm-rbadge{font-family:var(--mono,monospace);font-size:9px;font-weight:700;letter-spacing:.3px;line-height:1;text-align:center;padding:3px 4px;border-radius:5px}
body[data-mobile-mode="app"] .hdm-rmeta{flex:1;min-width:0}
body[data-mobile-mode="app"] .hdm-rname{font-size:15px;font-weight:600;color:var(--ink-solid);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-rsub{font-size:12px;color:rgba(var(--ink),0.45)}
body[data-mobile-mode="app"] .hdm-rkebab,body[data-mobile-mode="app"] .hdm-tkebab.hdm-rkebab{flex:none;width:34px;height:34px;border:0;background:none;color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer}
body[data-mobile-mode="app"] .hdm-star-on{position:absolute;top:5px;left:5px;color:#ffcf3a;font-size:14px;line-height:1;text-shadow:0 1px 3px rgba(0,0,0,.55);z-index:1}
body[data-mobile-mode="app"] .hdm-star-row{position:static;margin-left:4px;font-size:12px;text-shadow:none}
/* Empty states */
body[data-mobile-mode="app"] .hdm-empty{padding:44px 28px;text-align:center;color:rgba(var(--ink),0.5);font-size:14px;line-height:1.6}
body[data-mobile-mode="app"] .hdm-empty-ico{font-size:34px;margin-bottom:10px;opacity:.8}
body[data-mobile-mode="app"] .hdm-link{background:none;border:0;color:var(--m-accent);font:inherit;font-weight:600;cursor:pointer;padding:0}
/* FAB */
body[data-mobile-mode="app"] .hdm-fab{position:fixed;right:18px;bottom:calc(94px + env(safe-area-inset-bottom,0px));width:56px;height:56px;border-radius:18px;border:0;background:var(--m-accent);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:40;box-shadow:0 10px 26px rgba(124,92,255,.44);-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] .hdm-fab:active{transform:scale(.94)}
body[data-mobile-mode="app"] .hdm-fabmenu-ov{position:fixed;inset:0;z-index:50}
body[data-mobile-mode="app"] .hdm-fabmenu{position:absolute;right:18px;bottom:calc(160px + env(safe-area-inset-bottom,0px));min-width:200px;background:var(--surface);border:1px solid var(--border-d);border-radius:14px;overflow:hidden;box-shadow:0 16px 40px rgba(0,0,0,.42);transform-origin:bottom right;animation:hdmPop .16s cubic-bezier(.34,1.56,.64,1)}
@keyframes hdmPop{from{opacity:0;transform:scale(.9) translateY(8px)}to{opacity:1;transform:none}}
body[data-mobile-mode="app"] .hdm-fabm-item{display:flex;align-items:center;gap:13px;width:100%;padding:13px 16px;border:0;background:none;color:var(--ink-solid);font-family:var(--sans);font-size:15px;font-weight:500;cursor:pointer;text-align:left}
body[data-mobile-mode="app"] .hdm-fabm-item:not(:last-child){border-bottom:1px solid rgba(var(--line),0.08)}
body[data-mobile-mode="app"] .hdm-fabm-item:active{background:rgba(var(--line),0.05)}
body[data-mobile-mode="app"] .hdm-fabm-item svg{flex:none;opacity:.85}
/* Long-press action sheet */
body[data-mobile-mode="app"] .hdm-sheet-ov{position:fixed;inset:0;z-index:10050;background:rgba(0,0,0,.42);opacity:0;transition:opacity .2s ease}
body[data-mobile-mode="app"] .hdm-sheet-ov.show{opacity:1}
body[data-mobile-mode="app"] .hdm-sheet{position:absolute;left:0;right:0;bottom:0;background:var(--surface);border-radius:20px 20px 0 0;padding:6px 10px calc(14px + env(safe-area-inset-bottom,0px));transform:translateY(100%);transition:transform .26s cubic-bezier(.22,1,.36,1)}
body[data-mobile-mode="app"] .hdm-sheet-ov.show .hdm-sheet{transform:translateY(0)}
body[data-mobile-mode="app"] .hdm-sheet-grip{width:38px;height:4px;border-radius:2px;background:rgba(var(--ink),0.2);margin:6px auto 6px}
body[data-mobile-mode="app"] .hdm-sheet-name{font-size:13px;font-weight:600;color:rgba(var(--ink),0.5);padding:4px 14px 8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-act{display:flex;align-items:center;gap:15px;width:100%;padding:13px 14px;border:0;background:none;color:var(--ink-solid);font-family:var(--sans);font-size:16px;font-weight:500;cursor:pointer;text-align:left;border-radius:12px}
body[data-mobile-mode="app"] .hdm-act:active{background:rgba(var(--line),0.06)}
body[data-mobile-mode="app"] .hdm-act svg{flex:none;opacity:.85}
body[data-mobile-mode="app"] .hdm-act-danger{color:#ff453a}
/* In-app preview overlay */
body[data-mobile-mode="app"] .hdm-pv-ov{position:fixed;inset:0;z-index:10060;background:#000;display:flex;flex-direction:column;opacity:0;transition:opacity .2s ease}
body[data-mobile-mode="app"] .hdm-pv-ov.show{opacity:1}
body[data-mobile-mode="app"] .hdm-pv-top{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:calc(12px + env(safe-area-inset-top,0px)) 14px 12px;color:#fff}
body[data-mobile-mode="app"] .hdm-pv-name{flex:1;min-width:0;font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] .hdm-pv-actions{flex:none;display:flex;gap:6px}
body[data-mobile-mode="app"] .hdm-pv-btn{width:40px;height:40px;border:0;background:rgba(255,255,255,.13);border-radius:12px;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer}
body[data-mobile-mode="app"] .hdm-pv-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;overflow:auto;padding:0 8px 8px}
body[data-mobile-mode="app"] .hdm-pv-media{max-width:100%;max-height:100%;object-fit:contain}
body[data-mobile-mode="app"] .hdm-pv-ifr{width:100%;height:100%;border:0;background:#fff;border-radius:8px}
body[data-mobile-mode="app"] .hdm-pv-none{display:flex;flex-direction:column;align-items:center;gap:16px;color:#fff}
body[data-mobile-mode="app"] .hdm-pv-bigtag{font-family:var(--mono,monospace);font-size:40px;font-weight:800;letter-spacing:1px}
body[data-mobile-mode="app"] .hdm-pv-nolbl{font-size:13px;color:rgba(255,255,255,.6)}
body[data-mobile-mode="app"] .hdm-btn{padding:11px 24px;border-radius:12px;border:0;background:var(--m-accent);color:#fff;font-family:var(--sans);font-size:15px;font-weight:600;cursor:pointer}
/* Light theme: a soft tile shadow (the badges keep their own dark tint in both themes). */
html[data-theme="light"] body[data-mobile-mode="app"] .hdm-tile{box-shadow:0 1px 3px rgba(0,0,0,.05)}
/* Wraps now: the storage meter is a full-width row above the title/search line. */
.fm-topbar{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:14px 26px 10px;border-bottom:0}
.fm-navbtns{display:inline-flex;gap:4px;flex:none}
.fm-navbtn{width:32px;height:32px;border-radius:50%;border:0;background:transparent;color:var(--cream);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s}
.fm-navbtn svg{width:18px;height:18px}
.fm-navbtn:hover{background:rgba(255,255,255,.08)}
.fm-navbtn[disabled]{opacity:.28;cursor:default;background:transparent}
.fm-crumbs{display:flex;align-items:center;gap:6px;min-width:0;flex:1 1 auto;font:600 15px var(--sans);color:var(--muted);overflow:hidden;white-space:nowrap}
.fm-crumb-link{border:0;background:none;padding:4px 6px;border-radius:6px;color:var(--muted);font:inherit;cursor:pointer}
.fm-crumb-link:hover{background:rgba(255,255,255,.07);color:var(--cream)}
.fm-crumb-sep{color:rgba(235,235,245,.28)}
.fm-crumb-cur{padding:4px 6px;color:#fff;font-weight:700;overflow:hidden;text-overflow:ellipsis}
.fm-filterbar{flex:none;display:flex;align-items:center;gap:8px;padding:2px 26px 12px}
.fm-chip{display:inline-flex;align-items:center;gap:8px;height:32px;padding:0 10px 0 14px;border-radius:8px;border:1px solid var(--border-d);background:transparent;color:var(--cream);font:600 13px var(--sans);cursor:pointer;transition:background .12s,border-color .12s}
.fm-chip svg{width:14px;height:14px;color:var(--muted)}
.fm-chip:hover{background:rgba(255,255,255,.06)}
.fm-chip.on{background:color-mix(in srgb,var(--purple) 18%,transparent);border-color:color-mix(in srgb,var(--purple) 55%,transparent)}
.fm-chip.on svg{color:var(--cream)}
.fm-chip-clear{padding:0 12px;color:var(--muted);border-style:dashed}
.fm-filter-spacer{flex:1}
.fm-ask-shu{display:inline-flex;align-items:center;gap:8px;height:36px;padding:0 15px 0 10px;border-radius:10px;border:0;background:linear-gradient(135deg,color-mix(in srgb,var(--modal-col-color,#7c5cff) 78%,#fff),var(--modal-col-color,#7c5cff));color:#fff;font:600 13px var(--sans);cursor:pointer;flex:none;transition:filter .12s}
.fm-ask-shu:hover{filter:brightness(1.06)}
.fm-ask-shu .shu-av{width:22px;height:22px;image-rendering:pixelated}
.sd-menu-open{transform-origin:top left;animation:sdMenuOpen .22s cubic-bezier(.21,.61,.35,1)}
.fm-filter-dd{min-width:190px}
.fm-ask-pop{width:min(440px,calc(100vw - 32px));padding:10px;border-radius:14px;background:var(--dark);border:1px solid var(--border-d);box-shadow:0 18px 44px rgba(0,0,0,.55)}
.fm-ask-head{display:flex;align-items:center;gap:8px;padding:2px 4px 8px;color:var(--cream);font:700 13px var(--sans)}
.fm-ask-head .shu-av{width:22px;height:22px;image-rendering:pixelated}
.fm-ask-where{margin-left:auto;font:500 11px var(--sans);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:55%}
.fm-ask-out{margin:0 0 8px;max-height:280px;overflow-y:auto;font-size:13px}
.fm-ask-box{display:flex;align-items:flex-end;gap:8px;padding:8px 8px 8px 10px;border-radius:11px;background:var(--bg-inset,rgba(255,255,255,.06));border:1px solid transparent;transition:border-color .15s}
.fm-ask-box:focus-within{border-color:var(--hairline-2)}
.fm-ask-input{flex:1;min-width:0;resize:none;border:0;background:transparent;color:var(--cream);font:500 13px/1.45 var(--sans);outline:none;padding:4px 0}
.fm-ask-input::placeholder{color:var(--muted)}
.fm-ask-go{flex:none}
.fm-ask-thinking{padding:8px 4px 2px;font:500 12px var(--sans);color:var(--muted)}
.fm-ask-shu.on{filter:brightness(1.12)}
.fm-filter-dd .rad-head{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;padding:4px 8px;margin-bottom:4px}
.fm-filter-dd .rad-item{justify-content:space-between}
.fm-filter-check{width:13px;height:13px;color:var(--purple);flex:0 0 auto}
.fm-crumb{display:flex;align-items:center;gap:8px;font:600 14px var(--sans);color:rgba(235,235,245,.55)}
.fm-crumb .on{color:#fff;font-weight:700}
/* F3: the in-page breadcrumb is now a plain folder-name heading (the full path moved to the top). */
html[data-theme="light"] .fm-folder-title{color:#14141a}
/* F3: clickable segments in the app TOP breadcrumb (rendered into #pageTitle on the Files page). */
.tc-crumb-link{cursor:pointer;color:var(--muted,#8b8b93);transition:color .14s}
.tc-crumb-link:hover{color:var(--cream,#e6ded6)}
.tc-crumb-cur{color:inherit}
html[data-theme="light"] .tc-crumb-link{color:#7a7a86}
html[data-theme="light"] .tc-crumb-link:hover{color:#14141a}
.fm-actions{margin-left:auto;display:flex;align-items:center;gap:10px}
/* B5: the Settings-gear + New-folder icon buttons were wonky — inconsistent icon size/centering
   and no hover feedback on the glyph. Lock the box to 34x34, center + size the svg, and add a
   muted→bright icon-colour hover so both icon buttons read as a matched pair. */
.fm-gear{width:34px;height:34px;border-radius:10px;border:1px solid rgba(255,255,255,.1);background:none;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:none;color:rgba(235,235,245,.7);transition:background .14s,border-color .14s,color .14s}
.fm-gear svg{width:16px;height:16px;display:block}
.fm-gear:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.2);color:#fff}
.fm-upload{position:relative;height:34px;padding:0 15px;border-radius:10px;background:linear-gradient(135deg,color-mix(in srgb,var(--modal-col-color,#7c5cff) 78%,#fff),var(--modal-col-color,#7c5cff));border:none;display:inline-flex;align-items:center;gap:7px;cursor:pointer;font:700 13px var(--sans);color:#fff;flex:none}
.fm-upload svg{width:14px;height:14px;display:block;flex:none}
.fm-upload:hover{filter:brightness(1.06)}
.fm-search{display:flex;align-items:center;gap:10px;height:36px;width:260px;padding:0 13px;border-radius:10px;background:rgba(255,255,255,.05);border:1px solid var(--border-d)}
.fm-search input{flex:1;min-width:0;background:none;border:none;outline:none;font:400 13px var(--sans);color:#fff}
.fm-search input::placeholder{color:rgba(235,235,245,.45)}
.fm-cols{flex:1;display:flex;min-height:0}
.fm-col{overflow-y:auto;min-height:0}
.fm-col1{width:270px;flex:none;border-right:1px solid rgba(255,255,255,.06);padding:10px;display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain}
/* Files-page storage bar (above the columns) */
.fm-meter{flex:none;display:flex;align-items:center;gap:10px;padding:5px 7px 11px;margin:0 0 7px;border-bottom:1px solid rgba(255,255,255,.06)}
/* Drag a task onto the sidebar → new project */
.fm-meter-track{flex:1;min-width:0;height:6px;border-radius:4px;background:rgba(255,255,255,.07);overflow:hidden}
.fm-meter-fill{display:block;height:100%;border-radius:4px;background:linear-gradient(90deg,#8b6cff,#7c5cff);transition:width .3s ease}
.fm-meter-fill.is-amber{background:var(--color-warning)}
.fm-meter-fill.is-red{background:var(--color-error)}
.fm-meter-txt{flex:none;font:600 12px var(--sans);color:rgba(235,235,245,.6);white-space:nowrap}
.fm-meter-txt em{font-style:normal;color:rgba(235,235,245,.35);padding:0 1px}
/* Storage meter — inside the Files browser header, on the row ABOVE search/upload. It used
   to be a popup over the sidebar's Files entry, where the number was decoration; here it sits
   beside the controls that spend the quota. Compact and full-width so it reads as a header
   strip rather than a card. */
.fm-meter-row{flex:0 0 100%;order:-1;width:100%;margin:0}
.fm-meter-row:empty{display:none}
.fm-meter-row .fm-meter{padding:0 2px 10px;margin:0;gap:12px}
.fm-meter-row .fm-meter-track{height:5px}
.fm-col2{width:340px;flex:none;border-right:1px solid rgba(255,255,255,.06);padding:10px}
.fm-col3{flex:1;min-width:0;padding:24px 26px;background:#0c0c0e}
/* Drive layout: one list of folders and files, the preview beside it. */
.fm-drive .fm-col2{flex:1 1 auto;width:auto;min-width:0;padding:6px 14px 14px;border-right:0}
.fm-drive .fm-col3-wrap{position:relative;display:flex;flex:0 0 400px;width:400px;min-height:0}
.fm-drive .fm-col3{flex:1 1 auto;width:auto;min-width:0;padding:20px 22px}
.fm-col-resizer{position:absolute;top:0;bottom:0;left:-5px;width:10px;cursor:col-resize;z-index:2;touch-action:none}
.fm-col-resizer::before{content:'';position:absolute;top:0;bottom:0;left:4px;width:1px;background:linear-gradient(to bottom,transparent 0,rgba(255,255,255,.08) 120px,rgba(255,255,255,.08) 100%);transition:background .12s,width .12s,left .12s}
.fm-col-resizer:hover::before,.fm-col-resizer.is-dragging::before,.fm-col-resizer:focus-visible::before{left:3.5px;width:2px;background:linear-gradient(to bottom,transparent 0,var(--purple) 120px,var(--purple) 100%)}
.fm-col-resizer:focus-visible{outline:none}
body.fm-resizing{cursor:col-resize;user-select:none}
body.fm-resizing iframe,body.fm-resizing video{pointer-events:none}
.fm-stage-video .fm-stage-play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:#fff;z-index:2;transition:opacity .15s,transform .15s}
.fm-stage-video .fm-stage-play svg{width:26px;height:26px;margin-left:3px}
.fm-stage-video .fm-stage-play:hover{transform:translate(-50%,-50%) scale(1.06)}
.fm-stage-video.is-playing .fm-stage-play{opacity:0;pointer-events:none}
/* The preview column is a third of what it was, so its blocks stack instead of sitting
   side by side: name and meta on their own line, the actions under them, versions above
   info, and each version row on a grid so nothing lands on top of anything. */
.fm-drive .fm-col3 .fm-detail{flex-wrap:wrap;gap:10px 8px}
.fm-drive .fm-col3 .fm-detail-main{flex:1 1 100%}
.fm-drive .fm-col3 .fm-vi{flex-direction:column;gap:18px}
.fm-drive .fm-col3 .fm-icol{width:auto}
.fm-drive .fm-col3 .fm-vrow{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:10px}
.fm-drive .fm-col3 .fm-vwhen{white-space:normal;line-height:1.3;font-size:12px}
.fm-drive .fm-col3 .fm-vby{white-space:normal}
.fm-drive .fm-col3 .fm-current{white-space:nowrap}
.fm-drive .fm-col3 .fm-status-sel{max-width:150px}
.fm-lhead{display:grid;grid-template-columns:minmax(0,1fr) 130px 150px 90px 44px;align-items:center;gap:10px;padding:6px 12px 8px;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:4px;font:600 12px var(--sans);color:rgba(235,235,245,.55)}
.fm-lsort{display:inline-flex;align-items:center;gap:4px;border:0;background:none;padding:2px 4px;margin-left:-4px;border-radius:5px;color:inherit;font:inherit;cursor:pointer}
.fm-lsort:hover{color:var(--cream);background:rgba(255,255,255,.06)}
.fm-lsort.on{color:var(--cream)}
.fm-lsort svg{width:13px;height:13px}
.fm-crow.fm-lrow{display:grid;grid-template-columns:minmax(0,1fr) 130px 150px 90px 44px;gap:10px;height:46px;padding:0 12px}
.fm-lc{min-width:0;display:flex;align-items:center;gap:10px;font:500 12.5px var(--sans);color:rgba(235,235,245,.6);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fm-lc-name{font-weight:600;color:rgba(235,235,245,.9)}
.fm-lc-name .fm-cname{flex:1 1 auto}
.fm-lc-act{justify-content:flex-end}
.fm-lc-by .card-avatar{border:none;flex:0 0 auto}
.fm-lby-name{overflow:hidden;text-overflow:ellipsis}
.fm-crow.fm-lrow .fm-kebab{opacity:0;transition:opacity .1s}
.fm-crow.fm-lrow:hover .fm-kebab,.fm-crow.fm-lrow.on .fm-kebab{opacity:1}
@media(max-width:1180px){.fm-lhead,.fm-crow.fm-lrow{grid-template-columns:minmax(0,1fr) 110px 90px 44px}.fm-lc-by{display:none}.fm-drive .fm-col3-wrap{flex-basis:340px;width:340px}}
/* Task preview — a task's folder opens as the task, not as a folder of attachments.
   Read-first: the modal stays the one place a task is edited, so this never becomes a
   second editor to keep in step. */
.fm-task{display:flex;flex-direction:column;gap:18px;min-width:0}
.fm-task-head{display:flex;align-items:center;gap:8px}
.fm-task-kind{font:700 9.5px var(--sans);letter-spacing:.7px;text-transform:uppercase;color:var(--purple,#7c5cff)}
.fm-task-col{font:600 10.5px var(--sans);padding:3px 8px;border-radius:20px;border:1px solid var(--border-d);color:var(--muted)}
.fm-task-title{font:800 22px var(--display);color:var(--off-white,#fff);margin:0;line-height:1.2;word-break:break-word}
.fm-task-sec{display:flex;flex-direction:column;gap:7px}
.fm-task-lbl{font:700 9.5px var(--sans);letter-spacing:.7px;text-transform:uppercase;color:var(--muted)}
.fm-task-lbl em{font-style:normal;opacity:.8}
.fm-task-desc{font:400 13px/1.6 var(--sans);color:var(--cream,#e6ded6);word-break:break-word}
.fm-task-desc img{max-width:100%;height:auto;border-radius:8px}
.fm-task-desc ul.desc-checklist{list-style:none;padding:0;margin:6px 0}
.fm-task-none{font:400 12px var(--sans);color:var(--muted)}
.fm-task-props{display:flex;flex-direction:column;gap:5px}
.fm-task-prop{display:flex;align-items:baseline;justify-content:space-between;gap:12px;font-size:12.5px;
  padding:6px 0;border-bottom:1px solid var(--border-d)}
.fm-task-prop:last-child{border-bottom:0}
.fm-task-prop span{color:var(--muted);flex:none}
.fm-task-prop b{color:var(--cream);font-weight:600;text-align:right;min-width:0;word-break:break-word}
.fm-task-tag{color:var(--purple,#7c5cff);font-weight:600}
.fm-task-subs{display:flex;flex-direction:column;gap:4px}
.fm-task-sub{display:flex;align-items:flex-start;gap:9px;font:400 12.5px/1.5 var(--sans);color:var(--cream)}
.fm-task-sub.is-done{color:var(--muted);text-decoration:line-through}
.fm-task-box{flex:none;width:15px;height:15px;margin-top:1px;border-radius:4px;border:1.5px solid var(--border-d);
  display:inline-flex;align-items:center;justify-content:center;font-size:10px;color:#fff}
.fm-task-sub.is-done .fm-task-box{background:var(--green,#5BCF8E);border-color:var(--green,#5BCF8E)}
.fm-task-foot{display:flex;align-items:center;gap:12px;padding-top:4px}
/* flex:none is load-bearing. .fm-col1 is a flex column, so with the default
   flex-shrink:1 every row COMPRESSED once the tree outgrew the column — expanding a
   folder squeezed all 40px rows at once and the folder you just clicked slid upward
   under the cursor. Rows now keep their height and the column scrolls instead. */
.fm-frow{display:flex;align-items:center;gap:11px;height:40px;min-height:40px;flex:none;padding:0 11px;border-radius:9px;cursor:pointer;transition:background .12s}
.fm-frow:hover{background:rgba(255,255,255,.04)}
.fm-frow.on{background:rgba(255,255,255,.06)}
.fm-fname{flex:1;font:600 14px var(--sans);color:rgba(235,235,245,.62);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fm-frow.on .fm-fname{color:#fff;font-weight:700}
.fm-fcount{font:600 11px var(--sans);color:rgba(235,235,245,.4)}
.fm-crow{display:flex;align-items:center;gap:11px;height:44px;padding:0 11px;border-radius:9px;cursor:pointer;transition:background .12s}
.fm-crow:hover{background:rgba(255,255,255,.04)}
/* The selected row takes the task's status colour like everything else in this modal —
   a fixed violet tint under a red task was the only thing in the panel still purple. */
.fm-crow.on{background:color-mix(in srgb,var(--modal-col-color,#7c5cff) 12%,transparent)}
.fm-ico{width:30px;height:30px;border-radius:7px;flex:none;display:flex;align-items:center;justify-content:center;overflow:hidden}
/* Sub-workspace PFPs render circular (not the square folder tile) and fill the icon slot so they
   read a touch bigger than a folder glyph. */
.fm-ws-pfp{border-radius:50%;overflow:hidden;display:inline-flex;align-items:center;justify-content:center}
.fm-ws-pfp img{border-radius:50%}
.fm-ico:has(.fm-ws-pfp){background:none!important;border-radius:50%}
.fm-ico .fm-ws-pfp{width:100%!important;height:100%!important;font-size:14px!important}
.fm-ico-thumb{width:100%;height:100%;object-fit:cover;display:block}
.fm-tag{font:700 7px var(--pixel)}
.fm-cmeta{flex:1;min-width:0}
.fm-cname{font:600 13px var(--sans);color:rgba(235,235,245,.9);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fm-crow.on .fm-cname{color:#fff}
.fm-csize{font:500 11px var(--sans);color:rgba(235,235,245,.42)}
.fm-status{width:8px;height:8px;border-radius:50%;flex:none}
.fm-empty{font:500 13px var(--sans);color:rgba(235,235,245,.4);padding:16px}
.fm-drop{margin:14px 6px 6px}
.fm-stage{border-radius:16px;overflow:hidden;position:relative;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center}
.fm-bigplay{width:64px;height:64px;border-radius:50%;background:rgba(10,10,14,.45);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.25);display:flex;align-items:center;justify-content:center;cursor:pointer}
.fm-bigtag{font:700 30px var(--pixel)}
.fm-stage-tag{position:absolute;left:12px;top:12px;font:600 10px var(--pixel);color:#fff;background:rgba(0,0,0,.5);border-radius:5px;padding:3px 7px}
/* B5: compact the preview detail row. */
.fm-detail{display:flex;align-items:flex-start;gap:12px;margin-top:12px}
.fm-detail-main{flex:1;min-width:0}
/* B4: preview-pane file title was 800 22px and wrapped to many lines. Shrink it and clamp to
   at most 2 lines with an ellipsis so long scene names stay tidy. */
.fm-dname{font:700 15px var(--display);color:#fff;line-height:1.25;word-break:break-word;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.fm-dmeta{font:500 12px var(--sans);color:rgba(235,235,245,.5);margin-top:4px}
.fm-share{height:36px;padding:0 15px;border-radius:10px;background:linear-gradient(135deg,color-mix(in srgb,var(--modal-col-color,#7c5cff) 78%,#fff),var(--modal-col-color,#7c5cff));border:none;display:flex;align-items:center;gap:8px;cursor:pointer;font:600 13px var(--sans);color:#fff;flex:none}
.fm-dl{width:36px;height:36px;border-radius:10px;border:1px solid rgba(255,255,255,.1);background:none;color:rgba(235,235,245,.72);font:600 13px var(--sans);display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none;transition:background .14s,border-color .14s,color .14s}
.fm-share:hover{filter:brightness(1.06)}
.fm-dl:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.2);color:#fff}
.fm-vi{display:flex;gap:16px;margin-top:22px}
.fm-vcol{flex:1;min-width:0}
.fm-icol{width:230px;flex:none}
.fm-sec{font:700 10px var(--pixel);color:rgba(235,235,245,.4);letter-spacing:.4px;margin-bottom:10px}
.fm-vrow{display:flex;align-items:center;gap:11px;padding:9px 10px;border-radius:9px;cursor:pointer;transition:background .12s}
.fm-vrow:hover{background:rgba(255,255,255,.04)}
.fm-vrow.on{background:rgba(124,92,255,.1)}
.fm-vbadge{font:700 10px var(--pixel);color:rgba(235,235,245,.6);background:rgba(255,255,255,.06);border-radius:6px;padding:3px 7px}
.fm-vbadge.on{color:#c4b0ff;background:rgba(124,92,255,.18)}
.fm-vmeta{flex:1;min-width:0}
.fm-vwhen{font:600 13px var(--sans);color:#fff}
.fm-vby{font:500 11px var(--sans);color:rgba(235,235,245,.45)}
.fm-current{font:700 9px var(--pixel);color:#5BCF8E}
.fm-irow{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.06)}
.fm-ik{font:500 12px var(--sans);color:rgba(235,235,245,.5)}
.fm-iv{font:600 12px var(--sans);color:#fff}
.fm-settings-ov{position:fixed;inset:0;z-index:9000;display:flex;align-items:center;justify-content:center;background:rgba(6,6,9,.66);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.fm-settings{position:relative;width:600px;max-width:94vw;max-height:94vh;display:flex;flex-direction:column;background:#131318;border:1px solid rgba(255,255,255,.1);border-radius:20px;box-shadow:0 40px 100px rgba(0,0,0,.7);overflow:hidden}
.fm-set-head{display:flex;align-items:center;gap:13px;padding:22px 24px 18px;border-bottom:1px solid rgba(255,255,255,.07)}
.fm-set-ico{width:40px;height:40px;border-radius:11px;background:rgba(124,92,255,.16);color:var(--purple);display:flex;align-items:center;justify-content:center;flex:none}
.fm-set-title{flex:1;min-width:0}
.fm-set-title>div:first-child{font:800 20px var(--display);color:#fff}
.fm-set-sub{font:500 13px var(--sans);color:rgba(235,235,245,.5);margin-top:2px}
.fm-set-x{width:34px;height:34px;border-radius:9px;border:none;background:none;display:flex;align-items:center;justify-content:center;cursor:pointer}
.fm-set-x:hover{background:rgba(255,255,255,.06)}
.fm-set-body{flex:1;overflow-y:auto;padding:20px 24px 6px}
.fm-src{display:flex;align-items:center;gap:14px;padding:15px 16px;border-radius:14px;background:#0f0f13;border:1px solid var(--border-d);margin-bottom:11px}
.fm-src.on{border-color:rgba(124,92,255,.4)}
.fm-src-ico{width:44px;height:44px;border-radius:11px;display:flex;align-items:center;justify-content:center;flex:none}
.fm-src-txt{flex:1;min-width:0}
.fm-src-name{font:700 14px var(--sans);color:#fff}
.fm-src-sub{font:500 12px var(--sans);color:rgba(235,235,245,.45);margin-top:2px}
.fm-src-sub.on{color:#5BCF8E}
.fm-src-btn{height:34px;padding:0 15px;border-radius:9px;cursor:pointer;font:700 13px var(--sans);background:linear-gradient(135deg,#8b6cff,#7c5cff);color:#fff;border:none}
.fm-src-btn.on{background:rgba(255,255,255,.05);color:rgba(235,235,245,.7);border:1px solid rgba(255,255,255,.14)}
.fm-src-btn:disabled{opacity:.55;cursor:default}
/* Task 3: FTP/SFTP connect form (matches the settings-modal card styling) */
.fm-ftp-form{margin:-4px 0 11px;padding:15px 16px;border-radius:14px;background:#0f0f13;border:1px solid rgba(124,92,255,.4)}
.fm-ftp-grid{display:grid;grid-template-columns:1fr 1fr;gap:11px 12px}
.fm-ftp-col2{grid-column:1 / -1}
.fm-ftp-field{display:flex;flex-direction:column;gap:5px}
.fm-ftp-field>span{font:600 12px var(--sans);color:rgba(235,235,245,.6)}
.fm-ftp-opt{font-weight:500;color:rgba(235,235,245,.35)}
.fm-ftp-in{height:36px;padding:0 11px;border-radius:9px;background:#16161b;border:1px solid rgba(255,255,255,.1);color:#fff;font:500 13px var(--sans);width:100%;box-sizing:border-box}
select.fm-ftp-in{cursor:pointer}
.fm-ftp-in:focus{outline:none;border-color:rgba(124,92,255,.6)}
.fm-ftp-chk{display:flex;align-items:center;gap:9px;font:500 13px var(--sans);color:rgba(235,235,245,.7);cursor:pointer;margin-top:1px}
.fm-ftp-chk input{width:15px;height:15px;accent-color:#7c5cff;flex:none}
.fm-ftp-err{margin-top:11px;padding:9px 12px;border-radius:9px;background:var(--color-error-tint);border:1px solid rgba(239,68,68,.3);font:500 12px/1.45 var(--sans);color:var(--danger-text)}
.fm-ftp-actions{display:flex;justify-content:flex-end;gap:9px;margin-top:13px}
.fm-set-note{display:flex;align-items:flex-start;gap:9px;margin-top:14px;padding:12px 14px;border-radius:12px;background:rgba(124,92,255,.07);border:1px solid rgba(124,92,255,.16)}
.fm-set-note svg{flex:none;margin-top:1px}
.fm-set-note span{font:500 12px/1.5 var(--sans);color:rgba(196,176,255,.9)}
.fm-set-foot{display:flex;align-items:center;gap:10px;padding:16px 24px;border-top:1px solid rgba(255,255,255,.07);font:500 12px var(--sans);color:rgba(235,235,245,.45)}
.fm-set-done{margin-left:auto;height:38px;padding:0 20px;border-radius:10px;background:linear-gradient(135deg,#8b6cff,#7c5cff);border:none;display:flex;align-items:center;cursor:pointer;font:700 13px var(--sans);color:#fff}
@media(max-width:600px){
  body:has(#hdFilesSettingsDialog) .m-bottom-nav{display:none!important}
  .fm-settings{width:calc(100vw - 16px);max-width:none;max-height:calc(100dvh - 64px);border-radius:18px}
  .fm-set-head{gap:11px;padding:18px 16px 15px}
  .fm-set-body{padding:18px 16px 10px}
  .fm-set-foot{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px))}
  .fm-src{display:grid;grid-template-columns:44px minmax(0,1fr);gap:10px 12px;align-items:center;padding:14px}
  .fm-src-ico{grid-column:1;grid-row:1}
  .fm-src-txt{grid-column:2;grid-row:1}
  .fm-src-btn{grid-column:1 / -1;width:100%;margin:0}
}
/* ===== Review: inline top-right Share dropdown (replaces the bottom sheet) ===== */
.rev-share-pop{position:fixed;z-index:99999;width:340px;max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);display:flex;flex-direction:column;background:#16161b;border:1px solid rgba(255,255,255,.1);border-radius:14px;box-shadow:0 24px 60px rgba(0,0,0,.6);overflow:hidden;animation:revSpIn .16s ease}
.rev-share-pop .hd-share-list{overflow-y:auto;min-height:0}
@keyframes revSpIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}
.rev-sp-head{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--hairline-2);font:700 14px var(--sans);color:var(--text-1)}
.rev-sp-x{width:28px;height:28px;border:none;background:none;color:var(--text-2);border-radius:7px;display:flex;align-items:center;justify-content:center;cursor:pointer}
.rev-sp-x:hover{background:var(--bg-inset);color:var(--text-1)}
.rev-sp-body{padding:14px 16px 16px}
.rev-sp-linkrow{display:flex;align-items:center;gap:8px}
.rev-sp-linkrow input{flex:1;min-width:0;height:38px;border-radius:9px;background:var(--bg-inset);border:1px solid var(--hairline-3);color:var(--text-1);font:500 13px var(--mono);padding:0 12px;cursor:pointer;outline:none;text-overflow:ellipsis}
.rev-sp-linkrow input:hover{border-color:color-mix(in srgb,var(--purple) 50%,transparent)}
.rev-sp-copy{width:38px;height:38px;flex:none;border-radius:9px;background:linear-gradient(135deg,#8b6cff,#7c5cff);border:none;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer}
.rev-sp-copy:hover{filter:brightness(1.08)}
.rev-sp-hint{font:400 12px var(--sans);color:var(--text-3);margin-top:8px;line-height:1.4}
.rev-sp-more{display:flex;align-items:center;justify-content:space-between;width:100%;margin-top:12px;padding:9px 11px;border-radius:9px;background:var(--bg-inset);border:1px solid var(--hairline-2);color:var(--cream);font:600 13px var(--sans);cursor:pointer}
.rev-sp-more:hover{background:var(--hairline-2)}
.rev-sp-more.open svg{transform:rotate(180deg)}
.rev-sp-more svg{transition:transform .15s ease}
.rev-sp-opts{margin-top:10px;border-top:1px solid var(--hairline-2);padding-top:4px}
.rev-sp-opts .rev-set-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0}
.rev-sp-opts .rev-set-label{font:500 13px var(--sans);color:var(--cream)}
.rev-sp-opts .rev-seg-group{display:flex;gap:3px;background:rgba(0,0,0,.25);border-radius:8px;padding:3px}
.rev-sp-opts .rev-seg{font:600 12px var(--sans);color:var(--muted);background:none;border:none;border-radius:6px;padding:5px 9px;cursor:pointer;white-space:nowrap}
.rev-sp-opts .rev-seg.on{background:var(--modal-col-color,var(--purple));color:#fff}
.rev-sp-opts .rev-share-pw{width:150px;height:32px;border-radius:8px;background:var(--bg-inset);border:1px solid var(--hairline-3);color:var(--text-1);font:400 13px var(--sans);padding:0 10px;outline:none}
.rev-sp-optbtns{display:flex;gap:8px;margin-top:8px}
.rev-sp-btn{flex:1;height:34px;border-radius:9px;font:700 12px var(--sans);cursor:pointer;border:1px solid var(--hairline-3);background:var(--bg-inset);color:var(--cream)}
.rev-sp-btn:hover{background:var(--hairline-2)}
.rev-sp-apply{background:linear-gradient(135deg,#8b6cff,#7c5cff) !important;border:none !important;color:#fff !important}
.rev-sp-revoke{width:100%;margin-top:10px;padding:8px;border:none;background:none;color:#ff6b6b;font:600 12px var(--sans);cursor:pointer;border-radius:8px}
.rev-sp-revoke:hover{background:rgba(255,107,107,.1)}
/* ===== HDrive: drive tabs, tree, dialogs, upload tray, share/drop lists (extends .fm-*) ===== */
.fm-tabs{flex:none;display:flex;align-items:center;gap:6px;padding:12px 26px 0;border-bottom:none;overflow-x:auto}
.fm-tab{display:flex;align-items:center;gap:7px;height:34px;padding:0 14px;border-radius:10px 10px 0 0;border:1px solid rgba(255,255,255,.07);border-bottom:none;background:rgba(255,255,255,.03);color:rgba(235,235,245,.55);font:600 13px var(--sans);cursor:pointer;white-space:nowrap}
.fm-tab:hover{background:rgba(255,255,255,.06);color:rgba(235,235,245,.8)}
.fm-tab.on{background:rgba(124,92,255,.14);border-color:rgba(124,92,255,.35);color:#fff;font-weight:700}
.fm-tab-add{width:34px;justify-content:center;padding:0;font:700 16px var(--sans);color:rgba(235,235,245,.5)}
.fm-tab-warn{width:15px;height:15px;border-radius:50%;background:#FF8F6B;color:#141414;font:800 10px var(--sans);display:flex;align-items:center;justify-content:center;flex:none}
.fm-crumb-link{cursor:pointer}
.fm-crumb-link:hover{color:#fff}
.fm-link{color:#c4b0ff;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.fm-link:hover{color:#fff}
.fm-twist{width:16px;height:16px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:5px;transition:transform .12s}
.fm-twist:hover{background:var(--state-hover)}
.fm-twist.open{transform:rotate(90deg)}
.fm-twist-empty{pointer-events:none}
.fm-frow-new{margin-top:6px;border:1px dashed rgba(255,255,255,.12)}
.fm-colhead{display:flex;align-items:center;gap:8px;padding:4px 11px 10px;font:600 11px var(--sans);color:rgba(235,235,245,.45)}
.fm-colhead>span:first-child{margin-right:auto}
.fm-sortgrp{display:flex;gap:2px}
.fm-sortbtn{border:none;background:none;color:rgba(235,235,245,.4);font:600 11px var(--sans);padding:3px 7px;border-radius:6px;cursor:pointer}
.fm-sortbtn:hover{background:rgba(255,255,255,.06)}
.fm-sortbtn.on{color:#c4b0ff;background:rgba(124,92,255,.12)}
/* B10: folder access avatars (col2 header, top-right) */
.fm-faces-slot{display:inline-flex;align-items:center}
.fm-faces-slot:empty{display:none}
.fm-faces{display:inline-flex;align-items:center;padding-left:4px}
.fm-face{width:22px;height:22px;border-radius:50%;overflow:hidden;flex:none;margin-left:-6px;border:2px solid #0a0a0b;background:rgba(124,92,255,.22);display:inline-flex;align-items:center;justify-content:center;font:800 9px var(--sans);color:#fff}
.fm-face:first-child{margin-left:0}
.fm-face img{width:100%;height:100%;object-fit:cover;display:block}
.fm-face svg{width:100%;height:100%;display:block}
.fm-face-more{background:rgba(255,255,255,.1);color:rgba(235,235,245,.8);font:800 8.5px var(--sans)}
.fm-ico{position:relative}
.fm-vnum{position:absolute;right:-5px;bottom:-5px;background:#7c5cff;color:#fff;font:800 8px var(--sans);border-radius:6px;padding:1.5px 4px;border:1.5px solid #0a0a0b;line-height:1}
.fm-kebab{width:26px;height:26px;flex:none;border:none;background:none;border-radius:7px;display:none;align-items:center;justify-content:center;cursor:pointer}
.fm-crow:hover .fm-kebab{display:flex}
.fm-kebab:hover{background:rgba(255,255,255,.1)}
.fm-teach{display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;padding:36px 18px;line-height:1.5}
.fm-dropping{outline:2px dashed rgba(124,92,255,.55);outline-offset:-6px;border-radius:12px;background:rgba(124,92,255,.05)}
.fm-droprow{background:rgba(124,92,255,.16)!important;outline:1.5px dashed rgba(124,92,255,.6);outline-offset:-2px}
.fm-dropver{background:rgba(255,215,102,.1)!important;outline:1.5px dashed rgba(255,215,102,.55);outline-offset:-2px}
.fm-stage-media{background:#0a0a0e;aspect-ratio:16/9}
.fm-previmg,.fm-prevvid{max-width:100%;max-height:100%;width:auto;height:100%;object-fit:contain;display:block}
.fm-previfr{width:100%;height:100%;border:none;background:#0a0a0e;color-scheme:dark}
.fm-noprev{position:absolute;bottom:12px;left:0;right:0;text-align:center;font:500 12px var(--sans);color:rgba(235,235,245,.6)}
.fm-vmake{flex:none;border:1px solid rgba(124,92,255,.4);background:none;color:#c4b0ff;font:600 11px var(--sans);border-radius:7px;padding:4px 8px;cursor:pointer;display:none}
.fm-vrow:hover .fm-vmake{display:inline-block}
.fm-vmake:hover{background:rgba(124,92,255,.15)}
.fm-vdl{width:24px;height:24px;flex:none;border:none;background:none;border-radius:6px;display:none;align-items:center;justify-content:center;cursor:pointer}
.fm-vrow:hover .fm-vdl{display:flex}
.fm-vdl:hover{background:var(--state-hover)}
.fm-status-sel{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);color:#fff;font:600 12px var(--sans);border-radius:7px;padding:4px 7px;outline:none;max-width:170px}
.fm-status-sel option{background:#16161b}
/* dialogs */
.fm-dlg-ov{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;background:rgba(6,6,9,.6);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.fm-dlg{width:400px;max-width:92vw;background:#16161b;border:1px solid rgba(255,255,255,.1);border-radius:16px;box-shadow:0 30px 80px rgba(0,0,0,.65);padding:20px}
.fm-dlg-title{font:800 17px var(--display);color:#fff;margin-bottom:8px;word-break:break-word}
.fm-dlg-sub{font:500 13px/1.5 var(--sans);color:rgba(235,235,245,.55);margin-bottom:6px}
.fm-dlg-input{width:100%;height:38px;margin-top:8px;border-radius:9px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);color:#fff;font:500 13px var(--sans);padding:0 12px;outline:none;box-sizing:border-box}
.fm-dlg-input:focus{border-color:rgba(124,92,255,.55)}
.fm-dlg-btns{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;flex-wrap:wrap}
.fm-dlg-btn{height:34px;padding:0 14px;border-radius:9px;border:1px solid rgba(255,255,255,.12);background:none;color:rgba(235,235,245,.75);font:600 13px var(--sans);cursor:pointer}
.fm-dlg-btn:hover{background:rgba(255,255,255,.06)}
.fm-dlg-btn.primary{background:linear-gradient(135deg,#8b6cff,#7c5cff);border:none;color:#fff;font-weight:700}
.fm-dlg-btn.primary:hover{filter:brightness(1.07)}
.fm-share-dest-list{display:flex;flex-direction:column;gap:7px;max-height:min(420px,55vh);overflow:auto;margin:14px 0}
.fm-share-dest{width:100%;min-height:42px;padding:9px 12px;border:1px solid rgba(255,255,255,.12);border-radius:10px;background:rgba(255,255,255,.045);color:var(--cream);font:600 13px var(--sans);text-align:left;cursor:pointer}
.fm-share-dest:hover,.fm-share-dest:focus-visible{border-color:var(--purple);background:rgba(124,92,255,.12);outline:none}
.fm-share-dest:disabled{opacity:.65;cursor:wait}
.fm-share-dest-empty{padding:18px 4px;color:var(--muted);font:500 13px var(--sans)}
.fm-move-list{max-height:300px;overflow-y:auto;margin-top:10px;border:1px solid rgba(255,255,255,.07);border-radius:10px;padding:6px}
.fm-move-row{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:8px;cursor:pointer;font:600 13px var(--sans);color:rgba(235,235,245,.8)}
.fm-move-row:hover{background:rgba(124,92,255,.12);color:#fff}
/* context menu */
.fm-menu{position:fixed;z-index:99999;min-width:178px;background:#16161b;border:1px solid rgba(255,255,255,.1);border-radius:12px;box-shadow:0 20px 50px rgba(0,0,0,.6);padding:5px;animation:revSpIn .14s ease}
.fm-menu-it{display:block;width:100%;text-align:left;border:none;background:none;color:rgba(235,235,245,.85);font:600 13px var(--sans);padding:8px 11px;border-radius:8px;cursor:pointer}
.fm-menu-it:hover{background:rgba(255,255,255,.07);color:#fff}
.fm-menu-it.danger{color:var(--danger-text)}
.fm-menu-it.danger:hover{background:rgba(255,143,107,.1)}
.fm-menu-it.kb-on{background:rgba(255,255,255,.07);color:#fff;outline:none}
.fm-menu-it:focus{outline:none}
.fm-menu-it.is-disabled,.fm-menu-it[disabled]{opacity:.4;cursor:default}
.fm-menu-it.is-disabled:hover,.fm-menu-it[disabled]:hover{background:none;color:rgba(235,235,245,.85)}
.fm-menu-sub{display:flex;align-items:center;justify-content:space-between;gap:10px}
.fm-menu-arr{flex:none;opacity:.55}
.fm-menu-sep{height:1px;background:rgba(255,255,255,.07);margin:4px 6px}
/* B4: task HDrive tab — nested file tree + preview */
.hd-tree-wrap{display:flex;flex-direction:column;height:100%;min-height:360px}
.hd-tree-bar{display:flex;align-items:center;gap:10px;padding:2px 2px 12px}
.hd-tree-title{font:800 14px var(--display,var(--sans));color:#fff;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hd-tree-acts{display:flex;align-items:center;gap:8px;flex:none}
.hd-tree-body{display:flex;gap:14px;flex:1;min-height:0}
.hd-tree-list{flex:0 0 300px;min-width:0;overflow-y:auto;border:1px solid var(--border-d);border-radius:12px;padding:8px;background:rgba(255,255,255,.015)}
.hd-tree-list.fm-dropping{border-color:rgba(124,92,255,.55);background:rgba(124,92,255,.06)}
/* Preview reads as a peer panel of the list (matching container) instead of bare floating text. */
.hd-tree-prev{flex:1;min-width:0;overflow-y:auto;display:flex;flex-direction:column;border:1px solid var(--border-d);border-radius:12px;padding:14px;background:rgba(255,255,255,.015)}
.hd-tree-prev:empty{display:none}
.hd-tree-prev .fm-empty{margin:auto;text-align:center}
.hd-tree-row{display:flex;align-items:center;gap:8px;height:34px;padding:0 8px;border-radius:8px;cursor:pointer;transition:background .12s}
.hd-tree-row:hover{background:rgba(255,255,255,.045)}
/* The sliding selection, not a background that blinks from row to row: the pill travels,
   which is how selection reads everywhere else in the app (sidebar, view tabs, Home tabs). */
.hd-tree-row.on{background:transparent}
.hd-tree-list{position:relative}
.hd-tree-pill{position:absolute;left:0;top:0;border-radius:9px;pointer-events:none;z-index:0;
  background:color-mix(in srgb,var(--modal-col-color,#7c5cff) 15%,transparent);
  opacity:0;transition:transform .18s cubic-bezier(.22,1,.36,1),width .18s cubic-bezier(.22,1,.36,1),height .18s,opacity .12s}
.hd-tree-pill.show{opacity:1}
.hd-tree-row{position:relative;z-index:1}
.hd-tree-row.fm-droprow{background:rgba(124,92,255,.16);box-shadow:inset 0 0 0 1px rgba(124,92,255,.5)}
.hd-tree-row.fm-dropver{box-shadow:inset 0 0 0 1px rgba(127,232,212,.6)}
.hd-tree-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:600 13px var(--sans);color:rgba(235,235,245,.9)}
.hd-tree-row.on .hd-tree-name{color:#fff}
.hd-tree-size{flex:none;font:600 11px var(--sans);color:rgba(235,235,245,.4)}
.hd-tree-tw{width:16px;height:16px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:5px;transition:transform .12s}
.hd-tree-tw.open{transform:rotate(90deg)}
.hd-tree-tw-empty{visibility:hidden}
.hd-tree-file .fm-kebab{margin-left:auto}
/* B2: in-list "uploading" row at the top of the tree, with a live progress bar. */
.hd-tree-uprow{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-1-5) var(--sp-2);border-radius:8px;margin-bottom:2px;background:var(--color-brand-tint);border:1px solid var(--color-brand-tint-strong)}
.hd-tree-upico{width:22px;height:22px;flex:none;display:inline-flex;align-items:center;justify-content:center;border-radius:6px;background:var(--color-brand-tint-strong);color:var(--color-brand-text)}
.hd-tree-upmeta{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--sp-1)}
.hd-tree-upname{font:var(--fw-medium) var(--text-sm) var(--sans);color:var(--color-text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hd-tree-uptrack{position:relative;height:4px;border-radius:3px;background:var(--bg-inset);overflow:hidden}
.hd-tree-upfill{display:block;width:100%;height:100%;border-radius:3px;background:linear-gradient(90deg,var(--color-primary-hover),var(--color-primary));transform:scaleX(0);transform-origin:left center;transition:transform var(--dur-press) var(--ease-std);will-change:transform}
.hd-tree-uppct{flex:none;font:var(--fw-bold) var(--text-2xs) var(--sans);color:var(--color-brand-text);min-width:56px;text-align:right;font-variant-numeric:tabular-nums}
/* B1: multi-selected rows (shift/cmd-click) get a persistent tint distinct from the single .on. */
.hd-tree-row.sel{background:rgba(124,92,255,.20)}
.hd-tree-row.sel:hover{background:rgba(124,92,255,.26)}
.hd-tree-row.sel .hd-tree-name{color:#fff}
/* B1: floating selection bar pinned to the bottom of the tree, "N selected · Download selected". */
.hd-tree-selbar{position:sticky;bottom:0;margin-top:8px;display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:11px;background:var(--glass-bg,rgba(22,22,27,.92));backdrop-filter:var(--glass-blur,blur(20px));-webkit-backdrop-filter:var(--glass-blur,blur(20px));border:1px solid var(--glass-border,rgba(255,255,255,.12));box-shadow:0 8px 24px rgba(0,0,0,.4);z-index:5}
.hd-tree-selbar-ct{font:700 13px var(--sans);color:var(--cream);white-space:nowrap}
.hd-tree-selbar-btn{margin-left:auto;display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 13px;border-radius:8px;border:none;cursor:pointer;background:linear-gradient(135deg,#8b6cff,#7c5cff);color:#fff;font:700 13px var(--sans);white-space:nowrap}
.hd-tree-selbar-btn:hover{filter:brightness(1.07)}
.hd-tree-selbar-btn svg{flex:none}
.hd-tree-selbar-x{width:28px;height:28px;flex:none;display:inline-flex;align-items:center;justify-content:center;border-radius:7px;border:1px solid var(--border-d);background:none;color:var(--muted);cursor:pointer;transition:all .14s}
.hd-tree-selbar-x:hover{color:var(--cream);background:rgba(255,255,255,.06)}
html[data-theme="light"] .hd-tree-selbar-ct{color:#1a1a22}
html[data-theme="light"] .hd-tree-row.sel .hd-tree-name{color:#1a1a22}
@media(max-width:760px){.hd-tree-body{flex-direction:column}.hd-tree-list{flex:1 1 auto;min-height:200px}.hd-tree-prev{max-height:40vh}}
/* B3: whole-card file-drop affordance */
.card-modal.cm-file-drop{outline:2px dashed var(--purple,#7c5cff);outline-offset:-8px}
.card-modal.cm-file-drop::after{content:'Drop to add to this task';position:absolute;top:10px;left:50%;transform:translateX(-50%);z-index:40;background:var(--purple,#7c5cff);color:#fff;font:700 11px var(--sans);padding:5px 12px;border-radius:20px;pointer-events:none;box-shadow:0 6px 18px rgba(124,92,255,.4)}
/* upload tray */
.hd-tray{position:fixed;right:18px;bottom:18px;z-index:99998;width:320px;max-height:50vh;overflow-y:auto;background:var(--color-surface-modal);border:1px solid var(--color-hairline-3);border-radius:var(--r-card);box-shadow:var(--lg-shadow)}
.hd-tray-head{padding:var(--sp-3) var(--sp-3) var(--sp-2);font:var(--fw-bold) var(--text-sm) var(--sans);color:var(--color-text-1);border-bottom:1px solid var(--color-hairline-1)}
.hd-tray-row{display:flex;align-items:flex-start;gap:var(--sp-2);padding:var(--sp-2-5) var(--sp-3);border-bottom:1px solid var(--color-hairline-1)}
.hd-tray-row:last-child{border-bottom:none}
.hd-tray-main{flex:1;min-width:0}
.hd-tray-name{font:var(--fw-medium) var(--text-xs) var(--sans);color:var(--color-text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hd-tray-bar{position:relative;height:4px;border-radius:3px;background:var(--bg-inset);margin:var(--sp-1-5) 0 var(--sp-1);overflow:hidden}
.hd-tray-fill{display:block;width:100%;height:100%;border-radius:3px;background:linear-gradient(90deg,var(--color-primary-hover),var(--color-primary));transform:scaleX(0);transform-origin:left center;transition:transform var(--dur-press) var(--ease-std);will-change:transform}
.hd-tray-row.is-error .hd-tray-fill{background:var(--color-error)}
.hd-tray-subline{display:flex;align-items:center;gap:var(--sp-2);min-width:0}
.hd-tray-sub{min-width:0;font:var(--fw-medium) var(--text-2xs) var(--sans);color:var(--color-text-3);font-variant-numeric:tabular-nums}
.hd-tray-row.is-error .hd-tray-sub{color:var(--color-error-text)}
/* Retry only ever appears on a failed row, so it wears that row's red rather than the
   brand colour — a blue action beside red error text read as unrelated to it. */
.hd-tray-retry{border:0;background:none;color:var(--color-error-text);font:var(--fw-bold) var(--text-2xs) var(--sans);cursor:pointer;padding:0}
.hd-tray-retry:hover{text-decoration:underline}
.hd-tray-retry[hidden]{display:none}
.hd-tray-x{width:24px;height:24px;flex:none;border:none;background:none;color:var(--color-text-2);border-radius:6px;display:flex;align-items:center;justify-content:center;cursor:pointer;margin-top:2px;transition:background var(--dur-toggle) var(--ease-std),color var(--dur-toggle) var(--ease-std)}
.hd-tray-x:hover{background:var(--color-hairline-2);color:var(--color-text-1)}
.hd-tray-x:disabled{cursor:default;opacity:.45}
.hd-tray-bar.is-phase::after,.hd-tree-uptrack.is-phase::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi) 50%,var(--bg-inset) 75%);background-size:200% 100%;animation:skelShimmer 1.4s linear infinite}
@media(prefers-reduced-motion:reduce){
  .hd-tray-fill,.hd-tree-upfill,.rev-upl-ring-fg,.rev-upl-ring-pct{transition:none}
  .hd-tray-bar.is-phase::after,.hd-tree-uptrack.is-phase::after,.rev-upl-ringbox.is-phase::after{animation:none;background:var(--bg-inset)}
}
/* share/drop popover list */
.hd-share-list{max-height:180px;overflow-y:auto}
.hd-share-row{display:flex;align-items:center;gap:7px;padding:7px 0;border-bottom:1px solid rgba(255,255,255,.06)}
.hd-share-row:last-child{border-bottom:none}
.hd-share-meta{flex:1;min-width:0}
.hd-share-url{font:600 12px var(--mono,ui-monospace);color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hd-share-sub{font:500 11px var(--sans);color:rgba(235,235,245,.45);margin-top:1px}
.hd-btn-danger{color:var(--danger-text)!important;border-color:rgba(239,68,68,.35)!important}
.rev-share-pop .fm-sec{margin:0 0 6px}
/* external tabs */
.fm-colext{flex:none;width:460px;border-right:1px solid rgba(255,255,255,.06);padding:10px}
.fm-ext-banner{display:flex;align-items:center;gap:12px;justify-content:space-between;margin:10px 26px 0;padding:10px 14px;border-radius:11px;background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.25);font:600 13px var(--sans);color:var(--danger-text)}
.fm-ext-err{margin:10px 26px 0;padding:10px 14px;border-radius:11px;background:rgba(239,68,68,.08);border:1px solid rgba(255,143,107,.3);font:500 13px/1.5 var(--sans);color:var(--danger-text)}
/* settings usage meter */
/* B1: editable storage cap (settings) */
.fm-cap-row{display:flex;align-items:center;gap:9px}
.fm-cap-num{width:110px;height:34px;border-radius:9px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);color:#fff;font:600 13px var(--sans);padding:0 12px;outline:none}
.fm-cap-num:focus{border-color:color-mix(in srgb,var(--purple) 55%,transparent)}
.fm-cap-unit{height:34px;border-radius:9px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);color:#fff;font:600 13px var(--sans);padding:0 8px;outline:none;cursor:pointer}
/* B1: storage meter bar above the HDrive columns */
/* trash page files section */
.hd-trash-head{display:flex;align-items:center;gap:10px;margin:22px 20px 10px;padding-top:16px;border-top:1px solid rgba(255,255,255,.07);font:800 15px var(--display);color:#fff}
.hd-trash-head span{font:500 12px var(--sans);color:rgba(235,235,245,.45)}
.hd-trash-scope{display:flex;align-items:center;gap:8px;margin:16px 2px 8px;font:800 12px var(--display);letter-spacing:.01em;color:rgba(235,235,245,.72);text-transform:uppercase}
.hd-trash-scope span{font:700 10px var(--mono,var(--sans));color:rgba(235,235,245,.4);background:rgba(255,255,255,.06);border-radius:20px;padding:2px 8px}
/* ── HDrive F2: task attachment chips (under the card description) ── */
.hd-att-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.hd-att-chip{display:flex;align-items:center;gap:8px;max-width:100%;padding:6px 8px;border:1px solid rgba(255,255,255,.09);border-radius:10px;background:rgba(255,255,255,.03)}
.hd-att-chip:hover{border-color:rgba(124,92,255,.4);background:rgba(124,92,255,.06)}
.hd-att-chip .fm-ico{width:30px;height:30px;flex:none}
.hd-att-meta{display:flex;flex-direction:column;min-width:0;cursor:pointer}
.hd-att-name{font:600 12px var(--sans);color:rgba(235,235,245,.9);max-width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hd-att-meta:hover .hd-att-name{color:#fff;text-decoration:underline}
.hd-att-size{font:500 11px var(--sans);color:rgba(235,235,245,.45)}
.hd-att-btn{width:26px;height:26px;flex:none;border:none;background:none;border-radius:7px;display:flex;align-items:center;justify-content:center;cursor:pointer}
.hd-att-btn:hover{background:rgba(255,255,255,.1)}
/* ── HDrive F2: @file mention chips ── */
.mention-file{color:var(--purple,#7c5cff);background:rgba(124,92,255,.13);cursor:pointer;white-space:nowrap}
.mention-file:hover{background:rgba(124,92,255,.24)}
.mention-file svg{vertical-align:-1px}
.mention-file.is-gone{color:rgba(235,235,245,.5);background:rgba(255,255,255,.08);cursor:default;font-style:italic}
.mention-input .mention-chip[data-type="file"]{color:var(--purple,#7c5cff);background:rgba(124,92,255,.13)}
.mention-file-tag{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:30px;padding:2px 5px;border-radius:5px;font:800 8.5px var(--sans);letter-spacing:.4px;margin-right:7px}
/* ── HDrive F2: DOCX preview panel ── */
.fm-stage-doc{aspect-ratio:auto;min-height:180px;max-height:420px;background:rgba(255,255,255,.03);align-items:stretch;padding:0}
.hd-docx{flex:1;overflow-y:auto;max-height:420px;padding:20px 24px;background:#fff;color:#1c1c22;border-radius:inherit;font:400 13px/1.6 var(--sans)}
.hd-docx h1,.hd-docx h2,.hd-docx h3{color:#111;margin:14px 0 6px}
.hd-docx p{margin:6px 0}
.hd-docx img{max-width:100%}
.hd-docx table{border-collapse:collapse}
.hd-docx td,.hd-docx th{border:1px solid #ccc;padding:3px 7px}
.hd-docx a{color:#4b32d8}
/* ══════════ HDrive (.fm-* / .hd-*) — LIGHT overrides ══════════
   HDrive shipped with hardcoded dark literals and no token usage, so it would render
   dark-on-white / white-on-white in light mode. Flip its surfaces, text and hairlines
   here; purple gradient fills + status dots stay as-is. Dark is untouched (scoped). */
html[data-theme="light"] .fm-wrap{background:var(--bg-main)}
html[data-theme="light"] .fm-col3{background:var(--bg-dark)}
html[data-theme="light"] .fm-stage-media{background:#e6e8ec}
html[data-theme="light"] .fm-topbar,
html[data-theme="light"] .fm-col1,
html[data-theme="light"] .fm-col2,
html[data-theme="light"] .fm-colext,
html[data-theme="light"] .fm-irow,
html[data-theme="light"] .hd-share-row,
html[data-theme="light"] .fm-menu-sep,
html[data-theme="light"] .hd-tray-head,
html[data-theme="light"] .hd-tray-row{border-color:var(--border-d)}
/* Primary text → near-black */
html[data-theme="light"] .fm-crumb .on,
html[data-theme="light"] .fm-frow.on .fm-fname,
html[data-theme="light"] .fm-cname,
html[data-theme="light"] .fm-crow.on .fm-cname,
html[data-theme="light"] .fm-dname,
html[data-theme="light"] .fm-vwhen,
html[data-theme="light"] .fm-iv,
html[data-theme="light"] .fm-set-title>div:first-child,
html[data-theme="light"] .fm-src-name,
html[data-theme="light"] .fm-dlg-title,
html[data-theme="light"] .hd-tree-title,
html[data-theme="light"] .hd-tree-name,
html[data-theme="light"] .hd-tree-row.on .hd-tree-name,
html[data-theme="light"] .hd-tray-head,
html[data-theme="light"] .hd-share-url,
html[data-theme="light"] .hd-trash-head,
html[data-theme="light"] .fm-search input,
html[data-theme="light"] .fm-ftp-in,
html[data-theme="light"] .fm-dlg-input,
html[data-theme="light"] .fm-cap-num,
html[data-theme="light"] .fm-cap-unit,
html[data-theme="light"] .fm-status-sel{color:var(--off-white)}
html[data-theme="light"] .fm-crumb,
html[data-theme="light"] .fm-fname,
html[data-theme="light"] .fm-fcount,
html[data-theme="light"] .fm-csize,
html[data-theme="light"] .fm-empty,
html[data-theme="light"] .fm-dmeta,
html[data-theme="light"] .fm-sec,
html[data-theme="light"] .fm-vby,
html[data-theme="light"] .fm-ik,
html[data-theme="light"] .fm-set-sub,
html[data-theme="light"] .fm-src-sub,
html[data-theme="light"] .fm-dlg-sub,
html[data-theme="light"] .fm-colhead,
html[data-theme="light"] .fm-sortbtn,
html[data-theme="light"] .fm-tab-add,
html[data-theme="light"] .fm-noprev,
html[data-theme="light"] .hd-tree-size,
html[data-theme="light"] .hd-tray-name,
html[data-theme="light"] .hd-tray-sub,
html[data-theme="light"] .hd-share-sub,
html[data-theme="light"] .hd-trash-head span,
html[data-theme="light"] .hd-trash-scope,
html[data-theme="light"] .hd-att-size,
html[data-theme="light"] .fm-set-foot,
html[data-theme="light"] .fm-search input::placeholder{color:var(--muted)}
/* Rows / hover / active well surfaces (white-alpha → dark-alpha) */
html[data-theme="light"] .fm-frow:hover,
html[data-theme="light"] .fm-crow:hover,
html[data-theme="light"] .fm-vrow:hover,
html[data-theme="light"] .hd-tree-row:hover,
html[data-theme="light"] .fm-gear:hover,
html[data-theme="light"] .fm-set-x:hover,
html[data-theme="light"] .fm-kebab:hover,
html[data-theme="light"] .fm-twist:hover,
html[data-theme="light"] .fm-vdl:hover,
html[data-theme="light"] .hd-tray-x:hover,
html[data-theme="light"] .fm-dlg-btn:hover,
html[data-theme="light"] .fm-sortbtn:hover,
html[data-theme="light"] .fm-menu-it:hover,
html[data-theme="light"] .hd-att-btn:hover,
html[data-theme="light"] .fm-tab:hover{background:rgba(0,0,0,.05)}
html[data-theme="light"] .fm-frow.on{background:rgba(0,0,0,.06)}
/* Inputs / search / wells → white with dark hairline */
html[data-theme="light"] .fm-search,
html[data-theme="light"] .fm-ftp-in,
html[data-theme="light"] .fm-dlg-input,
html[data-theme="light"] .fm-cap-num,
html[data-theme="light"] .fm-cap-unit,
html[data-theme="light"] .fm-status-sel,
html[data-theme="light"] .fm-stage-doc,
html[data-theme="light"] .hd-tree-list,
html[data-theme="light"] .hd-tree-prev{background:#ffffff;border-color:rgba(0,0,0,.14)}
html[data-theme="light"] .fm-status-sel option{background:#ffffff}
/* Elevated panels: settings modal, source cards, dialogs, context menu, tray, popover */
html[data-theme="light"] .fm-settings,
html[data-theme="light"] .fm-dlg,
html[data-theme="light"] .fm-menu,
html[data-theme="light"] .hd-tray,
html[data-theme="light"] .rev-share-pop{background:#ffffff;border-color:var(--border-d);box-shadow:0 24px 60px rgba(16,16,24,.16)}
html[data-theme="light"] .fm-src,
html[data-theme="light"] .fm-ftp-form{background:var(--bg-main);border-color:var(--border-d)}
html[data-theme="light"] .fm-src.on{border-color:rgba(124,92,255,.4)}
html[data-theme="light"] .fm-settings-ov,
html[data-theme="light"] .fm-dlg-ov{background:rgba(20,20,30,.28)}
html[data-theme="light"] .fm-set-head,
html[data-theme="light"] .fm-set-foot{border-color:var(--border-d)}
/* Meters / progress / usage tracks (keep the purple fill) */
html[data-theme="light"] .hd-tray-bar{background:rgba(0,0,0,.08)}
/* Buttons / tabs / secondary controls */
html[data-theme="light"] .fm-gear,
html[data-theme="light"] .fm-dl,
html[data-theme="light"] .fm-dlg-btn,
html[data-theme="light"] .fm-tab{border-color:var(--border-d);color:var(--cream)}
html[data-theme="light"] .fm-tab{background:rgba(0,0,0,.03)}
html[data-theme="light"] .fm-menu-it{color:var(--off-white)}
html[data-theme="light"] .fm-move-row{color:var(--cream)}
html[data-theme="light"] .fm-dlg-btn{color:var(--cream)}
html[data-theme="light"] .fm-vbadge{color:var(--muted);background:rgba(0,0,0,.06)}
/* Faces / version-count badge borders (were solid dark → white to match light page) */
html[data-theme="light"] .fm-face{border-color:#ffffff}
html[data-theme="light"] .fm-vnum{border-color:#ffffff}
html[data-theme="light"] .fm-face-more{background:rgba(0,0,0,.08);color:var(--cream)}
/* Attachment chips + gone-mention chip */
html[data-theme="light"] .hd-att-chip{background:rgba(0,0,0,.03);border-color:var(--border-d)}
html[data-theme="light"] .hd-att-name{color:var(--off-white)}
html[data-theme="light"] .hd-trash-scope span{background:rgba(0,0,0,.06);color:var(--muted)}
html[data-theme="light"] .mention-file.is-gone{color:var(--muted);background:rgba(0,0,0,.06)}
/* Links stay pink-purple but readable on white */
html[data-theme="light"] .fm-link{color:var(--pink)}
html[data-theme="light"] .fm-link:hover,
html[data-theme="light"] .fm-crumb-link:hover{color:var(--off-white)}
/* File/folder icon tiles use hardcoded dark gradients (inline style, per-type tint) built
   for the dark UI; on white they read as dark squares with an invisible white glyph.
   In light mode force a neutral light tile + a dark-gray glyph (currentColor). Explicitly
   colored glyphs — e.g. the purple/amber folder icons — set their own stroke and are unaffected. */
html[data-theme="light"] .fm-ico{background:linear-gradient(140deg,#ECEEF2,#DFE2E9)!important}
html[data-theme="light"] .fm-ico svg{color:#5A5A66}

/* ===== D: "Allow download" toggle inside the Share-folder popup ===== */
.hd-fs-toggle{width:40px;height:22px;border-radius:12px;border:none;background:rgba(255,255,255,.16);position:relative;cursor:pointer;padding:0;flex:none;transition:background .16s}
.hd-fs-toggle.on{background:var(--purple,#7c5cff)}
.hd-fs-knob{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;transition:left .16s}
.hd-fs-toggle.on .hd-fs-knob{left:20px}
html[data-theme="light"] .hd-fs-toggle{background:rgba(0,0,0,.18)}
html[data-theme="light"] .hd-fs-toggle.on{background:var(--purple,#7c5cff)}

/* ===== F2: sidebar Help / Claude MCP stub popups ===== */
.sbnav-pop-overlay{position:fixed;inset:0;z-index:10250;display:flex;align-items:center;justify-content:center;padding:32px;background:rgba(0,0,0,.55);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);opacity:0;transition:opacity .18s ease}
.sbnav-pop-overlay.open{opacity:1}
.sbnav-pop-card{width:100%;max-width:420px;background:var(--glass-bg);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:1px solid var(--glass-border);border-radius:18px;box-shadow:var(--glass-shadow);overflow:hidden;transform:translateY(10px) scale(.98);transition:transform .18s ease}
.sbnav-pop-overlay.open .sbnav-pop-card{transform:translateY(0) scale(1)}
.sbnav-pop-head{display:flex;align-items:center;gap:10px;padding:16px 18px;border-bottom:1px solid var(--border-d)}
.sbnav-pop-title{font:700 16px var(--sans);color:var(--cream)}
.sbnav-pop-x{margin-left:auto;width:28px;height:28px;border-radius:7px;background:none;border:1px solid var(--border-d);color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none;transition:all .14s}
.sbnav-pop-x:hover{color:var(--cream);background:rgba(255,255,255,.06)}
.sbnav-pop-body{padding:18px}
.sbnav-pop-body-center{text-align:center}
.sbnav-pop-p{font:400 14px/1.55 var(--sans);color:var(--muted);margin:0 0 14px}
.sbnav-pop-body-center .sbnav-pop-p{margin:8px auto 0;max-width:320px}
.sbnav-help-row{display:flex;gap:12px;align-items:flex-start;padding:11px 0;border-top:1px solid var(--border-d)}
.sbnav-help-ic{font-size:18px;line-height:1;flex:none;margin-top:1px}
.sbnav-help-t{font:600 14px var(--sans);color:var(--cream);margin-bottom:2px}
.sbnav-help-s{font:400 13px/1.45 var(--sans);color:var(--muted)}
.sbnav-help-s a{color:var(--purple)}
.sbnav-mcp-badge{width:64px;height:64px;border-radius:16px;margin:4px auto 0;display:flex;align-items:center;justify-content:center;font-size:30px;background:var(--purple-soft,rgba(124,92,255,.16))}
html[data-theme="light"] .sbnav-pop-card{background:rgba(255,255,255,.96);border-color:rgba(0,0,0,.08)}
html[data-theme="light"] .sbnav-pop-title,html[data-theme="light"] .sbnav-help-t{color:#1a1a22}
html[data-theme="light"] .sbnav-pop-p,html[data-theme="light"] .sbnav-help-s{color:#5a5a66}
html[data-theme="light"] .sbnav-pop-head,html[data-theme="light"] .sbnav-help-row{border-color:rgba(0,0,0,.08)}

/* ==================== ONBOARDING / SIGNUP / INVITE / BILLING (wave-4) ==================== */
/* All token-driven so dark (default) + light[data-theme="light"] both work with no dark-flash. */

/* --- shared full-screen gate wrapper (signup + invite) --- */
.hs-onb-gate{position:fixed;inset:0;z-index:99998;background:var(--dark);color:var(--off-white);
  display:none;overflow:auto;font-family:var(--sans);-webkit-font-smoothing:antialiased}
.hs-onb-gate.open{display:block}
.hs-onb-gate.hidden{display:none}

/* --- Signup: two-pane layout --- */
.hs-signup{display:flex;min-height:100vh;min-height:100dvh}
/* Light rail — the purple gradient buried the (purple) logo; white/gray lets it pop. */
.hs-signup-rail{width:380px;min-width:340px;flex-shrink:0;position:relative;overflow:hidden;
  background:#f5f5f7;border-right:1px solid #e8e8ec;
  color:#14111C;display:flex;flex-direction:column;padding:44px 40px 40px}
.hs-rail-brand{display:flex;align-items:center;gap:10px;font-family:var(--display);font-weight:800;
  font-size:26px;letter-spacing:-.02em;position:relative;z-index:1;color:#14111C}
.hs-rail-brand-mark{width:34px;height:34px;border-radius:9px;background:rgba(124,92,255,.12);
  display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
.hs-rail-tag{margin-top:14px;font-size:14px;line-height:1.55;color:#5F5F6B;
  max-width:250px;position:relative;z-index:1}
.hs-rail-steps{margin-top:auto;display:flex;flex-direction:column;gap:4px;position:relative;z-index:1}
.hs-rail-step{display:flex;align-items:center;gap:14px;padding:9px 0;opacity:.5;transition:opacity .25s}
.hs-rail-step.active{opacity:1}
.hs-rail-step.done{opacity:.8}
.hs-rail-step-num{width:30px;height:30px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;
  justify-content:center;font-size:13px;font-weight:700;border:1.5px solid #c9c9d2;
  background:transparent;color:#5F5F6B;transition:all .25s}
.hs-rail-step.active .hs-rail-step-num{background:var(--purple);color:#fff;border-color:var(--purple)}
.hs-rail-step.done .hs-rail-step-num{background:rgba(124,92,255,.14);border-color:rgba(124,92,255,.4);color:var(--purple)}
.hs-rail-step-txt{display:flex;flex-direction:column;gap:1px}
.hs-rail-step-label{font-size:14px;font-weight:700;color:#14111C}
.hs-rail-step-sub{font-size:11px;color:#8a8a96}
.hs-rail-progress{margin-top:18px;height:4px;border-radius:3px;background:#e4e4ea;overflow:hidden;position:relative;z-index:1}
.hs-rail-progress-bar{height:100%;background:var(--purple);border-radius:3px;transition:width .35s cubic-bezier(.4,0,.2,1);width:33%}

/* Every step: ONE centered column, centered text — same position on every screen. */
.hs-signup-pane{flex:1;min-width:0;overflow-y:auto;display:flex;justify-content:center;
  padding:56px 32px 24px;background:var(--dark)}
.hs-signup-form{width:100%;max-width:520px;margin:auto 0;text-align:center}
.hs-signup-form.hs-form-wide{max-width:780px}
/* Big Slack-style question headings inside the flow */
.hs-signup-form .hs-step-h1{font-size:36px;line-height:1.12;margin-bottom:10px}
.hs-signup-form .hs-step-sub{font-size:14px;margin-bottom:22px}
.hs-signup-form .hs-onb-input{text-align:left}
.hs-signup-form .hs-onb-label{text-align:left}
.hs-signup-form .hs-pfp-row{justify-content:center}
.hs-signup-form .hs-chips,.hs-signup-form .hs-team-row{justify-content:center}
.hs-signup-form .hs-quiz-cards{max-width:560px;margin:0 auto}
.hs-signup-back{background:none;border:none;color:var(--muted);font-family:var(--sans);font-size:13px;
  cursor:pointer;padding:0;margin-bottom:12px;display:inline-flex;align-items:center;gap:6px;transition:color .15s}
.hs-signup-back:hover{color:var(--off-white)}
.hs-step-h1{font-family:var(--display);font-weight:800;font-size:24px;letter-spacing:-.02em;
  color:var(--off-white);margin:0 0 6px;line-height:1.15}
.hs-step-sub{font-size:14px;color:var(--muted);margin:0 0 16px;line-height:1.5}
.hs-onb-field{margin-bottom:14px}
.hs-onb-label{display:block;font-size:12px;font-weight:600;color:var(--cream);margin-bottom:6px}
.hs-onb-input{width:100%;padding:13px 15px;border-radius:10px;border:1.5px solid var(--border-d);
  background:rgba(255,255,255,.05);color:var(--off-white);font-family:var(--sans);font-size:14px;
  outline:none;box-sizing:border-box;transition:border-color .15s}
html[data-theme="light"] .hs-onb-input{background:rgba(0,0,0,.03)}
.hs-onb-input::placeholder{color:var(--muted)}
.hs-onb-input:focus{border-color:var(--purple)}
.hs-onb-input.error{border-color:var(--pink)}
.hs-onb-slug-wrap{display:flex;align-items:stretch;border-radius:10px;border:1.5px solid var(--border-d);
  overflow:hidden;background:rgba(255,255,255,.05);transition:border-color .15s}
html[data-theme="light"] .hs-onb-slug-wrap{background:rgba(0,0,0,.03)}
.hs-onb-slug-wrap:focus-within{border-color:var(--purple)}
.hs-onb-slug-input{flex:1;min-width:0;padding:13px 4px 13px 15px;border:none;background:transparent;
  color:var(--off-white);font-family:var(--sans);font-size:14px;outline:none}
.hs-onb-slug-suffix{display:flex;align-items:center;padding:0 14px 0 2px;font-size:13px;color:var(--muted);white-space:nowrap}
.hs-onb-avail{font-size:12px;margin-top:6px;min-height:16px}
.hs-onb-avail.ok{color:var(--green)}
.hs-onb-avail.bad{color:var(--pink)}
.hs-onb-avail.checking{color:var(--muted)}

.hs-onb-btn{width:100%;padding:12px;border-radius:11px;border:none;background:var(--purple);color:#fff;
  font-family:var(--sans);font-size:15px;font-weight:700;cursor:pointer;margin-top:8px;
  transition:background .15s,transform .1s}
/* Signup — Plan step */
.hs-plan-toggle{display:inline-flex;gap:2px;background:rgba(255,255,255,.06);border:1px solid var(--border-d);border-radius:10px;padding:3px;margin:4px 0 16px}
.hs-plan-toggle button{border:none;background:transparent;color:var(--muted);font:600 13px var(--sans);padding:7px 14px;border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.hs-plan-toggle button.on{background:var(--purple);color:#fff}
.hs-plan-toggle-save{font:700 10px var(--sans);opacity:.85}
.hs-plan-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:6px}
@media (max-width:900px){.hs-plan-cards{grid-template-columns:1fr}}
.hs-plan-card{text-align:left;background:rgba(255,255,255,.03);border:1.5px solid var(--border-d);border-radius:14px;padding:11px 14px;cursor:pointer;transition:border-color .15s,background .15s}
.hs-plan-card:hover{border-color:rgba(124,92,255,.5)}
.hs-plan-card.on{border-color:var(--purple);background:rgba(124,92,255,.09)}
.hs-plan-top{display:flex;align-items:center;justify-content:space-between}
.hs-plan-name{font:700 15px var(--sans);color:var(--off-white)}
.hs-plan-check{width:20px;height:20px;border-radius:50%;background:var(--purple);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px}
.hs-plan-priceline{display:flex;align-items:baseline;gap:8px;margin:3px 0 8px}
.hs-plan-price{font:800 22px var(--sans);color:var(--white)}
.hs-plan-per{font:500 12px var(--sans);color:var(--muted)}
.hs-plan-save{font:700 10px var(--sans);color:#7ccf84;background:rgba(124,207,132,.14);padding:2px 7px;border-radius:20px}
.hs-plan-feats{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.hs-plan-feats li{font:500 13px var(--sans);color:var(--muted);padding-left:16px;position:relative}
.hs-plan-feats li::before{content:'✓';position:absolute;left:0;color:var(--purple);font-weight:700}

/* --- Slack-style payment screen (recommended-plan view, centered) --- */
.hs-plan-created{font-size:14px;font-weight:600;color:var(--cream);margin-bottom:8px}
/* Benefits: the BLOCK centers; rows read left-aligned inside it */
.hs-plan-benefits{display:inline-block;text-align:left;margin:2px auto 4px;max-width:420px}
.hs-plan-lead{display:flex;gap:12px;margin-bottom:12px}
.hs-plan-lead-check{color:#7ccf84;font-weight:800;font-size:17px;line-height:1.3;flex:none}
.hs-plan-lead-t{font-size:16px;font-weight:700;color:var(--off-white);line-height:1.35}
.hs-plan-lead-sub{font-size:13px;color:var(--muted);margin-top:3px;line-height:1.5}
.hs-plan-mini{font-size:14px;font-weight:600;color:var(--cream);padding:5px 0 5px 2px;display:flex;align-items:baseline;gap:11px}
.hs-plan-mini-arrow{color:var(--purple);font-size:12px;flex:none}
.hs-plan-compare{display:block;margin:10px 0 16px;font-size:14px;font-weight:700;color:var(--purple);cursor:pointer}
.hs-plan-compare:hover{text-decoration:underline}
.hs-plan-reco-price{margin:0 0 14px;justify-content:center}
.hs-onb-btn:hover{background:var(--coral-shade,#5d3fe0)}
.hs-onb-btn:active{transform:scale(.99)}
.hs-onb-btn:disabled{opacity:.5;cursor:default}
.hs-onb-btn.secondary{background:rgba(255,255,255,.06);color:var(--off-white);border:1px solid var(--border-d)}
.hs-onb-btn.secondary:hover{background:rgba(255,255,255,.10)}
html[data-theme="light"] .hs-onb-btn.secondary{background:rgba(0,0,0,.04)}
.hs-onb-err{font-size:13px;color:var(--pink);margin-top:12px;min-height:18px}
.hs-onb-google{display:flex;justify-content:center;min-height:44px;margin-bottom:6px}
.hs-onb-google-fallback{width:100%;padding:12px;border-radius:11px;border:1px solid var(--border-d);
  background:rgba(255,255,255,.06);color:var(--off-white);font-family:var(--sans);font-size:14px;
  font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:10px;transition:all .15s}
.hs-onb-google-fallback:hover{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.2)}
html[data-theme="light"] .hs-onb-google-fallback{background:rgba(0,0,0,.03)}
.hs-onb-divider{display:flex;align-items:center;gap:12px;margin:18px 0;font-size:10px;color:var(--muted);
  letter-spacing:1px;text-transform:uppercase}
.hs-onb-divider::before,.hs-onb-divider::after{content:'';flex:1;height:1px;background:var(--border-d)}
.hs-onb-alt{font-size:13px;color:var(--muted);text-align:center;margin-top:18px}
.hs-onb-alt a,.hs-onb-link{color:var(--purple);cursor:pointer;font-weight:600;text-decoration:none}
.hs-onb-alt a:hover,.hs-onb-link:hover{text-decoration:underline}

/* --- Quiz cards + chips --- */
.hs-quiz-group{margin-bottom:8px}
.hs-quiz-legend{font-size:13px;font-weight:700;color:var(--off-white);margin-bottom:5px}
/* two quiz groups side-by-side (Team size + Clients managed) so the step fits one screen */
.hs-quiz-cols{display:flex;gap:12px}
.hs-quiz-cols>.hs-quiz-group{flex:1;min-width:0}
.hs-quiz-cols .hs-team-opt{min-width:0;padding:7px 4px;font-size:12px}
.hs-quiz-cards{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.hs-quiz-card{border:1.5px solid var(--border-d);border-radius:10px;padding:6px 11px 5px;
  background:rgba(255,255,255,.03);cursor:pointer;transition:all .15s;text-align:left;
  display:flex;flex-direction:column;gap:2px}
html[data-theme="light"] .hs-quiz-card{background:rgba(0,0,0,.02)}
.hs-quiz-card:hover{border-color:rgba(124,92,255,.5);background:var(--purple-soft,rgba(124,92,255,.12))}
.hs-quiz-card.selected{border-color:var(--purple);background:var(--purple-soft,rgba(124,92,255,.16));box-shadow:0 0 0 1px var(--purple) inset}
.hs-quiz-card-emoji{font-size:22px;line-height:1}
.hs-quiz-card-label{font-size:13px;font-weight:700;color:var(--off-white)}
.hs-quiz-card-desc{font-size:11px;color:var(--muted);line-height:1.35}
.hs-chips{display:flex;flex-wrap:wrap;gap:6px}
.hs-chip{padding:5px 10px;border-radius:22px;border:1.5px solid var(--border-d);background:rgba(255,255,255,.03);
  color:var(--cream);font-family:var(--sans);font-size:12px;font-weight:600;cursor:pointer;transition:all .15s;user-select:none}
html[data-theme="light"] .hs-chip{background:rgba(0,0,0,.02)}
.hs-chip:hover{border-color:rgba(124,92,255,.5)}
.hs-chip.selected{border-color:var(--purple);background:var(--purple-soft,rgba(124,92,255,.16));color:var(--off-white)}
.hs-team-row{display:flex;flex-wrap:wrap;gap:8px}
.hs-team-opt{flex:1;min-width:60px;padding:8px 6px;border-radius:10px;border:1.5px solid var(--border-d);
  background:rgba(255,255,255,.03);color:var(--cream);font-family:var(--sans);font-size:13px;font-weight:600;
  cursor:pointer;text-align:center;transition:all .15s}

/* --- Rail-less wizard chrome: corner logo + step kicker --- */
.hs-su-corner{position:fixed;top:20px;left:26px;display:flex;align-items:center;gap:9px;
  font-family:var(--display);font-weight:800;font-size:19px;letter-spacing:-.02em;
  color:var(--off-white);z-index:2;pointer-events:none}
.hs-su-corner img{width:24px;height:24px}
.hs-step-kicker{font-size:12px;font-weight:700;color:var(--muted);margin-bottom:10px}

/* --- Step 1: full-page centered get-started screen (no rail) --- */
.hs-signup-centered{display:block;overflow-y:auto;background:var(--dark)}
.hs-su-hero{width:100%;max-width:640px;margin:0 auto;text-align:center;
  padding:7vh 24px 48px;display:flex;flex-direction:column;align-items:center}
.hs-su-brand{display:flex;align-items:center;gap:10px;font-family:var(--display);font-weight:800;
  font-size:24px;letter-spacing:-.02em;color:var(--off-white);margin-bottom:6vh}
.hs-su-h1{font-family:var(--display);font-weight:800;font-size:44px;letter-spacing:-.025em;
  color:var(--off-white);margin:0 0 12px;line-height:1.08}
.hs-su-sub{font-size:15px;color:var(--muted);margin:0 0 26px;line-height:1.55}
.hs-su-sub strong{color:var(--cream)}
.hs-su-input{max-width:440px;text-align:left;font-size:15px;padding:14px 16px}
.hs-su-btn{max-width:440px;margin-top:4px}
.hs-su-err{width:100%;max-width:440px;text-align:left;margin-top:8px;min-height:16px}
.hs-su-div{width:100%;max-width:440px;margin:14px 0}
.hs-su-terms{font-size:12px;color:var(--muted);margin:24px 0 0;line-height:1.6;max-width:400px}
.hs-su-terms a{color:var(--muted);text-decoration:underline}
.hs-su-terms a:hover{color:var(--off-white)}
.hs-su-hero .hs-skip-link{margin-top:18px}
@media (max-width:560px){.hs-su-h1{font-size:32px}}

/* --- Slack-style wizard steps: profile photo, team invites, creating screen --- */
.hs-pfp-row{display:flex;align-items:center;gap:16px}
.hs-pfp-circle{width:76px;height:76px;border-radius:50%;flex-shrink:0;overflow:hidden;display:flex;
  align-items:center;justify-content:center;border:1.5px dashed var(--border-d);background:rgba(255,255,255,.04);
  color:var(--muted);font-size:28px;font-weight:300;cursor:pointer;transition:border-color .15s}
html[data-theme="light"] .hs-pfp-circle{background:rgba(0,0,0,.03)}
.hs-pfp-circle:hover{border-color:var(--purple)}
.hs-pfp-circle.set{border-style:solid}
.hs-pfp-circle img{width:100%;height:100%;object-fit:cover;display:block}
.hs-pfp-btns{display:flex;flex-direction:column;gap:7px;align-items:flex-start}
.hs-pfp-btn{width:auto;padding:8px 16px;margin-top:0;font-size:13px}
.hs-pfp-note{font-size:12px;color:var(--muted)}
.hs-invite-rows{display:flex;flex-direction:column;gap:10px;margin-bottom:8px}
.hs-invite-add{background:none;border:none;color:var(--purple);font-family:var(--sans);font-size:13px;
  font-weight:600;cursor:pointer;padding:0;text-align:left;margin-bottom:4px}
.hs-invite-add:hover{text-decoration:underline}
.hs-skip-link{display:block;text-align:center;margin-top:8px;font-size:13px;color:var(--muted);
  cursor:pointer;text-decoration:none}
.hs-skip-link:hover{color:var(--off-white)}
.hs-creating{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
  padding:48px 0;min-height:320px}
.hs-creating-spin{width:54px;height:54px;border-radius:50%;border:4px solid rgba(124,92,255,.18);
  border-top-color:var(--purple);animation:hsCreatingSpin 1s linear infinite;margin-bottom:24px}
@keyframes hsCreatingSpin{to{transform:rotate(360deg)}}
.hs-creating-h{font-family:var(--display);font-weight:800;font-size:22px;letter-spacing:-.02em;
  color:var(--off-white);margin:0 0 8px}
.hs-creating-sub{font-size:14px;color:var(--muted);min-height:20px;margin:0 0 18px;transition:opacity .3s}
html[data-theme="light"] .hs-team-opt{background:rgba(0,0,0,.02)}
.hs-team-opt:hover{border-color:rgba(124,92,255,.5)}
.hs-team-opt.selected{border-color:var(--purple);background:var(--purple-soft,rgba(124,92,255,.16));color:var(--off-white)}

/* --- Invite screen (centered card) --- */
.hs-invite-wrap{min-height:100vh;min-height:100dvh;display:flex;align-items:center;justify-content:center;
  padding:32px 20px;background:var(--dark)}
.hs-invite-card{width:100%;max-width:420px;background:var(--surface,#1a1a1f);border:1px solid var(--border-d);
  border-radius:18px;padding:36px 34px 34px;box-shadow:0 24px 80px rgba(0,0,0,.45);text-align:center}
html[data-theme="light"] .hs-invite-card{box-shadow:0 24px 80px rgba(0,0,0,.12)}
.hs-invite-brand{font-family:var(--display);font-weight:800;font-size:22px;letter-spacing:-.02em;
  color:var(--off-white);margin-bottom:22px}
.hs-invite-ws{display:flex;align-items:center;gap:12px;justify-content:center;padding:14px;border-radius:12px;
  background:rgba(255,255,255,.04);border:1px solid var(--border-d);margin-bottom:8px}
html[data-theme="light"] .hs-invite-ws{background:rgba(0,0,0,.03)}
.hs-invite-ws-icon{width:44px;height:44px;border-radius:11px;flex-shrink:0;display:flex;align-items:center;
  justify-content:center;font-size:22px;overflow:hidden;background:linear-gradient(135deg,var(--purple),var(--coral-shade,#5d3fe0));color:#fff}
.hs-invite-ws-icon img{width:100%;height:100%;object-fit:cover}
.hs-invite-ws-txt{text-align:left;min-width:0}
.hs-invite-ws-name{font-size:16px;font-weight:700;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hs-invite-ws-sub{font-size:12px;color:var(--muted)}
.hs-invite-inviter{display:flex;align-items:center;gap:9px;justify-content:center;font-size:13px;color:var(--muted);margin:16px 0 24px}
.hs-invite-avatar{width:26px;height:26px;border-radius:50%;overflow:hidden;flex-shrink:0;
  background:linear-gradient(135deg,var(--blue),var(--teal));display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;color:#fff}
.hs-invite-avatar img{width:100%;height:100%;object-fit:cover}
.hs-invite-inviter strong{color:var(--off-white);font-weight:700}
.hs-invite-form{text-align:left;margin-top:8px}
.hs-invite-locked{position:relative}
.hs-invite-locked .hs-onb-input{padding-right:38px}
.hs-invite-lock-i{position:absolute;right:13px;top:50%;transform:translateY(-50%);color:var(--muted);font-size:13px}
.hs-invite-state{text-align:center;padding:20px 6px}
.hs-invite-state-emoji{font-size:44px;margin-bottom:14px}
.hs-invite-state-h{font-family:var(--display);font-weight:800;font-size:22px;color:var(--off-white);margin:0 0 8px}
.hs-invite-state-p{font-size:14px;color:var(--muted);line-height:1.55;margin:0 0 20px}

/* --- Billing (settings section) --- */
.hs-bill-plan-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}
.hs-bill-badge{display:inline-flex;align-items:center;gap:6px;padding:4px 11px;border-radius:20px;font-size:11px;
  font-weight:700;background:var(--purple-soft,rgba(124,92,255,.16));color:var(--purple-text,#c4b0ff)}
html[data-theme="light"] .hs-bill-badge{color:var(--purple)}
.hs-bill-status{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);margin-top:4px}
.hs-bill-status .dot{width:7px;height:7px;border-radius:50%;background:var(--green)}
.hs-bill-status.past_due .dot,.hs-bill-status.canceled .dot{background:var(--pink)}
.hs-bill-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.hs-bill-invoices{margin-top:18px}
.hs-bill-inv-row{display:flex;align-items:center;justify-content:space-between;padding:11px 0;border-bottom:1px solid var(--border-d);font-size:13px}
.hs-bill-inv-row:last-child{border-bottom:none}
.hs-bill-inv-amt{color:var(--off-white);font-weight:600}
.hs-bill-inv-meta{color:var(--muted);font-size:12px}
.hs-bill-notconfig{padding:18px;border-radius:12px;border:1px dashed var(--border-d);background:rgba(255,255,255,.02);
  color:var(--muted);font-size:13px;line-height:1.55}
html[data-theme="light"] .hs-bill-notconfig{background:rgba(0,0,0,.02)}

/* --- Checkout modal --- */
.hs-checkout-overlay{position:fixed;inset:0;z-index:100000;background:rgba(0,0,0,.62);display:none;
  align-items:flex-start;justify-content:center;overflow-y:auto;padding:40px 16px}
.hs-checkout-overlay.open{display:flex}
.hs-checkout{width:100%;max-width:900px;background:var(--dark);border:1px solid var(--border-d);border-radius:18px;
  overflow:hidden;box-shadow:0 24px 80px rgba(0,0,0,.5);display:grid;grid-template-columns:1fr 380px;position:relative}
.hs-checkout-close{position:absolute;top:14px;right:14px;z-index:3;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--border-d);background:var(--dark);color:var(--muted);cursor:pointer;font-size:16px;
  display:flex;align-items:center;justify-content:center;transition:all .15s}
.hs-checkout-close:hover{color:var(--off-white);border-color:rgba(255,255,255,.25)}
.hs-checkout-plans{padding:30px 28px;border-right:1px solid var(--border-d);overflow-y:auto;max-height:88vh}
.hs-checkout-h{font-family:var(--display);font-weight:800;font-size:22px;color:var(--off-white);margin:0 0 4px}
.hs-checkout-toggle{display:inline-flex;padding:3px;border-radius:24px;background:rgba(255,255,255,.05);
  border:1px solid var(--border-d);margin:16px 0 20px}
html[data-theme="light"] .hs-checkout-toggle{background:rgba(0,0,0,.04)}
.hs-toggle-opt{padding:7px 16px;border-radius:20px;border:none;background:none;color:var(--muted);
  font-family:var(--sans);font-size:12px;font-weight:700;cursor:pointer;transition:all .15s}
.hs-toggle-opt.active{background:var(--purple);color:#fff}
.hs-toggle-save{font-size:10px;margin-left:5px;opacity:.85}
.hs-plan-card{border:1.5px solid var(--border-d);border-radius:14px;padding:18px;margin-bottom:12px;cursor:pointer;
  transition:all .15s;background:rgba(255,255,255,.02)}
html[data-theme="light"] .hs-plan-card{background:rgba(0,0,0,.015)}
.hs-plan-card:hover{border-color:rgba(124,92,255,.5)}
.hs-plan-card.selected{border-color:var(--purple);box-shadow:0 0 0 1px var(--purple) inset;background:var(--purple-soft,rgba(124,92,255,.1))}
.hs-plan-card-top{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.hs-plan-name{font-size:15px;font-weight:800;color:var(--off-white);font-family:var(--display)}
.hs-plan-price{font-size:15px;font-weight:700;color:var(--off-white)}
.hs-plan-price span{font-size:12px;color:var(--muted);font-weight:500}
.hs-plan-feats{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.hs-plan-feats li{font-size:12px;color:var(--cream);display:flex;align-items:flex-start;gap:8px;line-height:1.4}
.hs-plan-feats li::before{content:'✓';color:var(--green);font-weight:800;flex-shrink:0}
/* Seat picker — buckets come from the plan catalog, so this row is as long as the owner
   made it in the admin Plans tab. Wraps rather than scrolls; a hidden bucket is a bucket
   nobody buys. */
.hs-checkout-seats{margin-top:18px;padding-top:16px;border-top:1px solid var(--border-d)}
.hs-seats-l{font-size:12px;font-weight:700;color:var(--off-white);margin-bottom:8px}
.hs-seats-opts{display:flex;flex-wrap:wrap;gap:6px}
.hs-seat-opt{min-width:40px;padding:7px 12px;border-radius:9px;border:1px solid var(--border-d);
  background:transparent;color:var(--cream);font:600 13px var(--sans);cursor:pointer;
  font-variant-numeric:tabular-nums;transition:border-color .12s,background .12s,color .12s}
.hs-seat-opt:hover{border-color:rgba(124,92,255,.5)}
.hs-seat-opt.on{border-color:var(--purple);background:var(--purple-soft,rgba(124,92,255,.14));color:var(--off-white)}
.hs-seats-note{font-size:11px;color:var(--muted);margin-top:8px}
.hs-seats-note a{color:var(--purple)}
/* Seat count beside the plan badge on the Billing pane. */
.hs-bill-seats{display:inline-flex;align-items:center;margin-left:8px;padding:4px 10px;border-radius:20px;
  font-size:11px;font-weight:600;color:var(--muted);border:1px solid var(--border-d)}
.hs-checkout-pay{padding:30px 28px;display:flex;flex-direction:column;background:var(--surface,#1a1a1f)}
.hs-checkout-pay-h{font-size:13px;font-weight:700;color:var(--off-white);margin-bottom:14px}
.hs-express-slot{min-height:8px;margin-bottom:4px}
.hs-express-slot:not(:empty){margin-bottom:16px}
.hs-express-divider{display:flex;align-items:center;gap:12px;margin:4px 0 16px;font-size:10px;color:var(--muted);
  letter-spacing:1px;text-transform:uppercase}
.hs-express-divider:empty{display:none}
.hs-express-divider::before,.hs-express-divider::after{content:'';flex:1;height:1px;background:var(--border-d)}
.hs-payment-slot{min-height:40px;margin-bottom:16px}
.hs-checkout-summary{margin-top:auto;padding-top:16px;border-top:1px solid var(--border-d)}
.hs-checkout-total{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:12px}
/* Per-seat pricing: the headline is the whole charge, this line shows the maths behind it
   so "$570/yr" is never a number the customer has to take on trust. */
.hs-checkout-subtotal{font-size:11px;color:var(--muted);margin:-6px 0 12px;text-align:right}
.hs-checkout-total-l{font-size:13px;color:var(--muted)}
.hs-checkout-total-v{font-size:20px;font-weight:800;color:var(--off-white);font-family:var(--display)}
.hs-checkout-total-v small{font-size:12px;color:var(--muted);font-weight:500}
.hs-subscribe-btn{width:100%;padding:14px;border-radius:11px;border:none;background:var(--purple);color:#fff;
  font-family:var(--sans);font-size:15px;font-weight:700;cursor:pointer;transition:background .15s,transform .1s}
.hs-subscribe-btn:hover{background:var(--coral-shade,#5d3fe0)}
.hs-subscribe-btn:active{transform:scale(.99)}
.hs-subscribe-btn:disabled{opacity:.5;cursor:default}
.hs-checkout-err{font-size:12px;color:var(--pink);margin-top:10px;min-height:16px;text-align:center}
.hs-checkout-loading{display:flex;align-items:center;justify-content:center;padding:40px;color:var(--muted);font-size:13px}

@media(max-width:860px){
  .hs-checkout{grid-template-columns:1fr;max-width:460px}
  .hs-checkout-plans{border-right:none;border-bottom:1px solid var(--border-d);max-height:none}
}
@media(max-width:760px){
  .hs-signup{flex-direction:column}
  .hs-signup-rail{width:100%;min-width:0;padding:28px 24px 22px}
  .hs-signup-rail .hs-rail-steps{flex-direction:row;gap:6px;margin-top:20px;overflow-x:auto}
  .hs-signup-rail .hs-rail-step{flex-direction:column;text-align:center;gap:6px;padding:6px 4px;min-width:76px}
  .hs-rail-step-sub{display:none}
  .hs-rail-tag{display:none}
  .hs-signup-pane{padding:34px 22px 54px}
  .hs-step-h1{font-size:25px}
  .hs-quiz-cards{grid-template-columns:1fr}
}

/* ═══════════ Desktop light-mode fixes — "Light Mode Fixes" card (card_349410624289112064) ═══════════
   Surfaces whose dark-only colors survived into light mode on DESKTOP (the earlier light-mode pass
   was scoped mostly to body[data-mobile-mode="app"]). Dark mode is untouched. Verified in the local
   preview at 1440px, data-theme="light". */
/* Project view tabs (Board/List/Calendar/Canvas/Automations): inactive tabs were rgba(235,235,245,.7)
   (near-white) → invisible on light. Active tab already had a light override. */
/* Covers Board/List/Calendar/Canvas/Automations AND the right-side Filter/Settings tabs. */
html[data-theme="light"] .ws-view-tab:not(.active){color:var(--muted)}
html[data-theme="light"] .ws-view-tab:not(.active):hover{color:var(--off-white)}
/* Calendar: day numbers were forced near-white by a global !important; cell gridlines were white-alpha
   (invisible). The .today pill keeps its own higher-specificity purple rule. */
html[data-theme="light"] .calendar-day-num{color:var(--off-white) !important}
html[data-theme="light"] .calendar-day{border-color:var(--border-d)}
html[data-theme="light"] .cal-view-toggle{background:var(--bg-inset)}
/* Calendar top nav: month label + Day/Week/Month buttons were near-white on white (an existing
   !important rule set them light, so force them here). */
html[data-theme="light"] .cal-month-nav .workshop-view-btn,
html[data-theme="light"] .cal-month-nav [data-cal-tab-nav-label]{color:var(--off-white) !important}
/* Automations AND Canvas (widgets) views forced the whole page to #0a0a0b with a white-line grid
   overlay (::before) — both stayed fully dark in light mode. Flip the page to a light board bg and
   the grid lines to dark-alpha; drop the dark vignette (it only reads on a dark canvas). */
html[data-theme="light"] body.view-automations #page-custom-workshop.active,
html[data-theme="light"] body.view-automations #page-workshop.active,
html[data-theme="light"] body.view-widgets #page-custom-workshop.active,
html[data-theme="light"] body.view-widgets #page-workshop.active{background-color:var(--bg-board) !important}
/* Same backdrops as dark — ruled cells under Automations, dots under Canvas — in ink. */
html[data-theme="light"] body.view-automations #page-custom-workshop.active::before,
html[data-theme="light"] body.view-automations #page-workshop.active::before{
  background-image:
    radial-gradient(ellipse 125% 130% at 50% 42%,transparent 62%,rgba(0,0,0,.07) 100%),
    linear-gradient(rgba(0,0,0,.07) 1px,transparent 1px),
    linear-gradient(90deg,rgba(0,0,0,.07) 1px,transparent 1px) !important}
html[data-theme="light"] body.view-widgets #page-custom-workshop.active::before,
html[data-theme="light"] body.view-widgets #page-workshop.active::before{
  background-image:
    radial-gradient(ellipse 125% 130% at 50% 42%,transparent 68%,rgba(0,0,0,.06) 100%) !important}
html[data-theme="light"] .azp-step{background:#ffffff}
/* Home switcher: the card had a solid-white bg (killing the backdrop-blur → "no liquid glass"), and
   the active state carried a flat purple tint. Make the card translucent so the frosted glass reads,
   and drop the purple tint on the Home pill specifically (other active nav items keep theirs). */
html[data-theme="light"] .sidebar-ws-card{background:rgba(255,255,255,.62)}
html[data-theme="light"] .sidebar-ws-card .sidebar-ws-main.active{background:transparent}
/* Colored folder (category) labels + icons were mixed toward light --muted → too pale on white.
   Mix toward a dark ink instead so colored sidebar text/icons read clearly in light mode. */
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-item{color:color-mix(in srgb,var(--cat-color) 68%,#33333b)}
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-child .sidebar-channel-name{color:color-mix(in srgb,var(--cat-color) 68%,#33333b)}
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-child .sidebar-channel-icon svg{stroke:color-mix(in srgb,var(--cat-color) 62%,#33333b)}
/* Add-Property type picker: container flips via var(--dark) but the desktop light path had no explicit
   rule and the hover was white-alpha (invisible on white). */
html[data-theme="light"] .prop-type-picker{background:#ffffff;border-color:var(--border-d)}
html[data-theme="light"] .prop-type-item:hover{background:rgba(0,0,0,.05)}

/* ── Agency Dashboard ── */
.ad-row-menu{background:none;border:none;color:var(--muted);cursor:pointer;font-size:16px;padding:2px 8px;border-radius:6px;line-height:1;font-family:var(--sans)}
.ad-row-menu:hover{background:var(--bg-inset,rgba(255,255,255,.06));color:var(--cream)}

/* ── DM page styles (revived from the pre-split monolith @0095b51; DMs light up in channels Phase 2) ── */
.dm-unread-badge{min-width:18px;height:18px;border-radius:9px;background:var(--coral);color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;margin-left:auto;flex-shrink:0;padding:0 5px;line-height:1;animation:dmBadgePop .25s ease}
/* No negative margins. These cancelled .content's 28/36/60 padding back when this page
   lived inside it; #page-dm is now a flex sibling of .main-body, where there is no
   padding to cancel — so they dragged the page 36px left and 28px above its own
   container and the +88px made it taller than the space it had. It sizes as a flex item
   now, like the other hoisted pages below. */
#page-dm.active{margin:0;height:auto;display:flex!important;flex-direction:column;overflow:hidden}
/* Full-bleed margins must re-match .content's padding at every breakpoint
   (like #page-settings/#page-chatroom do) or the page hangs outside the
   scrollport: list rows clipped left, last conversations cut off bottom. */
.dm-layout{display:flex; flex:1;min-height:0; gap:0; overflow:hidden;}
.dm-chat-area{flex:1; min-width:0; min-height:0; display:flex; flex-direction:column; overflow:hidden;}
/* Secondary DM column: sidebar > dms > message */
/* 240, not 300: the column held one name and a one-line preview and had room to
   spare, while the conversation next to it did the actual work. */
.dm-list-col{width:240px;flex-shrink:0;display:flex;flex-direction:column;border-right:1px solid var(--border-d);background:var(--surf-3);min-height:0}
.dm-list-head{display:flex;align-items:center;justify-content:space-between;padding:12px 12px 8px;flex-shrink:0}
.dm-list-title{font-family:var(--sans);font-size:15px;font-weight:700;color:var(--off-white)}
.dm-list-new{width:30px;height:30px;border-radius:8px;border:none;background:transparent;color:var(--muted);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .14s,color .14s}
.dm-list-new:hover{background:rgba(255,255,255,.07);color:var(--cream)}
.dm-list-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding:4px 8px 10px;min-height:0;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.12) transparent}
.dk-scroll{overflow-x:hidden;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.12) transparent}
/* Empty state (no DM selected): hide the composer + header, show the people picker */
.dm-chat-area.dm-empty-mode .dm-chat-header,
.dm-chat-area.dm-empty-mode .chatroom-input-wrap{display:none}
.dm-picker{max-width:540px;margin:0 auto;width:100%;padding:44px 24px}
.dm-picker-head{font-family:var(--display);font-size:26px;font-weight:800;color:var(--white);letter-spacing:-.02em}
.dm-picker-sub{font-size:13px;color:var(--muted);margin:4px 0 18px}
.dm-picker-search{width:100%;box-sizing:border-box;padding:11px 14px;border-radius:10px;border:1px solid var(--border-d);background:rgba(255,255,255,.05);color:var(--cream);font-family:var(--sans);font-size:14px;outline:none;margin-bottom:12px}
.dm-picker-search:focus{border-color:var(--coral)}
.dm-picker-list{display:flex;flex-direction:column;gap:2px}
.dm-person-row{display:flex;align-items:center;gap:11px;width:100%;padding:9px 11px;border:none;background:transparent;border-radius:10px;cursor:pointer;text-align:left;transition:background .12s}
.dm-person-row:hover{background:rgba(255,255,255,.05)}
.dm-person-meta{display:flex;flex-direction:column;gap:1px;min-width:0}
.dm-person-name{font-size:14px;font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dm-person-email{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dm-chat-header{flex-shrink:0; border-bottom:1px solid var(--border-d);}
.dm-header-top{padding:12px 20px 0; display:flex; align-items:center; gap:10px;}
.dm-header-star{width:28px; height:28px; border-radius:6px; border:1px solid var(--border-d); background:none; color:var(--muted); display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all .15s; flex-shrink:0; font-size:14px;}
.dm-header-star:hover{border-color:var(--gold); color:var(--gold);}
.dm-header-star.starred{color:var(--gold); border-color:var(--gold);}
.dm-header-avatar{width:32px; height:32px; border-radius:8px; background:rgba(255,255,255,.08); display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; color:var(--cream); flex-shrink:0; overflow:hidden;}
.dm-header-avatar img{width:100%; height:100%; object-fit:cover;}
.dm-header-name{font-size:17px; font-weight:700; color:var(--cream);}
/* Conversation tabs — the project view-tab pill, reused. Everything that makes a tab
   look and move like a tab (.ws-view-tabs rail, .ws-view-tab, the sliding thumb) lives
   with the view tabs; only the placement is DM-specific. */
.dm-header-tabs{display:flex; padding:0 20px 10px; margin-top:8px; border-bottom:none;}
.dm-tabs{max-width:100%; overflow-x:auto; scrollbar-width:none;}
.dm-tabs::-webkit-scrollbar{display:none}
.dm-tab-content{display:none; flex:1; min-height:0;}
.dm-tab-content.active{display:flex; flex-direction:column; min-height:0; overflow:hidden;}
/* Canvas + Folder panes host components written for a full-height board area, so they
   get the padding here rather than each component learning about DMs. */
#dmTabCanvas{position:relative; padding:0 20px 16px}
#dmTabCanvas.active{display:flex}
#dmTabFolder{padding:14px 20px 16px; overflow:hidden}
.dm-canvas-load{padding:40px 0; text-align:center; color:var(--muted); font-size:13px; font-style:italic}
/* Bookmarks: one flat list, newest first. Not grouped by conversation — you come here
   for the message, and the conversation is a label on the row. */
.dm-bm-wrap{flex:1; min-height:0; overflow-y:auto; padding:14px 20px 20px}
.dm-bm-load{padding:30px 0; text-align:center; color:var(--muted); font-size:13px; font-style:italic}
.dm-bm-head-row{display:flex; align-items:center; gap:8px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.5px; color:var(--muted); margin-bottom:10px}
.dm-bm-count{font-size:10px; font-weight:600; color:var(--muted); background:rgba(255,255,255,.08); padding:1px 7px; border-radius:10px; letter-spacing:0}
.dm-bm-row{display:flex; gap:10px; width:100%; text-align:left; align-items:flex-start; padding:10px 12px; border:0; border-radius:10px; background:none; cursor:pointer; transition:background .12s; font-family:var(--sans)}
.dm-bm-row:hover{background:rgba(255,255,255,.05)}
.dm-bm-av{flex:none}
.dm-bm-main{display:flex; flex-direction:column; gap:2px; min-width:0; flex:1}
.dm-bm-head{display:flex; align-items:baseline; gap:8px; min-width:0}
.dm-bm-head b{font-size:13px; font-weight:700; color:var(--text-1)}
.dm-bm-conv{font-size:11px; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0}
.dm-bm-time{font-size:11px; color:var(--muted); margin-left:auto; flex:none}
.dm-bm-text{font-size:13px; color:var(--text-2); line-height:1.45; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden}
/* Jumping to a saved message marks it, briefly — otherwise you land mid-thread with
   no idea which row you came for. */
@keyframes dmxMsgFlash{0%{background:color-mix(in srgb,var(--purple) 26%,transparent)}100%{background:transparent}}
.dmx-msg-flash,.cr-msg-row.dmx-msg-flash{animation:dmxMsgFlash 1.4s ease-out; border-radius:8px}
.dm-messages-wrap{flex:1; height:0; min-height:0; overflow-y:auto; padding:8px 0;}
.dm-input-row{padding:16px 20px; flex-shrink:0; display:flex; gap:8px; border-top:1px solid var(--border-d);}
.dm-chat-input{flex:1; background:var(--bg-inset); border:1px solid var(--border-d); border-radius:8px; padding:12px 14px; color:var(--cream); font-size:14px; outline:none; transition:border-color .15s;}
.dm-chat-input:focus{border-color:rgba(255,255,255,.2);}
.dm-chat-input::placeholder{color:var(--muted);}
.dm-date-sep{display:flex; align-items:center; justify-content:center; margin:20px 0 16px; position:relative;}
.dm-date-sep::before{content:''; position:absolute; left:0; right:0; top:50%; height:1px; background:var(--border-d);}
.dm-date-sep span{position:relative; z-index:1; font-size:12px; font-weight:600; color:var(--cream); background:var(--dark); border:1px solid var(--border-d); border-radius:24px; padding:4px 16px; white-space:nowrap; cursor:default;}
.dm-time-gap{height:16px;}
.dm-files-list{padding:16px 20px;}
.dm-file-item{display:flex; align-items:center; gap:12px; padding:10px 0; border-bottom:1px solid var(--border-d);}
.dm-file-icon{width:36px; height:36px; border-radius:8px; background:rgba(255,255,255,.06); display:flex; align-items:center; justify-content:center; font-size:16px; flex-shrink:0;}
.dm-file-info{flex:1; min-width:0;}
.dm-file-name{font-size:13px; font-weight:600; color:var(--cream); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.dm-file-name a{color:var(--blue); text-decoration:none;}
.dm-file-name a:hover{text-decoration:underline;}
.dm-file-meta{font-size:11px; color:var(--muted);}
.chatroom-messages-wrap,.dm-messages-wrap{user-select:text;-webkit-user-select:text}
#dmMessages .cr-msg-row{padding-left:16px;padding-right:16px}
/* Discord-style desktop DM rows (share the channels cr- message CSS). */
#dmMessages .cr-msg-avatar-slot{width:40px;flex-shrink:0}
#dmMessages .cr-msg-avatar-slot .dmx-avwrap{width:40px}
#dmMessages .cr-msg-row{position:relative}
#dmMessages .cr-msg-row .dmx-tb{top:-26px;right:16px;left:auto}
#dmMessages .cr-msg-row:hover .dmx-tb{display:flex}
#dmMessages .dmx-receipt{text-align:left;padding-left:0}

/* Slash-command popup (/) — reuses .mention-popup container; item + help-overlay styling */
.slash-item{display:flex;align-items:baseline;gap:8px;padding:8px 12px;cursor:pointer}
.slash-item.selected,.slash-item:hover{background:rgba(124,92,255,.16)}
.slash-item-cmd{font-weight:700;font-size:13px;color:#8b6cff;flex:none}
.slash-item-args{font-size:11px;color:var(--text-3);flex:none}
.slash-item-argval{font-weight:600;font-size:13px;color:var(--text-1);flex:none}
.slash-item-hint{font-size:12px;color:var(--text-3);margin-left:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:150px}
.slash-help-row{display:flex;align-items:baseline;gap:12px;padding:9px 2px;border-bottom:1px solid rgba(255,255,255,.05)}
.slash-help-cmd{font-weight:700;font-size:13px;color:#8b6cff;flex:none;min-width:150px}
.slash-help-args{font-weight:400;color:rgba(235,235,245,.32);font-size:11px}
.slash-help-hint{font-size:13px;color:rgba(235,235,245,.6)}
html[data-theme="light"] .slash-item-cmd,html[data-theme="light"] .slash-help-cmd{color:#6c4bff}
.slash-item-preview{font-size:12px;color:#79b98a;margin-left:auto;white-space:nowrap;font-weight:600}
html[data-theme="light"] .slash-item-preview{color:#3d7f52}

/* ===== DM redesign (Claude Design mockup) — theme-aware re-skin ===== */
#page-dm{--dmx-grad:linear-gradient(135deg,#ec3f9c 0%,#8b3fd4 100%);--dmx-on:#3ddc97;--dmx-off:#6b6b73;}
/* --- conversation list rows --- */
.dmx-list-empty{padding:22px 16px;font-size:13px;color:var(--muted);font-style:italic;text-align:center}
.dmx-row{display:flex;align-items:center;gap:9px;width:100%;text-align:left;background:none;border:0;padding:5px 10px;margin:1px 0;border-radius:6px;cursor:pointer;transition:background .13s;box-sizing:border-box}
.dmx-row:hover{background:var(--bg-inset)}
.dmx-row.active{background:var(--bg-inset)}
/* No gradient rail. The active row already carries a background, and a second
   indicator in a colour that appears nowhere else on the page was doing the same
   job twice, louder. */
.dmx-row.active::before{content:none}
.dmx-row{position:relative}
.dmx-avwrap{position:relative;flex-shrink:0;line-height:0}
.dmx-av{border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:600;font-size:12px;width:34px;height:34px}
.dmx-av img{width:100%;height:100%;object-fit:cover;display:block}
/* Sized to a sidebar entry, not to a contact card. At 42px each conversation was
   taller than a project row in the sidebar beside it, for the same kind of thing. */
.dmx-av-lg{width:28px;height:28px;font-size:11px}
/* 11px + a 2.5px ring is 16px of dot on a 28px avatar — and because the avatar is a CIRCLE,
   a badge that big has its centre 9.9px from the middle against a 14px radius, i.e. sitting
   INSIDE the face rather than on its edge. That is what read as "too far left". At 10px the
   centre lands at 14.1px, on the circle edge at the 4-o'clock diagonal, which is where a
   presence dot belongs. right/bottom of -1px is the geometry, not a nudge: it is what puts
   the centre exactly one radius out along the diagonal. */
.dmx-dot{position:absolute;right:-1px;bottom:-1px;width:6px;height:6px;border-radius:50%;border:2px solid var(--surface);box-sizing:content-box}
.dmx-dot-online{background:var(--dmx-on)}
.dmx-dot-offline{background:var(--dmx-off)}
.dmx-row-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.dmx-row-top{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.dmx-row-name{font-size:13px;font-weight:600;color:var(--text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dmx-row-time{font-size:11px;color:var(--muted);flex-shrink:0;font-variant-numeric:tabular-nums}
.dmx-row-bot{display:flex;align-items:center;justify-content:space-between;gap:8px}
.dmx-row-prev{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}
.dmx-row.unread .dmx-row-name{font-weight:700}
.dmx-row.unread .dmx-row-prev{color:var(--text-1);font-weight:500}
.dmx-row-badge{flex-shrink:0;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--dmx-grad);color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;box-sizing:border-box}
/* --- chat header --- */
.dmx-header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:11px 20px}
/* The tab strip is a flex container, so its default min-width:auto refused to shrink and
   took the whole row — the name and presence column was squeezed to zero width, which is
   why the DM header showed an avatar and no name at all. The identity gets the free space
   and the tabs scroll instead of crushing it. */
/* Same separation as a channel's tab strip: flat header, shadow cast onto the messages. */
.dmx-header{position:relative;z-index:4;background:none}
.dmx-header-id{display:flex;align-items:center;gap:11px;flex:1 1 auto;min-width:min(230px,50%)}
.dmx-header .dm-header-tabs{min-width:0;flex:0 1 auto;overflow-x:auto;scrollbar-width:none}
.dmx-header .dm-header-tabs::-webkit-scrollbar{display:none}
.dmx-header .dmx-av,.dmx-header-avatar.dmx-av{width:38px;height:38px;font-size:14px;background:var(--bg3)}
.dmx-header-meta{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1 1 auto}
.dmx-header-name{font-family:var(--serif);font-size:18px;font-weight:500;font-style:italic;color:var(--text-1);letter-spacing:.2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:.14em;margin-right:-.14em}
.dmx-header-presence{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dmx-header .dm-header-star{margin-left:2px}
/* --- message feed --- */
.dm-messages-wrap{padding:14px 22px 20px}
.dmx-empty{margin:auto;padding:48px;text-align:center;font-size:13px;color:var(--muted);font-style:italic}
.dmx-day{display:flex;align-items:center;gap:12px;margin:16px 0 12px;color:var(--muted);font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase}
.dmx-day::before,.dmx-day::after{content:"";flex:1;height:1px;background:var(--border-d)}
.dmx-grp{display:flex;gap:10px;margin:2px 0}
.dmx-grp-them{justify-content:flex-start}
.dmx-grp-me{justify-content:flex-end}
.dmx-grp-av{align-self:flex-end;margin-bottom:2px}
.dmx-grp-av .dmx-av{width:32px;height:32px;font-size:12px}
.dmx-grp-main{display:flex;flex-direction:column;min-width:0;max-width:70%}
.dmx-grp-head{display:flex;align-items:baseline;gap:8px;margin:0 0 3px 3px}
/* Grouped DM rows carry the author's colour too, the same --cr-au a channel row uses, so a
   conversation is colour-coded whichever of the two row shapes it happens to render. */
.dmx-grp-name{font-size:13px;font-weight:600;color:var(--cr-au,var(--text-1))}
.dmx-grp-t{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.dmx-grp-me .dmx-grp-time{align-self:flex-end;font-size:11px;color:var(--muted);margin:0 3px 3px 0;font-variant-numeric:tabular-nums}
.dmx-grp-stack{display:flex;flex-direction:column;gap:3px;min-width:0}
.dmx-grp-me .dmx-grp-stack{align-items:flex-end;max-width:70%}
/* Mobile bubbles stack; the desktop row must stay horizontal (avatar left of the
   message). This was unscoped, so it overrode .cr-msg-row's flex-direction on desktop
   and put every avatar on top of its own message. */
.dmx-msg{position:relative}
body[data-mobile-mode="app"] .dmx-msg{display:flex;flex-direction:column;gap:5px}
.dmx-grp-me .dmx-msg{align-items:flex-end}
.dmx-bub{position:relative;padding:8px 13px;font-size:14px;line-height:1.45;max-width:100%;word-wrap:break-word;overflow-wrap:anywhere}
.dmx-bub-them{background:var(--bg3);color:var(--text-1);border-radius:6px 18px 18px 18px}
.dmx-bub-me{background:var(--dmx-grad);color:#fff;border-radius:18px 6px 18px 18px}
.dmx-bub-me a{color:#fff;text-decoration:underline}
.dmx-edited{font-size:10px;opacity:.6;margin-left:6px}
/* reactions */
.dmx-reax-row{display:flex;flex-wrap:wrap;gap:5px;margin-top:1px}
.dmx-reax{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:11px;border:1px solid var(--border-d);background:var(--bg-inset);color:var(--text-1);font-size:11px;font-weight:600;cursor:pointer;transition:background .12s}
.dmx-reax:hover{background:var(--bg3)}
.dmx-reax.mine{border-color:transparent;background:rgba(236,63,156,.16);color:#ec3f9c}
/* attachments */
.dmx-att-img{display:inline-block;max-width:260px;border-radius:12px;overflow:hidden;line-height:0}
.dmx-att-img img{max-width:100%;display:block}
.dmx-att-file{display:inline-flex;align-items:center;gap:10px;padding:9px 14px;margin:4px 0;border-radius:11px;background:var(--bg-inset);border:1px solid var(--border-d);text-decoration:none;max-width:260px}
.dmx-att-ext{flex-shrink:0;font-size:9px;font-weight:800;letter-spacing:.5px;color:var(--text-2);background:var(--surface-raised);border-radius:5px;padding:4px 6px}
.dmx-att-name{font-size:12px;color:var(--text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* hover toolbar */
.dmx-tb{position:absolute;top:-14px;display:none;align-items:center;gap:1px;padding:3px;border-radius:10px;background:var(--surface);border:1px solid var(--border-d);box-shadow:0 6px 20px rgba(0,0,0,.28);z-index:4}
.dmx-msg.them .dmx-tb{left:0}
.dmx-msg.me .dmx-tb{right:0}
.dmx-msg:hover .dmx-tb{display:flex}
.dmx-tb-b{display:flex;align-items:center;justify-content:center;min-width:26px;height:26px;padding:0 5px;border:0;background:none;border-radius:7px;cursor:pointer;font-size:14px;color:var(--muted);transition:background .1s}
.dmx-tb-b:hover{background:var(--bg-inset);color:var(--text-1)}
.dmx-tb-del:hover{color:#e5484d}
.dmx-tb-sep{width:1px;height:16px;background:var(--border-d);margin:0 2px}
/* thread indicator under a message */
.dmx-thread-ind{align-self:flex-start;margin-top:1px;padding:3px 10px;border-radius:11px;border:1px solid var(--border-d);background:none;color:#ec3f9c;font-size:11px;font-weight:600;cursor:pointer;transition:background .12s}
.dmx-grp-me .dmx-thread-ind{align-self:flex-end}
.dmx-thread-ind:hover{background:var(--bg-inset)}
.dmx-receipt{font-size:10px;color:var(--muted);margin-top:1px}
/* composer pill */
/* DM composer — the Design Rules comment bar, scaled up for a primary messaging
   surface. The stray 16px under the bar is gone; 10px is the gap to the window edge. */
/* Padding comes from .chatroom-input-wrap, the same as a channel's. The class stays only
   because .has-content keys the send split off it. */
/* No size overrides: the DM composer is EXACTLY the comment composer (.cmt-bar /
   .cmt-field / .cmt-actions / .cmt-btn). Only the max-height differs, because a
   message can run longer than a comment.
   The field's min-height matches the tallest action (the 34px send split) so that with
   align-items:flex-end a single line of text sits level with the buttons instead of
   riding above them — while a grown field still bottoms out correctly. */
.dmx-cmt-field{max-height:180px;min-height:34px;display:flex;align-items:center}
.dmx-composer-wrap .cmt-field{padding:7px 0 !important;line-height:20px}
/* Slack-style split send: arrow sends, caret opens the schedule menu. Both stay dim
   until there is something to send, so the bar reads as idle when it is. */
.dmx-send-split{display:inline-flex;align-items:stretch;margin-left:4px;border-radius:9px;overflow:hidden;
  background:var(--color-brand-tint);opacity:.45;pointer-events:none;transition:opacity .15s ease,background .15s ease}
.dmx-composer-wrap.has-content .dmx-send-split{opacity:1;pointer-events:auto;background:var(--purple)}
.dmx-send,.dmx-send-caret{border:0;background:none;color:var(--text-1);cursor:pointer;display:inline-flex;
  align-items:center;justify-content:center;padding:0;transition:background .12s ease}
.dmx-send{width:36px;height:34px}
.dmx-send-caret{width:22px;height:34px;border-left:1px solid rgba(255,255,255,.22)}
.dmx-send:hover,.dmx-send-caret:hover{background:rgba(255,255,255,.16)}
.dmx-send:active,.dmx-send-caret:active{transform:scale(.95)}
/* Schedule menu — a floating menu, so it takes the shared liquid-glass recipe. */
.dmx-sched-menu{position:fixed;z-index:10300;min-width:212px;border-radius:12px;padding:5px;display:none}
.dmx-sched-menu.open{display:block}
.dmx-sched-menu button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:14px;
  background:none;border:0;border-radius:8px;padding:8px 11px;cursor:pointer;
  font:600 13px var(--sans);color:var(--text-1);text-align:left}
.dmx-sched-menu button:hover{background:rgba(255,255,255,.09)}
.dmx-sched-menu .dmx-sched-when{font-weight:500;color:var(--text-3);font-size:12px}
.dmx-sched-head{padding:7px 11px 5px;font:800 10px var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
/* --- thread panel --- */
body[data-mobile-mode="app"] #page-dm.dmx-thread-open .dm-list-col{display:none}
.dmx-thread-panel{width:360px;flex-shrink:0;display:flex;flex-direction:column;border-left:1px solid var(--border-d);background:var(--bg2);min-height:0}
.dmx-thread-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:14px 18px;border-bottom:1px solid var(--border-d);flex-shrink:0}
.dmx-thread-head-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.dmx-thread-title{font-family:var(--serif);font-size:17px;font-weight:500;font-style:italic;color:var(--text-1)}
.dmx-thread-sub{font-size:11px;color:var(--muted)}
.dmx-thread-close{width:30px;height:30px;display:flex;align-items:center;justify-content:center;border:0;background:none;border-radius:8px;color:var(--muted);cursor:pointer}
.dmx-thread-close:hover{background:var(--bg-inset);color:var(--text-1)}
.dmx-thread-body{flex:1;min-height:0;overflow-y:auto;padding:16px 18px}
.dmx-thread-parent{display:flex;gap:10px;padding-bottom:14px}
.dmx-tr-main{min-width:0;flex:1}
.dmx-thread-ptext,.dmx-tr-text{font-size:13px;line-height:1.45;color:var(--text-1);margin-top:2px;word-wrap:break-word;overflow-wrap:anywhere}
.dmx-thread-count{display:flex;align-items:center;gap:12px;margin:2px 0 14px;font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.4px}
.dmx-thread-rule{flex:1;height:1px;background:var(--border-d)}
.dmx-thread-replies{display:flex;flex-direction:column;gap:14px}
.dmx-thread-reply{display:flex;gap:10px}
.dmx-thread-composer{flex-shrink:0;padding:10px 12px;border-top:1px solid var(--border-d)}
/* The thread reply box is the same .cmt-bar as the message box, just tighter
   horizontally — same height, so the two composers read as one control. */
.dmx-thread-composer .cmt-bar{padding:6px 6px 6px 12px;gap:6px}
.dmx-thread-composer .cmt-field{max-height:120px}
.dmx-thread-input{flex:1;resize:none;background:var(--bg-inset);border:1px solid var(--border-d);border-radius:16px;padding:8px 13px;font:inherit;font-size:13px;color:var(--text-1);max-height:120px;line-height:1.4}
.dmx-thread-input:focus{outline:none;border-color:var(--coral)}
.dmx-thread-send{width:34px;height:34px;flex-shrink:0;display:flex;align-items:center;justify-content:center;border:0;border-radius:50%;background:var(--dmx-grad);color:#fff;cursor:pointer}
.dmx-thread-send:hover{opacity:.9}

/* ===== Mobile DMs — Instagram-style (full-screen list → conversation) ===== */
.dm-mobile-back{display:none}
/* Reset the desktop negative-margin/width bleed so the list isn't shifted off-screen. */
body[data-mobile-mode="app"] #page-dm.active{margin:0!important;width:100%!important;max-width:100%!important}
body[data-mobile-mode="app"] #page-dm .dm-layout{display:block;gap:0}
/* List flows as a normal mobile page (header + bottom-nav padding from .page.active). */
body[data-mobile-mode="app"] #page-dm .dm-list-col{width:100%;max-width:none;border:0;background:transparent;display:flex;flex-direction:column}
body[data-mobile-mode="app"] #page-dm .dm-list-head{padding:12px 16px 6px}
body[data-mobile-mode="app"] #page-dm .dm-list-title{font-size:24px;font-weight:800;color:var(--ink-solid);font-family:var(--sans);letter-spacing:.2px}
body[data-mobile-mode="app"] #page-dm .dm-list-new{width:42px;height:42px;color:var(--ink-solid)}
body[data-mobile-mode="app"] #page-dm .dm-list-scroll{flex:1;min-height:0;padding:2px 0 90px}
/* IG list rows: big circular avatar + name + preview */
body[data-mobile-mode="app"] #page-dm .dmx-row{padding:8px 16px;gap:12px;margin:0;border-radius:0}
body[data-mobile-mode="app"] #page-dm .dmx-row.active::before{display:none}
body[data-mobile-mode="app"] #page-dm .dmx-row:active{background:rgba(var(--line),.06)}
body[data-mobile-mode="app"] #page-dm .dmx-av-lg{width:56px;height:56px;font-size:20px}
body[data-mobile-mode="app"] #page-dm .dmx-dot{border-width:3px;width:14px;height:14px}
body[data-mobile-mode="app"] #page-dm .dmx-row-name{font-size:15px;color:var(--ink-solid)}
body[data-mobile-mode="app"] #page-dm .dmx-row-time,
body[data-mobile-mode="app"] #page-dm .dmx-row-prev{font-size:14px;color:rgba(var(--ink),.5)}
body[data-mobile-mode="app"] #page-dm .dmx-row.unread .dmx-row-prev{color:var(--ink-solid);font-weight:600}
/* Conversation = fixed full-screen overlay (covers the shell), slides in over the list */
body[data-mobile-mode="app"] #page-dm .dm-chat-area{position:fixed;inset:0;background:var(--bg-main);transform:translateX(100%);transition:transform .22s ease;z-index:10060;display:flex;flex-direction:column;pointer-events:none}
body[data-mobile-mode="app"] #page-dm.dm-open .dm-chat-area{transform:translateX(0);pointer-events:auto}
body[data-mobile-mode="app"] #page-dm .dm-chat-header{padding-top:calc(8px + env(safe-area-inset-top,0px))}
body[data-mobile-mode="app"] #page-dm .dm-chat-area.dm-empty-mode .dm-chat-header,
body[data-mobile-mode="app"] #page-dm.dm-open .dm-chat-area.dm-empty-mode .chatroom-input-wrap{display:flex}
/* IG conversation header: back + avatar + name (no tabs/star) */
body[data-mobile-mode="app"] #page-dm .dm-chat-header{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid rgba(var(--line),.08);flex-shrink:0}
/* presence text already reads "Active now" — the overlapping status dot on the header avatar is redundant here */
body[data-mobile-mode="app"] #page-dm .dm-chat-header .dmx-dot{display:none}
body[data-mobile-mode="app"] #page-dm .dm-mobile-back{display:flex;align-items:center;justify-content:center;width:34px;height:38px;border:0;background:none;color:var(--ink-solid);flex:none;padding:0;-webkit-tap-highlight-color:transparent}
body[data-mobile-mode="app"] #page-dm .dm-header-tabs,
body[data-mobile-mode="app"] #page-dm .dm-header-star{display:none}
body[data-mobile-mode="app"] #page-dm .dmx-header-id{gap:9px;flex:1;min-width:0}
body[data-mobile-mode="app"] #page-dm .dmx-header .dm-header-avatar,
body[data-mobile-mode="app"] #page-dm .dmx-header .dmx-av{width:34px;height:34px;font-size:13px}
body[data-mobile-mode="app"] #page-dm .dmx-header-name{font-size:16px;font-style:normal;font-weight:700;font-family:var(--sans)}
body[data-mobile-mode="app"] #page-dm .dmx-header-presence{font-size:12px}
/* Bubbles: IG purple for mine, gray for theirs. width:fit-content stops the bubble collapsing to
   1-char columns (overflow-wrap:anywhere makes min-content = 1 char inside a shrink-to-fit flex parent). */
/* Block layout (NOT flex) so the bubble can't collapse onto its 1-char min-content in the narrow
   overlay. inline-block bubbles size to their text up to max-width — no flex circular dependency. */
body[data-mobile-mode="app"] #page-dm .dmx-grp{display:block;width:100%;margin:1px 0}
body[data-mobile-mode="app"] #page-dm .dmx-grp-av{float:left;margin:0 8px 0 0}
body[data-mobile-mode="app"] #page-dm .dmx-grp-main,
body[data-mobile-mode="app"] #page-dm .dmx-grp-stack,
body[data-mobile-mode="app"] #page-dm .dmx-msg{display:block;width:auto;max-width:100%;overflow:visible}
body[data-mobile-mode="app"] #page-dm .dmx-grp-them .dmx-grp-main{overflow:hidden}
body[data-mobile-mode="app"] #page-dm .dmx-grp-me{text-align:right}
body[data-mobile-mode="app"] #page-dm .dmx-grp-me .dmx-grp-time{display:block;text-align:right}
body[data-mobile-mode="app"] #page-dm .dmx-bub{display:inline-block;width:auto;max-width:80%;text-align:left;white-space:normal;overflow-wrap:break-word;word-break:break-word}
body[data-mobile-mode="app"] #page-dm .dmx-bub-me{background:#7b52ff;color:#fff;border-radius:22px 22px 5px 22px}
body[data-mobile-mode="app"] #page-dm .dmx-bub-them{border-radius:22px 22px 22px 5px}
body[data-mobile-mode="app"] #page-dm .dmx-grp-name,
body[data-mobile-mode="app"] #page-dm .dmx-grp-t{font-size:12px}
/* pill composer at bottom */
body[data-mobile-mode="app"] #page-dm .dmx-composer-wrap{padding:8px 12px calc(10px + env(safe-area-inset-bottom,0px))}
body[data-mobile-mode="app"] #page-dm .dmx-composer-wrap .chatroom-input-bar{border-radius:26px}

/* ============================================================================
   Mobile bug-fix batch (bottom bar, task modal, sheets). All mobile-scoped.
   ============================================================================ */

/* ── Item 1 (revised) — the bottom-nav selection pill SLIDES.
   It used to be pinned to opacity-only: back then the nav items were full-width flex
   children, so a pill travelling between them read as the whole bar flashing purple.
   The items are a fixed 58px now (.m-bn-item), which makes the pill a tab-sized
   highlight — gliding it is exactly what the bar was missing. _positionPillThumb still
   snaps it (inline transition:none for one frame) on first paint and whenever the item
   SET changes, so a board opening/closing never reads as a tab switch. */
body[data-mobile-mode="app"] #mBottomNav .m-pill-thumb{
  transition:transform var(--m-hotbar-slide-dur) var(--m-hotbar-slide-ease),
             width var(--m-hotbar-slide-dur) var(--m-hotbar-slide-ease),
             height var(--m-hotbar-slide-dur) var(--m-hotbar-slide-ease),
             opacity .15s ease
}
/* The icon leads the pill: it lifts and colours the moment the tab becomes active,
   while the pill catches up underneath. Transform-only, so it stays on the compositor. */
body[data-mobile-mode="app"] #mBottomNav .m-bn-item svg{
  transition:transform 260ms var(--m-hotbar-slide-ease),opacity 160ms ease
}
body[data-mobile-mode="app"] #mBottomNav .m-bn-item.is-active svg{transform:translateY(-1px) scale(1.08)}
/* Press feedback — the whole tab dips, instead of the old flat opacity fade. */
body[data-mobile-mode="app"] #mBottomNav .m-bn-item:active{opacity:1}
body[data-mobile-mode="app"] #mBottomNav .m-bn-item:active svg{transform:scale(.88);opacity:.75}
body[data-mobile-mode="app"] #mBottomNav .m-bn-item.is-active:active svg{transform:translateY(-1px) scale(.94)}
@media(prefers-reduced-motion:reduce){
  body[data-mobile-mode="app"] #mBottomNav .m-pill-thumb{transition:opacity .15s ease}
  body[data-mobile-mode="app"] #mBottomNav .m-bn-item svg,
  body[data-mobile-mode="app"] #mBottomNav .m-bn-item.is-active svg{transition:none;transform:none}
}

/* ── Item 9 — icon-only bottom nav: hide every label (incl. board-swap Modify/Add variants).
   The id-scoped selector beats the board-open display:block label rules. Icons stay centered. */
body[data-mobile-mode="app"] #mBottomNav .m-bn-label{display:none}
body[data-mobile-mode="app"] #mBottomNav .m-bn-item{gap:0}
body[data-mobile-mode="app"] #mBottomNav .m-bn-item svg{width:26px;height:26px}

/* ── Item 18 — remove the standing Settings tab OFF-board (it doubles as the board "+" add
   button, so keep it while a board is open). Settings now lives in the workspace picker. */
body[data-mobile-mode="app"]:not([data-board-open]) .m-bn-item[data-mnav="settings"]{display:none}

/* ── Item 16 — project view tabs (Kanban/List/Calendar/Canvas) match the Home task-tabs
   free-pill look (both already share the sliding-thumb engine; this is pure skin). */
body[data-mobile-mode="app"] .ws-view-tabs{background:none;border-radius:0;padding:0;gap:var(--m-tab-gap)}
body[data-mobile-mode="app"] .ws-view-tabs .ws-view-tab{
  height:var(--m-tab-h);min-height:var(--m-tab-h);padding:0 var(--m-tab-pad-x);
  border-radius:var(--m-tab-radius);gap:7px;
  background:rgba(var(--line),0.07);color:rgba(var(--ink),0.7);
  font:var(--m-tab-weight) var(--m-tab-font) var(--sans);
}
body[data-mobile-mode="app"] .ws-view-tabs .ws-view-tab.active{color:#16121f}
body[data-mobile-mode="app"] .ws-view-tabs .m-pill-thumb{background:var(--m-accent-soft);border:0;border-radius:var(--m-tab-radius)}
html[data-theme="light"] body[data-mobile-mode="app"] .ws-view-tabs .ws-view-tab.active{color:#fff}
html[data-theme="light"] body[data-mobile-mode="app"] .ws-view-tabs .m-pill-thumb{background:var(--m-accent,#7c5cff)}

/* ── Items 5 & 10 — task modal top tab strip must own its stacking + contain its own pill
   highlight, so neither the highlight nor a following panel (Description/Publish/History)
   can paint over the tabs. Removes the dependency on the JS-added .m-pillbar class. */
body[data-mobile-mode="app"] #mTaskTabs{position:relative;z-index:5;background:var(--bg)}

/* ── The tabs were being CUT IN HALF by the panel below them. Not a paint-order
   problem (that is what the rule above fixed) — a flex one. `.card-modal` is a
   column flex container, so #mTaskTabs is a flex item; giving it `overflow:hidden`
   (needed so the equal-width segments don't spill) drops its automatic minimum
   size from content-height to ZERO, and flexbox is then free to shrink it
   whenever the panel below overflows. The strip collapsed to ~45px around a 38px
   pill sitting 10px down, and clipped the bottom of every tab — worst on Review,
   whose player is the tallest panel.
   `.card-modal` is its own scroll container on mobile, so NOTHING in it should
   shrink: fix the strip's basis to its content and let the modal scroll. */
body[data-mobile-mode="app"] #mTaskTabs{
  flex:0 0 auto;
  min-height:calc(var(--m-tab-h) + 20px);   /* pill + the strip's 10px y-padding */
}
body[data-mobile-mode="app"] #mCardActionRow,
body[data-mobile-mode="app"] .card-modal-meta{flex:0 0 auto}

/* ============================================================================
   MOBILE — Review tab. The Review pane was built for a 1360px two-column modal
   and was simply dropped onto the phone: an 11-button transport row that
   overflowed its container by ~270px (six controls unreachable off the right
   edge), a floating file/version chip covering the top of the video, an
   orphaned upload/delete link row, and a comments column whose composer sat
   under the floating task hotbar. This block is the phone layout: one column,
   edge-to-edge player, a thumb-sized transport, everything else behind "More".
   Shape values come from the mobile tokens (Design Rules → #dr-mobile).
   ============================================================================ */
body[data-mobile-mode="app"] .rev-wrap.rev2{
  flex-direction:column;height:auto;gap:0;
  border:0;border-radius:var(--m-radius-card);overflow:hidden;background:#08080a;
}
/* Stage: no letterbox padding, no radial vignette — the video is the hero. */
body[data-mobile-mode="app"] .rev2 .rev-stage{
  display:flex;flex-direction:column;padding:0;background:#000;flex:none;container-type:normal;
}
body[data-mobile-mode="app"] .rev2 .rev-player{
  width:min(100%,calc(46vh * var(--rev-ar,1.77778)));height:auto;max-height:none;aspect-ratio:var(--rev-ar,16/9);
  border-radius:0;box-shadow:none;
}
/* Version chip: was position:absolute over the top-right of the frame, where it
   covered the picture and its 12px hit targets were unusable. On a phone it
   becomes a real row ABOVE the video (order:-1 — it is the stage's first child
   in the DOM already), full width, with proper touch targets. */
body[data-mobile-mode="app"] .rev2 .rev-stage>.rev-topright{
  position:static;order:-1;max-width:none;width:100%;
  background:var(--surface);backdrop-filter:none;-webkit-backdrop-filter:none;
  border:0;border-bottom:1px solid rgba(var(--line),0.08);border-radius:0;
  padding:0 var(--m-gap) 0 var(--m-pad);min-height:var(--m-touch-min);
}
body[data-mobile-mode="app"] .rev-tr-name{
  flex:1;min-width:0;max-width:none;font-size:13px;color:var(--ink-solid);
}
body[data-mobile-mode="app"] .rev-tr-arrow{width:var(--m-touch-min);height:var(--m-touch-min);border-radius:10px}
body[data-mobile-mode="app"] .rev-tr-arrow svg{width:var(--m-icon-sm);height:var(--m-icon-sm)}
body[data-mobile-mode="app"] .rev-tr-count{font-size:13px}
/* Transport: tighter gutters, and a scrub bar tall enough to grab. */
body[data-mobile-mode="app"] .rev2 .rev-transport{padding:var(--m-pad) var(--m-pad) var(--m-gap)}
body[data-mobile-mode="app"] .rev2 .rev-transport .rev-scrub{height:28px}
body[data-mobile-mode="app"] .rev-ctrlrow{gap:var(--m-gap);margin-top:var(--m-gap)}
body[data-mobile-mode="app"] .rev2 .rev-ctrlrow .rev-cbtn{
  width:var(--m-touch-min);height:var(--m-touch-min);border-radius:12px;
}
body[data-mobile-mode="app"] .rev-ctrlrow .rev-cbtn svg{width:var(--m-icon-md);height:var(--m-icon-md)}
body[data-mobile-mode="app"] .rev2 .rev-cbtn-play{width:52px !important;height:52px !important}
body[data-mobile-mode="app"] .rev2 .rev-cbtn-play svg{width:var(--m-icon-md);height:var(--m-icon-md)}
/* Timecode gets its own full-width line ABOVE the buttons (current time left,
   duration right). Sharing the button row cost it ~110px and pushed the row
   past the container even after the secondary controls folded away. */
body[data-mobile-mode="app"] .rev-ctrlrow{flex-wrap:wrap}
body[data-mobile-mode="app"] .rev-ctrlrow .rev-tcwrap{
  order:-1;flex:0 0 100%;justify-content:space-between;align-items:baseline;margin:0 0 2px;
}
body[data-mobile-mode="app"] .rev-ctrl-spacer{display:none}
body[data-mobile-mode="app"] .rev-cbtn-more{margin-left:auto}
body[data-mobile-mode="app"] .rev2 .rev-tcwrap .rev-tc{font-size:15px}
body[data-mobile-mode="app"] .rev-tc-dur{font-size:15px}
/* The six secondary controls fold into the "More" sheet; the sheet button is
   mobile-only (it is display:none everywhere else — see .rev-cbtn-more below). */
body[data-mobile-mode="app"] .rev-ctrlrow .rev-cbtn-sec{display:none}
body[data-mobile-mode="app"] .rev-cbtn-more{display:flex}
/* Upload / delete moved into that same sheet, so the stray link row goes. */
body[data-mobile-mode="app"] .rev2 .rev-replace{display:none}
/* Comments: full width, sitting under the player rather than beside it, with
   enough bottom room that the floating task hotbar never covers the composer. */
body[data-mobile-mode="app"] .rev2 .rev-side{
  width:100%;flex:none;height:auto;border:0;border-top:1px solid rgba(var(--line),0.08);
  background:var(--bg);
}
body[data-mobile-mode="app"] .rev2 .rev-list{max-height:none;padding:0 var(--m-gap)}
/* "Comments" was a one-item tab bar — a purple underline under a tab you can't
   leave. On the phone it becomes the same uppercase section label the rest of
   the task detail uses (DESCRIPTION / PROPERTIES), so Review stops looking like
   a different product. */
body[data-mobile-mode="app"] .rev2 .rev-subtabs{padding:var(--m-pad) var(--m-pad) 0}
body[data-mobile-mode="app"] .rev-subtab-static{
  font-size:var(--m-label);font-weight:700;letter-spacing:.8px;text-transform:uppercase;
  color:rgba(var(--ink),0.45);border-bottom:0;padding:0;margin:0;
}
/* Composer: the four action buttons plus Send were eating 178px of a 322px bar,
   squeezing the text field to 106px so "Leave a comment…" wrapped onto two
   lines behind the icons. Give the field the full first line and let the
   actions sit on their own row inside the same bar — every action stays
   reachable and the text has room. */
body[data-mobile-mode="app"] .rev2 .rev-input-row.cmt-bar{flex-wrap:wrap;align-items:center;padding:var(--m-gap) 10px}
body[data-mobile-mode="app"] .rev2 .rev-input-row .cmt-field{flex:1 0 100% !important;padding:4px 2px !important}
body[data-mobile-mode="app"] .rev2 .rev-input-row .cmt-actions{order:2;gap:4px}
body[data-mobile-mode="app"] .rev2 .rev-input-row .rev-send{order:3;margin-left:auto}
body[data-mobile-mode="app"] .rev2 .rev-input-row .cmt-btn{width:38px;height:38px;border-radius:10px}
body[data-mobile-mode="app"] .rev2 .rev-input-row .cmt-btn svg{width:19px;height:19px}
body[data-mobile-mode="app"] .rev2 .rev-filterbar{padding:var(--m-gap) var(--m-pad)}
body[data-mobile-mode="app"] .rev2 .rev-inputbar{
  padding:var(--m-pad) var(--m-pad) calc(var(--m-island-h) + 26px);
}
body[data-mobile-mode="app"] .rev-cm-acts{opacity:1}          /* no hover on a phone */
body[data-mobile-mode="app"] .rev-cm-text{font-size:15px}
/* Empty state (no video yet): a tappable card, not a desktop drag target. */
body[data-mobile-mode="app"] .rev-drop{
  min-height:200px;padding:26px var(--m-pad);border-radius:var(--m-radius-surface);
}
body[data-mobile-mode="app"] .rev-drop svg{width:38px;height:38px}
body[data-mobile-mode="app"] .rev-drop-title{font-size:15px}
/* "More" sheet rows show their current value on the right (quality, etc). */
.rev-more-val{margin-left:auto;font:500 13px var(--sans);color:var(--muted)}
/* The overflow button only exists on the phone. */
.rev-cbtn-more{display:none}

/* ── Item 6 — harden the comments composer row so it stays [avatar][input][mic][attach]
   horizontal (the layout already exists; !important guards against any future override). */
body[data-mobile-mode="app"] #mCommentsSheet #cardModalCommentInput{display:flex !important}

/* ── Item 8 — lock the task scroll behind the open comments sheet (backdrop opacity handled
   above). .card-modal is its own scroll container on mobile, so body-only lock wasn't enough. */
body[data-mobile-mode="app"]:has(#mCommentsSheet.open) .card-modal{overflow:hidden !important}

/* ── Item 11 — Subtasks & Properties open as bottom sheets matching the Comments sheet
   (backdrop + slide-up panel + grabber + top-right X + swipe-to-dismiss). Behind stays locked. */
/* Base state: gone entirely outside mobile app mode — these are static divs in normal flow
   (index.html), so without this they render as visible chrome at the bottom of desktop pages. */
.m-secsheet{display:none}
body[data-mobile-mode="app"] .m-secsheet{
  position:fixed;inset:0;z-index:10062;
  display:flex;flex-direction:column;justify-content:flex-end;
  visibility:hidden;pointer-events:none;transition:visibility 0s linear .34s;
}
body[data-mobile-mode="app"] .m-secsheet::before{
  content:'';position:absolute;inset:0;background:rgba(0,0,0,.82);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);opacity:0;transition:opacity .3s ease;
}
body[data-mobile-mode="app"] .m-secsheet.open{visibility:visible;pointer-events:auto;transition:visibility 0s}
body[data-mobile-mode="app"] .m-secsheet.open::before{opacity:1}
body[data-mobile-mode="app"] .m-secsheet .m-csheet-panel{height:88dvh;max-height:88dvh}
body[data-mobile-mode="app"] .m-secsheet.open .m-csheet-panel{transform:translateY(0)}
body[data-mobile-mode="app"]:has(.m-secsheet.open) .card-modal{overflow:hidden !important}
/* Align the Modify Project sheet to the Comments look (bg2 + 26px radius + bigger title). */
body[data-mobile-mode="app"] .mpc-sheet{background:var(--bg2);border-radius:26px 26px 0 0;border-top:0}
body[data-mobile-mode="app"] .mpc-sheet .rev-sheet-head{font-size:22px;color:var(--ink-solid)}
body[data-mobile-mode="app"] #mProjSettings.rev-sheet-ov{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}

/* ── Item 12 — mobile-friendly "Add subtask"/"Add Property" buttons + the property name form
   (16px inputs stop iOS zoom; 44px+ touch targets). !important beats the JS inline styles. */
body[data-mobile-mode="app"] .subtask-inline-add{
  display:flex;align-items:center;justify-content:center;gap:6px;width:100%;min-height:48px;
  margin-top:12px;font-size:15px;font-weight:600;border:1px solid rgba(var(--line),0.14);
  border-radius:14px;color:var(--ink-solid);background:rgba(var(--line),0.05);
}
body[data-mobile-mode="app"] .subtask-inline-add:active{background:rgba(var(--line),0.10)}
body[data-mobile-mode="app"] .inline-field-form{padding:14px !important;border-radius:14px !important;background:rgba(var(--line),0.05) !important}
body[data-mobile-mode="app"] .inline-field-form input{font-size:16px !important;padding:11px 12px !important;border-radius:10px !important;min-height:44px}
body[data-mobile-mode="app"] .inline-field-form > div:last-child{gap:10px !important}
body[data-mobile-mode="app"] .inline-field-form button{width:44px !important;height:44px !important;border-radius:12px !important}

/* ── Item 13 — subtasks on mobile: big reliable check target (was a 20px hover-only dot that
   mis-tapped into the title popup), always-visible delete, tap feedback. Toggle logic is fine. */
body[data-mobile-mode="app"] .subtask-inline-row{gap:8px;padding:8px 4px;min-height:48px}
body[data-mobile-mode="app"] .subtask-inline-check{width:40px;height:40px;flex-shrink:0;opacity:.9}
body[data-mobile-mode="app"] .subtask-inline-check svg{width:19px;height:19px}
body[data-mobile-mode="app"] .subtask-inline-check:active{transform:scale(.88)}
body[data-mobile-mode="app"] .subtask-inline-check.is-done{opacity:1}

/* ============================================================================
   Mobile swipe-to-reveal (DM + HDrive rows) + contextual bottom bar (HDrive folders / DMs).
   Reuses the Projects .m-project-actions / .m-proj-act pill CSS verbatim.
   ============================================================================ */

/* DM inbox swipe rows — opaque row slides over the fixed pill drawer behind it */
body[data-mobile-mode="app"] #page-dm .dmx-swipe{position:relative;overflow:hidden}
body[data-mobile-mode="app"] #page-dm .dmx-swipe:not(:last-child){border-bottom:0.5px solid rgba(var(--line),.07)}
body[data-mobile-mode="app"] #page-dm .dmx-swipe .dmx-row{position:relative;z-index:1;background:var(--bg-main,#0a0a0b);transform:translateX(0);touch-action:pan-y;will-change:transform;margin:0}
body[data-mobile-mode="app"] .m-proj-star{background:#ff9f0a}   /* amber Star pill */

/* HDrive Files swipe rows — divider moves onto the wrapper so it stays put while the row slides */
body[data-mobile-mode="app"] .hdm-swipe{position:relative;overflow:hidden}
body[data-mobile-mode="app"] .hdm-swipe:not(:last-child){border-bottom:0.5px solid rgba(var(--line),0.08)}
body[data-mobile-mode="app"] .hdm-swipe .hdm-row{position:relative;z-index:1;background:var(--bg-main,#0a0a0b);border-bottom:0;transform:translateX(0);touch-action:pan-y;will-change:transform}

/* Same guarantee the Projects rows get: the pill drawer is a swipe affordance
   ONLY. It stays unrendered until a gesture engages (.is-swiping) or the row is
   parked open, so a press-state tint — or any other translucency — can never
   flash the pills onto the screen during a plain tap. */
body[data-mobile-mode="app"] .m-swipe .m-project-actions{visibility:hidden}
body[data-mobile-mode="app"] .m-swipe.is-open .m-project-actions,
body[data-mobile-mode="app"] .m-swipe.is-swiping .m-project-actions{visibility:visible}
/* …and their press tints layer over the opaque fill instead of replacing it. */
body[data-mobile-mode="app"] .hdm-swipe .hdm-row:active{
  background:linear-gradient(rgba(var(--line),0.04),rgba(var(--line),0.04)),var(--bg-main,#0a0a0b);
}
body[data-mobile-mode="app"] #page-dm .dmx-swipe .dmx-row:active{
  background:linear-gradient(rgba(var(--line),.06),rgba(var(--line),.06)),var(--bg-main,#0a0a0b);
}

/* HDrive: Files nav item → Back (up one folder) while inside a folder (labels are icon-only) */
body[data-hdrive-folder-open] .m-bn-item[data-mnav="files"] .m-bn-ico-files{display:none}
body[data-hdrive-folder-open] .m-bn-item[data-mnav="files"] .m-bn-ico-back-files{display:inline-block}
body[data-hdrive-folder-open] .m-bn-item[data-mnav="files"]{color:#6b46d9}

/* DM: raise the bar over the full-screen conversation overlay + swap Messages → Back; the pinned
   pill composer reserves room so the raised bar doesn't cover it. */
body[data-dm-open] #mBottomNav{z-index:10061}
/* Mobile only: this reserves room for #mBottomNav over the full-screen conversation.
   Unscoped it also fired on DESKTOP, which is the stray 80px gap under the composer. */
body[data-mobile-mode="app"][data-dm-open] #page-dm .dmx-composer-wrap{padding-bottom:calc(80px + env(safe-area-inset-bottom,0px))}
body[data-dm-open] .m-bn-item[data-mnav="dm"] .m-bn-ico-dms{display:none}
body[data-dm-open] .m-bn-item[data-mnav="dm"] .m-bn-ico-back-dm{display:inline-block}
body[data-dm-open] .m-bn-item[data-mnav="dm"]{color:#6b46d9}

/* ============================================================================
   Platform Metrics (master-admin) — Shopify-style analytics panel
   ============================================================================ */
.pm-refresh:hover{color:var(--off-white);background:var(--state-hover)}

.pm-kpi-sub.up{color:var(--green,#4ea674)}


@media (max-width:900px){ .pm-grid{grid-template-columns:1fr} .pm-kpis{grid-template-columns:repeat(2,1fr)} }
@media (max-width:520px){ .pm-kpis{grid-template-columns:1fr} }

/* ============================================================================
   Signup wizard revamp: real logo, no emojis, inline "something else",
   signed-in banner, and the Sauce Media offer screen (rainbow bars).
   ============================================================================ */
.hs-rail-logo{height:30px;width:auto;border-radius:7px;display:inline-block;vertical-align:middle;flex:none}
.hs-invite-brand .hs-rail-logo{height:24px;margin-right:2px}
.hs-quiz-other{margin-top:10px}
.hs-signed-banner{
  font-size:13px;color:var(--muted);background:rgba(124,92,255,.08);
  border:1px solid rgba(124,92,255,.22);border-radius:10px;padding:9px 13px;margin-bottom:18px;line-height:1.5
}
.hs-signed-banner strong{color:var(--off-white)}
.hs-signed-banner a{color:#a78bfa;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.hs-upsell-ready{margin-bottom:22px}
.hs-upsell-card{border:1px solid var(--border-d);border-radius:14px;overflow:hidden;margin-bottom:22px;background:var(--bg-inset)}
.hs-upsell-bar{height:4px;background:var(--rainbow)}
.hs-upsell-body{padding:22px 24px}
.hs-upsell-kicker{font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:#fff;margin-bottom:8px}
.hs-upsell-h{font-family:var(--display,var(--sans));font-size:22px;font-weight:800;color:var(--off-white);margin-bottom:8px}
.hs-upsell-p{font-size:14px;line-height:1.6;color:var(--muted);margin:0 0 16px}
.hs-upsell-p strong{color:var(--off-white)}
.hs-upsell-cta{
  display:inline-block;background:#fff;color:#14111C;font-weight:800;font-size:14px;
  padding:11px 24px;border-radius:10px;text-decoration:none;transition:filter .15s
}
.hs-upsell-cta:hover{filter:brightness(1.08)}
/* invite state icons (were emojis) */
.hs-invite-state-emoji{display:flex;align-items:center;justify-content:center;color:var(--muted)}
/* workspace-manager row fallback initial (was an emoji) */
.aw-initial{
  width:24px;height:24px;border-radius:50%;background:rgba(124,92,255,.18);color:#a78bfa;
  display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex-shrink:0
}

/* ── Automations builder: Henshu-styled dropdowns (replace native <select> popups) ── */
.auto-sel-btn{
  display:inline-flex;align-items:center;justify-content:space-between;gap:10px;
  min-width:180px;max-width:100%;height:36px;padding:0 12px;
  background:#1d1d22;border:1px solid var(--border-d);border-radius:10px;
  color:var(--off-white);font:500 13px var(--sans);cursor:pointer;text-align:left;
  transition:background .13s,border-color .13s;
}
.auto-sel-btn:hover{background:#26262c;border-color:rgba(255,255,255,.16)}
.auto-sel-btn.is-placeholder .auto-sel-label{color:var(--muted)}
.auto-sel-btn svg{flex:none;color:var(--muted)}
.auto-sel-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.auto-sel-menu{
  position:fixed;z-index:10300;max-height:320px;overflow-y:auto;
  background:#171719;border:1px solid rgba(255,255,255,.1);border-radius:12px;
  box-shadow:0 18px 50px rgba(0,0,0,.55);padding:5px;
}
.auto-sel-item{
  padding:9px 13px;border-radius:8px;font:500 13px var(--sans);color:var(--off-white);
  cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.auto-sel-item:hover{background:rgba(255,255,255,.07)}
.auto-sel-item.on{color:#a78bfa;background:rgba(124,92,255,.12)}

/* "Something else" tile holds its own input (no layout shift below the grid) */
.hs-quiz-card-other{cursor:text}
.hs-quiz-other-input{
  width:100%;margin-top:6px;background:rgba(255,255,255,.06);border:1px solid rgba(124,92,255,.4);
  border-radius:8px;padding:8px 10px;color:var(--off-white);font:500 13px var(--sans);outline:none;
}
.hs-quiz-other-input:focus{border-color:var(--purple)}
.hs-quiz-other-input::placeholder{color:var(--muted)}

/* Platform panel: recent-signups table */
.pm-su-row:last-child{border-bottom:0}
/* ── Billing add-on steppers ─────────────────────────────────────────────── */
.bill-addons-card{margin-top:12px}
.bill-addon-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 0;border-bottom:1px solid var(--hairline-1)}
.bill-addon-row:last-of-type{border-bottom:none}
.bill-addon-name{font-size:13px;font-weight:600;color:var(--text-1)}
.bill-addon-meta{font-size:12px;color:var(--text-3);margin-top:2px}
.bill-stepper{display:inline-flex;align-items:center;gap:2px;background:var(--bg-inset);border:1px solid var(--hairline-2);border-radius:9px;padding:2px}
.bill-step-btn{width:28px;height:28px;border:none;background:none;color:var(--text-1);font-size:17px;line-height:1;border-radius:7px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background var(--dur-toggle,100ms) var(--ease-std,ease)}
.bill-step-btn:hover:not([disabled]){background:var(--color-brand-tint)}
.bill-step-btn[disabled]{opacity:.35;cursor:default}
.bill-step-val{min-width:30px;text-align:center;font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--text-1)}
.bill-addon-foot{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:14px;padding-top:14px;border-top:1px solid var(--hairline-2)}
.bill-addon-total{font-size:13px;color:var(--text-2)}
.bill-addon-total b{color:var(--text-1);font-weight:700}

/* One-frame transition kill around a theme flip so the whole UI does not cross-fade
   at 153 different durations (audit motion finding). applyTheme stamps this class. */
html.theme-switching, html.theme-switching *{transition:none !important}

/* WaveC reduced-motion */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important}
}
/* ── Home inbox skeleton loader (design-rules skeleton, ported) — shown while
   assigned tasks are still syncing, in place of the old sync banner. ── */
.hi-skel{display:flex;flex-direction:column;gap:10px;padding:4px 2px}
.hi-skel-row{display:flex;align-items:center;gap:12px}
.hi-skel-avatar{width:34px;height:34px;border-radius:50%;flex:none}
.hi-skel-lines{display:flex;flex-direction:column;gap:7px;flex:1;min-width:0}
/* Geometry only — the sweep and the reduced-motion opt-out come from the shared
   design-rules loader block ("Loading skeletons") further down. */
.hi-skel-line{height:11px;border-radius:5px}

/* ══════════════════ Wave D/F — app-wide interaction standards ══════════════════
   One focus ring, one selection colour, one disabled treatment, theme-aware
   scrollbars. Previously: 8 scattered :focus-visible rules (one REMOVED the ring),
   no ::selection at all (UA blue inside a purple product), 38 ad-hoc :disabled
   rules at four different opacities, and Firefox scrollbars that never flipped
   in light mode. */

/* Focus — visible on every interactive element, keyboard-only (never on mouse).
   No border-radius here: an outline already follows the element's own corners, and
   forcing a radius on focus silently reshaped the element (it was squaring off the
   task title's 12px well the moment you clicked it). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible,
[contenteditable="true"]:focus-visible{
  outline:2px solid var(--color-primary);
  outline-offset:2px;
}
/* …except text-entry surfaces, which opt straight back out. ":focus-visible is
   keyboard-only" is only true for buttons and links — per spec it ALSO matches a
   text field or a contenteditable focused with the MOUSE. That is why the purple
   ring turned up everywhere: every search box, person picker, task title and
   description painted a 2px slab the instant you clicked into it, and inside
   .card-desc-editor-wrap (overflow:hidden) the ring was clipped into a stray
   purple line under the toolbar. All of these already show focus through their own
   border plus a blinking caret, so the ring adds nothing.
   Buttons, links, selects, checkboxes and tabindex targets KEEP it — there it
   really is keyboard-only, and it is the whole reason the rule exists. */
input[type="text"]:focus-visible,
input[type="email"]:focus-visible,
input[type="password"]:focus-visible,
input[type="search"]:focus-visible,
input[type="url"]:focus-visible,
input[type="tel"]:focus-visible,
input[type="number"]:focus-visible,
input[type="date"]:focus-visible,
input[type="time"]:focus-visible,
input[type="datetime-local"]:focus-visible,
input:not([type]):focus-visible,
textarea:focus-visible,
[contenteditable="true"]:focus-visible{outline:none}

/* Selection — brand tint instead of the UA blue. */
::selection{background:var(--color-brand-tint-strong);color:var(--text-1)}

/* Disabled — one opacity + one cursor everywhere. */
button[disabled],
button:disabled,
input:disabled,
select:disabled,
textarea:disabled,
[aria-disabled="true"]{opacity:var(--opacity-disabled,.45);cursor:not-allowed}

/* Firefox scrollbars — the webkit thumb flips per theme, this one never did. */
html{scrollbar-color:var(--hairline-3) transparent}

/* ── Keyboard shortcut sheet ("?") — Wave E ──────────────────────────────── */
.hs-overlay{position:fixed;inset:0;z-index:12000;background:rgba(0,0,0,.45);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;padding:var(--sp-6);animation:hsFade var(--dur-modal) var(--ease-std)}
@keyframes hsFade{from{opacity:0}to{opacity:1}}
.hs-panel{width:min(880px,100%);max-height:86vh;overflow:auto;background:var(--surf-modal,var(--dark));border:1px solid var(--hairline-2);border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.4);padding:var(--sp-6);animation:hsRise var(--dur-modal) var(--ease-std)}
@keyframes hsRise{from{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:none}}
.hs-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);margin-bottom:var(--sp-5)}
.hs-title{font:700 var(--text-xl) var(--sans);color:var(--text-1);margin:0}
.hs-close{width:30px;height:30px;border:none;border-radius:8px;background:var(--bg-inset);color:var(--text-2);font-size:19px;line-height:1;cursor:pointer;transition:background var(--dur-toggle) var(--ease-std)}
.hs-close:hover{background:var(--color-brand-tint);color:var(--text-1)}
.hs-cols{columns:2;column-gap:var(--sp-8)}
@media(max-width:720px){.hs-cols{columns:1}}
.hs-group{break-inside:avoid;margin-bottom:var(--sp-6)}
.hs-group-title{font:700 var(--text-2xs) var(--sans);text-transform:uppercase;letter-spacing:.6px;color:var(--text-3);margin:0 0 var(--sp-2)}
.hs-row{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-1-5) 0;border-bottom:1px solid var(--hairline-2)}
.hs-row:last-child{border-bottom:none}
.hs-label{font:400 var(--text-sm) var(--sans);color:var(--text-2);min-width:0}
.hs-keys{display:inline-flex;align-items:center;gap:var(--sp-1);flex:none}
.hs-or{color:var(--text-3);font-size:var(--text-2xs)}
kbd.hs-key{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 6px;background:var(--bg-inset);border:1px solid var(--hairline-2);border-radius:6px;font:600 var(--text-2xs) var(--sans);color:var(--text-1);white-space:nowrap}
/* A chord is one pill: "⌘ + Z". The + is a quiet joiner, not a third key. */
kbd.hs-key-combo{gap:0}
.hs-key-plus{margin:0 3px;opacity:.5;font-weight:400}
.hs-foot{margin-top:var(--sp-2);padding-top:var(--sp-4);border-top:1px solid var(--hairline-2);font:400 var(--text-xs) var(--sans);color:var(--text-3);text-align:center}

/* Inline subtask draft row — type the name in place (Enter saves, Esc discards). */
.subtask-inline-draft{cursor:default}
.subtask-inline-draft .subtask-inline-check{opacity:.4}
.subtask-inline-input{flex:1;min-width:0;background:transparent;border:none;outline:none;color:var(--text-1);font:400 var(--text-sm) var(--sans);padding:0}
.subtask-inline-input::placeholder{color:var(--text-3)}

/* Keycap hint inside a toast button — right-aligned, quieter than the label. */
.toast-btn .toast-kbd{margin-left:var(--sp-2);min-width:18px;height:18px;padding:0 5px;font-size:10px;background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.2);color:inherit;opacity:.85}
.toast-btn.cancel .toast-kbd{background:var(--bg-inset);border-color:var(--hairline-2)}

/* Full-screen task expansion — the maxed state is a hard CSS swap, so the toggle
   FLIPs it (measure → invert → play). During the flight the panel must not
   re-wrap its own scroll content or paint a mid-transition scrollbar. */
.card-modal.card-modal-flip{will-change:transform;overflow:hidden}
.card-modal.card-modal-flip *{pointer-events:none}
@media(prefers-reduced-motion:reduce){.card-modal.card-modal-flip{transition:none !important}}

/* Destructive confirm toast — the surface itself signals danger (Design Rules →
   danger recipe: error tint + error hairline), not just the button. */
.toast.confirm.toast-danger{background:color-mix(in srgb,var(--color-error) 14%,var(--surf-3));border:1px solid color-mix(in srgb,var(--color-error) 42%,transparent);box-shadow:0 8px 32px rgba(0,0,0,.28),0 0 0 1px color-mix(in srgb,var(--color-error) 12%,transparent)}
.toast.confirm.toast-danger .toast-msg{color:var(--text-1)}

/* ── Tooltips ─────────────────────────────────────────────────────────────
   One engine, one look (Design Rules → Tooltips). 300ms in / 100ms out, one at
   a time, flips + clamps to stay on screen. Pointer-events off so a tooltip can
   never swallow the click it is describing. */
.app-tip{position:fixed;z-index:13000;max-width:260px;padding:6px 9px;border-radius:8px;
  background:var(--surf-modal,var(--dark));border:1px solid var(--hairline-2);
  color:var(--text-1);font:500 var(--text-xs) var(--sans);line-height:1.35;
  box-shadow:0 8px 24px rgba(0,0,0,.32);pointer-events:none;white-space:nowrap;
  opacity:0;transform:translateY(3px);display:none}
.app-tip.is-on{display:block;opacity:1;transform:none;
  transition:opacity var(--dur-toggle,100ms) var(--ease-std),transform var(--dur-toggle,100ms) var(--ease-std)}
.app-tip.is-below{transform:none}
.app-tip.is-on.is-out{opacity:0;transform:translateY(2px);
  transition:opacity 100ms var(--ease-exit,ease-in),transform 100ms var(--ease-exit,ease-in)}
@media(prefers-reduced-motion:reduce){.app-tip.is-on,.app-tip.is-on.is-out{transition:none;transform:none}}

/* Task-modal header controls — ONE icon-button (Wave D: these were 5 inline-styled
   one-offs, one of them purple while the rest were muted, all with a border). */
.card-modal-iconbtn{width:28px;height:28px;flex-shrink:0;padding:0;border:none;background:none;
  border-radius:8px;color:var(--text-3);cursor:pointer;display:inline-flex;align-items:center;
  justify-content:center;transition:background var(--dur-toggle) var(--ease-std),color var(--dur-toggle) var(--ease-std)}
.card-modal-iconbtn:hover{background:var(--bg-inset);color:var(--text-1)}
.card-modal-iconbtn:active{transform:scale(.94)}

/* Home skeleton variants — small avatar, single-line rows, trailing meta block,
   so each card's skeleton matches the row it stands in for. */
.hi-skel-avatar.is-sm{width:22px;height:22px}
/* Files use a rounded square, not a circle — it reads as a file icon, not a person. */
.hi-skel-avatar.is-sq{border-radius:7px}
/* Preview-pane skeleton: media block above the title/meta lines. */
.hi-skel-stage{gap:14px;padding:0;height:100%;min-height:180px}
.hi-skel-block{flex:1 1 auto;min-height:120px;border-radius:12px}
.hi-skel-stage .hi-skel-lines{flex:none}
.fm-skel-page{padding:18px 14px}
.hi-skel-trail{width:34px;flex:none;align-self:center;opacity:.7}
.hi-skel-row{align-items:center}

/* Liquid glass utility — same recipe as the workspace button (Design Rules → Liquid glass). */
.liquid-glass{background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);border:1px solid var(--lg-border);box-shadow:var(--lg-shadow)}

/* ── Liquid glass on every dropdown / menu / popover (Design Rules ->
   Liquid glass). Appended last so it also wins over the per-theme
   background overrides earlier in this file. --lg-menu is theme-aware, so this
   is correct in light and dark without a second block.
   The fill is --lg-menu (78%), NOT --lg-solid (97%): at 97% the backdrop-filter
   is still applied but nothing survives it, so every menu rendered as a flat
   grey box — the exact "opacity instead of tint+blur" failure Design Rules
   calls out. Nested panels must NOT get their own blur (see .ctx-submenu). */
.add-prop-popover,
.am-ctx-menu,
.auto-combo-menu,
.auto-sel-menu,
.azp-var-menu,
.cal-day-popover,
.card-ctx-menu,
.card-route-picker,
.card-tab-add-dropdown,
.client-switch-menu,
.cmd-popup,
.cw-dropdown,
.desc-link-popup,
.dmx-sched-menu,
.edit-ctx-menu,
/* .cr-profile-popout used to live in this list. It is not a floating menu — it fills the
   sidebar — and the glass treatment gave it a 1px border on every side (which pushed its
   identity row 1px off the workspace card it replaces), a translucent fill and a cast
   shadow. It defines its own chrome above. */
.emoji-picker,
.emote-input-picker,
.fm-menu,
.gv-edit-popover,
.kanban-col-dropdown,
.mention-popup,
.ms-dropdown-menu,
.multi-select-move-dropdown,
.multi-select-prop-dropdown,
.multiselect-dropdown,
.proj-icon-picker,
.prop-color-picker,
.prop-ctx-menu,
.prop-person-dropdown,
.prop-type-picker,
.reaction-quick-picker,
.rev-popover,
.role-assign-dropdown,
.server-dropdown,
.sidebar-clients-menu,
.sidebar-ctx-menu,
.spotlight-box,
.sticky-fmt-popup,
.tools-hub-menu,
.workshop-filter-panel,
.hwm-menu,
.wf-person-menu,
.wf-row-menu,
.workshop-sort-dropdown,
.ws-switch-dropdown,
.ws-view-picker-menu{
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-menu) !important;
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border);
  box-shadow:var(--lg-shadow);
}

/* Nested inside an already-glassed menu (Set Status ▸, and the sidebar's
   equivalent). Per Design Rules: never nest a blur inside a blur — the parent's
   backdrop-filter makes it a backdrop root, so a child's blur samples nothing and
   the submenu renders see-through. Tint over --lg-base, NO backdrop-filter. */
.card-ctx-menu .ctx-submenu,
.sidebar-ctx-menu .ctx-submenu{
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);
  border:1px solid var(--lg-border);
  box-shadow:var(--lg-shadow);
}

/* Audit follow-up: two floating menus missed the grouped liquid-glass rule.
   (The other unglassed 'floating' selectors are scrims/bottom-sheets/buttons,
   which correctly keep their own fill.) */
.hd-tray,
.workshop-sort-submenu{
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-menu) !important;
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border);
  box-shadow:var(--lg-shadow);
}

/* Discord-like density: tighter rows, one avatar per run, and the selected/hovered
   row slides its highlight instead of snapping — same token every other slider uses. */
#dmMessages .cr-msg-row{padding-top:1px;padding-bottom:1px;border-radius:6px;
  transition:background var(--tab-slide-dur,300ms) var(--tab-slide-ease,ease)}
#dmMessages .cr-msg-row:hover{background:rgba(255,255,255,.035)}
#dmMessages .cr-msg-row.is-selected{background:color-mix(in srgb,var(--purple) 14%,transparent)}
#dmMessages .cr-msg-row.cr-msg-grouped{margin-top:0}
#dmMessages .cr-msg-meta{margin-bottom:1px}
#dmMessages .cr-msg-text{line-height:1.42}
#dmMessages .dmx-day{margin:10px 0 6px}
html[data-theme="light"] #dmMessages .cr-msg-row:hover{background:rgba(0,0,0,.035)}

/* Reply quote above the composer. */
.dmx-reply-bar{display:flex;align-items:center;gap:9px;margin:0 0 7px;padding:7px 11px;border-radius:9px;
  background:var(--bg-inset);border-left:2px solid var(--purple);font:500 12.5px var(--sans);color:var(--text-2)}
.dmx-reply-bar .dmx-reply-ico{display:inline-flex;color:var(--purple);flex:none}
.dmx-reply-txt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dmx-reply-txt b{color:var(--text-1)}
.dmx-reply-x{border:0;background:none;color:var(--text-3);font-size:17px;line-height:1;cursor:pointer;padding:0 2px;flex:none}
.dmx-reply-x:hover{color:var(--text-1)}
/* Author context menu (right-click a name). */
.dmx-author-head{padding:7px 11px 5px;font:800 10px var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}

/* Delete is destructive: red, and only present while Shift is held. */
.dmx-tb .dmx-tb-del{display:none;color:var(--color-danger,#ff6b6b)}
body.is-shift .dmx-tb .dmx-tb-del{display:inline-flex}
.dmx-tb .dmx-tb-del:hover{background:color-mix(in srgb,var(--color-danger,#ff6b6b) 18%,transparent);color:var(--color-danger,#ff6b6b)}

/* Saved-for-later marker in the message hover row. */
.dmx-tb-bm.is-on{color:var(--color-warning,#ffb020)}
.dmx-tb-bm.is-on:hover{color:var(--color-warning,#ffb020);filter:brightness(1.12)}

/* DM conversation list, first load. Padding matches a real row so the column
   doesn't shift when the list replaces the skeleton. */
.dmx-list-skel{padding:10px 12px}

/* ═══════════ Unread indicator — Discord-style left-edge dot ═══════════
   A bright dot pinned to the LEFT edge of the row, half of it outside the row box, so it
   reads as a marker in the rail rather than as content inside the item. Driven purely by
   .has-unread, which _syncSidebarUnreadDots() stamps from the (server-backed, real-time)
   notification list — so it lights up the instant a mention or an assigned-task change
   arrives, and survives a reload because the notifications do.
   The row keeps position:relative from the pill-slider work above, so this anchors to it. */
.sidebar-nav-scroll .has-unread::before,
#sidebarFooterNav .has-unread::before{
  content:'';position:absolute;left:0;top:50%;
  transform:translate(-50%,-50%);
  width:9px;height:9px;border-radius:50%;
  /* The item's OWN colour, published on the row by _syncSidebarUnreadDots. A pink project
     announcing itself in purple read as a different system's badge stuck on the row. */
  background:var(--sb-unread-accent,var(--text-1,#fff));
  /* the "glow" — kept tight so a busy sidebar doesn't turn into a light show */
  box-shadow:0 0 7px 1px color-mix(in srgb,var(--sb-unread-accent,var(--text-1,#fff)) 55%,transparent);
  pointer-events:none;z-index:3;
  animation:sbUnreadIn .22s var(--ease-std,cubic-bezier(.22,1,.36,1)) both;
}
@keyframes sbUnreadIn{from{opacity:0;transform:translate(-50%,-50%) scale(.4)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
@media(prefers-reduced-motion:reduce){
  .sidebar-nav-scroll .has-unread::before,#sidebarFooterNav .has-unread::before{animation:none}
}
/* Unread rows read at full strength — the muted state is for "nothing here for you". */
.sidebar-nav-scroll .has-unread{color:var(--text-1)!important;font-weight:650}
/* The count, hard right — the Slack treatment. It used to be suppressed at 1 on the theory
   that the dot already said "something's here"; owner wants the number, and "1" vs "12" is
   the difference between glancing and prioritising. */
.sidebar-nav-scroll .has-unread[data-unread]::after{
  content:attr(data-unread);margin-left:auto;flex:none;
  font:700 10px var(--sans);line-height:1;padding:3px 6px;border-radius:9px;
  font-variant-numeric:tabular-nums;
  background:color-mix(in srgb,var(--sb-unread-accent,var(--purple,#7c5cff)) 26%,transparent);color:var(--text-1,#ECEAF3);
}

/* Lock badge on restricted projects — Discord treatment: a small padlock in the icon's
   TOP-RIGHT corner. Square, borderless, and filled with the SIDEBAR's own colour so it
   reads as a notch punched out of the icon rather than a chip stuck on top of it.
   Deliberately a real element (.sb-lock, injected by _syncSidebarLocks) and not a masked
   pseudo-element: a CSS mask clips everything the element paints. */
.sidebar-nav-scroll{--sb-bg:#050507}          /* == .sidebar's own background */
html[data-theme="light"] .sidebar-nav-scroll{--sb-bg:#ffffff}
.sidebar-nav-scroll .is-locked .fav-icon{position:relative;overflow:visible}
/* Every sidebar row paints its state as a TRANSLUCENT tint over the sidebar — it never
   sets an opaque colour of its own. So rather than guess the row's final colour, each
   state publishes its exact tint as --sb-row-tint and the badge composites that same
   tint over the same sidebar colour. Identical inputs → identical output, which is what
   makes the plate read as a notch punched out of the icon instead of a chip stuck on it.
   The tints below are copied verbatim from the row rules they mirror; both themes use
   the same values (light mode doesn't override sidebar row hover/active). */
/* ── The plate is gone; the icon has a HOLE in it instead ──────────────────────────
   Everything above tried to REPRODUCE the row's composited colour on a small opaque
   square behind the padlock. That can be made to match a static row, but it can never
   match a MOVING one: the selection pill is absolutely positioned and animates across
   rows, so mid-slide it covers part of the row and not the rest — and a plate painted
   from "row tint over pill over sidebar" assumes the pill is entirely underneath. That
   is exactly when it looked wrong, arriving at and leaving a locked row.
   So stop matching colours. The ICON is masked with a circular hole at its top-right
   and the badge draws into that hole with NO background of its own. Whatever is behind
   — sidebar, hover tint, the pill at any point in its travel — shows through, because
   it IS what is behind. Nothing to keep in sync, and no state can get it wrong.
   The badge itself is never masked (hence :not(.sb-lock)); masking the element that
   paints the padlock is what ruled a mask out the first time. */
.sidebar-nav-scroll .is-locked .fav-icon > *:not(.sb-lock),
.sidebar-nav-scroll .is-locked .sb-lock-anchor > *:not(.sb-lock){
  /* The hole shrinks with the badge — 2px off both, or the padlock would sit in a gap
     bigger than itself. */
  -webkit-mask-image:radial-gradient(circle at calc(100% - 2.5px) 2.5px,transparent 6.5px,#000 7px);
  mask-image:radial-gradient(circle at calc(100% - 2.5px) 2.5px,transparent 6.5px,#000 7px);
}
.sidebar-nav-scroll .sb-lock{
  position:absolute;top:-3px;right:-3px;
  width:11px;height:11px;
  display:flex;align-items:center;justify-content:center;
  background:transparent;
  /* Inherit, don't fix to white: the padlock belongs to the icon it sits on, so it takes
     the icon's colour — the folder's colour for a project inside a coloured folder, the
     row's colour otherwise. _syncSidebarLocks additionally mirrors a per-project icon
     tint onto the badge, which inheritance alone can't reach (that tint lives on a
     sibling span, not on the shared .fav-icon parent). */
  color:inherit;
  pointer-events:none;box-sizing:border-box;
  /* the plate has to repaint with the row, or it stays a dark square on a lit row */
  transition:background .12s ease;
}
.sidebar-nav-scroll .sb-lock svg{width:8px;height:8px;display:block}
/* mirrors .sidebar-fav-nav a:hover / .sidebar-cat-item:hover */
.sidebar-nav-scroll .sidebar-fav-nav a:hover,
.sidebar-nav-scroll .sidebar-cat-item:hover{--sb-row-tint:rgba(255,255,255,.035)}
/* mirrors .sidebar-section-nav a:hover */
.sidebar-nav-scroll .sidebar-section-nav a:hover{--sb-row-tint:rgba(255,255,255,.06)}
/* mirrors .sidebar-section-label:hover / .sidebar-fav-label:hover */
.sidebar-nav-scroll .sidebar-section-label:hover,
.sidebar-nav-scroll .sidebar-fav-label:hover{--sb-row-tint:rgba(255,255,255,.02)}
/* Active rows are painted by TWO rules, not one, and the badge used to mirror neither:
   it published rgba(124,92,255,.1) while the shared rule paints .16, and .sidebar-cat-item
   .active / .sidebar-fav-nav a.active then override that again with an opaque --bg-inset.
   So on a selected row the plate composited a weaker, bluer tint than the row underneath
   it and read as a grey chip sitting on the highlight. Each selector now publishes the
   value that actually wins for it. --bg-inset is opaque, so compositing it over --sb-bg
   returns exactly --bg-inset. */
.sidebar-nav-scroll .sidebar-section-nav a.active,
.sidebar-nav-scroll .sidebar-nav a.active{--sb-row-tint:rgba(124,92,255,0.16)}
.sidebar-nav-scroll .sidebar-fav-nav a.active,
.sidebar-nav-scroll .sidebar-cat-item.active{--sb-row-tint:var(--bg-inset)}
/* An ACTIVE row is not one colour, which is why the plate kept reading dark against it.
   It is TWO layers: the row's own rgba(124,92,255,.10) background, sitting over the
   sliding .m-pill-thumb (pill-accent at 16%) that is absolutely positioned behind it,
   over the sidebar. Compositing a single tint could never land on that sum. The plate now
   stacks the same two layers, in the same order, over the same ground -- first listed is
   topmost, so row tint over pill over sidebar -- which makes it the identical colour by
   construction rather than by matching a number. --pill-accent is inherited when a project
   sets its own; the fallback is the same purple the pill defaults to. */
/* The per-state plate colours are gone with the plate. Kept as a note rather than a rule:
   if a background ever comes back here it will be a square again on a moving selection. */
.sidebar-nav-scroll .sidebar-fav-nav a.active .sb-lock,
.sidebar-nav-scroll .sidebar-section-nav a.active .sb-lock,
.sidebar-nav-scroll .sidebar-nav a.active .sb-lock,
.sidebar-nav-scroll .sidebar-cat-item.active .sb-lock{background:transparent}
/* Folder headers draw their icon as a bare <svg>; _syncSidebarLocks wraps it in this
   anchor so the corner badge has something to position against. Inline-flex only — the
   glyph's own size and colour are untouched. */
/* A folder wearing a custom icon: the wrapper stands in for the bare <svg> the default
   glyph uses, so sizing, the lock-badge anchor and the colour rules all still find it. */
.sidebar-section-folder-custom{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px}
.sidebar-section-folder-custom svg{width:16px;height:16px;display:block}

/* Drop a task onto a project row. Deliberately loud — this MOVES a task between boards,
   so the target has to be unmistakable before the pointer is released. Uses an inset ring
   rather than an outline so it can't nudge the row and shift the thing you're aiming at. */
.sb-drop-target{
  box-shadow:inset 0 0 0 2px var(--purple,#7c5cff),0 0 0 1px color-mix(in srgb,var(--purple,#7c5cff) 40%,transparent);
  background:color-mix(in srgb,var(--purple,#7c5cff) 16%,transparent)!important;
  border-radius:9px;color:var(--off-white)!important;
}
.sb-drop-target::after{
  content:'Move here';position:absolute;right:10px;top:50%;transform:translateY(-50%);
  font:700 9px var(--sans);letter-spacing:.5px;text-transform:uppercase;
  color:var(--purple,#7c5cff);pointer-events:none;
}

.sidebar-nav-scroll .sb-lock-anchor{position:relative;display:inline-flex;align-items:center;justify-content:center;overflow:visible;flex:none}

/* ── Sidebar consistency (HANDOFF 4.1–4.4) ────────────────────────────────────
   One row grammar for everything in the sidebar. Appended last so it wins the
   base rules by cascade; the folder-colour rules (.sidebar-cat-colored …) and the
   light-theme overrides keep winning on specificity, which is exactly right —
   membership colour and light-mode dark text are deliberate exceptions. */

/* 4.4 — ONE text colour: near-white at rest, white on hover/active. The base
   rules disagreed: rgba(255,255,255,.5) on system rows, var(--muted) on the rest. */
.sidebar-nav a,
.sidebar-fav-nav a,
.sidebar-section-nav a,
.sidebar-cat-item{color:rgba(235,235,245,.82)}
.sidebar-nav a:hover,
.sidebar-fav-nav a:hover,
.sidebar-section-nav a:hover,
.sidebar-cat-item:hover{color:#fff}

/* 4.1 — A category's children need a real tree inset. The connector runs from
   15px to 26px, so a 16px row inset draws the guide through the child icon.
   Start category items at 36px instead: it preserves a clear 10px gap after the
   connector while keeping the folder header aligned with ordinary sidebar rows. */
.sidebar-section-label{padding:8px 12px 4px 16px}
.sidebar-cat-item{padding:6px 12px 6px 16px}
.sidebar-section-nav .sidebar-cat-item{padding-left:36px}
/* A folder holds TWO kinds of child and only one of them got the inset above:
   boards render as .sidebar-cat-item, channels as .sidebar-cat-child wrapping their own
   .sidebar-section-nav > a, which was left on the older 30px. That put the channel icon
   4px from a connector that ends at 26px — it read as sitting ON the line, and as a step
   left of the boards right above it. Same 36px, so every child in a folder starts on one
   edge whatever kind it is. */
.sidebar-cat-child .sidebar-section-nav a{padding-left:36px}

/* 4.3 — ONE font. Folder children were 12px against the rows' 14px, and two
   competing .sidebar-section-name rules left folder headers as 11px uppercase
   eyebrows (the sentence-case fix earlier in this file was silently losing the
   cascade). Children join the rows at 14px; headers get the approved 13px
   sentence case, one family throughout. */
.sidebar-cat-item{font-size:14px}
.sidebar-cat-item .fav-icon{font-size:16px;width:20px}
.sidebar-section-name{font:600 13px var(--sans);letter-spacing:.2px;text-transform:none;color:rgba(235,235,245,.82)}
.sidebar-section-label:hover .sidebar-section-name{color:#fff}

/* 4.2 — compact vertical density. Padding only — font size untouched. */
.sidebar-nav a{padding-top:8px;padding-bottom:8px}
.sidebar-fav-nav a,
.sidebar-section-nav a{padding-top:6px;padding-bottom:6px}

/* ── Mobile DMs: Slack-grouped rows, not IG bubbles (HANDOFF item 9) ──────────
   Mobile now renders the same flat .cr-msg-row markup as desktop. Two older
   mobile rules targeted .dmx-msg (which cr rows also carry) and forced
   display:block/column — corrected here, plus narrow-screen sizing. */
body[data-mobile-mode="app"] #page-dm .cr-msg-row.dmx-msg{display:flex;flex-direction:row;width:100%;gap:10px;padding:2px 12px}
body[data-mobile-mode="app"] #page-dm .cr-msg-row .cr-msg-body{display:block;flex:1;min-width:0}
body[data-mobile-mode="app"] #page-dm .cr-msg-author{font-size:14px}
body[data-mobile-mode="app"] #page-dm .cr-msg-text{font-size:15px;line-height:1.45}
body[data-mobile-mode="app"] #page-dm .cr-msg-spacer{width:32px;flex:none}


/* ── Workspace settings: top tabs, not a sidebar ──────────────────────────────
   The strip is the project page's own view-switcher component (.ws-view-tabs /
   .ws-view-tab + the shared sliding pill), so there is exactly one tab component
   in the product — Design Rules -> Tabs. Only two things differ here: the labels
   stay visible (six named destinations, not five icons you learn), and the strip
   sits on a header rule above the body. */
.ss-wrap{flex-direction:column}
/* Geometry is copied from the rule that ACTUALLY paints the project strip. The base
   .workshop-views rule (padding:10px 0, a border-bottom, --bg-main) is not what ships:
   #page-workshop.active .workshop-views overrides it wholesale with
   padding:6px 16px 4px; margin:0 0 6px; background:transparent; border-bottom:none.
   Matching the base rule instead put these tabs 36px right of every project tab -- and
   both pages cancel .content's own 36px gutter identically (#page-settings.active and
   #page-workshop.active carry the same -28px -36px -60px margins), so that 36px was
   pure surplus. Same padding, same margin, same transparent ground, and .ss-tab is back
   to .ws-view-tab's own 11px 13px. The border-bottom went with it -- the project strip
   explicitly kills its own, so a hairline here was a rule the app draws nowhere else. */
.ss-tabbar{display:flex;align-items:center;gap:12px;padding:6px 16px 4px;margin:0 0 6px;flex-shrink:0;
  background:transparent;overflow:hidden}
.ss-tabs{max-width:100%;flex-wrap:wrap;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.ss-tabs::-webkit-scrollbar{display:none}
/* These ARE the project's view tabs — same plate, same padding, same type. The strip used
   to drop the container and tighten the padding on the reasoning that the sliding pill was
   affordance enough; the result was two tab strips in one product that visibly disagreed,
   which is a worse outcome than one box too many. Everything now comes from .ws-view-tabs
   and .ws-view-tab; only the label rule stays, because settings tabs are named places. */
.ss-tab .ws-view-tab-label{display:inline}
/* Invite button = the email input's twin. .ss-btn-sm made it shorter than the field
   it sits beside; these are the input's own box values so both edges line up. */
.ss-invite-btn{padding:8px 18px;font-size:13px;border-radius:8px;border:1px solid transparent;line-height:normal}
/* Danger reads as danger. The colour was already declared but the icon kept the
   inherited .ws-view-tab svg treatment, so the tab read as a normal tab with slightly
   warm text; the active pill was neutral too. Tint all three states plus the glyph. */
/* Specificity, not colour, was the problem: .ss-tab-danger is one class and
   .ws-view-tab.active is two, so the active state kept winning and the tab read as an
   ordinary tab. Qualified with .ss-tabs .ss-tab so it outranks both the base and the
   active rule in every state, and the glyph is tinted explicitly rather than left to
   inherit at reduced opacity. */
.ss-tabs .ss-tab.ss-tab-danger,
.ss-tabs .ss-tab.ss-tab-danger:hover,
.ss-tabs .ss-tab.ss-tab-danger.active{color:#ef4444}
.ss-tabs .ss-tab.ss-tab-danger svg{color:#ef4444;opacity:.85}
.ss-tabs .ss-tab.ss-tab-danger:hover svg,
.ss-tabs .ss-tab.ss-tab-danger.active svg{opacity:1}
.ss-tab-danger:hover{background:rgba(239,68,68,.10)}
.ss-tabs:has(.ss-tab-danger.active) .m-pill-thumb{background:rgba(239,68,68,.16)}
/* The pane itself, not just its tab. */
#ssDanger h2,#ssDanger h3{color:var(--danger-text,#ef4444)}
body[data-mobile-mode="app"] .ss-tabbar{padding:0 12px}
body[data-mobile-mode="app"] .ss-body{padding:20px 16px 60px}

/* Members list: the project List view, so only the row-action reveal is local. */
.ss-member-row .ss-member-acts{opacity:0;transition:opacity .12s}
.ss-member-row:hover .ss-member-acts{opacity:1}
/* A pending member's actions are the whole point of the row -- Copy link and Resend are
   what you came to Members to do when someone has not accepted. Hover-to-reveal hid them
   so thoroughly they read as missing entirely. Revealed permanently on pending rows;
   everyone else keeps the quiet hover behaviour. */
.ss-member-row-pending .ss-member-acts{opacity:1}
.ss-member-row .cr-profile-role{white-space:nowrap}

/* Workspace overview stat row — the console's KPI card, ported to app tokens. */
.ss-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}
.ss-stat{background:var(--card);border:1px solid var(--border-d);border-radius:14px;padding:15px 17px;min-width:0}
.ss-stat-l{font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--muted)}
.ss-stat-v{font-family:var(--serif);font-size:28px;line-height:1.1;margin:6px 0 2px;color:var(--cream);font-variant-numeric:tabular-nums}
.ss-stat-s{font-size:12px;color:var(--muted)}

/* Dropping onto the sidebar bin. Red rather than the purple move-target, because this
   destination destroys rather than relocates — the colour IS the warning. */
.sb-drop-trash{background:color-mix(in srgb,var(--danger-text,#ef4444) 18%,transparent) !important;
  box-shadow:inset 0 0 0 1.5px var(--danger-text,#ef4444);border-radius:6px}
.sb-drop-trash svg{color:var(--danger-text,#ef4444) !important;stroke:var(--danger-text,#ef4444) !important;opacity:1 !important}
/* Trash uses the same page geometry as a project's List tab. The generic .panel
   wrapper is useful on dashboard pages, but here its 24px inset stacks on top of
   .content's 36px inset and the List card's own 16px margin. That triple frame is
   what made the table look like it was floating in the middle of the page. Let the
   page own the viewport, keep one 16px List inset, and leave row height/type to the
   shared .gv-flat-* rules (the canonical 42px list rhythm from #dr-listrows). */
#page-trash.active{
  margin:-28px -36px -60px;
  height:calc(100% + 88px);
  display:flex !important;flex-direction:column;
  min-height:0;overflow:hidden;padding:0 !important
}
#page-trash.active>.panel{
  flex:1;min-height:0;display:flex;flex-direction:column;
  padding:0;border:0;border-radius:0;background:transparent
}
#page-trash .trash-header{
  flex:0 0 auto;min-height:64px;box-sizing:border-box;
  margin:0;padding:16px
}
#page-trash #trashList{
  flex:1;min-height:0;overflow:hidden;
  padding:0;border:0;border-radius:0;background:transparent
}
#page-trash #trashList>.group-view-flat{height:100%;min-height:0}
#page-trash #trashList .gv-flat-table{
  margin:0 16px 24px !important;
  max-height:calc(100% - 24px)
}
/* Trash headers do not sort and rows do not open, so do not advertise click
   behaviour borrowed from the interactive project List table. */
#page-trash #trashList .gv-flat-header .gv-flat-col,
#page-trash #trashList .gv-flat-row{cursor:default}

/* Trash row actions follow the Members/List convention: quiet until the row is
   engaged, but visible for keyboard focus and on touch devices where hover does
   not exist. */
.trash-flat-row .trash-flat-acts{opacity:0;transition:opacity .12s}
.trash-flat-row:hover .trash-flat-acts,
.trash-flat-row:focus-within .trash-flat-acts{opacity:1}
@media(hover:none),(pointer:coarse){.trash-flat-row .trash-flat-acts{opacity:1}}

/* Keep the full-bleed calculation paired with .content's responsive insets, just
   like the project pages. */
@media(max-width:900px){
  #page-trash.active{margin:-20px -16px -60px;height:calc(100% + 80px)}
}
@media(max-width:768px){
  #page-trash.active{margin:-16px -12px -80px;height:calc(100% + 96px)}
  #page-trash .trash-header{padding:12px}
  #page-trash #trashList .gv-flat-table{margin:0 12px 16px !important;max-height:calc(100% - 16px)}
}
/* App mode already removes .content's padding. Zero the desktop bleed and reserve
   the measured fixed header/hotbar areas so the Trash controls and final rows stay
   tappable on notched phones. */
body[data-mobile-mode="app"] #page-trash.active{
  margin:0 !important;width:100% !important;max-width:100% !important;
  height:100dvh !important;
  padding-top:var(--m-app-header-h,calc(56px + env(safe-area-inset-top,0px))) !important;
  padding-bottom:var(--m-hotbar-h,calc(60px + env(safe-area-inset-bottom,0px))) !important
}
body[data-mobile-mode="app"] #page-trash .trash-header{align-items:flex-start;gap:8px}
body[data-mobile-mode="app"] #page-trash .trash-controls{width:100%;margin-left:0;justify-content:flex-end;flex-wrap:wrap}

/* Comment bodies keep the line breaks the author typed. Scoped to the text span, never
   the whole .card-comment-text — that element also contains image and reaction markup,
   and pre-wrap across concatenated tags would surface the gaps between them. */
.card-comment-text .cmt-body{white-space:pre-wrap}

/* ── Loading skeletons (design rules → admin #dr-loaders) ─────────────────────
   The rules define ONE loading vocabulary: a shimmer sweep, a bar, an avatar, and
   a skeleton card "shaped like the content it replaces". Everything that loads
   draws from these — the board below, the Home inbox (.hi-skel-*) and the
   reusable row list (.skl-*) all sweep with the same gradient at the same 1.4s.
   The sweep is the point: an opacity pulse on a filled grey box reads as a broken
   panel, a sweep across a bar reads as text that has not arrived yet. */
@keyframes skelShimmer{to{background-position:-200% 0}}
.skel-line,.skel-avatar,.hi-skel-line,.hi-skel-avatar,.hi-skel-block,.skl-c,.vg-loader{
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi,rgba(255,255,255,.13)) 50%,var(--bg-inset) 75%);
  background-size:200% 100%;animation:skelShimmer 1.4s linear infinite}
.skel-line{height:11px;border-radius:5px}
.skel-line-sm{height:9px;border-radius:4px}
.skel-avatar{width:34px;height:34px;border-radius:50%;flex:none}
/* The skeleton card, per the rules: bordered, radius 12, its lines stacked inside. */
.skel-card{display:flex;flex-direction:column;gap:8px;padding:13px;
  border:1px solid var(--border-d);border-radius:12px}

/* The board's loading state, shaped like the Kanban it becomes: the same column
   min/max width and the same gap, so nothing jumps when the real columns arrive.
   The columns are NOT filled slabs — a skeleton is the shape of the content, not
   a grey box where the content will be. Every block still has an explicit size,
   which is what the original bug was missing: three bare .co-skeleton-card divs
   with no width collapsed to their own 1px borders and painted three full-height
   hairlines. A skeleton whose blocks can collapse is not a skeleton, it's a stripe. */
.board-skel{display:flex;gap:14px;padding:16px;align-items:flex-start}
.board-skel-col{flex:1;min-width:220px;max-width:300px;display:flex;flex-direction:column;gap:10px}
.board-skel-head{display:flex;align-items:center;gap:9px;padding:0 2px 2px}
.board-skel-dot{width:9px;height:9px;border-radius:50%;flex:none}
/* Loading states for the other project views. Board had one; List / Calendar / Canvas /
   Automations sat blank for the whole fetch, which reads as broken rather than loading.
   Same .skel-line / .skel-avatar shimmer primitives, shaped like the view being waited on
   so the skeleton matches the final layout (design rules: skeleton-first, never a spinner). */
.list-skel{display:flex;flex-direction:column;padding:var(--sp-2) var(--sp-4)}
.list-skel-row{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--sp-1);border-bottom:1px solid var(--hairline)}
.list-skel-check{width:16px;height:16px;border-radius:5px;flex:none}
.list-skel-pill{width:74px;height:18px;border-radius:999px;flex:none;margin-left:auto}
.cal-skel{padding:var(--sp-4)}
.cal-skel-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sp-2)}
.cal-skel-cell{min-height:84px;border:1px solid var(--hairline);border-radius:8px;padding:var(--sp-2);display:flex;flex-direction:column;gap:var(--sp-2)}
.cal-skel-num{width:18px;height:12px;border-radius:4px}
.cal-skel-ev{width:80%;height:16px;border-radius:5px;margin-top:auto}
.auto-skel{display:flex;flex-direction:column;gap:var(--sp-3);padding:var(--sp-4);max-width:760px}
.auto-skel-rule{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-4);border:1px solid var(--hairline);border-radius:12px}
.auto-skel-ico{width:30px;height:30px;border-radius:9px;flex:none}
.auto-skel-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--sp-2)}
.auto-skel-toggle{width:38px;height:22px;border-radius:999px;flex:none}
@media(prefers-reduced-motion:reduce){
  .skel-line,.skel-avatar,.hi-skel-line,.hi-skel-avatar,.hi-skel-block,.skl-c,.vg-loader{animation:none}
}

/* ── Review player, light mode ────────────────────────────────────────────────
   (Superseded 2026-09-04: the owner asked for the Review and Publish stages to follow
   the light theme like every other container. The light remap lives in the
   "Review/Publish player, light mode" block near the end of this file. The history
   below is kept because it explains the token island it now undoes.)
   Deliberately almost empty. `.rev2 .rev-main` is a DARK ROOM: it redeclares the whole
   dark token set locally (--surf-1, --text-1, --hairline-*, …) so the picture, the
   transport bar and every control on it stay dark in BOTH themes. That is the point —
   it is a letterbox for judging picture, and every review tool keeps it dark.
   So do NOT add html[data-theme="light"] rules for anything inside .rev-main. An
   earlier pass added them for .rev-cbtn/.rev-tc/.rev-scrub-track (inert — they lost to
   `.rev2 .rev-ctrlrow .rev-cbtn`, 0-3-0) and for .rev-link/.rev-q-lbl (NOT inert — they
   won, and painted the upload/delete icons and the quality label dark-on-dark inside
   the dark room). The controls were already correct; the overrides only broke them.
   What genuinely IS theme-dependent is the comments rail (.rev-side), which sits
   OUTSIDE the dark room on the light panel — that is where the real bug was.

   Reply / Resolve use --text-3. On dark that is rgba(235,235,245,.45) over a dark
   panel and reads fine, but light resolves it to #9a9aa6 on white: measured 2.78:1,
   under even the 3.0 large-text floor. In the rev2 layout .rev-cm-acts is opacity:1
   permanently, so these are always-visible actions, not hover affordances — they have
   to clear AA. --text-2 (#5f5f6b) measures 4.87:1. */
html[data-theme="light"] .rev2 .rev-cm-act{color:var(--text-2)}
html[data-theme="light"] .rev2 .rev-cm-act:hover{color:var(--off-white)}

/* ── "Uploading onto this task" badge ─────────────────────────────────────────
   Reuses the existing bsoSpin keyframe rather than adding a sixth spinner — there are
   already five in this file and #dr-loaders is explicit that a second private loader
   vocabulary is a regression even when it renders correctly.
   Positioned absolutely inside whatever carries data-card-id, so Board, List and
   Calendar all get it without any of them knowing about it.
   .kanban-card is already position:relative, but .calendar-day-card and the list rows
   are not, so the badge needs a containing block. Scoped with :has() to ONLY the cards
   currently uploading — a blanket [data-card-id]{position:relative} would put a
   stacking context on every card in the app to serve the handful that have a badge.
   Where :has() is unsupported the badge anchors to the next positioned ancestor:
   misplaced, not broken. */
[data-card-id]:has(> .kc-upload-badge){position:relative}
.kc-upload-badge{position:absolute;top:6px;right:6px;width:13px;height:13px;border-radius:50%;
  border:2px solid var(--color-hairline-3);border-top-color:var(--kc-up-color,var(--color-primary));
  animation:bsoSpin var(--dur-complex,500ms) linear infinite;pointer-events:auto;z-index:3}
.kc-upload-badge.is-error{animation:none;border-color:var(--color-error);border-top-color:var(--color-error)}
@media (prefers-reduced-motion:reduce){.kc-upload-badge{animation:none}}

/* ── Task modal: header meta row, footer, tabs ────────────────────────────────
   The status selector, "Mark complete" and "Share" sit on ONE row under the
   title. "Created … by …" moved out of this row into the footer beside the trash
   can — it is provenance, not a control, and it was crowding the selector. */

/* Only the DOT carries the column colour. The trigger used to take it on the
   border AND the label, which drew a coloured ring around every status and made
   the modal read as an alert. Border returns to the neutral hairline; the label
   returns to normal text; the dot keeps the colour and is enough. */
#cardModalColWrap .ms-dropdown-trigger{
  border-color:var(--hairline-2);
  color:var(--cream);
  box-shadow:none}
/* ...but the leading dot IS the colour. It renders from the column's icon and takes
   currentColor, so neutralising the trigger's colour above greys it out too — which
   would leave the status with no colour at all. Give it the column colour back
   explicitly; it is now the single carrier, which is the whole point. */
#cardModalColWrap .ms-dropdown-trigger > span:first-child{
  color:var(--col-select-color,var(--cream));
  flex:none}
#cardModalColWrap .ms-dropdown-trigger:hover{border-color:var(--hairline-3)}
#cardModalColWrap .ms-dropdown-trigger:focus,
#cardModalColWrap .ms-dropdown.open .ms-dropdown-trigger{
  border-color:var(--hairline-3);
  box-shadow:none}
/* FIXED width — the box must not resize when the selected value changes. "IN EDIT"
   and "EDIT IN REVIEW" were rendering two different widths and the row jumped.
   The width goes on the WRAP: .ms-dropdown gets width:100% as an INLINE style from
   createMsDropdown, and .ms-dropdown-trigger is width:100%, so the wrap is the only
   element in the chain a stylesheet rule can size without !important.
   font-size:12px is load-bearing, not cosmetic: the wrap would otherwise inherit 11px
   from .card-modal-meta while the label renders at 12px (set on the trigger), so `ch`
   would resolve in the wrong font and 15ch would really measure ~13.7 characters.
   68px of chrome = 24 padding + 2 border + 16 (2x8 gap) + 14 dot + 12 chevron.
   The open MENU is unaffected: it is re-parented to <body> with position:fixed and
   width:max-content, so it is not a descendant of this box while open. */
#cardModalColWrap{font-size:12px;width:calc(15ch + 68px);flex:none}
#cardModalColWrap .ms-dropdown-trigger-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Mobile relocates this pill into #mCardActionRow, where a hard width would be a
   FLOOR on a narrow screen (it is flex-shrink:0 there). */
body[data-mobile-mode="app"] #cardModalColWrap{width:auto}

/* The meta-row buttons match the selector's box exactly so the row has one
   baseline: same height, same radius, same border, same vertical centre. */
.card-modal-meta{display:flex;align-items:center;gap:var(--sp-2)}
/* Bare icons — no container. They sit beside the status selector, which is the only
   boxed control on the row; boxing these too made three competing outlines out of what
   is really one control plus two actions. Height still matches the selector so the row
   keeps a single baseline, and the hit target stays 32px even though nothing is drawn.
   background:none overrides .card-modal-iconbtn:hover (line ~14199), which these also
   carry and which would otherwise paint a box back in on hover. */
.card-modal-meta .cm-meta-btn{
  height:32px;width:32px;padding:0;flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  border:0;border-radius:8px;background:none;color:var(--muted);
  cursor:pointer;transition:color .15s}
.card-modal-meta .cm-meta-btn:hover{background:none;color:var(--off-white)}
.card-modal-meta .cm-meta-btn:focus-visible{outline:2px solid var(--modal-col-color,var(--purple));outline-offset:2px}

/* Footer provenance line — quiet, and on the trash can's baseline. */
.cm-created{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}

/* No rule under the tabs, and no gap below it. The panel beneath already owns the
   separation; the border plus padding-bottom read as a double edge. */
.card-modal-tabs{border-bottom:none;padding-bottom:0;margin-bottom:0}

/* ── Bottom-right is ONE stack ────────────────────────────────────────────────
   The upload tray (.hd-tray) and the toast container are both position:fixed in
   the bottom-right corner, so they simply drew on top of each other — an upload
   in progress with any toast put "Moved … to EDIT IN REVIEW" straight through
   the tray. Toasts already stack among themselves (column + gap); the tray was
   never part of that stack.
   THE RULE: anything persistent pinned to that corner OWNS the bottom, and the
   transient toasts stack ABOVE it. --toast-stack-lift is the measured height of
   whatever is parked down there, published by _syncToastStackLift(); it is 0 when
   the corner is empty, so the default position is unchanged. Measured rather than
   hardcoded because the tray grows per file and can scroll to 50vh. */
.toast-container{bottom:calc(64px + var(--toast-stack-lift, 0px) + env(safe-area-inset-bottom,0px));transition:bottom .18s var(--ease-std,ease)}
@media(prefers-reduced-motion:reduce){.toast-container{transition:none}}

/* ── Uploading: say WHERE, in the status colour ───────────────────────────────
   Two surfaces, one idea. A card already carries a status dot to the left of its
   name, and the open task already carries a row of tabs. Spin the thing that is
   already there instead of adding a second mark beside it — the earlier corner
   badge sat next to the dot on a card and next to the title in the modal, so a
   task uploading showed two unrelated marks and neither said where the bytes were
   going. Both wear the status colour for the same reason the meter does. */

/* Card: the status dot becomes the ring. Its colour arrives as --kc-up-color,
   published from the dot's own inline background (a border cannot read one). */
.kc-stage-dot.is-uploading{
  background:transparent !important;
  border:2px solid var(--color-hairline-3);
  border-top-color:var(--kc-up-color,var(--color-primary));
  box-sizing:border-box;
  animation:bsoSpin var(--dur-complex,500ms) linear infinite;
  cursor:default}
.kc-stage-dot.is-uploading.is-error{animation:none;border-color:var(--color-error);border-top-color:var(--color-error)}
/* Same idea where the tile renders an ICON instead of a dot: the icon turns into the
   ring, so the upload is marked in the one place the eye already goes for this task.
   Its own paths are hidden rather than removed, which keeps the 12px box the row is
   laid out around. */
.kc-stage .task-glyph.is-uploading{
  border-radius:50%;
  border:2px solid var(--color-hairline-3);
  border-top-color:var(--kc-up-color,var(--color-primary));
  box-sizing:border-box;
  animation:bsoSpin var(--dur-complex,500ms) linear infinite;
  cursor:default}
.kc-stage .task-glyph.is-uploading > *{visibility:hidden}
.kc-stage .task-glyph.is-uploading.is-error{animation:none;border-color:var(--color-error);border-top-color:var(--color-error)}

/* Open task: destinations without their own numbered inline meter (currently
   Files) may use the target tab's icon as the compact ring. Review and Publish
   keep their ordinary icons because their panel already owns detailed progress.
   Sized to the 14px icon it replaces so the tab never shifts. */
.card-modal-tab.is-uploading > svg,.card-modal-tab.is-publishing > svg{display:none}
.card-modal-tab.is-uploading::before,.card-modal-tab.is-publishing::before{
  content:'';
  width:14px;height:14px;flex:none;border-radius:50%;
  border:2px solid var(--color-hairline-3);
  border-top-color:var(--modal-col-color,var(--color-primary));
  box-sizing:border-box;
  animation:bsoSpin var(--dur-complex,500ms) linear infinite}
.card-modal-tab.is-uploading.is-error::before{animation:none;border-color:var(--color-error);border-top-color:var(--color-error)}
@media(prefers-reduced-motion:reduce){
  .kc-stage-dot.is-uploading,.kc-stage .task-glyph.is-uploading,.card-modal-tab.is-uploading::before,.card-modal-tab.is-publishing::before{animation:none}
}
/* The focus ring on a tab was brand purple against an otherwise status-coloured
   modal. Same treatment. */
.card-modal-tabs .card-modal-tab:focus-visible{outline-color:var(--modal-col-color,var(--purple))}

/* Task details inherit the live status colour. Subtasks and properties used to
   fall back to the app's purple brand accent on hover/focus, which conflicted
   with the status-coloured modal border. Keep destructive and disabled states
   semantic/neutral; only interactive emphasis follows --modal-col-color. */
.card-modal .subtask-inline-row:hover{
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 6%,transparent)}
.card-modal .subtask-inline-title:hover{
  text-decoration-color:color-mix(in srgb,var(--modal-col-color,var(--coral)) 55%,transparent)}
.card-modal .subtask-inline-add:hover,
.card-modal .subtask-inline-add:focus-visible{
  color:var(--modal-col-color,var(--coral));
  border-color:var(--modal-col-color,var(--coral));
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 8%,transparent);
  outline-color:var(--modal-col-color,var(--coral))}
.card-modal .card-prop-row.drag-over-top{
  box-shadow:inset 0 2px 0 var(--modal-col-color,var(--coral))}
.card-modal .card-prop-row.drag-over-bottom{
  box-shadow:inset 0 -2px 0 var(--modal-col-color,var(--coral))}
.card-modal .card-prop-label:hover{
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 7%,transparent)}
.card-modal .card-prop-row:hover .card-prop-icon,
.card-modal .card-prop-row:focus-within .card-prop-icon{
  color:var(--modal-col-color,var(--coral));opacity:.9}
.card-modal .prop-pill-add:hover,
.card-modal .prop-pill-add:focus-visible{
  color:var(--modal-col-color,var(--coral));
  border-color:var(--modal-col-color,var(--coral));
  background:color-mix(in srgb,var(--modal-col-color,var(--coral)) 8%,transparent);
  outline-color:var(--modal-col-color,var(--coral))}
.card-modal .card-prop-value .ms-dropdown-trigger:hover,
.card-modal .card-prop-value .ms-dropdown-trigger:focus,
.card-modal .card-prop-value .ms-dropdown.open .ms-dropdown-trigger{
  border-color:var(--modal-col-color,var(--coral));
  box-shadow:0 0 0 3px color-mix(in srgb,var(--modal-col-color,var(--coral)) 12%,transparent)}
.card-modal .card-prop-value .due-date-input:focus,
.card-modal .card-prop-value .due-date-btn.gv-edit-open,
.card-modal .card-prop-value .kanban-input:focus{
  border-color:var(--modal-col-color,var(--coral))}
.card-modal .card-prop-value button:focus-visible,
.card-modal .due-date-btn:focus-visible{
  outline-color:var(--modal-col-color,var(--coral))}

/* ── Categorized @mention picker ────────────────────────────────────────────
   One shared picker is used by task descriptions/comments and every other
   setupMentionPopup surface. The tab treatment mirrors the supplied reference:
   quiet icon labels, a filled active tab and one purple indicator line. */
.mention-popup.mention-categorized{
  width:320px !important;max-width:min(360px,calc(100vw - 16px)) !important;
  max-height:none;overflow:hidden;padding:0;border-radius:13px}
.mention-tabs{
  display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.45fr) minmax(0,.7fr);
  align-items:stretch;background:rgba(255,255,255,.035);
  border-bottom:1px solid rgba(255,255,255,.07)}
.mention-tab{
  position:relative;min-width:0;height:43px;padding:0 9px;border:0;border-radius:0;
  background:transparent;color:var(--muted);font:600 12px/1 var(--sans);
  display:flex;align-items:center;justify-content:center;gap:7px;white-space:nowrap;
  cursor:pointer;transition:background .14s,color .14s}
.mention-tab:hover{background:rgba(255,255,255,.045);color:var(--cream)}
.mention-tab.active{background:rgba(255,255,255,.1);color:var(--off-white)}
.mention-tab.active::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:3px;
  background:var(--purple,#7c5cff)}
.mention-tab:focus-visible{outline:2px solid var(--purple,#7c5cff);outline-offset:-3px;z-index:1}
.mention-tab-icon{display:inline-flex;align-items:center;justify-content:center;flex:none;opacity:.9}
.mention-tab-icon svg{width:16px;height:16px}
.mention-panel{min-height:48px;background:rgba(10,10,13,.12)}
.mention-options{max-height:238px;overflow-y:auto;overscroll-behavior:contain;padding:0}
.mention-item{
  min-height:46px;padding:8px 12px;gap:10px;border-bottom:1px solid rgba(255,255,255,.055);
  color:var(--cream);box-sizing:border-box;outline:none}
.mention-item:last-child{border-bottom:0}
.mention-item:hover,.mention-item.selected{background:rgba(255,255,255,.105)}
.mention-item.selected{box-shadow:inset 3px 0 0 var(--purple,#7c5cff)}
.mention-popup .mention-avatar{
  width:26px !important;height:26px !important;min-width:26px !important;max-width:26px !important;
  font-size:12px !important}
.mention-popup .mention-avatar img,.mention-popup .mention-avatar svg{
  width:26px !important;height:26px !important;max-width:26px !important;max-height:26px !important}
.mention-bot-avatar{background:rgba(255,255,255,.08) !important;color:var(--cream)}
.mention-type-icon{
  width:26px;height:26px;border-radius:7px;display:inline-flex;align-items:center;
  justify-content:center;flex:none;color:var(--muted);background:rgba(255,255,255,.055)}
.mention-special-icon{color:#f5c542;background:rgba(245,197,66,.12)}
.mention-item-copy{display:flex;flex-direction:column;justify-content:center;gap:2px;min-width:0;flex:1}
.mention-item-label{font-size:13px;font-weight:600;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mention-item-detail{font-size:10.5px;font-weight:500;line-height:1.2;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mention-item-kind{font-size:9px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.45px;color:var(--muted);flex:none}
.mention-empty{display:flex;align-items:center;justify-content:center;min-height:78px;padding:14px;text-align:center;color:var(--muted);font-size:12px}
.mention-keyhint{
  min-height:27px;padding:0 9px;border-top:1px solid rgba(255,255,255,.065);
  display:flex;align-items:center;justify-content:space-between;gap:6px;
  color:var(--muted);font:500 8.5px/1 var(--sans);white-space:nowrap}
html[data-theme="light"] .mention-tabs{background:rgba(0,0,0,.035);border-bottom-color:rgba(0,0,0,.08)}
html[data-theme="light"] .mention-tab:hover{background:rgba(0,0,0,.045)}
html[data-theme="light"] .mention-tab.active{background:rgba(0,0,0,.075)}
html[data-theme="light"] .mention-panel{background:rgba(255,255,255,.18)}
html[data-theme="light"] .mention-item{border-bottom-color:rgba(0,0,0,.07)}
html[data-theme="light"] .mention-item:hover,html[data-theme="light"] .mention-item.selected{background:rgba(0,0,0,.075)}
html[data-theme="light"] .mention-keyhint{border-top-color:rgba(0,0,0,.08)}
@media(max-width:370px){
  .mention-tab{padding:0 6px;gap:5px;font-size:11px}
  .mention-tab-icon{display:none}
  .mention-keyhint{font-size:8px;padding:0 7px}
}
body[data-mobile-mode="app"] .m-cmt-mpick{padding:0 4px 10px;gap:0}
.m-cmt-mpick-tabs{
  position:sticky;top:0;z-index:1;display:grid;
  grid-template-columns:minmax(0,.8fr) minmax(0,1.45fr) minmax(0,.7fr);
  margin:0 -4px 6px;background:var(--bg2);border-bottom:1px solid rgba(255,255,255,.07)}
.m-cmt-mpick-tab{
  position:relative;min-width:0;height:44px;padding:0 7px;border:0;background:transparent;
  color:var(--muted);font:600 11px/1 var(--sans);display:flex;align-items:center;
  justify-content:center;gap:6px;white-space:nowrap;cursor:pointer}
.m-cmt-mpick-tab > span{display:inline-flex;flex:none}
.m-cmt-mpick-tab.active{background:var(--state-hover);color:var(--off-white)}
.m-cmt-mpick-tab.active::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--purple,#7c5cff)}
.m-cmt-mpick-tab:focus-visible{outline:2px solid var(--purple,#7c5cff);outline-offset:-3px}
.m-cmt-mpick-options{display:flex;flex-direction:column;gap:1px}
.m-cmt-mpick-row.selected{background:rgba(255,255,255,.055)}
.m-cmt-mpick-type{width:36px;height:36px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex:none;color:var(--muted);background:rgba(255,255,255,.055)}
html[data-theme="light"] .m-cmt-mpick-tabs{border-bottom-color:rgba(0,0,0,.08)}
html[data-theme="light"] .m-cmt-mpick-tab.active,html[data-theme="light"] .m-cmt-mpick-row.selected{background:rgba(0,0,0,.06)}

/* Pending comment attachment: Discord's spinner over the local preview while the bytes
   are still going up. The image is already on screen -- this only says it is not saved
   yet, so hitting send is understood to be allowed rather than premature. */
.cmt-att-spin{position:absolute;top:50%;left:50%;width:22px;height:22px;margin:-11px 0 0 -11px;
  border:2px solid rgba(255,255,255,.28);border-top-color:#fff;border-radius:50%;
  animation:cmtAttSpin .7s linear infinite;pointer-events:none}
@keyframes cmtAttSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.cmt-att-spin{animation-duration:2.2s}}

/* Reset mode on the login form: the password field collapses out rather than vanishing.
   Height, padding, margin and opacity all travel, so the button rises into its place
   instead of jumping. */
.login-local-form #loginLocalPassword{
  transition:opacity .22s ease,max-height .32s cubic-bezier(.4,0,.2,1),
    margin .32s cubic-bezier(.4,0,.2,1),padding .32s cubic-bezier(.4,0,.2,1),
    border-width .32s cubic-bezier(.4,0,.2,1);
  max-height:60px;overflow:hidden}
.login-local-form.is-reset #loginLocalPassword{
  opacity:0;max-height:0;margin-top:0;margin-bottom:0;padding-top:0;padding-bottom:0;
  border-width:0;pointer-events:none}
.login-local-btn{transition:background .15s ease,color .15s ease}
@media (prefers-reduced-motion:reduce){
  .login-local-form #loginLocalPassword{transition:opacity .15s ease,max-height 0s}
}

/* ── Branded login: the workspace's own front door ───────────────────────────
   Logo is a circle because a workspace mark is an identity, the same shape it wears
   in the sidebar card and the members list -- not a rounded app tile. Henshu is
   credited underneath at a size that reads as a footnote, not a competing brand. */
.login-brand{display:flex;flex-direction:column;align-items:center;gap:10px;margin-bottom:18px}
/* An unbranded workspace leaves this block hidden. The class rule above outranks the UA's
   [hidden]{display:none}, so without this guard the empty logo circle and "Powered by Henshu"
   render on top of Henshu's own wordmark. */
.login-brand[hidden]{display:none}
.login-brand-logo{width:76px;height:76px;border-radius:50%;overflow:hidden;flex:none;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,#7c5cff,#6a4bff);color:#fff;
  font:700 26px var(--sans);letter-spacing:.5px;
  box-shadow:0 10px 30px rgba(124,92,255,.28)}
.login-brand-logo img{width:100%;height:100%;object-fit:cover;display:block}
.login-brand-name{font-family:var(--serif);font-size:24px;font-weight:400;text-align:center;
  margin:0;color:var(--off-white);line-height:1.25}
.login-brand-powered{display:inline-flex;align-items:center;gap:6px;font-size:11px;
  color:var(--muted);letter-spacing:.2px}
.login-brand-powered img{width:14px;height:14px;border-radius:4px;display:block;opacity:.85}


/* ── LOGIN GATE: light, with the landing page's hero behind it ───────────────
   Every rule here is scoped under .login-gate. The app behind the gate stays dark --
   this is a door, not a theme switch, and nothing outside it should shift. */
.login-gate{background:#f5f6f8;color:#16171a;overflow:hidden}
.login-gate .login-box{
  position:relative;z-index:1;max-width:380px;
  background:#fff;border:1px solid rgba(16,17,26,.08);border-radius:16px;
  padding:34px 30px;
  box-shadow:0 24px 60px rgba(16,17,26,.10),0 2px 8px rgba(16,17,26,.05);
}
.login-gate .login-title{color:#16171a}
.login-gate .login-sub,
.login-gate .login-provider-hint,
.login-gate .login-brand-powered{color:#6b6f76}
.login-gate .login-brand-name{color:#16171a}
.login-gate .login-local-divider,
.login-gate .login-oauth-divider{color:#8a8f97}
.login-gate .login-local-divider::before,.login-gate .login-local-divider::after,
.login-gate .login-oauth-divider::before,.login-gate .login-oauth-divider::after{background:rgba(16,17,26,.12)}
.login-gate .login-local-input{
  background:#fff;border:1px solid rgba(16,17,26,.14);color:#16171a}
.login-gate .login-local-input::placeholder{color:#9aa0a8}
.login-gate .login-local-input:focus{border-color:#7c5cff;box-shadow:0 0 0 3px rgba(124,92,255,.16)}
.login-gate .login-local-btn{background:#7c5cff;color:#fff}
.login-gate .login-local-btn:hover{background:#6a4bff;color:#fff}
.login-gate .login-forgot-link{color:#6b6f76}
.login-gate .login-forgot-link:hover{color:#16171a}
.login-gate .login-oauth-btn{
  background:#fff;border:1px solid rgba(16,17,26,.14);color:#16171a}
.login-gate .login-oauth-btn:hover{background:#f7f7f9;border-color:rgba(16,17,26,.22)}
.login-gate .login-error{color:#b91c1c}

/* the hero itself — same geometry as the landing page, on the light ground */
.login-gate .scene{position:absolute;inset:0;perspective:1400px;perspective-origin:60% 45%;pointer-events:none;z-index:0}
.login-gate .scene-in{position:absolute;inset:0;transform-style:preserve-3d}
.login-gate .cell{position:absolute;display:block;width:var(--w,84px);aspect-ratio:60/54;left:var(--x);top:var(--y);transform-style:preserve-3d;will-change:transform;
  --fc-body:color-mix(in srgb,#7c5cff 15%,transparent);
  --fc-edge:color-mix(in srgb,#7c5cff 46%,transparent);
  --fc-hole:#f5f6f8;
  --fc-gate:color-mix(in srgb,#7c5cff 7%,transparent);
  --fc-edge2:color-mix(in srgb,#7c5cff 24%,transparent)}
.login-gate .cell svg{width:100%;height:100%;display:block;overflow:visible}
.login-gate .cell[data-depth="far"]{opacity:.5}
.login-gate .cell[data-depth="mid"]{opacity:.76}
.login-gate .scene-loose .cell{animation:cellDrift var(--dur,22s) ease-in-out infinite;animation-delay:var(--delay,0s)}
.login-gate .scene-strip{position:absolute;left:var(--sx,52%);top:var(--sy,42%);display:flex;gap:var(--sgap,10px);transform:rotateY(-13deg) rotateX(4deg);transform-style:preserve-3d;animation:stripRun 26s linear infinite}
.login-gate .scene-strip .cell{position:relative;left:auto;top:auto;width:var(--sw);flex:none}
.login-gate .scene-floor{position:absolute;left:-2%;right:20%;top:78%;height:20%;background:radial-gradient(60% 50% at 40% 50%,color-mix(in srgb,#7c5cff 18%,transparent),transparent 70%);filter:blur(26px);animation:floorBreathe 24s ease-in-out infinite}
@keyframes cellDrift{
  0%,100%{transform:translate3d(0,0,0) rotateX(var(--rx0,0deg)) rotateY(var(--ry0,0deg)) rotateZ(var(--rz0,0deg))}
  50%    {transform:translate3d(var(--dx,0),var(--dy,0),var(--dz,0)) rotateX(var(--rx1,0deg)) rotateY(var(--ry1,0deg)) rotateZ(var(--rz1,0deg))}
}
@keyframes stripRun{to{transform:rotateY(-13deg) rotateX(4deg) translateX(calc((var(--sw) + var(--sgap)) * -1))}}
@keyframes floorBreathe{0%,100%{transform:none;opacity:.75}50%{transform:translate3d(2%,-1%,0) scaleX(1.05);opacity:.95}}
@media (prefers-reduced-motion:reduce){
  .login-gate .scene-loose .cell,.login-gate .scene-strip,.login-gate .scene-floor{animation:none}
}

/* Signup is the other half of the same front door as Login. Keep every onboarding
   step and control, but place it on the same light landing-film scene and white-card
   vocabulary. All overrides stay under #signupGate so invite and in-app dark gates
   retain their workspace styling. */
#signupGate{background:#f5f6f8;color:#16171a}
#signupGate .hs-signup-scene{position:fixed;inset:0;perspective:1400px;perspective-origin:60% 45%;pointer-events:none;z-index:0;overflow:hidden}
#signupGate .hs-signup-scene .scene-in{position:absolute;inset:0;transform-style:preserve-3d}
#signupGate .hs-signup-scene .cell{position:absolute;display:block;width:var(--w,84px);aspect-ratio:60/54;left:var(--x);top:var(--y);transform-style:preserve-3d;will-change:transform;
  --fc-body:color-mix(in srgb,#7c5cff 15%,transparent);
  --fc-edge:color-mix(in srgb,#7c5cff 46%,transparent);
  --fc-hole:#f5f6f8;
  --fc-gate:color-mix(in srgb,#7c5cff 7%,transparent);
  --fc-edge2:color-mix(in srgb,#7c5cff 24%,transparent)}
#signupGate .hs-signup-scene .cell svg{width:100%;height:100%;display:block;overflow:visible}
#signupGate .hs-signup-scene .cell[data-depth="far"]{opacity:.5}
#signupGate .hs-signup-scene .cell[data-depth="mid"]{opacity:.76}
#signupGate .hs-signup-scene .scene-loose .cell{animation:cellDrift var(--dur,22s) ease-in-out infinite;animation-delay:var(--delay,0s)}
#signupGate .hs-signup-scene .scene-strip{position:absolute;left:var(--sx,52%);top:var(--sy,42%);display:flex;gap:var(--sgap,10px);transform:rotateY(-13deg) rotateX(4deg);transform-style:preserve-3d;animation:stripRun 26s linear infinite}
#signupGate .hs-signup-scene .scene-strip .cell{position:relative;left:auto;top:auto;width:var(--sw);flex:none}
#signupGate .hs-signup-scene .scene-floor{position:absolute;left:-2%;right:20%;top:78%;height:20%;background:radial-gradient(60% 50% at 40% 50%,color-mix(in srgb,#7c5cff 18%,transparent),transparent 70%);filter:blur(26px);animation:floorBreathe 24s ease-in-out infinite}
#signupGate .hs-signup{position:relative;z-index:1;background:transparent;color:#16171a}
#signupGate .hs-signup-centered{display:flex;align-items:center;justify-content:center;min-height:100vh;min-height:100dvh;padding:32px;box-sizing:border-box;overflow:visible;background:transparent}
#signupGate .hs-su-hero,
#signupGate .hs-signup-form{background:#fff;border:1px solid rgba(16,17,26,.08);border-radius:16px;padding:34px 30px;box-shadow:0 24px 60px rgba(16,17,26,.10),0 2px 8px rgba(16,17,26,.05)}
#signupGate .hs-su-hero{max-width:500px;margin:auto}
#signupGate .hs-signup-pane{position:relative;z-index:1;background:transparent;padding:56px 32px 32px}
#signupGate .hs-signup-form{max-width:560px;margin:auto}
#signupGate .hs-signup-form.hs-form-wide{max-width:860px}
#signupGate .hs-su-corner{color:#16171a}
#signupGate .hs-su-brand,
#signupGate .hs-su-h1,
#signupGate .hs-step-h1,
#signupGate .hs-onb-label,
#signupGate .hs-plan-name,
#signupGate .hs-plan-price,
#signupGate .hs-plan-lead-t,
#signupGate .hs-plan-created,
#signupGate .hs-plan-mini,
#signupGate .hs-quiz-legend,
#signupGate .hs-quiz-card-label{color:#16171a}
#signupGate .hs-su-sub,
#signupGate .hs-step-sub,
#signupGate .hs-step-kicker,
#signupGate .hs-su-terms,
#signupGate .hs-onb-alt,
#signupGate .hs-plan-per,
#signupGate .hs-plan-lead-sub,
#signupGate .hs-plan-feats li,
#signupGate .hs-quiz-card-desc{color:#6b6f76}
#signupGate .hs-su-sub strong{color:#34373d}
#signupGate .hs-su-terms a{color:#6b6f76}
#signupGate .hs-su-terms a:hover{color:#16171a}
#signupGate .hs-onb-input,
#signupGate .hs-onb-slug-wrap{background:#fff;border-color:rgba(16,17,26,.14);color:#16171a}
#signupGate .hs-onb-input::placeholder,
#signupGate .hs-onb-slug-input::placeholder{color:#9aa0a8}
#signupGate .hs-onb-input:focus,
#signupGate .hs-onb-slug-wrap:focus-within{border-color:#7c5cff;box-shadow:0 0 0 3px rgba(124,92,255,.16)}
#signupGate .hs-onb-slug-input{color:#16171a}
#signupGate .hs-onb-slug-suffix{color:#6b6f76}
#signupGate .hs-onb-divider{color:#8a8f97}
#signupGate .hs-onb-divider::before,
#signupGate .hs-onb-divider::after{background:rgba(16,17,26,.12)}
#signupGate .hs-onb-btn{background:#7c5cff;color:#fff}
#signupGate .hs-onb-btn:hover{background:#6a4bff;color:#fff}
#signupGate .hs-onb-btn.secondary{background:#fff;color:#16171a;border-color:rgba(16,17,26,.14)}
#signupGate .hs-onb-btn.secondary:hover{background:#f7f7f9}
#signupGate .hs-quiz-card,
#signupGate .hs-chip,
#signupGate .hs-team-opt,
#signupGate .hs-plan-card,
#signupGate .hs-plan-toggle{background:#fff;border-color:rgba(16,17,26,.14);color:#34373d}
#signupGate .hs-quiz-card:hover,
#signupGate .hs-chip:hover,
#signupGate .hs-team-opt:hover,
#signupGate .hs-plan-card:hover{border-color:rgba(124,92,255,.55);background:#faf9ff}
#signupGate .hs-quiz-card.selected,
#signupGate .hs-chip.selected,
#signupGate .hs-team-opt.selected,
#signupGate .hs-plan-card.on{border-color:#7c5cff;background:rgba(124,92,255,.08);color:#16171a}
#signupGate .hs-plan-toggle button{color:#6b6f76}
#signupGate .hs-plan-toggle button.on{background:#7c5cff;color:#fff}
#signupGate .hs-signed-banner{background:rgba(124,92,255,.08);border-color:rgba(124,92,255,.2);color:#34373d}
@media (max-width:560px){
  #signupGate .hs-signup-centered{padding:18px}
  #signupGate .hs-su-hero,#signupGate .hs-signup-form{padding:28px 20px}
  #signupGate .hs-signup-pane{padding:72px 18px 24px}
}
@media (prefers-reduced-motion:reduce){
  #signupGate .hs-signup-scene .scene-loose .cell,
  #signupGate .hs-signup-scene .scene-strip,
  #signupGate .hs-signup-scene .scene-floor{animation:none}
}

/* Faces on the typing indicator. Overlapped slightly so two or three people read as a
   group rather than a list, and small enough that the row height does not change. */
.presence-typing-avs{display:inline-flex;align-items:center;margin-right:6px;flex:none}
.presence-typing-av{width:18px;height:18px;border-radius:50%;overflow:hidden;flex:none;
  display:inline-flex;align-items:center;justify-content:center;font-size:9px;
  border:1.5px solid var(--bg,#0c0c0e);margin-left:-6px}
.presence-typing-av:first-child{margin-left:0}
.presence-typing-av svg,.presence-typing-av span{width:100%;height:100%;display:block}

/* ══ Sidebar: folder slide, multi-select, and the delete suck-out ══════════════════════
   Appended 2026-08-14. */

/* FOLDERS SLIDE. The nav is wrapped in a grid shell whose single row animates 1fr → 0fr,
   which is the only way to transition to "as tall as the contents are" without measuring
   them: max-height needs a number, and the open state was max-height:none, which cannot
   be animated from. The nav keeps .collapsed for anything else that reads it, so that
   rule is neutralised here — the shell is what moves now. */
.sidebar-cat-body{display:grid;grid-template-rows:1fr;transition:grid-template-rows .28s cubic-bezier(.22,1,.36,1),opacity .18s ease}
.sidebar-cat-body>.sidebar-section-nav{overflow:hidden;min-height:0;max-height:none!important;transition:none}
.sidebar-cat-body.is-collapsed{grid-template-rows:0fr;opacity:0}
@media (prefers-reduced-motion:reduce){.sidebar-cat-body{transition:none}}

/* MULTI-SELECT. Cmd/Ctrl-click or Shift-click marks rows; the marker has to read as
   "chosen", distinct from .active, which means "this is the page you are on". Active is
   a filled tint; selected is a tint plus a left edge, so both can be true at once. */
#sidebarUnifiedItems a.sb-multi-selected,
#sidebarUnifiedItems a.sidebar-cat-item.sb-multi-selected{
  background:rgba(124,92,255,.20);color:#fff;position:relative}
#sidebarUnifiedItems a.sb-multi-selected::after{
  content:'';position:absolute;left:0;top:4px;bottom:4px;width:2.5px;border-radius:0 2px 2px 0;background:var(--coral)}
/* While a selection is live the rows stop offering their individual hover, so the group
   reads as one thing rather than a list you are still picking through. */
#sidebarUnifiedItems.sb-has-selection a:hover:not(.sb-multi-selected){background:transparent}

/* THE SUCK-OUT. Two stages on purpose. First the row LEAVES: it collapses toward its own
   centre, blurs and fades — small, fast, and clearly gone rather than merely hidden.
   Then the LAYOUT heals: height and margins go to zero on a separate, gentler curve,
   and that is what draws every row below it smoothly upward into the gap. */
@keyframes sbSuckOut{
  0%  {opacity:1;transform:scale(1);filter:blur(0)}
  55% {opacity:.55;transform:scale(.82) translateX(-6px);filter:blur(1px)}
  100%{opacity:0;transform:scale(.35) translateX(-14px);filter:blur(4px)}
}
.sb-sucking{animation:sbSuckOut .2s cubic-bezier(.4,0,.7,.2) both;pointer-events:none;transform-origin:left center}
.sb-collapsing{transition:height .24s cubic-bezier(.22,1,.36,1),margin .24s cubic-bezier(.22,1,.36,1);pointer-events:none}
@media (prefers-reduced-motion:reduce){
  .sb-sucking{animation:none;opacity:0}
  .sb-collapsing{transition:none}
}

/* The batch menu's header — states what the following actions will act on. */
.sidebar-ctx-menu .ctx-batch-head{
  padding:7px 12px 5px;font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--muted);pointer-events:none}

/* ============================================================================
   DM composer + message rendering — mobile batch 2.
   ============================================================================ */

/* ── The open conversation is a FULL-SCREEN overlay with its own header (back +
   avatar + name). The app header is fixed at the top of the shell and offsets by the
   same safe-area inset, so the two landed on each other — the person's name rendered
   straight through "Sauce Media". The overlay owns the screen while it's up. */
body[data-mobile-mode="app"][data-dm-open] .m-app-header{display:none !important}

/* ── Emoji-only messages (≤3 emoji / custom emotes) read 50% larger, the convention
   every chat app uses so a reaction-sized message lands as one. Sized off the SAME base
   each context sets on .cr-msg-text (14px desktop / 15px in the mobile thread), because
   `em` here would resolve against the row, not the message. The mobile rule has to carry
   #page-dm or the base wins on specificity. Inline custom emotes need no rule of their
   own — .inline-emote is already sized in em, so it scales with this automatically,
   which is what keeps an emote and an emoji the same size. */
.cr-msg-text.cr-msg-jumbo{font-size:21px;line-height:1.35}
body[data-mobile-mode="app"] #page-dm .cr-msg-text.cr-msg-jumbo{font-size:22.5px;line-height:1.3}

/* ── Consistent vertical rhythm in the thread. Text rows, emote-only rows and voice
   memos were each spaced by whatever their own inner padding happened to be, so the
   gaps between them were arbitrary. One row gap, one grouped-row gap, everywhere. */
body[data-mobile-mode="app"] #page-dm{--dm-row-gap:10px;--dm-row-gap-grouped:3px}
body[data-mobile-mode="app"] #page-dm .cr-msg-row{margin:var(--dm-row-gap) 0 0}
body[data-mobile-mode="app"] #page-dm .cr-msg-row.cr-msg-grouped{margin-top:var(--dm-row-gap-grouped)}
body[data-mobile-mode="app"] #page-dm .cr-msg-row:first-child{margin-top:0}
body[data-mobile-mode="app"] #page-dm .cr-msg-text{margin:0}
body[data-mobile-mode="app"] #page-dm .cr-msg-text.cr-msg-jumbo{margin:2px 0}
body[data-mobile-mode="app"] #page-dm .dmx-att-audio,
body[data-mobile-mode="app"] #page-dm .dmx-att-img,
body[data-mobile-mode="app"] #page-dm .dmx-att-file{margin:var(--dm-row-gap-grouped) 0 0}
body[data-mobile-mode="app"] #page-dm .dmx-reax-row{margin:5px 0 0}

/* ── Staged attachments: a tray directly ABOVE the composer, never inside the thread.
   Horizontally scrollable so a handful of photos can't push the field off screen. */
body[data-mobile-mode="app"] #page-dm .dm-pending-atts{
  flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;
  gap:8px;padding:8px 12px 4px;margin:0
}
body[data-mobile-mode="app"] #page-dm .dm-pending-att{flex:none;width:64px;height:64px;border-radius:12px}
body[data-mobile-mode="app"] #page-dm .dm-pending-att img{width:100%;height:100%;object-fit:cover;display:block}
.dm-pending-att.is-uploading img{opacity:.45}
.dm-pending-att .dm-att-voice{display:flex;align-items:center;justify-content:center;height:100%;padding:0 10px;font-size:12px;color:var(--ink-solid)}
.dm-pending-att-spin{
  position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-9px 0 0 -9px;
  border:2px solid rgba(255,255,255,.28);border-top-color:#fff;border-radius:50%;
  animation:dm-att-spin .7s linear infinite;pointer-events:none
}
@keyframes dm-att-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.dm-pending-att-spin{animation-duration:2.4s}}

/* ── Voice memo TAKES OVER the composer: while recording, and while a finished memo
   waits to be sent, there is no text field — you are sending a voice message or you
   are not. Nothing is posted until Send. */
.dmx-voice-stage{display:flex;align-items:center;gap:10px;flex:1;min-width:0;padding:4px 2px}
.dmx-voice-stage[hidden]{display:none}
.dmx-cmt-bar.dmx-voice-recording .dmx-cmt-field,
.dmx-cmt-bar.dmx-voice-staged .dmx-cmt-field{display:none !important}
/* While recording, the only actions are Discard and Stop (both live in the stage). */
.dmx-cmt-bar.dmx-voice-recording .dmx-cmt-actions{display:none !important}
.dmx-cmt-bar.dmx-voice-staged .cmt-btn{display:none !important}
.dmx-voice-live{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;color:var(--ink-solid);flex:none}
.dmx-voice-pulse{width:9px;height:9px;border-radius:50%;background:#ff453a;animation:dm-voice-pulse 1.1s ease-in-out infinite}
@keyframes dm-voice-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.78)}}
@media(prefers-reduced-motion:reduce){.dmx-voice-pulse{animation:none}}
.dmx-voice-time{font:500 12px var(--mono,ui-monospace,monospace);color:rgba(var(--ink),.6);flex:none;font-variant-numeric:tabular-nums}
.dmx-voice-audio{flex:1;min-width:0;height:34px}
.dmx-voice-x{
  flex:none;width:30px;height:30px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(var(--line),.10);color:rgba(var(--ink),.75);font-size:19px;line-height:1;
  -webkit-tap-highlight-color:transparent
}
.dmx-voice-stop{
  flex:none;display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 14px;
  border:0;border-radius:999px;cursor:pointer;background:var(--purple);color:#fff;
  font:700 13px var(--sans);-webkit-tap-highlight-color:transparent
}
.dmx-voice-stop span{width:9px;height:9px;border-radius:2px;background:#fff;display:inline-block}
/* The mic reads as ARMED while recording, so the bar's state is legible at a glance. */
#dmVoiceBtn.recording,.cmt-mic.recording{color:#ff453a}

/* ── "New message" people picker: a real mobile screen, not a desktop panel squeezed
   into a phone. Full-height column, one-line search, thumb-sized rows. */
body[data-mobile-mode="app"] #page-dm .dm-picker{
  display:flex;flex-direction:column;height:100%;min-height:0;padding:4px 0 0;gap:0
}
body[data-mobile-mode="app"] #page-dm .dm-picker-head{font:800 26px var(--display,var(--sans));padding:6px 16px 2px;color:var(--ink-solid)}
body[data-mobile-mode="app"] #page-dm .dm-picker-sub{font-size:14px;color:rgba(var(--ink),.5);padding:0 16px 12px}
body[data-mobile-mode="app"] #page-dm .dm-picker-search{
  margin:0 12px 10px;padding:0 14px;height:44px;box-sizing:border-box;width:auto;
  font-size:16px;                         /* <16px makes iOS zoom the page on focus */
  border-radius:12px;border:1px solid rgba(var(--line),.12);
  background:rgba(var(--line),.06);color:var(--ink-solid)
}
body[data-mobile-mode="app"] #page-dm .dm-picker-list{
  flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding-bottom:calc(var(--m-island-h,58px) + 46px + env(safe-area-inset-bottom,0px))
}
body[data-mobile-mode="app"] #page-dm .dm-person-row{
  display:flex;align-items:center;gap:12px;width:100%;box-sizing:border-box;
  padding:10px 16px;min-height:60px;border:0;background:none;text-align:left;
  -webkit-tap-highlight-color:transparent
}
body[data-mobile-mode="app"] #page-dm .dm-person-row:active{background:rgba(var(--line),.06)}
body[data-mobile-mode="app"] #page-dm .dm-person-row .dm-sb-av{
  flex:none;width:46px;height:46px;border-radius:50%;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:17px;font-weight:700;color:#fff
}
body[data-mobile-mode="app"] #page-dm .dm-person-row .dm-sb-av img{width:100%;height:100%;object-fit:cover;display:block}
body[data-mobile-mode="app"] #page-dm .dm-person-meta{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
body[data-mobile-mode="app"] #page-dm .dm-person-name{font-size:16px;font-weight:600;color:var(--ink-solid);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
body[data-mobile-mode="app"] #page-dm .dm-person-email{font-size:13px;color:rgba(var(--ink),.45);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ============================================================================
   Mobile header + nav drawer — workspace-left, Slack/Claude shape.
   ============================================================================ */
/* The workspace is the LEFT anchor now, not a centred title: icon + name + chevron,
   and it opens the drawer. It no longer needs flex:1 to centre itself, and it must
   be allowed to shrink so a long workspace name ellipsises instead of shoving the
   right-hand actions off screen. */
body[data-mobile-mode="app"] .m-app-header-brand{flex:1 1 auto;justify-content:flex-start;min-width:0}
body[data-mobile-mode="app"] .m-app-brand-trigger{padding-left:0;min-width:0}
body[data-mobile-mode="app"] .m-app-header-title{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;
  font-weight:800;letter-spacing:-.2px
}
body[data-mobile-mode="app"] .m-app-brand-icon{width:30px;height:30px;border-radius:50%;flex:none}
/* The chevron points DOWN on a dropdown; this opens a drawer from the left, so it
   reads as a disclosure rather than a menu. */
body[data-mobile-mode="app"] .m-app-brand-chev{width:15px;height:15px;flex:none;opacity:.55}
body[data-mobile-mode="app"][data-drawer="open"] .m-app-brand-chev{opacity:.9}
/* You move to the right, beside the bell — the conventional slot once identity owns
   the left (Slack, Notion, Linear all land here). */
body[data-mobile-mode="app"] .m-app-header-actions{flex:none;gap:6px}
body[data-mobile-mode="app"] .m-app-header-actions .m-app-pfp-btn{margin-left:2px}
body[data-mobile-mode="app"] .m-app-header-actions .m-app-pfp{width:30px;height:30px}

/* ── The drawer itself. Base rules already exist (.m-drawer / .m-drawer-backdrop /
   .m-drawer-item); these are the mobile-mode additions that the "#10 removed the
   drawer" change left unwritten. */
body[data-mobile-mode="app"] .m-drawer-nav{
  padding-bottom:12px;overscroll-behavior:contain;-webkit-overflow-scrolling:touch
}
body[data-mobile-mode="app"] .m-drawer-item{min-height:46px;font-size:15px;border-radius:11px}
body[data-mobile-mode="app"] .m-drawer-section{margin-top:14px}
/* Current workspace: tinted row + a check. */
.m-drawer-check{width:17px;height:17px;flex:none;color:var(--purple)}
.m-drawer-item.is-current-ws{background:color-mix(in srgb,var(--purple) 14%,transparent)}
/* A drawer is a full-screen surface on a phone — the hotbar underneath it is dead
   chrome and its glass reads through the backdrop. */
body[data-mobile-mode="app"][data-drawer="open"] .m-bottom-nav{opacity:0;pointer-events:none;transition:opacity .16s ease}
/* .m-drawer-profile is a <button>, so its text inherits the UA's text-align:center —
   the name sat centred over a left-aligned status line. */
.m-drawer-profile{text-align:left}

/* ============================================================================
   Slack-shaped mobile: hotbar search, DM thread, Activity.
   ============================================================================ */

/* ── Search sits OUTSIDE the island, to its right. The island shortens to make
   room rather than the button overlapping it. Same glass material so the two read
   as one control cluster. */
body[data-mobile-mode="app"] .m-bottom-nav{right:calc(16px + var(--m-bn-search-size,54px) + 10px)}
.m-bn-search{display:none}
body[data-mobile-mode="app"] .m-bn-search{
  --m-bn-search-size:54px;
  display:flex;align-items:center;justify-content:center;
  position:fixed;z-index:60;
  right:16px;bottom:calc(22px + env(safe-area-inset-bottom,0px));
  width:var(--m-bn-search-size);height:var(--m-island-h);
  border-radius:var(--m-radius-island);
  border:0.5px solid rgba(var(--line),0.14);
  background:rgba(var(--surface-rgb),0.72);
  backdrop-filter:blur(36px) saturate(200%);-webkit-backdrop-filter:blur(36px) saturate(200%);
  box-shadow:inset 0 0.8px 0 rgba(255,255,255,0.75),inset 0 -0.6px 0 rgba(0,0,0,0.06),0 16px 36px rgba(0,0,0,0.55);
  color:rgba(var(--ink),0.72);cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:transform 160ms var(--m-hotbar-slide-ease,ease),opacity .16s ease
}
body[data-mobile-mode="app"] .m-bn-search svg{width:23px;height:23px}
body[data-mobile-mode="app"] .m-bn-search:active{transform:scale(.9)}
/* Follows the hotbar everywhere the hotbar goes. */
body[data-mobile-mode="app"][data-card-open] .m-bn-search,
body[data-mobile-mode="app"][data-dm-open] .m-bn-search,
body:has(#hdFilesSettingsDialog) .m-bn-search{display:none !important}
body[data-mobile-mode="app"][data-drawer="open"] .m-bn-search{opacity:0;pointer-events:none}

/* ── DM thread, Slack shape ────────────────────────────────────────────────
   The renderer already emits Slack's structure (avatar slot + author + text rows,
   with consecutive messages grouped). What was missing was the typography and
   rhythm: a message is a ROW, not a bubble. The .dmx-bub* rules above are dead —
   nothing renders that class any more — so this is the live styling. */
body[data-mobile-mode="app"] #page-dm .dm-messages-wrap{padding:4px 0 10px}
body[data-mobile-mode="app"] #page-dm .cr-msg-row{
  display:flex;gap:10px;align-items:flex-start;padding:0 16px;background:none
}
body[data-mobile-mode="app"] #page-dm .cr-msg-avatar-slot{flex:none;width:36px}
body[data-mobile-mode="app"] #page-dm .cr-msg-avatar-slot .dmx-av,
body[data-mobile-mode="app"] #page-dm .cr-msg-avatar-slot img{
  width:36px;height:36px;border-radius:9px    /* Slack's rounded square, not a circle */
}
/* A grouped message keeps the avatar column empty and hugs the one above it. */
body[data-mobile-mode="app"] #page-dm .cr-msg-row.cr-msg-grouped{margin-top:2px}
body[data-mobile-mode="app"] #page-dm .cr-msg-row.cr-msg-grouped .cr-msg-avatar-slot{width:36px}
body[data-mobile-mode="app"] #page-dm .cr-msg-author{
  font-size:15px;font-weight:800;color:var(--ink-solid);letter-spacing:-.1px
}
body[data-mobile-mode="app"] #page-dm .cr-msg-time{font-size:12px;color:rgba(var(--ink),.45);font-weight:500;margin-left:7px}
body[data-mobile-mode="app"] #page-dm .cr-msg-text{font-size:15px;line-height:1.47;color:rgba(var(--ink),.92)}
/* Day divider: a left-aligned label on a hairline, not a centred chip. */
body[data-mobile-mode="app"] #page-dm .dmx-day{
  display:flex;align-items:center;gap:10px;margin:14px 0 8px;padding:0 16px;position:relative
}
body[data-mobile-mode="app"] #page-dm .dmx-day::after{content:'';flex:1;height:1px;background:rgba(var(--line),.10)}
body[data-mobile-mode="app"] #page-dm .dmx-day span{
  font-size:14px;font-weight:800;color:var(--ink-solid);background:none;border:0;padding:0
}

/* ── DM composer: a single rounded field with the actions INSIDE it, Slack-style. */
body[data-mobile-mode="app"] #page-dm .dmx-cmt-bar{
  border-radius:22px;padding:6px 6px 6px 14px;gap:6px;align-items:center;
  background:rgba(var(--line),.05);border:1px solid rgba(var(--line),.12)
}
body[data-mobile-mode="app"] #page-dm .dmx-cmt-field{
  font-size:16px;                      /* <16px makes iOS zoom the page on focus */
  padding:8px 0;background:none;border:0
}
body[data-mobile-mode="app"] #page-dm .dmx-cmt-actions{gap:2px}
body[data-mobile-mode="app"] #page-dm .dmx-cmt-actions .cmt-btn{width:36px;height:36px}
/* Send only appears once there is something to send — until then the mic is the
   right-hand action, which is exactly how Slack's composer behaves. */
body[data-mobile-mode="app"] #page-dm .dmx-composer-wrap:not(.has-content) .dmx-send-split{display:none}
body[data-mobile-mode="app"] #page-dm .dmx-composer-wrap.has-content #dmVoiceBtn{display:none}
body[data-mobile-mode="app"] #page-dm .dmx-send-caret{display:none}   /* schedule-send lives on desktop */

/* ── Activity (notifications), Slack shape: filter pills + avatar/name/context/preview
   rows, instead of a flat list of one-line strings. */
body[data-mobile-mode="app"] .m-notif-filters{
  display:flex;gap:8px;padding:4px 16px 12px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none
}
body[data-mobile-mode="app"] .m-notif-filters::-webkit-scrollbar{display:none}
body[data-mobile-mode="app"] .m-notif-filter{
  flex:none;height:38px;padding:0 18px;border-radius:999px;cursor:pointer;
  border:1px solid rgba(var(--line),.14);background:none;color:rgba(var(--ink),.75);
  font:600 15px var(--sans);-webkit-tap-highlight-color:transparent
}
body[data-mobile-mode="app"] .m-notif-filter.is-on{
  background:color-mix(in srgb,var(--purple) 16%,transparent);
  border-color:transparent;color:var(--ink-solid)
}
body[data-mobile-mode="app"] .m-notif-row{
  display:flex;align-items:flex-start;gap:12px;width:100%;box-sizing:border-box;
  padding:13px 16px;border:0;border-bottom:1px solid rgba(var(--line),.07);
  background:none;text-align:left;-webkit-tap-highlight-color:transparent
}
body[data-mobile-mode="app"] .m-notif-row:active{background:rgba(var(--line),.05)}
body[data-mobile-mode="app"] .m-notif-av{
  flex:none;width:40px;height:40px;border-radius:10px;overflow:hidden;position:relative;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:700;color:#fff;background:var(--purple)
}
body[data-mobile-mode="app"] .m-notif-av img{width:100%;height:100%;object-fit:cover;display:block}
/* The type badge that overlaps the avatar's corner — how Slack tells a DM from a
   mention from a thread without a word of text. */
body[data-mobile-mode="app"] .m-notif-kind{
  position:absolute;right:-3px;bottom:-3px;width:18px;height:18px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:var(--bg);border:2px solid var(--bg);color:rgba(var(--ink),.65)
}
body[data-mobile-mode="app"] .m-notif-kind svg{width:11px;height:11px}
body[data-mobile-mode="app"] .m-notif-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
body[data-mobile-mode="app"] .m-notif-top{display:flex;align-items:baseline;gap:8px}
body[data-mobile-mode="app"] .m-notif-name{
  font-size:15px;font-weight:800;color:var(--ink-solid);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
body[data-mobile-mode="app"] .m-notif-time{font-size:13px;color:rgba(var(--ink),.45);flex:none}
body[data-mobile-mode="app"] .m-notif-ctx{font-size:13px;color:rgba(var(--ink),.5)}
body[data-mobile-mode="app"] .m-notif-prev{
  font-size:15px;line-height:1.4;color:rgba(var(--ink),.85);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden
}
body[data-mobile-mode="app"] .m-notif-row.unread .m-notif-name{color:var(--ink-solid)}
body[data-mobile-mode="app"] .m-notif-unread-dot{
  flex:none;width:9px;height:9px;border-radius:50%;background:var(--purple);margin-top:6px
}
body[data-mobile-mode="app"] .m-notif-empty{padding:44px 24px;text-align:center;color:rgba(var(--ink),.5);font-size:15px}
/* The shared .dmx-day rule centres the label between two rules and uppercases it;
   Slack's is a left-aligned sentence-case label with the hairline running out to the
   right. Kill the leading rule and the transform. */
body[data-mobile-mode="app"] #page-dm .dmx-day::before{display:none}
body[data-mobile-mode="app"] #page-dm .dmx-day span{text-transform:none}

/* ── Drawer: circles, and the profile pinned to the floor ──────────────────
   Henshu draws people and workspaces as CIRCLES everywhere else (the DM inbox,
   mentions, comments, the sidebar profile), so the drawer follows — including the
   DM thread, whose avatars had gone rounded-square chasing Slack's look. One shape
   for a face across the whole app beats matching another product. */
body[data-mobile-mode="app"] .m-drawer-item-icon,
body[data-mobile-mode="app"] .m-drawer-item-icon img,
body[data-mobile-mode="app"] .m-drawer-server-icon,
body[data-mobile-mode="app"] .m-drawer-server-icon img,
body[data-mobile-mode="app"] .m-drawer-profile-avatar,
body[data-mobile-mode="app"] .m-drawer-profile-avatar img{border-radius:50%}
body[data-mobile-mode="app"] #page-dm .cr-msg-avatar-slot .dmx-av,
body[data-mobile-mode="app"] #page-dm .cr-msg-avatar-slot img{border-radius:50%}
body[data-mobile-mode="app"] .m-notif-av,
body[data-mobile-mode="app"] .m-notif-av img{border-radius:50%}
/* Nav glyphs are square-ish line icons, not faces — the circle rule above must not
   reach them (the drawer reuses .m-drawer-item-icon for both). */
body[data-mobile-mode="app"] .m-drawer-item > svg{border-radius:0}

/* The profile is the drawer's FLOOR: it never scrolls with the nav and it spans the
   full width, so "you" is always in the same place no matter how long the project
   list gets. .m-drawer-nav is already flex:1, so this only needs to opt out of
   shrinking and grow a hairline above it. */
body[data-mobile-mode="app"] .m-drawer-profile{
  flex:none;margin:0;border-radius:0;border:0;
  border-top:1px solid rgba(var(--line),.10);
  padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));
  background:rgba(var(--line),.03)
}
body[data-mobile-mode="app"] .m-drawer-profile-avatar{width:36px;height:36px}

/* ── Workspace switcher lives behind the workspace itself ─────────────────── */
body[data-mobile-mode="app"] .m-drawer-server-block{
  display:flex;align-items:center;gap:12px;width:100%;box-sizing:border-box;
  border:0;background:none;text-align:left;cursor:pointer;
  -webkit-tap-highlight-color:transparent
}
body[data-mobile-mode="app"] .m-drawer-server-block:active{background:rgba(var(--line),.05)}
body[data-mobile-mode="app"] .m-drawer-server-meta{flex:1;min-width:0;padding-top:0}
.m-drawer-ws-chev{
  width:17px;height:17px;flex:none;color:rgba(var(--ink),.5);
  transition:transform .2s var(--m-hotbar-slide-ease,ease)
}
.m-drawer[data-ws-switch="open"] .m-drawer-ws-chev{transform:rotate(180deg)}
/* Collapsed until the workspace is tapped. */
.m-drawer-ws-group{display:none;flex-direction:column;gap:2px}
.m-drawer[data-ws-switch="open"] .m-drawer-ws-group{display:flex}

/* ── @mentioning a file or a folder reads like @mentioning a person ────────────────────
   The base .mention/.mention-chip rule is already an inline-flex row with a 6px gap and a
   fixed chip height, so a file/folder chip only needs its lead glyph and its label to sit
   in that row the way a person's avatar and name do. */
/* Unresolved chips shouldn't flash their placeholder: hold the row, stay quiet, and let
   the batched hydration swap the real name in a moment later. */
.mention-file.is-loading{opacity:.55}
.mention-file.is-loading .mention-chip-label{min-width:34px}

/* ── Card modal: one vertical rhythm, one inset ───────────────────────────────
   The blocks down the card had grown apart: gaps of 10px (title→status), 2px
   (status→tabs) and 32px (tabs→description) against the sections' 20px, so the
   card read as four unrelated bands rather than one column. And three different
   text left-edges — title 140.5, status pill 138.5, section labels 125.5.

   Two variables drive it now. --cm-gap is the single step between every top-level
   block. --cm-inset is the internal padding of anything that renders as a BOX on
   the content column (the editable title, the status control, the description
   editor); those boxes align their OUTER edge to the column, so sharing one inset
   is what makes their text line up with each other. Section labels stay flush to
   the column edge — a label and a control are different roles and shouldn't
   pretend otherwise.

   Declared last so it beats the earlier per-element rules (several of which were
   already overriding each other further down the file). */
.card-modal{--cm-gap:20px;--cm-inset:12px}
.card-modal-title{margin-bottom:var(--cm-gap);padding:6px var(--cm-inset)}
/* The title and status sit in an unnamed wrapper that carried its own 16px. The
   status is that wrapper's last child, so its margin only padded the wrapper from
   the inside — the gap to the tabs belongs to the wrapper, and now to the tabs. */
.card-modal-meta{margin-bottom:0}
/* The title/status wrapper. It used to carry an inline margin-bottom:16px, which
   no stylesheet rule could beat — that has moved here so the rhythm is in one place. */
.card-modal-headrow{margin-bottom:0}
/* top:auto neutralises the tab strip's `top:-32px`. That offset was written for
   `position:sticky`, but the element also carries .m-pillbar, whose
   `position:relative` is declared later at equal specificity and wins — so the
   strip has never actually stuck, and the -32px was only ever shifting it up 32px
   and knocking a hole in the spacing below it. Its padding-top carries the gap
   above the pills (and the background band, if sticky is ever restored). */
.card-modal-tabs{margin-top:0;margin-bottom:var(--cm-gap);padding-top:var(--cm-gap);padding-bottom:0;top:auto}
.card-modal-section{margin-bottom:var(--cm-gap)}
.card-modal-section:last-child{margin-bottom:0}
/* Same inset for the control sitting on the column beneath the title. */
#cardModalCol .ms-dropdown-trigger{padding-left:var(--cm-inset);padding-right:var(--cm-inset)}

/* ── Card modal: one text size ────────────────────────────────────────────────
   The card carried nine distinct sizes — 22 / 16 / 14 / 13.33 / 13 / 12 / 11 / 10 / 9.
   Property VALUES rendered at 11px next to 13px labels, controls at 12, tab labels
   at 14, and several buttons at the browser's default 13.333 because nothing set
   them. Everything that is CONTENT now reads at one size.

   Two deliberate exceptions, because they are different roles rather than the same
   role at a different size:
     • .card-modal-title — the task's name, the one thing meant to dominate
     • .card-modal-section-title — the uppercase DESCRIPTION / SUBTASKS / PROPERTIES
       eyebrows, which are section markers, not content

   Scoped to .card-modal on purpose: .group-inline-edit and .ms-dropdown also render
   in the List view, and that view's density is not this one's to change. */
.card-modal{--cm-text:13px}
.card-modal .group-inline-edit,
.card-modal .card-prop-value input,
.card-modal .card-prop-value select,
.card-modal .card-prop-value textarea,
.card-modal .ms-dropdown-trigger,
.card-modal .ms-dropdown-trigger-label,
.card-modal .due-date-btn,
.card-modal .hd-date-btn-text,
.card-modal .prop-pill,
.card-modal .prop-pill-add,
.card-modal .subtask-inline-status,
.card-modal .subtask-inline-val,
.card-modal .subtask-inline-due,
.card-modal .subtask-inline-add,
.card-modal .subtask-expand-desc,
.card-modal .card-modal-tab,
.card-modal .card-modal-iconbtn,
.card-modal .card-modal-share,
.card-modal .card-modal-delete-btn,
.card-modal .cmt-btn,
.card-modal .cm-created{font-size:var(--cm-text)}


/* ── Card modal: no outlines on the input surfaces ────────────────────────────
   Status, description and the comment composer each carried a 1px hairline border.
   Their background fill already reads as "this is a field", so the border was a
   second, louder signal saying the same thing. Focus still gets a border so it is
   clear where the caret is. */
.card-modal #cardModalCol .ms-dropdown-trigger,
.card-modal .card-desc-editor-wrap,
.card-modal #cardModalCommentInput{border-color:transparent}
.card-modal .card-desc-editor-wrap:focus-within,
.card-modal #cardModalCommentInput:focus{border-color:var(--hairline,rgba(255,255,255,.18))}


/* ── Inline rename: no jump ───────────────────────────────────────────────────
   Both rename affordances swap a text node for an <input>. If that input carries a
   different size or padding, the label visibly jumps and resizes the instant you
   click Rename. These match what they replace, so only a caret appears. */
.card-modal .prop-rename-input{
  flex:1;min-width:0;width:100%;box-sizing:border-box;
  font-family:var(--sans);font-size:var(--cm-text,13px);line-height:inherit;
  color:var(--cream);background:rgba(255,255,255,.06);
  border:1px solid var(--hairline,rgba(255,255,255,.18));border-radius:6px;
  /* -6 = 5px padding + 1px border, so the text sits exactly where it did and only
     the input's box appears around it. -5 left it a pixel out. */
  outline:none;padding:1px 5px;margin:-2px -6px}
.card-modal .subtask-rename-input{
  flex:0 0 auto;width:62px;min-width:0;box-sizing:border-box;
  font-family:var(--sans);font-size:var(--cm-text,13px);line-height:inherit;
  color:var(--cream);background:rgba(255,255,255,.06);
  border:1px solid var(--hairline,rgba(255,255,255,.18));border-radius:6px;
  /* -6 = 5px padding + 1px border, so the text sits exactly where it did and only
     the input's box appears around it. -5 left it a pixel out. */
  outline:none;padding:1px 5px;margin:-2px -6px}


/* A property label is a fixed 110px column. At the old 11px most names fitted; at
   13px longer ones wrapped to two and three lines and made the rows ragged. Keep the
   column fixed and ellipsis instead — the full name is in the title attribute and the
   rename input shows it in full. */
.card-modal .card-prop-label > span:not(.card-prop-icon){
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}


/* Drag-to-reorder feedback. The dragged row is moved live rather than shadowed by a
   drop indicator, so it only needs to read as "this is the one you are holding". */
.is-reordering{opacity:.45}
.card-modal [draggable="true"].card-prop-row,
.card-modal [draggable="true"].subtask-inline-row{cursor:grab}
.card-modal [draggable="true"].card-prop-row:active,
.card-modal [draggable="true"].subtask-inline-row:active{cursor:grabbing}


/* ── Destructive actions read red ─────────────────────────────────────────────
   The task's delete and the shift-to-reveal comment delete were both neutral white,
   which made the two most destructive controls on the card the least marked. */
.card-modal-delete-btn{color:var(--danger-text)!important;opacity:.55}
.card-modal-delete-btn:hover{color:var(--danger-text)!important;opacity:1;
  background:color-mix(in srgb,var(--danger-text) 12%,transparent)!important}
body.shift-held .hover-delete-btn{display:inline-flex!important;color:var(--danger-text)!important}
body.shift-held .hover-delete-btn:hover{
  background:color-mix(in srgb,var(--danger-text) 16%,transparent)!important;
  color:var(--danger-text)!important}

/* ── Drag-to-reorder: matches how a task drags on the board ───────────────────
   A ghost that tracks the cursor at the exact point it was grabbed, the source row
   dimmed in place, and a line showing where it will land. */
.row-reorder-ghost{
  position:fixed;z-index:10300;pointer-events:none;
  border-radius:8px;background:var(--dark,#141417);
  box-shadow:0 12px 32px rgba(0,0,0,.55);
  opacity:.95;will-change:transform}
.row-reorder-line{
  position:fixed;z-index:10299;pointer-events:none;height:2px;border-radius:2px;
  background:var(--coral,#7c5cff);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--coral,#7c5cff) 35%,transparent);
  /* Fades in on first appearance, then glides between slots. Both are transitions on
     compositor-friendly properties, so neither costs a layout pass mid-drag. */
  opacity:0;transition:opacity .12s ease,transform .12s cubic-bezier(.22,1,.36,1);
  will-change:transform,opacity}
.row-reorder-line.is-visible{opacity:1}
/* One cursor for the entire drag — it was changing over every element it crossed. */
body.is-row-dragging,body.is-row-dragging *{cursor:grabbing!important}
.is-reordering{opacity:.28}
.card-modal .card-prop-row,
.card-modal .subtask-inline-row{cursor:default}
.card-modal .card-prop-row.is-reorderable,
.card-modal .subtask-inline-row.is-reorderable{cursor:grab}
.card-modal .is-reordering{cursor:grabbing}


/* The subtask description's formatting bar. Same component as the task's, sitting
   directly on top of the field rather than in its own bordered strip. */
.subtask-desc-toolbar{
  border:0;background:transparent;padding:0 0 4px;margin:0;
  display:flex;flex-wrap:wrap;gap:2px}
.subtask-expand-descwrap:focus-within .subtask-expand-desc{
  border-color:var(--hairline,rgba(255,255,255,.18))}

/* ==================== ONE PROPERTY CONTAINER ====================
   Before this, every control type brought its own box: three background tints
   (.06 / .05 / .06), three radii (4 / 5 / 8px), three paddings, and all of them
   outlined. Eleven properties therefore drew eleven slightly different containers.

   One token set now draws all of them, and it goes DARKER than the modal rather than
   lighter — an inset well the value sits in, instead of a raised chip sitting on top.
   Outlines are gone: the fill alone marks the field, so the column reads as a stack of
   wells rather than a stack of boxes. Borders stay in the box model as `transparent`
   so the 26px control height (and the row rhythm built on it) is unchanged.

   Appended at the end of the sheet deliberately: the older hover/focus rules around
   line 15500 set border-color at the same specificity, so source order is what makes
   these win without a pile of !important. */
/* Checkmark used as a MASK so the same tick can be recoloured and resized without
   redrawing it: the box tints the glyph via background-color, the mask cuts it out. */
:root{--cm-check-mask:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%223.2%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%2220%206%209%2017%204%2012%22%2F%3E%3C%2Fsvg%3E")}
/* The wells take the DESCRIPTION's fill, not a darker one. The description box is the
   biggest surface in the modal, so anything that reads as "a field" should sit on the
   same value — a second, darker tier just made the properties look like a different
   component. Kept as tokens so the two can never drift apart again. */
.card-modal{
  --cm-field-bg:rgba(255,255,255,.04);
  --cm-field-bg-focus:rgba(255,255,255,.075);
  --cm-field-radius:7px}
.card-modal .card-prop-value > input:not([type="checkbox"]),
.card-modal .card-prop-value > button,
.card-modal .card-prop-value > .cm-ctl-wrap,
.card-modal .card-prop-value > .ms-dropdown > .ms-dropdown-trigger{
  background:var(--cm-field-bg);
  border:1px solid transparent;
  border-radius:var(--cm-field-radius);
  box-shadow:none}
/* The wrapper is the container now, so its input must not paint a second one inside it. */
.card-modal .card-prop-value > .cm-ctl-wrap > input{
  background:none;border:none;border-radius:0;box-shadow:none;height:100%}
/* Focus deepens the well instead of drawing a ring — the outline is what we removed,
   so bringing one back on focus would undo the point. */
.card-modal .card-prop-value > input:not([type="checkbox"]):focus,
.card-modal .card-prop-value > button:focus,
.card-modal .card-prop-value > button.gv-edit-open,
.card-modal .card-prop-value > .cm-ctl-wrap:focus-within,
.card-modal .card-prop-value > .ms-dropdown > .ms-dropdown-trigger:focus,
.card-modal .card-prop-value > .ms-dropdown > .ms-dropdown-trigger:hover,
.card-modal .card-prop-value > .ms-dropdown.open > .ms-dropdown-trigger{
  background:var(--cm-field-bg-focus);
  border-color:transparent;
  box-shadow:none;
  outline:none}
/* Person chips share the well's fill so an Owner row belongs to the same family as
   the boxed controls above it. Multi-select pills keep their per-option colours —
   those carry meaning, and flattening them would throw information away. */
.card-modal .card-prop-value .prop-person-pill{background:var(--cm-field-bg)}
.card-modal .card-prop-value input[type="checkbox"]{
  background:var(--cm-field-bg);border-color:transparent}
.card-modal .card-prop-value input[type="checkbox"]:checked{
  background:var(--green);border-color:var(--green)}

/* ---- Description preview: the real thing, just quiet -------------------------
   Mentions render as the chips they are everywhere else rather than flattened to
   text, but the whole cell is dimmed so it stays secondary to the subtask name it
   sits beside. The chips give up their own background here — at 11px on one line,
   a row of filled pills reads as clutter. */
.subtask-inline-desc{opacity:.55;line-height:20px;max-height:20px}
/* The chips keep their identity (the @name, bolder than the prose around it) but give
   up their box. A mention pill renders 22px with its own padding, which was 2px taller
   than every other cell and put person rows at 36px against everyone else's 34.
   !important because .mention.mention-person out-specifies a descendant selector. */
.subtask-inline-desc .mention,
.subtask-inline-desc .mention.mention-person,
.subtask-inline-desc .mention.mention-special{
  background:none!important;padding:0!important;border:none!important;
  height:auto!important;line-height:inherit!important;
  font-weight:600;color:var(--muted)}

/* ---- An open subtask takes over its row --------------------------------------
   With a panel open the row is that panel's header, not a row in a table, so the
   title gets the full width and is shown in full rather than ellipsised.
   The column headers stay put: they still describe the rows that are NOT open, and
   dropping them out shifted the whole section every time a subtask was clicked. */
.subtask-inline-row.is-expanded .subtask-inline-vals{opacity:0;display:none}
/* One line, always. Wrapping was an attempt to show a long name in full, but it made
   an opened subtask reflow into two or three lines and shove the panel down — the row
   stopped looking like a row. With the value strip hidden the title already has the
   whole width, so almost everything fits; what does not, ellipsises like anywhere else. */
.subtask-inline-row.is-expanded .subtask-inline-title{
  flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The row grows with a wrapped title instead of clipping it.

   align-items stays CENTER and the padding stays 7px, matching a collapsed row exactly.
   An earlier version used flex-start + 8px so a wrapped title would sit correctly, but
   a subtask title is one line almost every time — and in that case those two changes
   moved the title 1.3px up and grew the row 34px to 37 the instant you opened it, so
   the name visibly jumped. height:auto still lets a genuinely wrapped title grow the
   row; centring just means it grows evenly around the middle instead of downward. */
.subtask-inline-row.is-expanded{height:auto;min-height:34px;overflow:visible}

/* ---- No page-level horizontal scroll ----------------------------------------
   #globalRightSidebar hides itself with transform:translateX(100%), and a transform
   still contributes to scrollable overflow — so the closed panel sat 332px past the
   right edge and the whole document scrolled out into empty space. Its containing
   block is the viewport (nothing above it is positioned), so no ancestor's overflow
   could clip it.

   `clip` rather than `hidden`: hidden would turn the root into a scroll container,
   which breaks position:sticky inside and hands scrolling to the wrong element. clip
   just cuts the overflow off. The board's own horizontal scroll is unaffected — that
   is an inner container with its own overflow-x:auto. */
html,body{overflow-x:clip}
/* Clipping the ROOT is not enough on its own: nothing above #globalRightSidebar is
   positioned, so its containing block is the viewport and it escapes every ancestor's
   overflow. Making #app positioned brings the panel inside #app's box, where the clip
   actually reaches it. #app already spans the viewport, so `right:0` resolves to the
   same place it did before and the slide-in animation is untouched. */
#app{position:relative;overflow-x:clip}

/* ---- Person chips carry their own person's colour ----------------------------
   --pp-hue is the SAME hue henshuAvatarColor() paints the avatar with, handed to the
   chip inline, so a pill and the face inside it can never drift apart. The fill is the
   avatar colour heavily lightened (16% alpha) rather than the colour itself: at full
   strength four assignees turned a property row into a paint chart, and the names
   stopped being readable. Falls back to the neutral field fill when no hue is set, so
   any chip this misses still looks deliberate.

   No rim: the tint alone marks the chip, matching the outline-free property
   containers. A ring here was the one outline left in the section. */
.card-modal .card-prop-value .prop-person-pill,
.subtask-inline-cell .prop-person-pill{
  background:hsla(var(--pp-hue,0),52%,50%,.16);
  box-shadow:none;border:none;
  color:var(--cream)}
.prop-person-pill:not([style*="--pp-hue"]){background:var(--cm-field-bg)}
/* A rendered person chip now brings its own tinted pill, so the generic value wrapper
   must not paint a second, differently-coloured one around it. */
.subtask-inline-cell .subtask-inline-val:has(.prop-person-pill){
  background:none;padding:0}
.subtask-inline-cell .prop-person-pill{
  padding:2px 8px 2px 2px;gap:5px;font-size:11px;border-radius:999px;
  display:inline-flex;align-items:center;max-width:100%;overflow:hidden}
.subtask-inline-cell .prop-person-pill > span:last-child{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---- @mentions carry their person's colour too -------------------------------
   Same --pp-hue the avatar and the property chips use, so one person is ONE colour
   everywhere they appear — assigned on a task, and mentioned in a comment or a
   description. They were all a single purple, which made four different people look
   like four instances of the same thing.

   !important is unavoidable here: the dark-theme rule near line 12816 pins the purple
   with !important of its own, and only !important can answer that. The :not() guard
   keeps the old purple for any mention that never got a hue (an unresolved name in
   older stored text), so nothing falls back to an untinted transparent chip. */
.mention-person[style*="--pp-hue"],
.mention-chip[data-type="person"][style*="--pp-hue"]{
  background:hsla(var(--pp-hue),52%,50%,.18)!important;
  color:var(--cream)!important;
  border:none!important}
.mention-person[style*="--pp-hue"]:hover,
.mention-chip[data-type="person"][style*="--pp-hue"]:hover{
  background:hsla(var(--pp-hue),52%,50%,.3)!important}
/* The row preview stays flat — see the .subtask-inline-desc block above. Repeating the
   guard here because the rules above are !important and would otherwise re-paint the
   pill the preview deliberately strips. */
.subtask-inline-desc .mention-person[style*="--pp-hue"]{
  background:none!important;color:var(--muted)!important}

/* ---- Project + task mentions carry their own colour ---------------------------
   --mn-color is a real colour rather than a hue, because unlike people these have one
   assigned: a project's iconColor (the colour its sidebar row is painted with) and a
   task's column colour (the colour its own status dot already shows). color-mix keeps
   one declaration working for hex, rgb or a var.

   The [style*="--mn-color"] guard means a project with no colour set, or a task in an
   uncoloured column, keeps its existing look instead of falling through to a
   transparent chip. */
.mention-project[style*="--mn-color"],
.mention-task[style*="--mn-color"],
.mention-chip[data-type="project"][style*="--mn-color"],
.mention-chip[data-type="task"][style*="--mn-color"]{
  background:color-mix(in srgb,var(--mn-color) 18%,transparent)!important;
  color:var(--cream)!important;
  border:none!important}
.mention-project[style*="--mn-color"]:hover,
.mention-task[style*="--mn-color"]:hover,
.mention-chip[data-type="project"][style*="--mn-color"]:hover,
.mention-chip[data-type="task"][style*="--mn-color"]:hover{
  background:color-mix(in srgb,var(--mn-color) 30%,transparent)!important}
/* The status dot on a task chip is the chip's own colour at full strength — the tint
   behind it is the same colour, so the dot has to stay saturated to read against it. */
.mention-task[style*="--mn-color"] .mention-chip-status,
.mention-chip[data-type="task"][style*="--mn-color"] .mention-chip-status{
  background:var(--mn-color)!important}
/* A project's icon keeps its own colour; only its container is tinted. */
.mention-project img,.mention-chip[data-type="project"] img{
  width:13px;height:13px;object-fit:cover;border-radius:3px;vertical-align:middle}
/* Row previews stay flat, same as person chips. */
.subtask-inline-desc .mention-project[style*="--mn-color"],
.subtask-inline-desc .mention-task[style*="--mn-color"]{
  background:none!important;color:var(--muted)!important}

/* ---- No ring around a standalone avatar --------------------------------------
   .card-avatar carries border:2px solid var(--dark), which reads as a black outline
   on every single avatar — in a mention chip, a person property chip, a subtask cell.

   It is NOT purely decorative though: .card-avatar+.card-avatar{margin-left:-6px}
   stacks avatars into overlapping groups, and there the ring is what separates one
   face from the one beneath it. So the ring is dropped by default and put back only
   where avatars actually overlap — the second onwards in a stack, plus anything inside
   an explicit .card-avatars group. A lone avatar has nothing to be separated from. */
.card-avatar{border:none}
.card-avatars .card-avatar,
.card-avatar + .card-avatar{border:2px solid var(--dark)}

/* A project with no iconColor set has no colour to match, so its chip stays neutral —
   the same treatment its sidebar row gets, where the icon draws in plain currentColor.
   Overrides the legacy purple so an uncoloured project reads as uncoloured rather than
   as "some other colour". Set an icon colour on the project and the rule above
   ([style*="--mn-color"]) takes over. */
.mention-project:not([style*="--mn-color"]),
.mention-chip[data-type="project"]:not([style*="--mn-color"]){
  background:rgba(255,255,255,.07)!important;
  color:var(--cream)!important;
  border:none!important}
.mention-project:not([style*="--mn-color"]):hover,
.mention-chip[data-type="project"]:not([style*="--mn-color"]):hover{
  background:rgba(255,255,255,.12)!important}

/* ==================== DOCK MAGNIFY ON DROPDOWN HOVER ====================
   Generalised from .sd-ws-row in the workspace switcher: the hovered row's CONTENT
   scales up, and the rows immediately above and below scale a little too, the way a
   macOS dock swells around the cursor.

   The two things that make it work, both inherited from the original:
   - It scales an inner wrapper, never the row itself. Scaling the row would scale its
     hover background and padding with it, so highlights would grow past the menu edge
     and overlap their neighbours.
   - transform-origin:left center, so text grows rightward from a fixed left edge
     instead of drifting sideways under the cursor.
   Trailing elements (a checkmark, an arrow) sit OUTSIDE the wrapper and stay pinned. */
.dd-hop-row{
  flex:1;min-width:0;display:inline-flex;align-items:center;gap:8px;
  transform-origin:left center;
  transition:transform .16s cubic-bezier(.2,.6,.3,1)}
.ms-dropdown-item:hover > .dd-hop-row,
.prop-type-item:hover > .dd-hop-row,
.server-dropdown-item:hover > .dd-hop-row,
.prop-ctx-menu button:hover > .dd-hop-row{transform:scale(1.08)}
/* The neighbour falloff — the part that reads as a dock rather than a plain hover.
   For the single-column menus, the neighbour is simply the adjacent sibling. */
.ms-dropdown-item:hover + .ms-dropdown-item > .dd-hop-row,
.ms-dropdown-item:has(+ .ms-dropdown-item:hover) > .dd-hop-row,
.server-dropdown-item:hover + .server-dropdown-item > .dd-hop-row,
.server-dropdown-item:has(+ .server-dropdown-item:hover) > .dd-hop-row,
.prop-ctx-menu button:hover + button > .dd-hop-row,
.prop-ctx-menu button:has(+ button:hover) > .dd-hop-row{transform:scale(1.03)}
/* The property picker is a TWO-COLUMN grid (.prop-type-picker-grid, 150px 150px, filled
   row-major), so the adjacent sibling is the item ACROSS, not the one below: hovering
   Text was magnifying Select. A dock magnifies along its own axis, so the falloff has to
   step by a full row — two siblings — to reach the item under the cursor's column.
   Tied to the 2-column template above; a third column would need +3. */
.prop-type-item:hover + .prop-type-item + .prop-type-item > .dd-hop-row,
.prop-type-item:has(+ .prop-type-item + .prop-type-item:hover) > .dd-hop-row{transform:scale(1.03)}
/* The picker's icon column is fixed-width, so let the wrapper keep the row's own gap
   rather than adding a second one on top of it. */
.prop-type-item > .dd-hop-row{gap:8px}
@media (prefers-reduced-motion:reduce){
  .dd-hop-row{transition:none}
  .ms-dropdown-item:hover > .dd-hop-row,
  .prop-type-item:hover > .dd-hop-row,
  .server-dropdown-item:hover > .dd-hop-row,
  .ms-dropdown-item:hover + .ms-dropdown-item > .dd-hop-row,
  .prop-type-item:hover + .prop-type-item + .prop-type-item > .dd-hop-row,
  .server-dropdown-item:hover + .server-dropdown-item > .dd-hop-row{transform:none}
}


/* ---- Fade the column values in and out with the panel ------------------------
   Opening a subtask hides its value strip so the title can take the row. That was a
   hard display:none — the values vanished between one frame and the next while the
   panel below them animated open, so the two halves of the same interaction moved at
   different speeds.

   display cannot be transitioned on its own, hence `allow-discrete`: the display flip
   is held back until the opacity transition finishes when hiding, and applied straight
   away when showing. @starting-style supplies the opacity:0 the strip starts from on
   the way back in — without it the element leaves display:none already at opacity:1
   and there is nothing to animate, so the fade only ever worked one way.

   The row itself keeps no transition: its height must not animate, or the panel below
   would slide while the row above it resized. Only the strip fades. */
.subtask-inline-vals{
  opacity:1;
  transition:opacity .16s ease, display .16s allow-discrete}
@starting-style{
  .subtask-inline-row:not(.is-expanded) .subtask-inline-vals{opacity:0}
}
/* Asymmetric on purpose, and in this direction: the strip leaves in 130ms so it is out
   of the way before the panel below finishes opening, and returns over 160ms so the
   values ease back rather than snapping in the moment the panel closes. */
.subtask-inline-row.is-expanded .subtask-inline-vals{
  transition:opacity .13s ease, display .13s allow-discrete}
@media (prefers-reduced-motion:reduce){
  .subtask-inline-vals{transition:none}
}


/* ---- (3) Checkbox reads light again ------------------------------------------
   The unified dark field fill turned this into a black square, which read as a hole
   rather than a control — a checkbox is the one input whose empty state has to look
   fillable. Light box, dark tick, green when checked. */
.card-modal .card-prop-value input[type="checkbox"]{
  background:rgba(255,255,255,.88);
  border:1px solid rgba(255,255,255,.28)}
.card-modal .card-prop-value input[type="checkbox"]:hover{
  background:#fff;border-color:rgba(255,255,255,.5)}
.card-modal .card-prop-value input[type="checkbox"]::before{background:var(--bg-main)}
.card-modal .card-prop-value input[type="checkbox"]:checked{
  background:var(--green);border-color:var(--green)}

/* ---- Checkbox: a square that always shows its tick ---------------------------
   Empty state used to be a blank white box, which reads as "nothing here" rather than
   "this is checkable". The tick is drawn at all times — muted on the unfilled square,
   then the square goes green and the tick grows when it is actually checked, so the
   change of state is a change of WEIGHT and not just of colour (which is the part that
   survives being glanced at, and the part colour-blind users still get). */
.card-modal .card-prop-value input[type="checkbox"]{
  background:var(--cm-field-bg);
  border:1px solid var(--border-d);
  position:relative}
.card-modal .card-prop-value input[type="checkbox"]:hover{
  background:var(--cm-field-bg-focus);border-color:var(--muted)}
/* The tick is a stroked SVG-ish mask rather than the old clip-path polygon: clip-path
   scaled the SHAPE and the stroke with it, so a "bigger" tick also got fatter and
   blurred. A mask keeps the stroke crisp at both sizes. */
.card-modal .card-prop-value input[type="checkbox"]::before{
  content:"";position:absolute;left:50%;top:50%;
  width:12px;height:12px;margin:-6px 0 0 -6px;
  transform:scale(.82);
  background:var(--muted);
  clip-path:none;
  -webkit-mask:var(--cm-check-mask) center/contain no-repeat;
  mask:var(--cm-check-mask) center/contain no-repeat;
  transition:transform .16s cubic-bezier(.22,1,.36,1),background .12s}
.card-modal .card-prop-value input[type="checkbox"]:checked{
  background:var(--green);border-color:var(--green)}
.card-modal .card-prop-value input[type="checkbox"]:checked::before{
  transform:scale(1.18);background:var(--bg-main)}
/* The same object in the list/table cell, so a row and its task modal agree. */
.cm-check-cell{display:inline-grid;place-content:center;width:18px;height:18px;
  border-radius:5px;background:var(--cm-field-bg,rgba(255,255,255,.04));
  border:1px solid var(--border-d);position:relative;vertical-align:middle}
.cm-check-cell::before{content:"";position:absolute;left:50%;top:50%;
  width:12px;height:12px;margin:-6px 0 0 -6px;transform:scale(.82);
  background:var(--muted);
  -webkit-mask:var(--cm-check-mask) center/contain no-repeat;
  mask:var(--cm-check-mask) center/contain no-repeat}
.cm-check-cell.is-on{background:var(--green);border-color:var(--green)}
.cm-check-cell.is-on::before{transform:scale(1.18);background:var(--bg-main)}

/* ---- (5) The subtask status chip is a control -------------------------------- */
.subtask-inline-status.is-editable{cursor:pointer;border-radius:6px;padding:2px 6px;
  margin:-2px -6px;transition:background .12s}
.subtask-inline-status.is-editable:hover{background:rgba(255,255,255,.07)}
.subtask-inline-status.is-editable:focus-visible{outline:2px solid var(--coral);outline-offset:1px}
/* The dot in the status picker matches the 8px dot every other dropdown now uses. */
.prop-ctx-menu .stm-dot{display:inline-block;width:8px;height:8px;border-radius:50%;
  flex-shrink:0;margin-right:8px}
.prop-ctx-menu button.is-current{color:var(--cream);background:rgba(255,255,255,.06)}


/* The status picker is a .prop-ctx-menu, so its rows need the wrapper laid out like a
   menu row rather than inheriting the button's own flex. */
.prop-ctx-menu button > .dd-hop-row{display:inline-flex;align-items:center;gap:0;
  flex:1;min-width:0}
/* An emote is a character, not an attachment: never let the pasted-image affordances
   (selection ring, resize handles) attach to one. The JS refuses to select them; this
   stops the browser drawing its own drag/select chrome over them too. */
/* user-select:none here was the bug behind "you can't select in between the emotes" —
   it took the images out of text selection entirely, so a drag across a run of them
   selected nothing. They select like the characters they are; they just cannot be
   dragged out as images. */
.card-modal-description img.inline-emote,
.subtask-expand-desc img.inline-emote,
.inline-emote{-webkit-user-drag:none;user-select:auto;cursor:text}
.card-modal-description img.inline-emote.selected,
.card-modal-description .card-desc-img-resize-wrap:has(> img.inline-emote) .card-desc-img-resize-handle{display:none}

/* The row's description preview is a summary of the subtask, and the whole row opens
   that subtask. Clicks must reach the row rather than the chips inside the summary —
   otherwise clicking a name opened that person's profile instead of the subtask. The
   handlers are stripped in _subtaskDescPreviewHtml too; this makes it structural. */
.subtask-inline-desc{pointer-events:none}
.subtask-inline-desc *{pointer-events:none;cursor:inherit}


/* ---- File and folder mention chips ------------------------------------------
   There were per-type rules for bot, person, task, journal, page, special and drive —
   and none at all for file or folder. So those chips inherited no container and no
   colour and rendered as bare bold text in the middle of a line of proper chips.
   Same neutral treatment a project with no colour gets, so the two read as siblings. */
.mention-chip[data-type="file"],
.mention-chip[data-type="folder"],
.mention.mention-file,
.mention.mention-folder{
  background:rgba(255,255,255,.07);
  color:var(--cream);
  border:none}
.mention-chip[data-type="file"]:hover,
.mention-chip[data-type="folder"]:hover{background:rgba(255,255,255,.12)}
.mention-input .mention-chip[data-type="file"],
.mention-input .mention-chip[data-type="folder"]{
  background:rgba(255,255,255,.07);color:var(--cream)}
/* The glyph sits with the name rather than crowding it. */
.mention-chip[data-type="file"] svg,
.mention-chip[data-type="folder"] svg{margin-right:4px;opacity:.7;flex:none}

/* Search-and-create at the TOP of a Select menu — the same shape and position the
   multi-select picker uses, so the two menus are one pattern rather than two. */
.ms-dropdown-search{padding:8px 8px 6px;border-bottom:1px solid var(--border-d);margin-bottom:4px}
.ms-dropdown-search-input{width:100%;background:rgba(255,255,255,.05);border:1px solid transparent;
  border-radius:6px;color:var(--cream);font-family:var(--sans);font-size:12px;padding:6px 9px;outline:none}
.ms-dropdown-search-input::placeholder{color:var(--muted)}
.ms-dropdown-search-input:focus{background:rgba(255,255,255,.09)}
.ms-dropdown-createrow{cursor:pointer}
.ms-dropdown-createrow .ms-dropdown-item-label{color:var(--coral)}
.ms-create-dot{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0;
  background:rgba(255,255,255,.15);margin-right:8px}

/* ---- Emoji button: faces on hover -------------------------------------------
   The face sits ON TOP of the button's own smiley, which fades out rather than being
   replaced — so leaving the button restores the real icon exactly, and the button never
   changes size as the glyphs swap (different emoji have different metrics). */
/* The icon is swapped IN PLACE inside the button's own <svg>, so it keeps the button's
   stroke weight, colour and size — the drawing changes, nothing else does. A short
   pop on each swap makes it feel deliberate rather than like a flicker. */
#cardCommentEmojiBtn,[data-emoji-hover]{position:relative}
#cardCommentEmojiBtn svg.is-swapping,[data-emoji-hover] svg.is-swapping{animation:emojiIconSwap .24s ease both}
@keyframes emojiIconSwap{
  0%{opacity:.25;transform:scale(.82) rotate(-8deg)}
  60%{opacity:1;transform:scale(1.06) rotate(2deg)}
  100%{opacity:1;transform:scale(1) rotate(0)}}
@media (prefers-reduced-motion:reduce){
  #cardCommentEmojiBtn svg.is-swapping,[data-emoji-hover] svg.is-swapping{animation:none}
}

/* ---- Mention preview popout --------------------------------------------------
   Deliberately smaller than the person profile card: a project or a task has far less
   to say about itself, and a card padded out to the same size would be mostly empty. */
/* Liquid glass — the same recipe .liquid-glass, .mention-popup and the multi-select
   dropdowns use, rather than a flat panel that happens to sit near them. */
.mention-popout{position:fixed;z-index:10002;min-width:200px;max-width:280px;
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border);border-radius:14px;
  box-shadow:var(--lg-shadow);padding:12px;font-family:var(--sans)}
.mention-popout .mp-head{display:flex;align-items:center;gap:8px;min-width:0}
.mention-popout .mp-ico{display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;flex:none;color:var(--cream);opacity:.85}
.mention-popout .mp-ico svg{width:16px;height:16px;border-radius:0}
.mention-popout .mp-ico img{width:18px;height:18px;object-fit:contain;border-radius:4px}
.mention-popout .mp-title{font-size:13px;font-weight:600;color:var(--cream);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
/* Detail rows: label left, value right. A key/value list rather than one run-on line,
   because the whole point is being able to find one fact at a glance. */
.mention-popout .mp-rows{margin:9px 0 11px;display:flex;flex-direction:column;gap:5px}
.mention-popout .mp-row{display:flex;align-items:baseline;gap:10px;font-size:11px;min-width:0}
.mention-popout .mp-k{color:var(--muted);flex:none;min-width:62px}
.mention-popout .mp-v{color:var(--cream);flex:1;min-width:0;text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The header carries the thing's own colour where it has one, so the card is visibly
   about THAT project or task rather than being a generic panel. */
.mention-popout .mp-head{border-bottom:1px solid var(--lg-border);padding-bottom:9px}
.mention-popout[style*="--mn-color"] .mp-ico{color:var(--mn-color)}
.mention-popout .mp-go{width:100%;padding:7px 10px;border:none;border-radius:7px;
  background:rgba(255,255,255,.07);color:var(--cream);font-family:var(--sans);font-size:12px;
  font-weight:600;cursor:pointer;transition:background .12s}
.mention-popout .mp-go:hover{background:rgba(255,255,255,.13)}
/* A chip is now a control everywhere it appears — except in the row preview, which stays
   click-through so the click reaches the subtask row underneath. */
.mention-project,.mention-task,.mention-file,.mention-folder,
.mention-chip[data-type="project"],.mention-chip[data-type="task"],
.mention-chip[data-type="file"],.mention-chip[data-type="folder"]{cursor:pointer}
.subtask-inline-desc .mention-project,.subtask-inline-desc .mention-task,
.subtask-inline-desc .mention-file,.subtask-inline-desc .mention-folder{cursor:inherit}

/* ---- Option colour picker ----------------------------------------------------
   Reached two ways, because there are two places you think about an option's colour:
   the dot in the dropdown (while browsing options) and the pill itself (once it is on
   the card). Both open the same swatch grid. */
.opt-color-picker{position:fixed;z-index:10003;
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border);border-radius:14px;box-shadow:var(--lg-shadow);
  padding:10px;font-family:var(--sans)}
.opt-color-picker .ocp-title{font-size:9px;font-weight:700;letter-spacing:1px;
  text-transform:uppercase;color:var(--muted);margin-bottom:8px}
.opt-color-picker .ocp-grid{display:grid;grid-template-columns:repeat(5,20px);gap:7px}
.opt-color-picker .ocp-swatch{width:20px;height:20px;border-radius:50%;border:2px solid transparent;
  cursor:pointer;padding:0;transition:transform .12s,border-color .12s}
.opt-color-picker .ocp-swatch:hover{transform:scale(1.15)}
.opt-color-picker .ocp-swatch.is-current{border-color:var(--cream)}
/* "No colour" reads as an empty slot rather than as another colour to choose. */
.opt-color-picker .ocp-none{background:transparent;
  box-shadow:inset 0 0 0 1px var(--border-d);position:relative}
.opt-color-picker .ocp-none::after{content:"";position:absolute;left:50%;top:2px;bottom:2px;width:1px;
  background:var(--muted);transform:rotate(45deg);transform-origin:center}
/* The dot in a dropdown row is a control now, so it needs to look like one on hover. */
.multiselect-dropdown-item .msd-dot-btn{border:none;padding:0;cursor:pointer;
  transition:transform .12s,box-shadow .12s}
.multiselect-dropdown-item .msd-dot-btn:hover{transform:scale(1.3);
  box-shadow:0 0 0 2px rgba(255,255,255,.18)}
.prop-pill.is-recolorable{cursor:pointer}


/* The rest of the task modal's menus join the same glass family, so a dropdown does not
   change material depending on which control opened it. */
.prop-ctx-menu,.prop-type-picker,.prop-person-dropdown,.multiselect-dropdown{
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base)!important;
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border)!important;
  box-shadow:var(--lg-shadow)!important;
  border-radius:14px}
.ms-dropdown-menu{
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border);box-shadow:var(--lg-shadow);border-radius:12px}

/* ---- Per-option ⋮ ------------------------------------------------------------
   Hidden until the row is hovered, like the ⋮ on property and subtask rows. visibility
   rather than display so the slot stays reserved and the label never shifts sideways
   when it appears. */
.opt-menu-btn{visibility:hidden;background:none;border:none;color:var(--muted);
  font-size:14px;line-height:1;cursor:pointer;padding:0 2px;margin-left:auto;
  flex-shrink:0;opacity:.55;transition:opacity .1s,color .1s}
.multiselect-dropdown-item:hover .opt-menu-btn,
.ms-dropdown-item:hover .opt-menu-btn{visibility:visible}
.opt-menu-btn:hover{opacity:1;color:var(--cream)}
.multiselect-dropdown-item .msd-label{flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* On a SELECTED row the ⋮ takes the checkmark's place on hover — the tick has already
   told you it is selected, and the two sharing a slot keeps the row width fixed. */
.ms-dropdown-item .opt-menu-btn{position:absolute;right:12px;top:50%;transform:translateY(-50%)}
.ms-dropdown-item{position:relative}
.ms-dropdown-item:hover .ms-dropdown-item-check{opacity:0}
.multiselect-dropdown-item{position:relative;display:flex;align-items:center;gap:8px}


/* A person mention is clickable (it opens their profile), so it must say so. It was the
   one mention kind still showing a text cursor. */
.mention-person,.mention-chip[data-type="person"]{cursor:pointer}
.subtask-inline-desc .mention-person,
.subtask-inline-desc .mention-chip[data-type="person"]{cursor:inherit}

/* ---- Allowed roles: one row per role, three states -------------------------- */
.eim-role-name{font-size:12px;font-weight:600;color:var(--cream);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Three segments need a little more room than the old two, and No access reads as the
   quiet default rather than as a destructive choice. */
.eim-access-toggle.eim-access-3{flex:none;display:inline-flex;border-radius:7px;overflow:hidden}
.eim-access-toggle.eim-access-3 .eim-access-opt{padding:5px 10px;font-size:11px;white-space:nowrap}
.eim-access-toggle.eim-access-3 .eim-access-opt.is-none.active{color:var(--muted)}

/* ---- Mentions whose target is gone or binned ---------------------------------
   A mention is a live reference. When what it points at has been deleted or trashed it
   has to look different, or a dead link is indistinguishable from a working one until
   you click it and nothing happens. */
.mention-chip.is-trashed,.mention.is-trashed{opacity:.6;font-style:italic}
.mention-chip.is-trashed .mention-chip-label,.mention.is-trashed .mention-chip-label{
  text-decoration:line-through;text-decoration-thickness:1px;text-decoration-color:var(--muted)}
.mention-chip.is-missing,.mention.is-missing{opacity:.5;font-style:italic;
  background:rgba(255,255,255,.05)!important;color:var(--muted)!important;cursor:not-allowed}
.mention-chip.is-missing .mention-chip-label,.mention.is-missing .mention-chip-label{
  text-decoration:line-through;text-decoration-thickness:1px}

/* Edit Project description: the same toolbar the card description uses, sitting on top
   of the field rather than floating beside it. */
.eim-desc-toolbar{border-radius:8px 8px 0 0;margin-bottom:0}
.eim-desc-input{border-radius:0 0 8px 8px!important;padding:9px 10px;overflow-y:auto;
  max-height:180px;line-height:1.5;text-align:left}
.eim-desc-input:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}

/* ---- Edit Project: title reads like a task's -------------------------------- */
.eim-name-field > label{display:none}          /* the title IS the label */
.eim-name-row{display:flex;align-items:center;gap:10px}
/* Serif, 22px, borderless — the same treatment .card-modal-title gets, so a project's
   name and a task's name look like the same class of thing. Sized to sit level with the
   icon button rather than being a small field beside a large button. */
/* Specificity has to beat .roles-field input[type="text"] and .field-modal input, both
   of which are (0,2,1) and would otherwise keep this a 13px bordered field. */
.field-modal .eim-name-row input.eim-name-input{
  flex:1;min-width:0;width:auto;background:none;border:none;outline:none;box-shadow:none;
  font-family:var(--serif);font-size:22px;line-height:1.25;color:var(--off-white);
  padding:4px 4px;border-radius:6px;transition:background .12s;display:block}
.field-modal .eim-name-row input.eim-name-input:focus{
  background:rgba(255,255,255,.04);border:none;box-shadow:none;outline:none}
.field-modal .eim-name-row input.eim-name-input::placeholder{color:var(--muted)}
#editItemIconBtn.edit-item-icon-btn{width:34px;height:34px;flex:none}
#editItemIconBtn.edit-item-icon-btn svg,#editItemIconBtn.edit-item-icon-btn img{width:20px;height:20px}

/* ---- Description: no outline ------------------------------------------------ */
.eim-desc-toolbar{border:none!important;background:rgba(255,255,255,.03);border-radius:8px 8px 0 0}
.eim-desc-input{border:none!important;background:rgba(255,255,255,.04)!important;box-shadow:none!important}
.eim-desc-input:focus{background:rgba(255,255,255,.06)!important;outline:none!important}

/* ---- Specific people -------------------------------------------------------- */
.eim-add-person{margin-top:8px;background:none;border:1px dashed var(--border-d);
  border-radius:8px;color:var(--muted);font-family:var(--sans);font-size:11px;
  padding:6px 10px;cursor:pointer;transition:all .12s}
.eim-add-person:hover{border-color:var(--coral);color:var(--cream);background:rgba(255,255,255,.04)}
.eim-person-remove{background:none;border:none;color:var(--muted);cursor:pointer;
  font-size:14px;line-height:1;padding:0 2px;margin-left:6px;opacity:0;transition:opacity .1s}
.edit-item-role-row:hover .eim-person-remove{opacity:.6}
.eim-person-remove:hover{opacity:1;color:var(--danger-text)}

/* ---- Footer provenance, same as a task's ------------------------------------ */
.eim-footer{margin-top:16px;padding-top:14px;border-top:1px solid var(--border-d);
  display:flex;align-items:center;justify-content:space-between;gap:12px}

/* The name row is a heading, not a form field — so neither half of it wears a box. The
   icon keeps a hover affordance since it IS clickable (it opens the icon picker). */
.field-modal .eim-name-row #editItemIconBtn.edit-item-icon-btn{
  background:none;border:none;box-shadow:none;border-radius:8px;transition:background .12s}
.field-modal .eim-name-row #editItemIconBtn.edit-item-icon-btn:hover{
  background:rgba(255,255,255,.06)}

/* A locked option is visibly unavailable rather than absent — the row keeps the same
   three-segment shape as every other role, so the control reads consistently. */
.eim-access-opt.is-disabled{opacity:.3;cursor:not-allowed;pointer-events:auto}
.eim-access-opt.is-disabled:hover{background:none}

/* ---- Edit Project: task-modal padding and accent ---------------------------- */
/* Matches .card-modal's 32px and its border-takes-the-accent rule, so the two modals
   read as the same surface at the same scale. */
#editItemModal .field-modal{padding:32px;border-radius:14px;max-width:460px;
  border:1px solid var(--modal-col-color,var(--border-d))}

/* The person picker has to clear the modal overlay (z-index 10100) — at 10001 it opened
   BEHIND the modal, which is why clicking a name did nothing. */
.eim-person-picker{z-index:10200!important}

/* ---- Description: taller, with an advisory limit ---------------------------- */
.eim-desc-input{min-height:120px;max-height:260px}
/* Past the limit the text goes red but is NEVER truncated — losing what someone typed
   is worse than showing them they are over. */
.eim-over{color:var(--danger-text,#ff6b6b)}
.eim-desc-count{margin-top:6px;text-align:right;font-size:10px;color:var(--muted);
  font-variant-numeric:tabular-nums;transition:color .12s}
.eim-desc-count.is-over{color:var(--danger-text,#ff6b6b);font-weight:600}

/* ---- Access toggle: sliding thumb, same as the task tabs -------------------- */
#editItemModal .eim-access-toggle{position:relative}
#editItemModal .eim-access-toggle .m-pill-thumb{
  background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 22%,transparent);
  border:0;border-radius:6px;
  transition:transform var(--tab-slide-dur,.22s) var(--tab-slide-ease,cubic-bezier(.22,1,.36,1)),
             width var(--tab-slide-dur,.22s) var(--tab-slide-ease,cubic-bezier(.22,1,.36,1)),
             height var(--tab-slide-dur,.22s) var(--tab-slide-ease,cubic-bezier(.22,1,.36,1)),
             opacity .15s ease}
/* The thumb is the selection now, so the active segment stops painting its own. */
#editItemModal .eim-access-opt{position:relative;z-index:1;background:none!important}
#editItemModal .eim-access-opt.active{color:var(--cream)}

/* ---- Provenance: face + name, clickable ------------------------------------- */
.eim-created{display:inline-flex;align-items:center;gap:7px;background:none;border:none;
  padding:4px 6px;margin-left:-6px;border-radius:8px;cursor:pointer;
  font-family:var(--sans);transition:background .12s}
.eim-created:hover{background:rgba(255,255,255,.06)}
.eim-created:disabled{cursor:default}
.eim-created:disabled:hover{background:none}

/* ---- Access rows: one grid, so roles and people line up --------------------- */
/* Every row reserves the same four slots — glyph, name, toggle, tail — so a person row
   (which has an avatar and a remove button) sits on exactly the same columns as a role
   row (which has neither). They were drifting because each row sized itself. */
#editItemModal .edit-item-role-row{display:flex;align-items:center;gap:10px;padding:7px 0}
#editItemModal .eim-role-dot{width:16px;height:16px;flex:none;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center}
#editItemModal .eim-person-dot{background:none!important}
#editItemModal .eim-person-dot .card-avatar{width:16px!important;height:16px!important}
#editItemModal .eim-role-name{flex:1;min-width:0}
#editItemModal .eim-access-toggle{flex:none}
/* The tail slot exists on every row so the toggle's right edge never moves; only the
   person rows put anything in it. */
#editItemModal .eim-row-tail{width:18px;flex:none;display:inline-flex;justify-content:flex-end}
#editItemModal .eim-person-remove{margin-left:0}
/* @everyone reads as the bulk control it is: a hollow dot rather than a role colour. */
#editItemModal .eim-everyone-dot{background:none!important;
  box-shadow:inset 0 0 0 1.5px var(--muted);opacity:.8}
/* A real divider between "which roles" and "which people" — they are two different
   kinds of grant and were running together. */
.eim-people-sep{height:1px;background:var(--border-d);margin:10px 0 4px}

/* ---- Description: shorter now the limit is 100 ------------------------------ */
.eim-desc-input{min-height:76px;max-height:180px}

/* The accent fades rather than snapping when the colour changes, so picking a swatch
   reads as the modal responding rather than as a repaint. The thumbs inherit the same
   custom property, so border and selection move together. */
#editItemModal .field-modal{transition:border-color .35s ease}
#editItemModal .eim-access-toggle .m-pill-thumb{transition:transform var(--tab-slide-dur,.22s) var(--tab-slide-ease,cubic-bezier(.22,1,.36,1)),
  width var(--tab-slide-dur,.22s) var(--tab-slide-ease,cubic-bezier(.22,1,.36,1)),
  height var(--tab-slide-dur,.22s) var(--tab-slide-ease,cubic-bezier(.22,1,.36,1)),
  background-color .35s ease,opacity .15s ease}

/* ---- @everyone: the glyph is the @ ------------------------------------------ */
#editItemModal .eim-everyone-dot{background:none!important;box-shadow:none;
  color:var(--muted);font-family:var(--sans);font-size:13px;font-weight:700;
  line-height:1;opacity:.85}

/* ---- Even spacing across roles AND people ----------------------------------- */
/* Both lists share one row rhythm. They were drifting because the people list carried
   its own margin on top of the separator's, so the gap above the first person was
   larger than the gaps between roles. */
#editItemModal #editItemAccessRows,
#editItemModal #editItemPeopleRows{margin:0}
#editItemModal .edit-item-role-row{padding:8px 0;margin:0}
#editItemModal .edit-item-role-row + .edit-item-role-row{
  border-top:1px solid rgba(255,255,255,.045)}
/* The separator replaces a row border rather than adding to it, so the divider sits on
   the same rhythm as the hairlines between rows. */
.eim-people-sep{height:1px;background:var(--border-d);margin:0}
#editItemModal #editItemPeopleRows .edit-item-role-row:first-child{border-top:none}
#editItemModal .eim-add-person{margin-top:10px}

/* ---- Description: one line shorter ------------------------------------------ */
.eim-desc-input{min-height:56px;max-height:150px}

/* ---- Task footer: creator face, clickable ----------------------------------- */
.cm-created-btn{display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  padding:4px 6px;margin-left:-6px;border-radius:8px;transition:background .12s}
.cm-created-btn:hover{background:rgba(255,255,255,.06)}

/* ---- Task icon beside the title --------------------------------------------- */
/* Matched to the title's own size. Note the size is also passed to taskIconHtml, because
   appIconHtml writes width/height as an INLINE style that outranks these rules. */
.card-modal-icon-btn{width:34px;height:34px;flex:none;display:inline-flex;align-items:center;
  justify-content:center;background:none;border:none;border-radius:9px;cursor:pointer;
  padding:0;margin-right:10px;transition:background .12s;vertical-align:middle}
.card-modal-icon-btn:hover{background:rgba(255,255,255,.07)}
.card-modal-icon-btn svg,.card-modal-icon-btn img{width:26px;height:26px;display:block}
/* One row, centred on each other. align-items:center is the whole point — the previous
   rule targeted a wrapper that does not exist, so the two were never in a flex context
   at all and fell back to inline alignment. min-width:0 keeps the title's ellipsis. */
.card-modal-titlerow{display:flex;align-items:center;min-width:0;margin-bottom:var(--cm-gap)}
/* The gap below the title moves to the ROW. Left on the title it broke the centring:
   align-items:center centres a flex item's MARGIN box, so a 20px bottom margin lifted
   the title's border box by exactly half that — the 10px the icon was off by. */
.card-modal-title{display:block;min-width:0;flex:1;margin-bottom:0}

/* The status glyph replaces the old dot, so the ::before dot must go or there are two. */
.subtask-inline-status.has-glyph::before{display:none}
.subtask-inline-status.has-glyph{gap:6px}
.subtask-inline-status .task-glyph{flex:none}
.prop-ctx-menu .task-glyph{flex:none;margin-right:8px}
/* Faces instead of a name list in a popout row. */
.mention-popout .mp-v-faces{display:inline-flex;align-items:center;gap:-4px}
.mention-popout .mp-v-faces .card-avatar{width:18px!important;height:18px!important;
  margin-left:-5px;border:1.5px solid var(--dark)}
.mention-popout .mp-v-faces .card-avatar:first-child{margin-left:0}

/* The @ is the everyone row's glyph, so it occupies the same 16px slot the colour dots
   do — at 13px it sat visibly smaller than the circles beside it. */
#editItemModal .eim-everyone-dot{font-size:16px;line-height:16px;width:16px;height:16px;
  display:inline-flex;align-items:center;justify-content:center;opacity:.75}
/* + Add person sits on the same left edge as every row above it, with the row rhythm's
   spacing rather than its own. */
#editItemModal .eim-add-person{margin:8px 0 0;padding:6px 10px;display:inline-flex;
  align-items:center;line-height:1}

/* "Default" reads as an empty slot — a dashed outline rather than another icon to pick. */
.pip-btn-default svg{opacity:.55}
.pip-btn-default.on svg{opacity:1}
/* Emotes sit in the same grid as the drawn icons — same cell, same size. */
.pip-btn-emote img{width:20px;height:20px;object-fit:contain;display:block}

/* ---- Icon picker: grid scrolls, colours stay put ----------------------------
   The colour row is the one control you always want reachable, and adding emotes to the
   grid made the list long enough to push it off the bottom. Only the grid scrolls. */
.proj-icon-picker{display:flex;flex-direction:column;max-height:min(60vh,420px)}
.proj-icon-picker .pip-grid{overflow-y:auto;flex:1 1 auto;min-height:0;
  scrollbar-width:thin;padding-right:2px}
.proj-icon-picker .pip-colors{flex:none;border-top:1px solid var(--border-d);
  margin-top:8px;padding-top:8px}
/* "Default colour" reads as an empty slot: dashed ring, struck through — the same shape
   every other reset control uses, rather than a rainbow that says "pick a colour". */
.pip-swatch.pip-swatch-default{background:none!important;position:relative;
  border:1.5px dashed var(--muted)!important;opacity:.8}
.pip-swatch.pip-swatch-default::after{content:"";position:absolute;left:50%;top:1px;bottom:1px;
  width:1.5px;background:var(--muted);transform:rotate(45deg);transform-origin:center;
  border-radius:1px}
.pip-swatch.pip-swatch-default.on{opacity:1;border-color:var(--cream)!important}
.pip-swatch.pip-swatch-default.on::after{background:var(--cream)}
/* The card's stage glyph replaces the old dot. */
.kc-stage svg{width:12px;height:12px;flex:none;display:block}

/* ---- The "no value" dash ------------------------------------------------------
   A drawn bar rather than the "—" character. See createMsDropdown for why: the glyph's
   ink is not centred in its own text box, so it always painted low beside the dot. */
.ms-dd-dash{display:block;width:11px;height:1.5px;border-radius:1px;
  background:var(--muted);flex:none}
/* It sits inside the label span (which owns flex:1), so the bar is placed with a
   margin rather than by flex — the label is not a flex container. */
.ms-dropdown-trigger-label > .ms-dd-dash,
.ms-dropdown-item-label > .ms-dd-dash{margin:0}

/* ---- Time zones ---------------------------------------------------------------
   The strip under a time picker showing one instant on every teammate's clock. The
   day-shift badge is the point of the whole thing — Tokyo being on tomorrow is the
   failure mode, so it gets the only colour in the block. */
.hz-input-zone{font:600 10.5px var(--sans);color:var(--muted);margin-bottom:8px;
  letter-spacing:.01em}
.hz-input-zone .hz-abbr{color:var(--cream)}
.hz-strip{background:var(--cm-field-bg,rgba(255,255,255,.04));border-radius:8px;
  padding:8px 10px;margin-bottom:8px}
.hz-strip-head{font:700 9.5px var(--sans);letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);margin-bottom:6px}
.hz-zrow{display:grid;grid-template-columns:46px 1fr auto minmax(0,1fr);align-items:center;
  gap:8px;padding:2px 0;font:500 11px var(--sans);color:var(--cream)}
.hz-zrow.is-you .hz-zname{color:var(--coral)}
.hz-zname{font-weight:700;font-size:10px;color:var(--muted);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.hz-ztime{font-variant-numeric:tabular-nums;white-space:nowrap}
.hz-zshift{font:700 9.5px var(--sans);white-space:nowrap;min-width:0}
.hz-zshift.is-ahead{color:var(--gold)}
.hz-zshift.is-behind{color:var(--blue)}
.hz-zwho{color:var(--muted);font-size:10px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;min-width:0}

/* ---- Menus that sit over CONTENT need a fill that stands on its own -----------
   The glass language is "tint + blur, NOT opacity", and that is right for a menu over
   a page background. But `backdrop-filter` composites only when the compositor gives
   the element a real backdrop, and for these menus it silently no-ops — the property
   computes, nothing frosts, and at --lg-menu's 78% you can read the card text straight
   through the panel. Legibility must not depend on an effect that can quietly do
   nothing, so these take --lg-solid. The blur stays: where it DOES composite the panel
   still reads as glass, and where it doesn't the fill already carries it.
   Scoped to menus that overlap dense content — menus over empty page chrome keep the
   lighter --lg-menu fill and the glass look it was designed for. */
.kanban-col-dropdown,
.ms-dropdown-menu,
.workshop-sort-dropdown,
.workshop-sort-submenu{
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-solid) !important;
}

/* A status with a chosen icon shows the icon INSTEAD of the coloured square — two
   glyphs side by side would just be noise, and the square exists precisely because
   there was nothing better to show. */
.kanban-col-title.has-icon::before{display:none}
.kanban-col-glyph{display:inline-flex;align-items:center;flex:none;line-height:0;cursor:pointer}
/* The coloured square, as a real element so it can be clicked. Same box the
   .kanban-col-title::before drew, which .has-icon now always suppresses. */
/* Composer drop state — the bar says it will take the file before you let go. */
.chatroom-input-bar.is-file-over{outline:2px dashed var(--purple);outline-offset:3px;border-radius:12px}
.kanban-col-dot{width:11px;height:11px;border-radius:3px;
  background:var(--col-color,var(--muted));
  box-shadow:0 0 0 3px color-mix(in srgb,var(--col-color,var(--muted)) 16%,transparent)}
.kanban-col-glyph svg,.kanban-col-glyph img{width:15px;height:15px;display:block}


/* ---- Pages that fill the shell ------------------------------------------------
   These pages bleed past .content's gutter with negative margins and then tried to
   win the height back with `height:calc(100% + 88px)`. That arithmetic only holds if
   the gutter is exactly what the rule assumed — and a negative BOTTOM margin gives
   back no visible space at all, it just tells the parent to ignore it. The result was
   a chatroom 739px tall inside a 700px shell: the bottom 60px (the composer) rendered
   below the fold and got clipped by .main's overflow:hidden.

   .main is a flex column with a definite height, so the honest way to say "fill what
   is left" is to be a flex item. No arithmetic to keep in sync with the padding.

   These pages are hoisted OUT of .content and sit as flex siblings of .main-body, so
   .main-body still contributed its (empty) gutter — ~126px — above them. Collapse it for
   exactly these pages and let the page be the flex item that fills what is left.

   Scoped by id rather than to every hoisted page on purpose: #page-workshop and
   #page-files already lay out correctly with .main-body present, and their own
   calc() heights are written against that. Collapsing it for them would push the
   board 88px past the bottom — the same bug, moved. */
.main:has(> #page-chatroom.active) > .main-body,
.main:has(> #page-dm.active) > .main-body,
.main:has(> #page-settings.active) > .main-body,
.main:has(> #page-agency-dashboard.active) > .main-body{
  flex:0 0 0;height:0;min-height:0;padding:0;overflow:hidden}
#page-chatroom.active,
#page-dm.active,
#page-settings.active,
#page-agency-dashboard.active{
  height:auto;
  flex:1 1 auto;
  min-height:0;
  margin:0}

/* Router pill — the same object as a multi-select pill, plus two lead glyphs: the
   router mark (what KIND of thing this is) and the destination project's own icon
   (WHERE it goes). Sized to the pill's 10px text so neither glyph outweighs the name. */
.router-pill{gap:4px}
.router-pill-ico,.router-pill-proj{display:inline-flex;align-items:center;flex:none;line-height:0}
.router-pill-ico svg,.router-pill-proj svg,.router-pill-proj img{width:11px;height:11px;display:block}
.router-pill-ico{opacity:.65}

/* ---- Page titles line up across pages ----------------------------------------
   A project's title carries padding:6px 14px + a 1px transparent border because it is
   an EDITABLE control (the padding is its hover target). A page title that is not
   editable had neither, so its text started ~15px to the left — the same title in a
   different place on every page.

   Give the non-editable title the identical BOX so the text lands in the same spot,
   without the background/cursor that would falsely imply you can rename it. */
.ws-title-row > .ws-page-title:not(.is-editable){
  padding:var(--page-title-pad);
  border:1px solid transparent;
  border-radius:var(--page-title-radius);
  background:none}

/* ---- Trash controls wear the project view-tab treatment ------------------------
   Same row grammar as a project's tabs: 36px tall, 600 13px, the tabs' muted ink, a
   10px radius and NO border or fill until hovered. They were a bordered select and a
   red outlined button — two different shapes from two different systems sitting where
   the eye expects the tab row. Right-aligned is kept (margin-left:auto below). */
.trash-controls{display:flex;align-items:center;justify-content:flex-end;gap:2px;
  padding:0 16px 6px 0}
.trash-purge-label{
  font:600 13px var(--sans);color:rgba(235,235,245,.7);
  height:36px;display:inline-flex;align-items:center;padding:0 6px 0 14px}
/* The old rule styled this as a <select> — fill, border, radius. It is a bare mount
   point for the dropdown now, so that box has to go or it paints a container around a
   control that is meant to read as a tab. */
.trash-purge-select{background:none;border:none;border-radius:0;padding:0;
  display:inline-flex;align-items:center}
/* The dropdown's trigger IS the tab. createMsDropdown writes width inline, so the
   sizing lives on the trigger where a stylesheet can still reach it. */
.trash-purge-select .ms-dropdown-trigger{
  height:36px;padding:0 14px;border-radius:10px;gap:7px;
  font:600 13px var(--sans);color:rgba(235,235,245,.7);
  background:none;border:none;box-shadow:none;
  transition:background .15s,color .15s}
.trash-purge-select .ms-dropdown-trigger:hover,
.trash-purge-select .ms-dropdown.open .ms-dropdown-trigger{
  background:rgba(255,255,255,.06);color:var(--cream);border-color:transparent;box-shadow:none}
.trash-empty-btn{
  height:36px;padding:0 14px;border-radius:10px;gap:7px;
  font:600 13px var(--sans);color:var(--danger-text);
  background:var(--color-error-tint);border:none;
  display:inline-flex;align-items:center;cursor:pointer;
  transition:background .15s}
.trash-empty-btn svg{width:16px;height:16px;opacity:.9;flex-shrink:0;transition:opacity .15s}
.trash-empty-btn:hover{background:rgba(239,68,68,.22)}
.trash-empty-btn:hover svg{opacity:1}
/* A little air between the neutral controls and the destructive one, so "30 days" and
   "Empty trash" cannot be clicked for one another. */
.trash-empty-btn{margin-left:10px}

/* A channel that has been given its own colour shows it at full strength, and beats the
   folder tint. Without the second rule a channel inside a coloured category kept the
   category's stroke — that rule sets `stroke` outright, so an inline `color` (which only
   drives currentColor) could never win. */
.sidebar-channel-icon.has-icon-color{opacity:1}
.sidebar-cat-colored .sidebar-cat-child .sidebar-channel-icon.has-icon-color svg,
.sidebar-cat-colored .sidebar-cat-child:hover .sidebar-channel-icon.has-icon-color svg{
  stroke:currentColor}

/* ---- Trash row actions match "Empty trash" ------------------------------------
   Delete takes the header button's exact treatment — red tint fill, danger ink, no
   border. Restore is its neutral sibling: same shape, quiet fill. Both lose the outline.

   Scoped to .trash-flat-acts on purpose: .ss-btn-secondary / .ss-btn-danger are shared
   with the Settings pages, and restyling them globally would silently redress buttons
   on screens this change was never about. */
.trash-flat-acts .ss-btn{border:none;border-radius:8px;transition:background .15s}
.trash-flat-acts .ss-btn-secondary{
  background:rgba(255,255,255,.06);color:var(--cream)}
.trash-flat-acts .ss-btn-secondary:hover{background:rgba(255,255,255,.11)}
.trash-flat-acts .ss-btn-danger{
  background:var(--color-error-tint);color:var(--danger-text)}
.trash-flat-acts .ss-btn-danger:hover{background:rgba(239,68,68,.22)}

/* ---- Rich chat composers -------------------------------------------------------
   Now contenteditable rather than <textarea>, so mentions render as chips while you
   type. A div has no `placeholder`, and no `resize`/`rows` to inherit — the height is
   whatever the content needs, bounded by the same max-height the textarea had. */
#chatroomInput:empty::before,
#dmInput:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}
#chatroomInput{white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word;
  height:auto;max-height:220px;overflow-y:auto}
#dmInput{white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word;
  height:auto;max-height:200px;overflow-y:auto}
/* Centred on the text, not sat on its baseline. A composer chip carries an avatar, so its
   box is taller than a line — on the baseline its extra height all hangs below, and the pill
   rides low against the words on either side of it. This is an id selector, so it was
   quietly beating the .mention-chip rule that had already worked this out everywhere else. */
#chatroomInput .mention-chip,#dmInput .mention-chip{vertical-align:middle}

/* ---- Trash sits higher than a project page ------------------------------------
   A project spends the room under its title on a tab row; Trash has none, so the same
   spacing left a band of empty page above the table. Only the space BELOW the title is
   closed up — the title itself keeps .ws-header's 18px top padding so it stays level with
   a project's title, which is the whole point of the shared header.
   Scoped to .trash-top: .hi-top is shared with Home, which is not being moved. */
#page-trash .ws-header{padding-bottom:2px}
.hi-top.trash-top{margin-bottom:4px}

/* ---- Chat channel header + tabs ------------------------------------------------
   Channels were the one page type with no heading: .cr-topbar (which held the name) is
   display:none, leaving just a breadcrumb. They now use the shared .ws-header /
   .ws-title-row / .ws-page-title structure, so the title inherits the --page-title-*
   tokens and lands in the same place as a project's or Trash's.

   The panel supplies its own horizontal inset, so the header cancels .ws-header's left
   padding rather than adding a second one. */
#page-chatroom .cr-ws-header{padding:var(--page-header-pad)}
/* The tabs sit in a .workshop-views strip, the same row a project uses, so the pill lands
   in the identical spot. Search + Settings take the right-hand end (a channel has nothing
   to Filter). Project styles are untouched — .cr-views only adds what is channel-specific. */
.cr-views{gap:10px;padding:16px 16px 4px;margin:0 0 6px}
/* The tab strip met the message list on a hard line, so a message scrolling up stopped dead
   against it. Rather than dissolving the list into the page, the strip sits ABOVE it and
   casts a shadow down over it — the header stays flat and fully opaque, and the separation
   comes from depth instead of a fade. Needs the stacking context: without position+z-index
   the shadow paints under the scroller and is invisible. */
/* No cast shadow on the header. The strip and the message list are the same ground, so a
   shadow between them reads as a seam rather than as depth — the same reason the sidebar's
   was taken off once. The stacking is kept: the strip still sits above the list. */
#page-chatroom .cr-views{position:relative;z-index:4;background:none}
.cr-views .ws-view-tabs{order:1;margin-right:auto}
.cr-search-wrap{order:4}
#crMenuWrap{order:5}
.cr-search-wrap{display:flex;align-items:center;gap:8px;height:36px;padding:0 12px;
  border-radius:10px;background:var(--bg-inset);color:var(--text-3);flex:none;width:210px}
.cr-search-wrap svg{width:14px;height:14px;flex:none;opacity:.8}
.cr-search-input{flex:1;min-width:0;background:none;border:none;outline:none;
  font:400 13px var(--sans);color:var(--cream)}
.cr-search-input::placeholder{color:var(--text-3)}
@media(max-width:900px){.cr-search-wrap{width:150px}}

/* ---- Channel composer: message on top, tools underneath -----------------------
   The old bar was one row — icon, text, icon — so there was nowhere to put a toolbar and
   nowhere to show an attachment before it was sent. */
.chatroom-input-bar{display:flex;flex-direction:column;align-items:stretch;gap:6px;
  padding:10px 12px;border-radius:12px;background:var(--bg-inset);
  border:1px solid transparent;transition:border-color .15s}
.chatroom-input-bar:focus-within{border-color:var(--hairline-2)}
/* (kept intentionally identical to the class above — the class is the source now) */
.cr-compose-tools{display:flex;align-items:center;gap:2px}
.cr-tool{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;
  border:none;background:none;border-radius:8px;color:var(--muted);cursor:pointer;
  transition:background .12s,color .12s}
.cr-tool svg{width:18px;height:18px}
.cr-tool:hover{background:rgba(255,255,255,.07);color:var(--cream)}
/* Send sits at the far end, the way it does in every messaging app. */
.cr-send{margin-left:auto;width:32px;height:30px;display:inline-flex;align-items:center;
  justify-content:center;border:none;background:none;border-radius:8px;color:var(--muted);
  cursor:pointer;transition:background .12s,color .12s}
.cr-send svg{width:18px;height:18px}
.cr-send:hover{background:rgba(124,92,255,.18);color:var(--purple)}
.cr-send:disabled{opacity:.45;cursor:default}
/* Recording reads as live: the mic goes red and wears its own elapsed time. */
.cr-mic.recording{color:var(--danger-text);background:var(--color-error-tint)}
.cr-mic.recording::after{content:attr(data-rectime);position:absolute;font:700 9px var(--sans);
  transform:translateY(19px)}
.cr-mic{position:relative}
/* Pending attachments sit ABOVE the message, so what you are about to send is visible
   before you send it rather than after. */
.cr-attach-tray{display:flex;flex-wrap:wrap;gap:6px;padding-bottom:2px}
.cr-att{display:inline-flex;align-items:center;gap:7px;max-width:250px;padding:4px 6px 4px 4px;
  border-radius:8px;background:rgba(255,255,255,.06);font:500 11px var(--sans);color:var(--cream)}
.cr-att img{width:26px;height:26px;border-radius:5px;object-fit:cover;display:block;flex:none}
.cr-att-glyph{width:26px;height:26px;border-radius:5px;display:inline-flex;align-items:center;
  justify-content:center;background:rgba(255,255,255,.07);color:var(--muted);flex:none}
.cr-att-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.cr-att-state{color:var(--muted);font-size:10px;flex:none}
.cr-att.is-failed{background:var(--color-error-tint)}
.cr-att.is-failed .cr-att-state{color:var(--danger-text)}
.cr-att.is-uploading{opacity:.7}
.cr-att-x{border:none;background:none;color:var(--muted);cursor:pointer;font-size:13px;
  line-height:1;padding:0 2px;flex:none}
.cr-att-x:hover{color:var(--cream)}
.cr-att-retry{border:0;background:none;color:var(--accent);padding:0;font:inherit;font-size:10px;font-weight:700;cursor:pointer}

/* ── Going out: scheduled social posts (Home) ────────────────────────────────
   Rows read left-to-right as medium · what · when, and the when column is fixed so a
   list of five posts scans as a column of times rather than five ragged endings. */
.hh-social .hh-card-body{padding:0 10px 10px}
.hs-row{display:flex;align-items:center;gap:10px;padding:8px;border-radius:9px;cursor:pointer;transition:background .12s}
.hs-row:hover{background:var(--state-hover)}
.hs-kind{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;flex:none;
  border-radius:8px;background:var(--surface-raised);color:var(--text-2)}
.hs-main{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.hs-row .hi-row-title{font:600 13px var(--sans);color:var(--off-white);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hs-sub{display:flex;align-items:center;gap:5px;font:500 11px var(--sans);color:var(--text-3);min-width:0;flex-wrap:wrap}
/* Platform chips take the shared pill contract, so they cannot drift from the pills
   everywhere else; only the tint is per-platform. */
.hs-plat{display:inline-flex;align-items:center;height:18px;padding:0 7px;border-radius:var(--pill-radius);
  font:600 10px var(--sans);letter-spacing:.02em;line-height:1;text-transform:capitalize;
  background:var(--surface-inset);color:var(--text-2)}
.hs-tiktok{background:color-mix(in srgb,#25f4ee 16%,transparent);color:#4fd8e3}
.hs-instagram{background:color-mix(in srgb,#e1306c 18%,transparent);color:#f0629a}
.hs-youtube{background:color-mix(in srgb,#ff0033 16%,transparent);color:#ff6b7f}
.hs-facebook{background:color-mix(in srgb,#1877f2 18%,transparent);color:#61a0f7}
.hs-linkedin{background:color-mix(in srgb,#0a66c2 20%,transparent);color:#5fa3e8}
.hs-x,.hs-twitter{background:var(--surface-inset);color:var(--off-white)}
.hs-when{display:flex;flex-direction:column;align-items:flex-end;gap:1px;flex:none;
  font:600 11px var(--sans);color:var(--text-2);text-align:right}
.hs-clock{font:500 11px var(--sans);color:var(--text-3)}

/* ── Mention popouts wear the profile card ──────────────────────────────────
   A person, a task, a file and a project are all "the thing whose chip I tapped", so
   they get ONE card. Everything structural comes from .cr-profile-* above — this block
   only supplies what a floating card needs and what a thing-that-isn't-a-person puts in
   the icon slot. No banner here: a person has one because a person CHOSE one, and a file
   inventing a coloured strip was decoration standing in for detail. */
.cr-profile-popout.mention-profile{position:fixed;inset:auto;width:290px;max-height:85vh;
  border:1px solid var(--border-d);border-radius:10px;animation:crPopIn .15s ease;
  box-shadow:0 18px 48px rgba(0,0,0,.55)}
/* Header: the glyph sits where a person's face sits, name and kind stacked beside it. */
.mention-profile .mp-head2{display:flex;align-items:center;gap:12px;padding:14px 14px 0}
.mention-profile .mp-headtext{min-width:0;flex:1}
.mention-profile .mp-head2 .cr-profile-name{font-size:15px;margin-bottom:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mention-profile .mp-head2 .cr-profile-title{margin-bottom:0}
.mention-profile .cr-profile-avatar-lg{width:44px;height:44px;border:0;flex:none;
  border-radius:12px;background:var(--surface-raised);
  color:var(--mn-color,var(--cream))}
.mention-profile .cr-profile-avatar-lg svg{width:22px;height:22px}
.mention-profile .cr-profile-avatar-lg img{width:26px;height:26px;object-fit:contain;border-radius:6px}
.mention-profile .cr-profile-avatar-lg > span{display:inline-flex;align-items:center;justify-content:center}
.mention-profile .cr-profile-body{padding:0 14px 14px}
/* The first label sits under the header, which already provides the gap. */
.mention-profile .mp-first-label{margin-top:14px}
.mention-profile .cr-profile-info-row{font-size:11.5px;margin-bottom:5px;align-items:baseline}
.mention-profile .cr-profile-info-label{min-width:78px;flex:none}
.mention-profile .cr-profile-info-value{flex:1;min-width:0;text-align:right;word-break:normal;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* A value the browser is still reading out of the media file. */
.mention-profile [data-mp-probe]{color:var(--text-3)}
/* Faces sit where roles sit on a profile, and overlap so four assignees still read as a
   group rather than as a row that has to wrap. */
.mention-profile .mp-faces{gap:0;margin-bottom:0}
.mention-profile .mp-faces .card-avatar,.mention-profile .mp-faces > img{margin-left:-6px;
  border:2px solid var(--bg-shell);border-radius:50%;box-sizing:content-box}
/* The overlap margin and the ring belong to the FACE, i.e. the span, or a bare <img>.
   The old selector also caught the photo inside a span, so every uploaded face was
   shoved 6px left of its own circle and grew a second ring. */
.mention-profile .mp-faces .card-avatar img{margin:0;border:0;box-sizing:border-box;width:100%;height:100%}
.mention-profile .mp-faces .mp-more{background:var(--bg-inset);color:var(--text-2);font-size:9px;font-weight:700;letter-spacing:.02em}
.mention-profile .mp-faces > :first-child{margin-left:0}
/* Same footprint as the profile card's message field: the bottom of this card is where
   the one action lives, whichever kind of thing it is. */
.mention-profile .mp-go{width:100%;padding:9px 12px;border:0;border-radius:9px;
  background:var(--surface-inset);color:var(--cream);font:600 12px var(--sans);
  cursor:pointer;transition:background .12s}
.mention-profile .mp-go:hover{background:var(--state-hover)}

/* ── Mention thumbnails ─────────────────────────────────────────────────────
   A file mention leads with its own first frame, the way a person mention leads with
   that person's face. Both crop to FILL their slot: a 16:9 frame letterboxed inside a
   square is mostly empty space, and the point is recognising the shot, not preserving
   its aspect ratio at thumbnail size. */
.mention-thumb{width:15px;height:15px;flex:none;border-radius:50%;object-fit:cover;
  background:var(--surface-inset);display:inline-block;vertical-align:-3px}
.mention-profile .cr-profile-avatar-lg .mp-thumb{width:100%;height:100%;object-fit:cover;border-radius:inherit;display:block}
/* The frame fills the icon slot edge to edge, so the slot itself stops being a tinted
   plate behind a glyph and becomes the picture. */
.mention-profile .cr-profile-avatar-lg:has(.mp-thumb){background:transparent;overflow:hidden}

/* ── Task property values ───────────────────────────────────────────────────
   The [+] is a member of the pill row, so it takes the pill's height and corner —
   it was a 20px circle next to 22px rounded pills, which is why it read as
   crammed in and sat a pixel off the line they share. */
.card-modal .prop-pill-add{
  width:var(--pill-h);height:var(--pill-h);border-radius:var(--pill-radius);
  font-size:var(--pill-font-size);line-height:1;padding:0}
/* Inline glyphs replace the literal emoji these values used to print. Emoji render as
   whatever face the reader's OS ships and never match the app's own line weight. */
.prop-glyph{flex:none;opacity:.6;vertical-align:-1px}
.prop-pill .prop-glyph{margin-right:2px;opacity:.75}
.prop-count{display:inline-flex;align-items:center;gap:3px;font:600 11px var(--sans);color:var(--muted)}
.prop-num{font:600 11px var(--sans);color:var(--muted)}
.prop-num.is-currency{color:var(--green)}
/* A card with only a title kept its empty meta row's 8px top margin, so the space under
   the title was that much deeper than the space above it. */
.kanban-card-meta:empty{display:none}

/* A property's option menu ("Rename", "Change colour") is a menu ABOUT a row in another
   menu, so it belongs one layer above it. It shared z-index 10001 with the dropdowns it
   opens over — .multiselect-dropdown, .prop-person-dropdown, .prop-type-picker — which
   left paint order to whichever happened to be later in the document, and the option menu
   came out UNDER the very list it was describing. */
.prop-ctx-menu{z-index:10050}

/* ── Workspace Settings page header ─────────────────────────────────────────
   Settings used to open straight onto its tab strip, so its title lived only in the
   topbar crumb while every other page carried an icon and a 34px title on the same line.
   It reuses .ws-header / .ws-title-row / .ws-page-title outright — no copied values — so
   the line it lands on is by definition the same one. */
.ss-header{flex-shrink:0}
.ss-header .ws-title-icon{display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:50%;overflow:hidden;flex:none;background:transparent}
.ss-header .ws-title-icon img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
/* The sidebar badge's own rule sizes it 42px for the sidebar; here it fills this slot. */
.ss-header .ss-title-badge{width:100%;height:100%;font-size:12px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center}

/* ── Connected storage / social ─────────────────────────────────────────────
   One row shape for both, because "what this workspace is wired to" is one question. */
.ss-conn-row{display:flex;align-items:center;gap:10px;padding:9px 0;
  border-bottom:1px solid var(--hairline-2,rgba(255,255,255,.05))}
.ss-conn-ico{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex:none}
.ss-conn-ico:empty{display:none}
.ss-conn-ico img,.ss-conn-ico svg{width:15px;height:15px;display:block}
.ss-conn-main{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.ss-conn-title{font:600 13px var(--sans);color:var(--off-white);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ss-conn-sub{font:500 11px var(--sans);color:var(--muted)}
.ss-conn-right{flex:none}
.ss-conn-tag{display:inline-flex;align-items:center;height:var(--pill-h);padding:0 var(--pill-pad-x);
  border-radius:var(--pill-radius);font-size:11px;font-weight:var(--pill-font-weight);line-height:1;
  background:var(--surface-inset);color:var(--text-2)}
.ss-conn-tag.is-live{background:color-mix(in srgb,var(--success,#3fb950) 16%,transparent);color:var(--success,#3fb950)}

/* Connection sections: a heading with its own add controls on the right. */
.ss-conn-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.ss-conn-head h3{margin:0}
.ss-conn-add{display:inline-flex;gap:6px;flex-wrap:wrap}
.ss-conn-right{display:inline-flex;align-items:center;gap:8px}
/* The remove control stays out of the way until the row is pointed at — it is destructive,
   and a row of red buttons reads as a warning rather than as a list. */
.ss-conn-row .ss-btn-danger{opacity:0;transition:opacity .12s}
.ss-conn-row:hover .ss-btn-danger,.ss-conn-row:focus-within .ss-btn-danger{opacity:1}

/* ── Settings > Permissions ─────────────────────────────────────────────────
   A matrix, because the question is comparative: not "what can a Member do" but "what can
   a Member do that a Guest cannot". Three columns side by side answer that in one look. */
.ss-perm-legend{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 18px}
.ss-perm-tier{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:10px;
  background:var(--surface-container,rgba(255,255,255,.03));font:600 13px var(--sans);color:var(--off-white)}
.ss-perm-count{font:500 11px var(--sans);color:var(--muted)}
.ss-perm-note{font:500 11px var(--sans);color:var(--text-3)}
.ss-perm-reset{background:none;border:0;padding:0;font:600 11px var(--sans);color:var(--coral);cursor:pointer}
.ss-perm-reset:hover{text-decoration:underline}
.ss-perm-table{border-radius:0;background:none}
.ss-perm-head,.ss-perm-row{display:grid;grid-template-columns:minmax(240px,1fr) 90px 90px 90px;align-items:center;gap:8px}
.ss-perm-head{padding:10px 0;font:700 10px var(--sans);letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.ss-perm-head span:not(:first-child),.ss-perm-cell{justify-self:center}
.ss-perm-group{padding:12px 0 6px;font:700 10px var(--sans);letter-spacing:.6px;text-transform:uppercase;color:var(--text-3)}
.ss-perm-row{padding:8px 0;border-top:1px solid var(--hairline-2,rgba(255,255,255,.05))}
.ss-perm-row:hover{background:var(--state-hover);box-shadow:0 0 0 8px var(--state-hover);border-radius:2px}
.ss-perm-what{display:flex;flex-direction:column;gap:1px;min-width:0}
.ss-perm-what b{font:600 13px var(--sans);color:var(--off-white)}
.ss-perm-what span{font:500 11px var(--sans);color:var(--muted)}


/* ── Settings > Customize > Icon colours ────────────────────────────────────
   Eight fixed slots, each labelled by the role it plays, because position is meaning
   here — the first is what a new icon gets, the last is where near-greys land. */
.ss-pal-row{display:flex;gap:10px;flex-wrap:wrap}
.ss-pal-slot{display:flex;flex-direction:column;align-items:center;gap:4px;cursor:pointer;position:relative;background:none;border:0;padding:0;font:inherit;color:inherit;text-align:center}
.ss-pal-slot[aria-disabled="true"]{cursor:default;opacity:.7}
/* A product colour: shown, so you can see what a workspace already draws from, but not a
   control. No pointer, no hover, nothing that suggests it can be changed. */
.ss-pal-slot.is-locked{cursor:default}
.ss-pal-slot.is-locked .ss-pal-chip{box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
/* Remove sits on the swatch, appearing when the slot is pointed at — same idea as the
   remove control on a pill. */
.ss-pal-x{position:absolute;top:-5px;right:-5px;width:16px;height:16px;border-radius:50%;
  border:0;padding:0;line-height:14px;font-size:12px;cursor:pointer;opacity:0;
  background:var(--surface-overlay,#141416);color:var(--muted);transition:opacity .12s}
.ss-pal-slot:hover .ss-pal-x,.ss-pal-slot:focus-within .ss-pal-x{opacity:1}
.ss-pal-x:hover{color:var(--danger-text,#ef4444)}
/* The add tile IS a swatch — same box, same corner — drawn as an empty one waiting to be
   filled, rather than a button sitting beside the row it belongs to. */
.ss-pal-add{background:none;border:0;padding:0;font:inherit;cursor:pointer}
.ss-pal-chip.ss-pal-chip-add{display:flex;align-items:center;justify-content:center;
  box-sizing:border-box;background:none;color:var(--muted);padding:0;border:0;
  box-shadow:none;outline:1px dashed var(--hairline-3,rgba(255,255,255,.3));outline-offset:-1px}
.ss-pal-chip.ss-pal-chip-add::before{content:'+';font:300 21px/1 var(--sans);display:block}
.ss-pal-add:hover .ss-pal-chip-add{border-color:var(--coral);color:var(--coral)}
.ss-pal-chip{width:34px;height:34px;border-radius:10px;display:block;box-sizing:border-box;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
/* The native colour input is the real control; it sits over its own swatch so the swatch
   IS the button, rather than a preview parked next to a second thing to click. */
.ss-pal-slot input[type="color"]{position:absolute;top:0;left:0;width:34px;height:34px;opacity:0;
  border:0;padding:0;cursor:pointer}
.ss-pal-slot input[type="color"]:disabled{cursor:default}
.ss-pal-name{font:600 10px var(--sans);color:var(--muted)}
.ss-pal-hex{font:500 10px var(--mono,var(--sans));color:var(--text-3);letter-spacing:.02em}
.ss-pal-acts{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap}

/* A provider the deployment cannot complete: present, legible, and plainly not pickable. */
.sch-platform-choice.is-unavailable{opacity:.45;cursor:default}
.sch-platform-choice.is-unavailable small{display:block;font:500 10px var(--sans);color:var(--muted);margin-top:2px}

/* Pending is a STATE, not a tier. Filled and gold it read as a third role sitting beside
   Owner and Member; an outline says "this person has no tier yet" without competing with
   the two that are real. Italic because it describes a condition, not a name. */
.ss-pending-chip{display:inline-flex;align-items:center;height:var(--pill-h);padding:0 var(--pill-pad-x);
  border-radius:var(--pill-radius);border:1px solid var(--hairline-3,rgba(255,255,255,.14));
  background:none;color:var(--muted);font:500 italic 11px var(--sans);line-height:1;white-space:nowrap}
.ss-pending-chip.is-failed{border-color:color-mix(in srgb,var(--danger-text,#ef4444) 45%,transparent);
  color:var(--danger-text,#ef4444);margin-left:6px}


/* Theme picker: the same sliding thumb the tabs use, so a segmented control behaves the
   same way wherever it appears. .theme-seg.on is the state _wirePillBar tracks. */
.theme-toggle{position:relative}
.theme-toggle .m-pill-thumb{background:var(--coral)}
.theme-toggle .theme-seg{position:relative;z-index:1;transition:color .15s}
.theme-toggle .theme-seg.on{background:none}

/* ── Colour picker ─────────────────────────────────────────────────────────
   The native <input type="color"> opens an OS panel in the corner of the screen, nowhere
   near what you clicked. This is the app's own, on the same anchored-popover primitive the
   mention cards use, so a picker behaves like every other panel here. */
.hs-cp{position:fixed;z-index:10050;width:232px;padding:12px;border-radius:14px;
  background:linear-gradient(var(--lg-tint),var(--lg-tint)),var(--lg-base);
  backdrop-filter:var(--lg-blur);-webkit-backdrop-filter:var(--lg-blur);
  border:1px solid var(--lg-border);box-shadow:var(--lg-shadow);font-family:var(--sans)}
.hs-cp-sv{position:relative;height:118px;border-radius:9px;cursor:crosshair;
  background-image:linear-gradient(to top,#000,transparent),linear-gradient(to right,#fff,var(--hs-hue))}
.hs-cp-hue{position:relative;height:12px;margin-top:10px;border-radius:999px;cursor:pointer;
  background:linear-gradient(to right,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
.hs-cp-dot{position:absolute;width:12px;height:12px;border-radius:50%;border:2px solid #fff;
  box-shadow:0 0 0 1px rgba(0,0,0,.45);transform:translate(-50%,-50%);pointer-events:none}
.hs-cp-hue .hs-cp-dot{top:50%}
.hs-cp-row{display:flex;align-items:center;gap:8px;margin-top:10px}
.hs-cp-prev{width:26px;height:26px;border-radius:8px;flex:none;box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
.hs-cp-hex{flex:1;min-width:0;padding:6px 9px;border-radius:8px;border:0;background:var(--surface-inset);
  color:var(--off-white);font:500 12px var(--mono,var(--sans));letter-spacing:.02em}
.hs-cp-hex:focus{outline:1px solid var(--coral);background:var(--state-hover)}


/* ── The shared flat list, inside a settings pane ───────────────────────────
   This is the project List view, unchanged: the same --surface-container panel, the same
   14px corner, the same 22px cells and per-row divider. The only difference a settings
   pane needs is the outer horizontal margin — the pane already starts on the tab strip's
   line, so the panel starts there too instead of 16px further in. */
.ss-body .gv-flat-table{margin:0 0 12px !important;max-height:none;overflow:hidden}
.ss-body .gv-flat-header{position:static}
/* A group heading inside the list — the area names on the Permissions page. Sits on the
   panel, above the rows it introduces, like the status header on a grouped board. */
.gv-flat-group{padding:14px 22px 6px;font:700 10px var(--sans);letter-spacing:.6px;
  text-transform:uppercase;color:var(--text-3);background:var(--surface-container)}
.ss-perm-cell{justify-content:center}


/* ── Permissions: holders ───────────────────────────────────────────────────
   A permission is a thing people HAVE, so the row lists who has it: tiers as pills, people
   as person pills, and one + that adds either. Same pill contract as everywhere else. */
/* One line, scrolled — not wrapped. Wrapping made a row as tall as the number of people
   who hold the permission, which pushed every other row down the page. Past
   SS_HOLDER_PILL_LIMIT the row stops listing and says how many are left, so the scroll
   is only ever a short one. */
.ss-perm-holders{gap:var(--pill-gap);flex-wrap:nowrap;align-items:center;min-height:26px;
  max-width:100%;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;
  scrollbar-color:var(--border-d) transparent;padding-bottom:2px}
.ss-perm-holders::-webkit-scrollbar{height:6px}
.ss-perm-holders::-webkit-scrollbar-thumb{background:var(--border-d);border-radius:3px}
.ss-perm-holders::-webkit-scrollbar-track{background:transparent}
/* Reads as a count, not as another holder: no dot, no colour of its own. */
.ss-perm-more{padding:0 var(--pill-pad-x);background:var(--surface-inset);color:var(--muted);
  border:none;cursor:pointer;font-family:var(--sans);white-space:nowrap}
.ss-perm-more:hover{background:var(--state-hover);color:var(--off-white)}
.ss-perm-holder{height:var(--pill-h);border-radius:var(--pill-radius);font-size:11px;
  font-weight:var(--pill-font-weight);line-height:1;display:inline-flex;align-items:center;box-sizing:border-box}
.ss-perm-holder.is-tier{padding:0 var(--pill-pad-x);background:var(--surface-inset);color:var(--text-2)}
.ss-perm-holders .prop-person-pill{padding:0 var(--pill-pad-x) 0 2px;background:var(--surface-inset)}
.ss-perm-holders .prop-pill-add{width:var(--pill-h);height:var(--pill-h);border-radius:var(--pill-radius);
  font-size:var(--pill-font-size);line-height:1;padding:0}
/* The grant picker — tiers and people in one searchable list. */
.ss-grant{width:268px;padding:6px;max-height:300px;display:flex;flex-direction:column}
.ss-grant-search{width:100%;padding:7px 10px;margin-bottom:4px;border:0;border-radius:8px;
  background:var(--surface-inset);color:var(--off-white);font:500 12px var(--sans)}
.ss-grant-search:focus{outline:1px solid var(--coral);background:var(--state-hover)}
.ss-grant-list{overflow-y:auto;min-height:0}
.ss-grant-row{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:8px;cursor:pointer}
.ss-grant-row:hover{background:var(--state-hover)}
.ss-grant-row.is-on{background:color-mix(in srgb,var(--coral) 14%,transparent)}
.ss-grant-row.is-on::after{content:'✓';margin-left:auto;color:var(--coral);font:600 12px var(--sans)}
.ss-grant-ico{width:20px;height:20px;border-radius:50%;flex:none;display:inline-flex;align-items:center;
  justify-content:center;background:var(--surface-raised);color:var(--text-2);font:700 10px var(--sans)}
.ss-grant-name{font:600 12px var(--sans);color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ss-grant-sub{font:500 10px var(--sans);color:var(--muted);white-space:nowrap}
.ss-grant-empty{padding:12px;font:500 12px var(--sans);color:var(--muted);text-align:center}

/* ── Workspace Settings: no outlines ────────────────────────────────────────
   Every box on these pages was drawn with a 1px hairline AND a fill, so the page read as a
   grid of outlined cards. A surface is enough on its own — the rest of the product stopped
   outlining things a while ago and settings had not caught up. Dividers stay: a rule
   BETWEEN two things is not an outline around one. */
#page-settings .ss-stat{border:0;background:var(--surface-container)}
#page-settings .ss-field input[type="text"],
#page-settings .ss-field textarea,
#page-settings .ss-field select,
#page-settings input[type="text"],
#page-settings input[type="email"],
#page-settings textarea{border:0 !important;background:var(--surface-inset)}
#page-settings .ss-field input:focus,
#page-settings .ss-field textarea:focus,
#page-settings .ss-field select:focus,
#page-settings input:focus,
#page-settings textarea:focus{border:0 !important;background:var(--state-hover);outline:1px solid var(--coral)}
#page-settings .ss-btn-secondary{border:0;background:var(--surface-inset)}
#page-settings .ss-btn-secondary:hover{background:var(--state-hover)}
/* Danger loses its outline too. Secondary had its border removed here and danger did
   not, so a 1px border on each edge made every Remove 2px taller than the Resend beside
   it — two buttons in one row sitting at different heights. Tint instead of outline,
   which is what the rest of settings does. */
#page-settings .ss-btn-danger{border:0;background:color-mix(in srgb,var(--color-error,#ef4444) 14%,transparent)}
#page-settings .ss-btn-danger:hover{background:var(--color-error,#ef4444);color:#fff}
#page-settings .emote-card{border:0;background:var(--surface-container)}
#page-settings .ss-icon-current{border:0}
/* The theme toggle carries a sliding thumb now, so the box around it was a second frame
   around a control that already shows its own state. */
#page-settings .theme-toggle{border:0}
/* The access-level pills say which is chosen by fill, not by a ring. */
#page-settings .ss-role-pill{border:0;background:var(--surface-inset)}
#page-settings .ss-role-pill.selected{border:0}


/* ── Permission holders ─────────────────────────────────────────────────────
   Tier pills carry the tier's own colour and person pills the hue that person already
   wears everywhere else, so the column can be read at a glance instead of parsed. */
.ss-perm-dot{width:7px;height:7px;border-radius:50%;flex:none;margin-right:1px}
/* Enough people on one permission used to overflow the cell and clip the × on the ones at
   the end — they could be added and then never removed. The list scrolls inside its own
   cell now, so a long row is a short scroll rather than a reason to scroll the page. */
.ss-perm-holders{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;padding-bottom:2px;
  scrollbar-width:thin;scrollbar-color:var(--hairline-3,rgba(255,255,255,.2)) transparent}
.ss-perm-holders::-webkit-scrollbar{height:5px}
.ss-perm-holders::-webkit-scrollbar-thumb{background:var(--hairline-3,rgba(255,255,255,.2));border-radius:99px}
.ss-perm-holders::-webkit-scrollbar-track{background:transparent}
.ss-perm-holders > *{flex:none}
/* Member actions: side by side, never wrapped or clipped. */
#page-settings .ss-member-acts{flex-wrap:nowrap;white-space:nowrap}
#page-settings .ss-member-acts .ss-btn-sm{flex:none}


/* The person tint is scoped to the card modal, so a person pill anywhere else fell back to
   the generic field fill. A permission holder is the same person, and one person is ONE
   colour across the product — here too. */
.ss-perm-holders .prop-person-pill[style*="--pp-hue"]{
  background:hsla(var(--pp-hue,0),52%,50%,.16);box-shadow:none;border:none;color:var(--cream)}
.ss-grant .prop-person-dropdown-item{color:var(--off-white)}

/* ── A reference whose target is gone ──────────────────────────────────────────
   Last in the sheet on purpose: .mention-project and .mention-task are each restyled
   by later !important passes, so anything earlier loses to them on colour and cursor.
   It reads as absent rather than as a thing you can click — muted, italic, no hover. */
.mention.mention-missing,.prop-pill.router-pill-missing{
  color:var(--muted)!important;background:var(--bg-inset)!important;
  font-style:italic;cursor:default!important}
.mention.mention-missing:hover,.prop-pill.router-pill-missing:hover{
  background:var(--bg-inset)!important;color:var(--muted)!important}

/* ── Danger zone, at the foot of the Workspace tab ──────────────────────────
   Separated by space and a hairline rather than by being a place you navigate to:
   deleting a workspace is the last thing you do to one, not a destination. */
.ss-danger-section{margin-top:48px;padding-top:26px;border-top:1px solid var(--border-d)}
.ss-danger-section .ss-danger-h{color:var(--color-error,#ef4444);margin:0 0 4px}
.ss-danger-section .ss-danger-p{color:var(--muted);margin-bottom:20px}

/* ── Custom sidebar icons: the slot shimmers until the image arrives ──────────
   Same sweep as every other skeleton in the app (skelShimmer), sized to the icon so
   the row never reflows when the picture lands. `is-loaded` is set by the image's own
   onload — and by onerror too, so a dead URL leaves a quiet empty slot rather than a
   shimmer that never stops. */
.app-icon-skel{display:inline-flex;align-items:center;justify-content:center;flex:none;
  vertical-align:middle;overflow:hidden;border-radius:5px;
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi,rgba(255,255,255,.13)) 50%,var(--bg-inset) 75%);
  background-size:200% 100%;animation:skelShimmer 1.4s linear infinite}
.app-icon-skel.is-loaded{background:none;animation:none}
/* The image is NEVER faded in. It used to start at opacity 0 and animate on load, which
   made every sidebar repaint — deleting an item, renaming one — flash every custom emote
   in the list: the <img> is recreated, so even a cached one began invisible. The shimmer
   sits BEHIND the picture instead, and a cached image simply paints over it on the first
   frame with nothing to see. */
.app-icon-skel img{opacity:1}
@media(prefers-reduced-motion:reduce){
  .app-icon-skel{animation:none;background:var(--bg-inset)}
}

/* ── Type-the-name delete confirmation ─────────────────────────────────────────
   The second of two gates. A native prompt() was doing this job — it looks like
   nothing else in the app and it accepts a stray Return. Here the button stays
   disabled until the typed name matches. */
.ss-del-back{position:fixed;inset:0;z-index:12000;background:rgba(0,0,0,.62);
  display:flex;align-items:center;justify-content:center;padding:24px}
.ss-del-card{background:var(--surface-container);border:1px solid var(--border-d);
  border-radius:16px;padding:24px 26px;max-width:460px;width:100%}
.ss-del-h{margin:0 0 8px;font:600 17px var(--sans);color:var(--danger-text)}
.ss-del-p{margin:0 0 12px;font:500 13px/1.55 var(--sans);color:var(--muted)}
.ss-del-p b{color:var(--off-white)}
.ss-del-input{width:100%;box-sizing:border-box;padding:11px 14px;border-radius:9px;
  border:1px solid var(--border-d);background:var(--surface-inset);color:var(--off-white);
  font:600 14px var(--sans);outline:none}
.ss-del-input:focus{border-color:var(--danger-text)}
.ss-del-acts{display:flex;gap:10px;justify-content:flex-end;margin-top:18px}
/* The dialog's buttons wear the app's control spec (36px, r10, filled surface) — the bare
   .ss-btn base is transparent with settings-page padding, which is the odd one out here. */
.ss-del-acts .ss-btn{height:36px;padding:0 16px;border-radius:10px;font-size:13px;
  display:inline-flex;align-items:center;border:0}
.ss-del-acts .ss-btn:not(.ss-btn-danger){background:var(--control-surface);color:var(--text-1)}
.ss-del-acts .ss-btn:not(.ss-btn-danger):hover{background:var(--control-surface-hover)}
.ss-del-acts .ss-btn[disabled]{opacity:.4;cursor:not-allowed}

/* ── Home tabs ────────────────────────────────────────────────────────────────
   The project view-tab strip, reused: same plate, same sliding pill, same icon+label
   button. Home is a page like any other, so its tabs are the app's tabs. */
.home-tabs{margin:2px 0 20px}
.home-tab-pane{display:block}
.home-tab-pane .ss-stats{margin-top:0}
/* .gv-flat-table carries margin:14px 16px 22px — an inset sized for the project pane it
   was written for, where the pane itself has no padding. Here the pane is already inset,
   so the 16px pushed the panel 16px right of the tab strip, the greeting and the stat
   tiles: everything on the page lined up except the tables. */
.home-tab-pane .gv-flat-table{margin:0 0 4px 0 !important;max-height:none}
/* Widgets are a surface, not an outlined box — same call as the settings tiles. */
.home-tab-pane .ss-stat{border:0;background:var(--surface-container)}
.home-tab-pane .ss-section-head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:12px}
.home-tab-pane .ss-section-head h3{margin:0}
/* Sortable headers read as clickable — the project List view's own header cells do not
   sort, so this is the one place the affordance is added rather than inherited. */
.home-tab-pane .gv-flat-header .gv-flat-col{cursor:pointer;user-select:none}
.home-tab-pane .gv-flat-header .gv-flat-col:hover{color:var(--cream)}
.home-tab-pane .gv-flat-cell .tm-av{display:inline-flex;flex:none;margin-right:9px}
.gv-flat-cell .tm-status{margin-left:0}
/* A roster is mostly faces, and an uploaded photo arrives a beat after the row does — so
   the list painted with holes in it and then filled them in one by one. The circle is
   already there, in the same grey as the surfaces around it, and the photo lands into it. */
/* Sized to the avatar it holds — personAvatarHtml is called with 26 and .tm-av defaults to
   30, so the placeholder showed as a 2px ring around every photo: the circle peeking out
   from underneath. */
.home-tab-pane .gv-flat-cell .tm-av{width:26px;height:26px;background:var(--surface-raised)}
.home-tab-pane .gv-flat-cell .tm-av > *{width:100%;height:100%}
.home-tab-pane .gv-flat-cell .tm-av img{width:100%;height:100%;object-fit:cover;display:block}
.home-tab-pane .gv-flat-cell .sd-ws-ic{margin-right:9px}
.home-tab-pane .gv-flat-row{cursor:pointer}
.home-tab-pane .hm-name{font-weight:600;color:var(--off-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.home-tab-pane .tm-sub{font:500 11px var(--sans);color:var(--muted)}

/* ── The app's own select ─────────────────────────────────────────────────────
   A native <select> paints its menu with the OS widget — a white Chrome list on macOS
   in the middle of a dark dialog — and no amount of CSS reaches inside it. This is a
   button that matches the text fields beside it and opens the same anchored popover
   every other picker uses (.prop-person-dropdown). */
.hs-select{display:flex;align-items:center;justify-content:space-between;gap:10px;
  width:100%;box-sizing:border-box;padding:8px 12px;border:1px solid var(--border-d);
  border-radius:6px;background:rgba(255,255,255,.04);color:var(--cream);
  font:500 13px var(--sans);cursor:pointer;text-align:left;transition:border-color .12s,background .12s}
.hs-select:hover{background:rgba(255,255,255,.07)}
.hs-select:focus-visible{outline:none;border-color:var(--purple)}
.hs-select-label{flex:1;min-width:0;display:grid;white-space:nowrap}
/* Both labels occupy the SAME grid cell, so the cell measures the wider of the two and the
   control keeps one width whichever option is selected. */
.hs-select-label > *{grid-area:1/1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hs-sel-ghost{visibility:hidden;pointer-events:none}
.hs-select-caret{width:14px;height:14px;flex:none;color:var(--muted);transition:transform .16s ease}
/* Open: the caret turns over and the button's bottom edge squares off, so the menu
   below it is the same box continuing rather than a second one. */
.hs-select.is-open{border-color:var(--purple);border-bottom-left-radius:0;border-bottom-right-radius:0}
.hs-select.is-open .hs-select-caret{transform:rotate(180deg)}
/* Grows out of the button — same easing and the same idea as the workspace menu
   growing out of its pill, with the seam between them left open. */
/* 220px (the shared person-dropdown cap) cut a list of eight off at five and a half, so
   the remaining sounds were only reachable by scrolling a menu that gave no sign it
   scrolled. These lists are short — let them stand up to the viewport instead. */
.hs-select-menu{z-index:100001;max-height:min(360px,60vh);transform-origin:top center;border-top-left-radius:0;border-top-right-radius:0;
  border-top-color:transparent;border-color:var(--purple);padding:4px 0;
  animation:sdMenuOpen .2s cubic-bezier(.21,.61,.35,1)}
.hs-select-menu .hs-select-item{display:flex;align-items:center;padding:8px 12px;font-size:13px;
  animation:sdCascadeIn .24s cubic-bezier(.21,.61,.35,1) backwards;
  animation-delay:calc(var(--sd-i,0)*22ms)}
.hs-select-menu .hs-select-item.is-on{color:var(--off-white);background:rgba(124,92,255,.14)}
.hs-select-menu .hs-select-item.is-on::after{content:'✓';margin-left:auto;color:var(--purple);font-weight:700}
/* The dock hover: the hovered row's content scales, its neighbours scale less. */
.hs-select-menu .hs-select-item:hover > .dd-hop-row{transform:scale(1.06)}
.hs-select-menu .hs-select-item:hover + .hs-select-item > .dd-hop-row,
.hs-select-menu .hs-select-item:has(+ .hs-select-item:hover) > .dd-hop-row{transform:scale(1.02)}
@media(prefers-reduced-motion:reduce){
  .hs-select-menu,.hs-select-menu .hs-select-item{animation:none}
  .hs-select-menu .dd-hop-row,.hs-select-caret{transition:none}
}
html[data-theme="light"] .hs-select{background:rgba(0,0,0,.03)}
html[data-theme="light"] .hs-select:hover{background:rgba(0,0,0,.06)}

/* ── Connected-drives menu (the Files + tab) ──────────────────────────────────
   The workspace switcher's own panel, floated. .server-dropdown is positioned inside
   the sidebar card (absolute, top:100%, left/right:8px); this one is placed by
   attachAnchoredPopover, so the position is overridden and everything else — the glass,
   the radius, the opening animation, the row cascade and the dock hover — is inherited
   from the classes it already carries. */
.hd-drives-menu.server-dropdown{position:fixed;top:0;left:0;right:auto;
  min-width:274px;max-width:340px;z-index:10001;
  transform-origin:top center;animation:sdMenuOpen .2s cubic-bezier(.21,.61,.35,1)}
.hd-drives-menu .server-dropdown-item{width:100%;gap:9px;
  animation:sdCascadeIn .24s cubic-bezier(.21,.61,.35,1) backwards;
  animation-delay:calc(var(--sd-i,0)*22ms)}
.hd-drives-menu .server-dropdown-item[disabled]{opacity:.5;cursor:default}
.hd-drives-menu .server-dropdown-item[disabled]:hover{background:none}
.hd-drives-menu .server-dropdown-item[disabled] .dd-hop-row{transform:none}
.hd-drives-menu .sdi-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hd-drives-menu .hd-dm-state{flex:none;font-size:10px;color:var(--muted);white-space:nowrap}
.hd-drives-menu .hd-dm-note{padding:9px 11px;font:500 11px var(--sans);color:var(--muted)}
.hd-drives-menu .hd-dm-err{color:var(--danger-text)}
.hd-drives-menu img,.hd-drives-menu .dd-hop-row > svg{flex:none;width:15px;height:15px}
@media(prefers-reduced-motion:reduce){
  .hd-drives-menu.server-dropdown,.hd-drives-menu .server-dropdown-item{animation:none}
}


/* ── Image viewer ────────────────────────────────────────────────────────────
   Same scrim as the task modal (rgba(0,0,0,.6)), so the conversation is still
   legible behind the picture rather than replaced by it. */
.img-viewer{position:fixed;inset:0;z-index:10600;display:flex;align-items:center;justify-content:center;
  padding:48px 32px;background:rgba(0,0,0,.6);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  animation:crPopIn .14s ease}
.img-viewer-fig{margin:0;display:flex;flex-direction:column;align-items:center;gap:10px;max-width:100%;max-height:100%}
.img-viewer img{max-width:min(92vw,1400px);max-height:82vh;width:auto;height:auto;object-fit:contain;
  border-radius:10px;box-shadow:0 24px 70px rgba(0,0,0,.6);display:block}
.img-viewer figcaption{font:500 12px var(--sans);color:rgba(255,255,255,.72);
  max-width:min(92vw,1400px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.img-viewer-x{position:absolute;top:16px;right:18px;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--glass-border);background:rgba(20,20,24,.72);color:var(--ink-solid);
  display:grid;place-items:center;cursor:pointer;transition:background .12s ease}
.img-viewer-x:hover{background:rgba(40,40,48,.9)}
.img-viewer-x svg{width:17px;height:17px}
@media (prefers-reduced-motion:reduce){.img-viewer{animation:none}}


/* ── New message dropdown ────────────────────────────────────────────────────
   Structure comes from .server-dropdown (glass, sdMenuOpen, the row cascade and
   the dock hover); this only sizes it and lays out a person row. */
.dm-new-menu.server-dropdown{position:fixed;inset:auto;z-index:10300;width:270px;padding:6px;
  max-height:min(60vh,420px);display:flex;flex-direction:column}
.dm-new-search{flex:none;width:100%;margin:2px 2px 6px;padding:7px 9px;border-radius:8px;
  border:1px solid var(--glass-border);background:var(--bg-inset);color:var(--ink-solid);
  font:500 12px var(--sans);outline:none}
.dm-new-search:focus{border-color:var(--purple)}
.dm-new-list{overflow-y:auto;min-height:0}
.dm-new-menu .dm-new-row{padding:6px 8px}
.dm-new-menu .dm-new-row > .dd-hop-row{gap:9px}
.dm-new-menu .dm-sb-av{width:26px;height:26px;border-radius:50%;overflow:hidden;flex:none;
  display:flex;align-items:center;justify-content:center;font-size:11px;color:#fff}
.dm-new-menu .dm-sb-av img,.dm-new-menu .dm-sb-av svg{width:100%;height:100%;object-fit:cover;display:block}
.dm-new-menu .dm-person-meta{min-width:0;display:flex;flex-direction:column;gap:1px}
.dm-new-menu .dm-person-name{font-size:12.5px;font-weight:600;color:var(--ink-solid);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dm-new-menu .dm-person-email{font-size:10.5px;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dm-new-empty{padding:10px;font-size:12px;color:var(--muted)}

/* Preview button beside the notification-sound picker. */
/* Height tracks the select (stretch), so the two always share a baseline no matter what
   the select's padding becomes. aspect-ratio cannot size the width here — a flex item takes
   its base size from content first — so the width is the select's own box math: 13px text
   + 8px padding + 1px border, top and bottom. */
.us-sound-play{align-self:stretch;height:auto;width:34px;flex:none;border-radius:6px;
  border:1px solid var(--border-d);
  background:var(--bg-inset);color:var(--ink-solid);display:grid;place-items:center;cursor:pointer;
  transition:background .12s ease,border-color .12s ease}
.us-sound-play:hover{background:var(--surface-raised);border-color:var(--purple)}
.us-sound-play svg{width:14px;height:14px}

/* An <a class="ss-btn"> and a <button class="ss-btn"> are the same control, so they have
   to measure the same. A button inherits none of the page's type by default and carries
   the UA's own padding, which is why Open and Edit — identical classes, different tags —
   came out different sizes side by side in the Templates row. */
a.ss-btn,button.ss-btn,.ss-btn{font-family:var(--sans);font-size:12px;font-weight:600;box-sizing:border-box;
  display:inline-flex;align-items:center;justify-content:center;text-decoration:none;
  line-height:1.2;vertical-align:middle}
a.ss-btn.ss-btn-sm,button.ss-btn.ss-btn-sm,.ss-btn.ss-btn-sm{font-size:11px}

/* "& N more" — a count that opens the full list, sized to sit level with the pill
   beside it rather than reading as a second name. */
.prop-person-more{flex:none;margin-left:4px;padding:2px 8px;border-radius:999px;
  border:1px solid var(--border-d);background:var(--bg-inset);color:var(--muted);
  font:600 10px var(--sans);cursor:pointer;white-space:nowrap;
  transition:background .12s ease,color .12s ease,border-color .12s ease}
.prop-person-more:hover{background:var(--surface-raised);color:var(--ink-solid);border-color:var(--purple)}
.prop-people-menu.server-dropdown{position:fixed;inset:auto;z-index:10300;width:250px;padding:6px;
  max-height:min(52vh,360px);overflow-y:auto}
.prop-people-head{padding:6px 9px 5px;font:700 10px var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted)}
.prop-people-menu .prop-people-row{padding:6px 8px}
.prop-people-menu .prop-people-row > .dd-hop-row{gap:9px}
.prop-people-meta{min-width:0;display:flex;flex-direction:column;gap:1px}
.prop-people-name{font-size:12.5px;font-weight:600;color:var(--ink-solid);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prop-people-mail{font-size:10.5px;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ── Home: Ask ───────────────────────────────────────────────────────────
   No inset well and no outline: the composer sits ON the card, in the card's own
   colour, so it reads as part of it rather than a control dropped into it. */
/* The composer is a direct child of the card, so the card carries the inset itself —
   without it the placeholder and the answer ran into the card's left edge while every
   other card on Home stayed indented. Matches the .hh-card-head rhythm beside it. */
/* Padding matches .hh-card-head's 18/22 so the composer lines up with every other
   card's content, and the 16px bottom margin is the one .hh-load already carries — cards
   here are stacked in a plain block, so each provides its own gap and this one had none,
   leaving it welded to Coming up. */
.hh-ask{padding:18px 22px 16px;margin:0 0 16px}
.hh-ask-box{display:block;padding:0;border:0;background:none}
.hh-ask-field{position:relative;min-height:26px}
/* Room to actually write a question, and a box with enough presence to be the thing you
   reach for — at one line tall it read as a search field someone had left behind. */
.hh-ask-input{display:block;width:100%;border:0;background:none;outline:none;
  color:var(--ink-solid);font:500 15px var(--sans);padding:2px 0 16px;
  min-height:46px;white-space:pre-wrap;word-break:break-word}
.hh-ask-input:empty::before{content:attr(data-placeholder);color:var(--muted);pointer-events:none}
/* Replaces the field outright while it works — a caret blinking in a box you cannot
   type into is what reads as broken. */
.hh-ask-thinking{display:flex;align-items:flex-start;gap:9px;padding:2px 0 16px;
  min-height:46px;font:500 15px var(--sans);color:var(--muted)}
/* A `display` rule beats the [hidden] attribute's UA style, so anything given one here
   has to opt back out explicitly — otherwise the thinking row sat on screen next to the
   placeholder from first paint. */
.hh-ask-thinking[hidden],.hh-ask-atts[hidden],.hh-ask-out[hidden]{display:none !important}
.hh-ask-spin{width:15px;height:15px;flex:none;border-radius:50%;
  border:2px solid var(--border-d);border-top-color:var(--purple);
  animation:bsoSpin var(--dur-complex,500ms) linear infinite}
.hh-ask-tools{display:flex;align-items:center;gap:8px}
.hh-ask-tool{width:32px;height:32px;flex:none;border-radius:50%;cursor:pointer;
  border:1px solid var(--border-d);background:var(--surface-raised);color:var(--muted);
  display:grid;place-items:center;transition:background .12s ease,color .12s ease,border-color .12s ease}
.hh-ask-tool:hover{background:var(--bg-inset);color:var(--ink-solid);border-color:var(--purple)}
.hh-ask-tool svg{width:15px;height:15px}
.hh-ask-go{margin-left:auto}
/* Same 32px as the @ and the paperclip: three controls on one row, one size. */
.hh-ask-go{flex:none;width:32px;height:32px;border-radius:50%;border:0;cursor:pointer;
  background:var(--purple);color:#fff;display:grid;place-items:center;
  transition:filter .12s ease,background .12s ease}
.hh-ask-go:hover{filter:brightness(1.12)}
.hh-ask-go.is-cancel{background:var(--color-error)}
.hh-ask-go svg{width:15px;height:15px}
.hh-ask-atts{display:flex;flex-wrap:wrap;gap:6px;padding:0 0 10px}
.hh-ask-att{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:8px;
  background:var(--surface-raised);border:1px solid var(--border-d);
  font:600 11px var(--sans);color:var(--ink-solid)}
.hh-ask-att button{border:0;background:none;color:var(--muted);cursor:pointer;font-size:13px;line-height:1;padding:0}
.hh-ask-att button:hover{color:var(--color-error-text)}
/* No box. The answer is the card's own content, and wrapping it in a second bordered
   panel inside the card read as a quote from somewhere else. */
/* Dropping files on the composer: the same purple the app uses for a live drop target. */
.hh-ask.is-dropping{outline:2px dashed var(--purple);outline-offset:-4px;
  background:color-mix(in srgb,var(--purple) 7%,transparent)}
/* Above the composer now: the margin is below it, and the hairline sits under the answer
   to separate it from the box rather than floating under the whole card. */
.hh-ask-out{margin:0 0 14px;padding:0 0 12px;border:0;border-bottom:1px solid var(--border-d);background:none;
  font:500 13.5px var(--sans);color:var(--ink-solid);line-height:1.55;white-space:pre-wrap}
.hh-ask-out.is-error{color:var(--color-error-text)}
@media (prefers-reduced-motion:reduce){.hh-ask-spin{animation:none}}

/* Template workspace: the two verbs that end the job, where the bell used to be. */
.topbar-tpl-actions{display:flex;align-items:center;gap:8px}
body.is-template-ws .topbar-search,
body.is-template-ws #helpBtn,
body.is-template-ws #notifBell{display:none !important}

/* Template actions sit at the far right of the topbar, where the bell was. */
.topbar-tpl-actions{margin-left:auto}
/* While editing a template the crumb says what you are doing, not where you are. */
body.is-template-ws .topbar-crumb > :not(#topbarTplLabel){display:none !important}
/* Home inside a template: shown, so you can see what the layout produces, and completely
   inert, because none of it means anything until the template is used. Grayscale rather
   than a blur — the shapes still have to read as the cards they are. */
.home-inbox.is-tpl-locked{filter:grayscale(1);opacity:.42;pointer-events:none;user-select:none}
.home-inbox.is-tpl-locked *{cursor:default !important}
.tc-tpl{font-style:normal}

/* ── Ask: collecting what it needs ───────────────────────────────────────────
   One question on screen at a time with its place in the run, instead of a
   numbered list to answer all at once. Takes over the field while it is up. */
.hh-ask-wiz{padding:2px 0 14px}
.hh-ask-wiz[hidden]{display:none !important}
.hh-wiz-head{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.hh-wiz-intent{font:700 11px var(--sans);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.hh-wiz-step{margin-left:auto;font:700 11px var(--sans);color:var(--purple);
  padding:2px 8px;border-radius:999px;background:color-mix(in srgb,var(--purple) 16%,transparent)}
.hh-wiz-q{font:500 15px var(--sans);color:var(--ink-solid);margin-bottom:10px;line-height:1.4}
.hh-wiz-input{width:100%;padding:9px 12px;border-radius:10px;border:1px solid var(--border-d);
  background:var(--bg-inset);color:var(--ink-solid);font:500 14px var(--sans);outline:none}
.hh-wiz-input:focus{border-color:var(--purple)}
.hh-wiz-input.is-missing{border-color:var(--color-error)}
.hh-wiz-opts{display:flex;flex-wrap:wrap;gap:6px}
.hh-wiz-opt{padding:7px 12px;border-radius:999px;cursor:pointer;
  border:1px solid var(--border-d);background:var(--surface-raised);
  color:var(--ink-solid);font:600 12px var(--sans);transition:background .12s ease,border-color .12s ease}
.hh-wiz-opt:hover{border-color:var(--purple)}
.hh-wiz-opt.is-on{background:color-mix(in srgb,var(--purple) 24%,transparent);border-color:var(--purple)}
.hh-wiz-actions{display:flex;align-items:center;gap:8px;margin-top:12px}
.hh-wiz-btn{padding:7px 14px;border-radius:9px;cursor:pointer;border:1px solid var(--border-d);
  background:var(--surface-raised);color:var(--ink-solid);font:600 12px var(--sans);
  transition:background .12s ease,border-color .12s ease}
.hh-wiz-btn:hover{border-color:var(--purple)}
.hh-wiz-btn.is-primary{margin-left:auto;background:var(--purple);border-color:var(--purple);color:#fff}
.hh-wiz-btn.is-primary:hover{filter:brightness(1.1)}
/* Comment count on a kanban card. Was an emoji pair (robot + speech balloon); the rule is
   no emoji in product UI, so it is the app's own icon, tinted when a bot has replied. */
.kc-cmt-count{display:inline-flex;align-items:center;gap:3px;color:var(--muted);font-size:10.5px;line-height:1}
.kc-cmt-count svg{opacity:.75}
.kc-cmt-count.has-bot{color:var(--purple)}
.kc-cmt-count.has-bot svg{opacity:1}

/* The answer's own light formatting. */
.hh-ask-out strong{font-weight:700;color:var(--ink-solid)}
/* Provenance, not prose — it had no rule at all, so it ran straight into the last
   sentence of the answer at the same weight and size. */
.hh-ask-note{margin-top:10px;padding-top:0;border-top:0;
  font:600 11px var(--sans);letter-spacing:.02em;color:var(--muted);white-space:normal}
.hh-ask-out p{margin:0 0 10px}
.hh-ask-out p:last-of-type{margin-bottom:0}
.hh-ask-out code{font:600 12px var(--mono,ui-monospace,monospace);padding:1px 5px;border-radius:5px;
  background:var(--surface-raised)}

/* ── Composer glass + reserved space ─────────────────────────────────────────
   Last in the file on purpose: .chatroom-input-bar's background and
   .chatroom-messages-wrap's padding-bottom are both set again further down than
   where the composer's own rules live, so stating these earlier lost to them. */
.chatroom-input-bar{background:var(--glass-bg);
  backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur)}
.chatroom-messages-wrap,.dm-messages-wrap{padding-bottom:var(--cr-composer-inset,96px)}

/* ── Message rhythm, one definition for both messengers ──────────────────────
   Spacing was set in six places that overrode each other and differently again for
   DMs, which is why a channel showed three different gaps: 1px under the author name,
   10px between a person's own consecutive lines, and 25px before a new speaker. One
   scale now, stated last and with the #dmMessages selector spelled out so it beats the
   DM-specific rules rather than losing to their specificity.
     - under the author name: enough to separate, not enough to detach
     - between one person's consecutive lines: a single step
     - before a new speaker: four steps, which is what makes turns readable */
:root{--msg-step:4px}
.cr-msg-row,#dmMessages .cr-msg-row{
  padding-top:calc(var(--msg-step)/2);padding-bottom:calc(var(--msg-step)/2)}
.cr-msg-row.cr-msg-grouped,#dmMessages .cr-msg-row.cr-msg-grouped{margin-top:0}
.cr-msg-row:not(.cr-msg-grouped),#dmMessages .cr-msg-row:not(.cr-msg-grouped){
  margin-top:calc(var(--msg-step)*4)}
.cr-msg-meta,#dmMessages .cr-msg-meta{margin-bottom:calc(var(--msg-step)/2)}
.cr-msg-text,#dmMessages .cr-msg-text{line-height:1.5}

/* ── Typing indicator + messenger chrome ─────────────────────────────────────
   "X is typing" was left in flow after the composer, which now overlays the list — so it
   rendered UNDERNEATH the box it belongs above. It floats over the list at the composer's
   own height instead, the same number the list reserves. */
.cr-typing-indicator,#dmTypingIndicator{position:absolute;left:0;right:0;
  bottom:var(--cr-composer-inset,96px);z-index:6;pointer-events:none;padding:0 22px}
/* No rules between the messenger's parts. The header, the conversation list and the
   messages are one surface; a hairline between them reads as a seam, which is the same
   thing the header shadow was doing. */
.dmx-header,.dm-chat-header{border-bottom:0}
#dmListCol{border-right:0}

/* The DM views strip is a channel's views strip: tabs left, controls right. */
.dm-views{gap:10px;padding:10px 16px 4px;margin:0 0 6px;display:flex;align-items:center}
.dm-views .dm-header-tabs{margin-right:auto;min-width:0}
.dm-views .cr-search-wrap{flex:none}

/* The DM composer IS the channel composer now, so it inherits .chatroom-input-bar and
   .cr-tool wholesale. Only the send split is DM-only: two .cr-send buttons joined into one
   control, the arrow sending and the caret scheduling. */
.dmx-send-split{display:inline-flex;align-items:stretch;gap:2px}
.dmx-send-split .cr-send{border-radius:8px}
.dmx-send-split .dmx-send-caret{padding-left:6px;padding-right:6px}
.dmx-send-split .dmx-send-caret svg{width:14px;height:14px}
/* The old .cmt-* skin no longer applies to anything in a DM. */

/* ── Deleting from the sidebar ───────────────────────────────────────────────
   A delete used to blink: the row was gone the instant the sidebar re-rendered, so
   nothing connected the click to the thing that left. The row collapses out of the list
   first — height and opacity together, so its neighbours close the gap rather than
   snapping up into it. */
/* Height is set inline from the element's own measurement (see _sbAnimateRemove) — a
   stylesheet number cannot know whether this is a one-line row or a whole folder. 150ms:
   long enough to see the row leave, short enough that it never delays the list closing up. */
.sidebar-cat-item.is-removing,.sidebar-cat-section.is-removing,
.sidebar [data-sidebar-id].is-removing,
.sidebar-section-nav a.is-removing,.sidebar-fav-nav a.is-removing{
  overflow:hidden !important;pointer-events:none;
  transition:height .15s cubic-bezier(.4,0,1,1),opacity .12s ease,transform .15s cubic-bezier(.4,0,1,1),
             margin .15s cubic-bezier(.4,0,1,1),padding .15s cubic-bezier(.4,0,1,1) !important;
  opacity:0 !important;transform:translateX(-18px) !important;
  margin-top:0 !important;margin-bottom:0 !important;
  padding-top:0 !important;padding-bottom:0 !important}
@media(prefers-reduced-motion:reduce){
  .sidebar [data-sidebar-id].is-removing{transition-duration:.01s !important}
}

/* ── Spotlight: asking the assistant ─────────────────────────────────────────
   When nothing in the workspace matches, the magnifier crossfades into the agent's face so
   the palette shows what Enter will do. Both icons occupy the same cell — the second is
   absolutely placed over the first — so nothing shifts as they swap. */
/* Both live in the magnifier's own slot, one stacked on the other, so the swap is a
   crossfade in place and the input never shifts. */
.spotlight-search-icon{position:relative;width:18px;height:18px;display:inline-flex;
  align-items:center;justify-content:center}
.spotlight-search-icon .spotlight-mag,.spotlight-agent-icon{position:absolute;inset:0;
  transition:opacity .18s ease,transform .22s cubic-bezier(.22,1,.36,1)}
.spotlight-agent-icon{opacity:0;transform:scale(.7);pointer-events:none;
  display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px}
.spotlight-agent-icon .shu-av{width:18px !important;height:18px !important}
.spotlight-box.is-agent .spotlight-agent-icon{opacity:1;transform:scale(1)}
.spotlight-box.is-agent .spotlight-mag{opacity:0;transform:scale(.7)}
@media(prefers-reduced-motion:reduce){
  .spotlight-agent-icon,.spotlight-search-icon{transition-duration:.01s}
}

/* ── Coming up: a day you can open ───────────────────────────────────────────
   The bars were a picture of the week with no way in. A day with anything due is now a
   button, and clicking it lists that day in the app's own dropdown. */
.hl-day[role="button"]{cursor:pointer;border-radius:8px;transition:background .12s ease}
.hl-day[role="button"]:hover{background:rgba(255,255,255,.05)}
.hl-day[role="button"]:hover .hl-bar{filter:brightness(1.25)}
.hl-day[role="button"]:focus-visible{outline:2px solid var(--purple);outline-offset:2px}
.hl-pop{min-width:260px;max-width:340px;max-height:340px;overflow-y:auto}
.hl-pop-head{padding:8px 12px 6px;font:700 10.5px var(--sans);letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
.hl-pop-row{align-items:flex-start}
.hl-pop-row .dd-hop-row{display:flex;flex-direction:column;gap:1px;align-items:flex-start;min-width:0}
.hl-pop-title{font:600 12.5px var(--sans);color:var(--cream);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;max-width:280px}
.hl-pop-sub{font:500 11px var(--sans);color:var(--muted)}

/* ── Shu ─────────────────────────────────────────────────────────────────────
   A 16x16 sprite, not a generated head. No circle and no plate: the art is transparent and
   he sits on whatever is behind him. image-rendering:pixelated keeps the pixels crisp at
   any size — the whole point of drawing him at 16x16. Multi-frame poses are one row of
   16px cells stepped by a steps() animation, which is why the sheet width is n*100%. */
/* Sprite stepping, size-independent. background-size makes the sheet exactly N element-
   widths wide, so one frame fills the box; background-position-x then runs 0%→100%, which
   for an over-wide image spans 0 → -(N-1)·W. To land on all N frames and no half-frames
   that needs N values across that range, which is steps(N-1, jump-none) — NOT steps(N).
   steps(N) gives k/N of the range (0, -0.75W, -1.5W, -2.25W for four frames), i.e. every
   position BETWEEN frames, which is what made him flash. */
/* He is drawn in TWO layers. The sheet on the element itself is everything that never
   changes colour — the black outline, the cream belly and beak, the coral feet. The ::after
   carries only his violet plumage, and that layer is what takes the colour of whatever he
   is labelling. Hue-rotating the whole penguin would have turned his belly and feet too.
   His three violets (highlight, base, shadow) all sit at 246deg, so ONE rotation moves them
   together and the shading survives — which flattening them to a tinted silhouette would not.
   --shu-hue defaults to the source hue, so a rotation of zero leaves him exactly as drawn. */
.shu-av{display:inline-block;flex:none;line-height:0;background-repeat:no-repeat;
  background-position:0 0;position:relative;
  image-rendering:pixelated;image-rendering:crisp-edges;border-radius:0;overflow:visible}
.shu-av::after{content:'';position:absolute;inset:0;pointer-events:none;
  background-repeat:no-repeat;background-position:0 0;
  image-rendering:pixelated;image-rendering:crisp-edges;
  filter:hue-rotate(calc(var(--shu-hue,246.1deg) - 246.1deg)) saturate(var(--shu-sat,1))}
/* steps(N, jump-none) — N stops, one per frame. steps(N-1, jump-none) gives N-1 stops:
   for four frames that is 0%, 50%, 100%, so it showed frame 1, a point halfway BETWEEN
   frames 2 and 3, then frame 4. That half-frame is what looked like him sliding left. */
.shu-sit{background-image:url('/img/shu-sit-base.png?v=f7b8bf87');background-size:100% 100%}
.shu-sit::after{background-image:url('/img/shu-sit-tint.png?v=00f309c6');background-size:100% 100%}
.shu-chill{background-image:url('/img/shu-chill-base.png?v=a0673ed1');background-size:100% 100%}
.shu-chill::after{background-image:url('/img/shu-chill-tint.png?v=0c3be81b');background-size:100% 100%}
.shu-run{background-image:url('/img/shu-run-base.png?v=f8fcb2e0');background-size:400% 100%;
  animation:shuStep .48s steps(4,jump-none) infinite}
.shu-run::after{background-image:url('/img/shu-run-tint.png?v=714496b4');background-size:400% 100%;
  animation:shuStep .48s steps(4,jump-none) infinite}
.shu-spin{background-image:url('/img/shu-spin-base.png?v=4a7ba1ed');background-size:700% 100%;
  animation:shuStep .70s steps(7,jump-none) infinite}
.shu-spin::after{background-image:url('/img/shu-spin-tint.png?v=adab1c12');background-size:700% 100%;
  animation:shuStep .70s steps(7,jump-none) infinite}
@keyframes shuStep{from{background-position-x:0%}to{background-position-x:100%}}
@media(prefers-reduced-motion:reduce){
  .shu-run,.shu-spin{animation:none;background-image:url('/img/shu-sit-base.png?v=f7b8bf87')}
  .shu-run::after,.shu-spin::after{animation:none;background-image:url('/img/shu-sit-tint.png?v=00f309c6')}
}
/* Nothing may put him back in a frame: the avatar slots across the app paint a round plate
   and a background colour for a generated head, and he is not one. */
.card-avatar:has(.shu-av),.dmx-av:has(.shu-av),.cr-msg-avatar:has(.shu-av),
.mention-avatar:has(.shu-av),.spotlight-item-icon:has(.shu-av),
.cr-profile-avatar-lg:has(.shu-av),.dm-header-avatar:has(.shu-av){
  /* border too. The profile card's avatar plate carries a 4px ring in the card's own dark,
     which is invisible against a round plate and became a hard dark SQUARE the moment the
     radius came off for him. */
  background:none !important;border:0 !important;border-radius:0 !important;overflow:visible !important}
.shu-av > *{display:none}

/* ── Shu working, and Shu speaking ───────────────────────────────────────────
   The spinner and the words "is thinking" are gone. What you get instead is the character
   himself, animating, next to a skeleton where the sentence will be — the same shape the
   answer takes, so nothing jumps when it arrives. */
.hh-ask-thinking{display:block;min-height:1.5em}
/* Shu sits in the composer whether or not he is doing anything — he is a member of the
   workspace, not a loading state that appears and vanishes. The box makes room for him. */
/* Shu sits in his own column at the left of the composer, directly above the @ button and
   level with the FIRST line of the field — so he reads as sitting beside what you type
   rather than floating in the padding. The tools moved left to sit under him; the column
   width and the tool size are the same number, which is what makes them line up. */
.hh-ask-box{position:relative;padding-left:0}
.hh-shu-perch{position:absolute;left:0;top:0;width:32px;height:32px;z-index:2;
  /* centred on the first text line: half the line box, minus half his height */
  transform:translateY(calc((1.5em - 32px) / 2))}
.hh-ask-field{padding-left:44px}
.hh-ask-tools{padding-left:0}
.hh-ask-wiz,.hh-ask-atts{padding-left:44px}
.sk-lines{display:flex;flex-direction:column;gap:6px;flex:1;min-width:0}
.sk-lines i{display:block;height:9px;border-radius:5px;
  background:linear-gradient(90deg,rgba(255,255,255,.05) 25%,rgba(255,255,255,.12) 37%,rgba(255,255,255,.05) 63%);
  background-size:400% 100%;animation:skShimmer 1.4s ease infinite}
.sk-lines i:nth-child(1){width:78%}
.sk-lines i:nth-child(2){width:92%;animation-delay:.12s}
.sk-lines i:nth-child(3){width:54%;animation-delay:.24s}
@keyframes skShimmer{0%{background-position:100% 0}100%{background-position:0 0}}

/* One word at a time: blurred and slightly low, resolving into place. inline-block is what
   makes the transform and filter apply at all — an inline span ignores both. */
.shu-word{display:inline-block;animation:shuWordIn .34s cubic-bezier(.22,1,.36,1) both}
@keyframes shuWordIn{
  from{opacity:0;filter:blur(6px);transform:translateY(3px)}
  to{opacity:1;filter:blur(0);transform:none}
}
@media(prefers-reduced-motion:reduce){
  .sk-lines i{animation:none}
  .shu-word{animation:none}
}

/* Nothing in the bubble while he writes — just enough height that the row does not collapse
   and jump when the words arrive. The row's OWN avatar animates (below).
   The skeleton that used to live here is gone: the words arriving IS the transition, so a
   second thing to watch only had to be swapped out again. width:1px is what made the
   spotlight's copy of this span show as a stray vertical line, so it holds no width there. */
/* vertical-align:top matters as much as the height. An inline-block sits on the BASELINE
   by default, so its box adds the font's descender space under it and the line grows taller
   than a line of text — the row was a couple of pixels taller while he wrote and settled
   when the words arrived, which is the chat nudging itself as he answers. */
/* One line of skeleton while Shu composes. It was width:0 — collapsed to literally
   nothing when the walking sprite's layout shift was fixed, which threw out the "he is
   typing" signal with the shift. A shimmer LINE moves nothing when the reply lands. */
.shu-pending{display:inline-block;height:1em;width:180px;max-width:60%;vertical-align:middle;
  border-radius:6px;
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi,rgba(255,255,255,.14)) 50%,var(--bg-inset) 75%);
  background-size:200% 100%;animation:skelShimmer 1.4s linear infinite}
@media(prefers-reduced-motion:reduce){.shu-pending{animation:none}}
.spot-answer-body .shu-pending{display:inline-flex;height:auto;width:auto}
/* While he is writing, the avatar already beside the message does the work. */
.cr-msg-row.is-shu-working .shu-av{
  background-image:url('/img/shu-run-base.png?v=f8fcb2e0');background-size:400% 100%;
  animation:shuStep .48s steps(4,jump-none) infinite}
.cr-msg-row.is-shu-working .shu-av::after{
  background-image:url('/img/shu-run-tint.png?v=714496b4');background-size:400% 100%;
  animation:shuStep .48s steps(4,jump-none) infinite}

/* Shu answering inside the palette, where the results were. */
.spot-answer{padding:14px 16px 16px}
.spot-answer-q{font:600 12px var(--sans);color:var(--muted);margin-bottom:10px;
  letter-spacing:.02em}
.spot-answer-body{font:500 13.5px var(--sans);color:var(--ink-solid);line-height:1.55;
  white-space:pre-wrap;max-height:320px;overflow-y:auto}
.spotlight-box.is-answering .spotlight-footer{opacity:.45}

/* The sidebar sits a shade darker than the canvas, so the two planes read apart without a
   border or a cast shadow between them. --sb-bg above is kept in step: the lock badge
   composites against it and would otherwise show as a lighter square. */
.sidebar{background:#050507}

/* A mention sits ON the text baseline. The chip is inline-flex with its own avatar, which
   makes its box taller than a line of text — without an explicit alignment the browser
   drops it to the bottom edge and the sentence steps down around every mention. */
/* The jump sheet: same 20px-wide cell as every other pose, so a pixel stays the same size,
   on a 23-row cell (21 of art + the 2 empty rows sit/chill carry under their feet). shuJump()
   grows the box by that ratio and pulls it up by the difference, so the ground line holds.
   Two animations at once: the frames, and the travel. Real gravity means the two halves are
   NOT the same curve — he leaves the ground fast and slows into the apex, then accelerates
   the whole way down. One symmetric ease for both reads as floating, not falling. */
@keyframes shuHop{
  0%   {transform:translateY(var(--shu-base,0px));
        animation-timing-function:cubic-bezier(.15,.75,.4,1)}
  /* The apex sits at 50%, exactly where steps(4) crosses from the second frame to the
     third — so the two rise frames play on the way up and the two fall frames on the way
     down, instead of the sprite changing state a beat before he turns over. */
  50%  {transform:translateY(calc(var(--shu-base,0px) - var(--shu-hop,18px)));
        animation-timing-function:cubic-bezier(.62,0,.86,.4)}
  100% {transform:translateY(var(--shu-base,0px))}
}
/* He has to be able to leave the card he is standing on. */
.hi-card.hh-ask.shu-hopping{overflow:visible}
/* z-index ONLY. position:relative here put the perch back into normal flow — it is
   absolutely positioned, so the taller jump box started taking up real space and the
   composer grew and shoved the page down under him mid-hop. */
.shu-jump{z-index:4}
/* forwards on the frames: without it the finished animation reverts to its 0% position for
   the moment before the class comes off, which shows as a single standing frame on landing. */
.shu-jump{background-image:url('/img/shu-jump-base.png?v=70d5f89f');background-size:400% 100%;
  animation:shuStep var(--shu-hop-dur,620ms) steps(4,jump-none) 1 forwards,
            shuHop var(--shu-hop-dur,620ms) 1 forwards}
.shu-jump::after{background-image:url('/img/shu-jump-tint.png?v=8ccc454b');background-size:400% 100%;
  animation:shuStep var(--shu-hop-dur,620ms) steps(4,jump-none) 1 forwards}
@media(prefers-reduced-motion:reduce){.shu-jump{animation:none}}
.hh-shu-perch{cursor:pointer}
/* Carries the same arrival as a word without display:inline-block, which would flatten a
   chip that lays itself out as inline-flex. */
.shu-word-el{animation:shuWordIn .34s cubic-bezier(.22,1,.36,1) both}
@media(prefers-reduced-motion:reduce){.shu-word-el{animation:none}}

.mention,.mention-chip{vertical-align:middle;position:relative;top:-1px}
.mention .card-avatar,.mention-chip .card-avatar,.mention-chip-label{vertical-align:middle}

/* ── Shu's transparent art, everywhere it lands ──────────────────────────────
   A slot that paints its own round plate and a fill colour shows as a dark square behind
   transparent pixel art. :has() covers the containers; the direct rules cover the ones
   whose fill is set inline (.card-avatar sets background per person). */
.card-avatar:has(.shu-av),.user-mini-avatar:has(.shu-av),.ws-member-av:has(.shu-av),
.mv-mention-avatar:has(.shu-av),.cal-mention-avatar:has(.shu-av),
.dmx-avwrap:has(.shu-av),.cr-msg-avatar-slot:has(.shu-av),.hi-avatar:has(.shu-av),
.ha-avatar:has(.shu-av),.sidebar-profile-avatar:has(.shu-av){
  background:none !important;background-color:transparent !important;
  border:none !important;border-radius:0 !important;overflow:visible !important}
/* His own colour is the Henshu purple — used wherever a person contributes a hue (mention
   chips, name colours, the pill accent) so he reads as one of us rather than a stray blue. */
.mention-chip[data-type="bot"],.mention.mention-person:has(.shu-av){--pp-hue:258}
.shu-av{--shu-accent:#7c5cff}

/* The strip under the DM tabs was a rule between the header and the messages. Same surface,
   no line — the channel's strip does not draw one either. */
.dm-views{border-bottom:0;box-shadow:none}
#page-dm .workshop-views{border-bottom:0}

/* A folder header hovers like the rows inside it. It was .02 against a row's .035, with the
   name going to 65% white instead of the row's full colour — so the same gesture looked
   like two different affordances depending on which line you were over. */
.sidebar-nav-scroll .sidebar-section-label:hover,
.sidebar-nav-scroll .sidebar-cat-label:hover{background:rgba(255,255,255,.035)}
.sidebar-nav-scroll .sidebar-section-label:hover .sidebar-section-name,
.sidebar-nav-scroll .sidebar-cat-label:hover .sidebar-section-name{color:var(--off-white)}
.sidebar-nav-scroll .sidebar-section-label,
.sidebar-nav-scroll .sidebar-cat-label{border-radius:8px}


/* ── Channel threads ─────────────────────────────────────────────────────────
   The right third of the room. A side conversation needs somewhere to go that is not the
   middle of the main list, and it needs to stay next to the room rather than replacing it,
   so this splits the body instead of covering it. */
/* A real third. The cap is high enough that a third is actually reachable on a wide
   monitor — a 460px ceiling made it a quarter there — and low enough that an ultra-wide
   does not hand a two-reply thread 900px of empty column. */
.cr-thread-panel{flex:0 0 33%;min-width:320px;max-width:640px;display:flex;flex-direction:column;
  position:relative;background:var(--bg2);min-height:0}
/* The divider is a drag handle. Its hairline fades in from the top so the panel edge
   does not slice straight through the header; no rule under the thread head — the
   parent message's own spacing separates it. */
.cr-thread-resizer{position:absolute;top:0;bottom:0;left:-5px;width:10px;cursor:col-resize;z-index:2;touch-action:none}
.cr-thread-resizer::before{content:'';position:absolute;top:0;bottom:0;left:4px;width:1px;
  background:linear-gradient(to bottom,transparent 0,var(--border-d) 140px,var(--border-d) 100%);transition:background .12s,width .12s,left .12s}
.cr-thread-resizer:hover::before,.cr-thread-resizer.is-dragging::before,.cr-thread-resizer:focus-visible::before{left:3.5px;width:2px;
  background:linear-gradient(to bottom,transparent 0,var(--purple) 140px,var(--purple) 100%)}
.cr-thread-resizer:focus-visible{outline:none}
body.cr-thread-resizing{cursor:col-resize;user-select:none}
body.cr-thread-resizing iframe{pointer-events:none}
.cr-thread-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 18px 8px;flex-shrink:0}
.cr-thread-head-txt{display:flex;flex-direction:column;gap:2px;min-width:0}
.cr-thread-title{display:flex;align-items:center;gap:8px;min-width:0;font-family:var(--serif);font-size:17px;font-weight:500;font-style:italic;color:var(--text-1)}
.cr-thread-title-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex:0 0 auto;color:var(--text-2)}
.cr-thread-title-icon svg{width:16px;height:16px}
.cr-thread-title-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-thread-sub{display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cr-thread-word{font-weight:600}
.cr-thread-by{display:inline-flex;align-items:center;gap:5px;min-width:0;color:var(--cr-au,var(--cream));font-weight:600}
.cr-thread-by .card-avatar{width:16px;height:16px;border:none;flex:0 0 auto}
.cr-thread-by-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-thread-body{flex:1;overflow-y:auto;padding:14px 16px;min-height:0}
.cr-thread-row{display:flex;gap:10px;padding:6px 0}
.cr-thread-main{min-width:0;flex:1}
.cr-thread-parent{padding-bottom:10px}
.cr-thread-count{display:flex;align-items:center;gap:10px;margin:4px 0 8px;
  font-size:11.5px;font-weight:600;color:var(--muted);white-space:nowrap}
.cr-thread-rule{flex:1;height:1px;background:var(--border-d)}
.cr-thread-input-wrap{flex-shrink:0;padding:0 16px 18px;position:relative}
/* The pill that opens one. Sits under the message, aligned with its text, so it reads as
   part of that message rather than as a row of its own. A filled grey pill rather than an
   outlined one: an outline at this size competes with the message it hangs under. */
.cr-thread-ind{align-self:flex-start;margin:4px auto 0 0;padding:3px 10px 3px 7px;
  display:inline-flex;align-items:center;gap:5px;border-radius:11px;border:0;
  background:var(--surface-raised);color:var(--text-2);font-size:11px;font-weight:600;
  cursor:pointer;transition:background .12s,color .12s}
.cr-thread-ind svg{width:13px;height:13px;flex:none}
.cr-thread-ind:hover{background:rgba(255,255,255,.1);color:var(--cream)}
/* Under about 1000px there is not room for a room AND a third of one beside it, so the
   thread takes the whole width and the main list steps aside rather than both being
   squeezed into something neither is usable at. */
@media(max-width:1000px){
  #page-chatroom.cr-thread-open .cr-main-col{display:none}
  .cr-thread-panel{flex:1 1 100%!important;max-width:none}
  .cr-thread-resizer{display:none}
}

/* The icon picker on a folder, which has no icon to offer. Same panel, one sentence
   instead of a grid, so the control explains itself rather than swallowing the click. */
.proj-icon-picker .pip-fixed-note{padding:12px 14px;max-width:220px;font:500 12px var(--sans);
  color:var(--muted);line-height:1.5}


/* ── List view: people overflow, drop indicator ──────────────────────────────
   A row is one line high, so a cell with five names showed two and clipped the rest. The
   count is a control, not a label — it opens the full list. */
.prop-people{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden}
/* A lone pill has to be able to give way when the count will not fit beside it at full
   width — a shortened name still identifies someone. */
.prop-people .prop-person-pill{flex:none;min-width:0;overflow:hidden}
.prop-people .prop-person-pill > span:not(.prop-person-initials){
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
/* The `hidden` ATTRIBUTE is display:none from the user-agent sheet, and .prop-person-pill
   declares display:inline-flex — an author rule, which wins. So setting .hidden = true in
   the fit pass changed nothing at all and the pills stayed exactly where they were, clipped.
   Say it here, where it outranks the display that was beating it. */
.prop-people .prop-person-pill[hidden],
.prop-people .prop-person-more[hidden]{display:none !important}
.prop-person-more{display:inline-flex;align-items:center;height:22px;padding:0 9px;
  border:0;border-radius:11px;background:var(--surface-raised);color:var(--text-2);
  font:600 11px var(--sans);cursor:pointer;white-space:nowrap;flex:none;
  transition:background .12s,color .12s}
.prop-person-more:hover{background:rgba(255,255,255,.1);color:var(--cream)}
#propPeoplePop{max-height:320px;overflow-y:auto;min-width:200px}
#propPeoplePop .server-dropdown-item{gap:8px}

/* Where the row will land. A drag with no target told you something was moving and nothing
   about where it was going — the line sits ON the boundary the row will drop into. */
.gv-flat-row.gv-drop-before{box-shadow:inset 0 2px 0 0 var(--purple)}
.gv-flat-row.gv-drop-after{box-shadow:inset 0 -2px 0 0 var(--purple)}
.gv-flat-table.gv-dragging .gv-flat-row{transition:box-shadow .08s linear}
/* The rows travelling with the pointer, so a multi-row drag looks like one gesture rather
   than one row moving and the rest silently coming along. */
.gv-flat-row.gv-drag-src{opacity:.42}

/* ── One icon box in the sidebar, whatever is in it ──────────────────────────
   .fav-icon was given a WIDTH but never a height, so a chosen icon that happened to be
   taller — an emote, a penguin, anything not one of the drawn 24x24 SVGs — grew its row
   and shunted every row under it. Picking an icon should never move the list. Fixed box,
   and whatever goes in is contained by it rather than sizing it. */
.sidebar .fav-icon{
  width:20px;height:20px;flex:none;
  display:inline-flex;align-items:center;justify-content:center;line-height:0;
}
.sidebar .fav-icon > *{flex:none;max-width:100%;max-height:100%}
.sidebar .fav-icon svg{width:18px;height:18px;display:block}
.sidebar .fav-icon img{width:100%;height:100%;object-fit:contain;display:block}
/* The Shu wrapper carries its own inline px from appIconHtml; the box owns the size here. */
.sidebar .fav-icon .app-icon-shu,
.sidebar .fav-icon .app-icon-shu .shu-av{width:18px !important;height:18px !important}
/* The lock badge is positioned against this box and must not be counted as content. */
.sidebar .fav-icon > .sb-lock{position:absolute}


/* ── Comment replies ─────────────────────────────────────────────────────────
   A reply sits under the comment it answers, indented, behind a count you can collapse —
   the same shape a channel thread has, so the two read alike. */
.cmt-replying{display:flex;align-items:center;gap:7px;margin:0 0 8px;padding:5px 10px;
  border-radius:9px;background:var(--surface-raised);color:var(--text-2);font:600 11.5px var(--sans)}
.cmt-replying b{color:var(--cream);font-weight:700}
.cmt-replying svg{flex:none;color:var(--muted)}
.cmt-replying-x{margin-left:auto;background:none;border:0;color:var(--muted);cursor:pointer;
  display:inline-flex;padding:2px;border-radius:5px}
.cmt-replying-x:hover{background:rgba(255,255,255,.1);color:var(--cream)}

.cmt-replies{margin:2px 0 6px 32px;border-left:2px solid var(--border-d);padding-left:12px}
.cmt-replies-toggle{display:inline-flex;align-items:center;gap:6px;margin:2px 0 6px 32px;
  padding:3px 10px 3px 7px;border:0;border-radius:11px;background:var(--surface-raised);
  color:var(--text-2);font:600 11px var(--sans);cursor:pointer;transition:background .12s,color .12s}
.cmt-replies-toggle:hover{background:rgba(255,255,255,.1);color:var(--cream)}
.cmt-replies-toggle svg{width:12px;height:12px;flex:none;transition:transform .15s}
.cmt-replies-toggle.is-collapsed svg{transform:rotate(-90deg)}

/* A reaction is a button. It said so to a screen reader and not to a pointer. */
.reaction-strip button,.reaction-hover-btn,.cmt-replies-toggle{cursor:pointer}


/* ── Slash commands ──────────────────────────────────────────────────────────
   The command name is the content, so it reads as text — white — rather than as a link.
   Purple is the app's accent and it was carrying no meaning here beyond decoration. */
.slash-popup .slash-name,.slash-popup b,.slash-popup .mention-name,
#slashHelpModal .slash-name,#slashHelpModal b{color:var(--cream) !important}
.slash-popup .mention-item.active .slash-name,
.slash-popup .mention-item.on .slash-name{color:#fff !important}

/* The notifications rail is part of the sidebar family, not the canvas. */
.global-right-sidebar{background:#050507}

/* A reaction is a button; the pointer should say so. */
.reaction-strip button{cursor:pointer}


/* A command that cannot run yet says why, and the popup stays up so the fix is one
   keystroke away rather than a toast over a box you have already lost. */
.slash-popup.is-incomplete{border-color:var(--coral)}
.slash-popup .slash-error{
  padding:8px 12px;margin:0;border-bottom:1px solid var(--border-d);
  font:600 11.5px var(--sans);color:var(--coral);background:color-mix(in srgb,var(--coral) 10%,transparent)}


/* ── Replying in a channel ───────────────────────────────────────────────────
   The reply stays in the room and carries a line saying what it answers. Clicking that line
   goes back to the original — a quote you cannot follow is just decoration. */
.cr-replying{display:flex;align-items:center;gap:7px;margin:0 0 6px;padding:5px 10px;
  border-radius:9px;background:var(--surface-raised);color:var(--text-2);font:600 11.5px var(--sans)}
.cr-replying b{color:var(--cream);font-weight:700}
.cr-replying svg{flex:none;color:var(--muted)}
.cr-replying-x{margin-left:auto;background:none;border:0;color:var(--muted);cursor:pointer;
  display:inline-flex;padding:2px;border-radius:5px}
.cr-replying-x:hover{background:rgba(255,255,255,.1);color:var(--cream)}

.cr-quote{display:flex;align-items:center;gap:6px;margin:0 0 3px;cursor:pointer;
  font:500 12px var(--sans);color:var(--muted);min-width:0;max-width:100%}
/* The shaft comes DOWN from the message above and the head points RIGHT — into the name and
   text that follow it, which is the direction you read. The drawn glyph runs the opposite way
   on both axes (up from the bottom-right, then left), so it is flipped rather than redrawn:
   the arrowhead is symmetric about the box's middle, so the vertical flip costs it nothing,
   and the horizontal one puts the tip on the side the text is on.
   The tip stays at y=12 of a 24 viewBox — dead centre either way — and the box is sized to
   the TEXT's line box rather than the row, which is taller than the text in it, so the tip
   lands on the middle of the line. */
.cr-quote svg{flex:none;color:var(--muted);opacity:.7;transform:scale(-1,-1);
  align-self:center;height:1lh;width:12px}
@supports not (height:1lh){.cr-quote svg{height:12px}}
.cr-quote-au{font-weight:700;color:var(--cr-au,var(--cream));flex:none}
.cr-quote-tx{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;opacity:.85}
.cr-quote:hover .cr-quote-tx{opacity:1;color:var(--cream)}
.cr-quote.is-gone{cursor:default;font-style:italic}

@keyframes crJumpFlash{
  0%{background:color-mix(in srgb,var(--purple) 26%,transparent)}
  100%{background:transparent}
}
.cr-msg-row.cr-jump-flash{animation:crJumpFlash 1.2s ease-out}

/* ── Top bar: the search is the centre of the page ───────────────────────────
   It was pinned to the right by margin-left:auto, sharing that edge with the help and bell
   buttons. Centred absolutely so it stays centred on the PAGE rather than on whatever is
   left over after the breadcrumb — a breadcrumb that grows must not push it sideways. */
.topbar{position:sticky}
.topbar-search{
  /* Narrow, and seated a little left of centre, so the bell has room to land beside it when
     the notifications rail opens — nothing has to move. */
  position:absolute;left:calc(50% - 60px);transform:translateX(-50%);
  margin-left:0;width:min(400px,28vw);max-width:none;z-index:1;
}
/* Safety net for narrow windows: keep the left edge where it is and only shorten the right
   edge if the travelling bell would otherwise cover it. */
body.grs-open .topbar-search{transform:none;left:calc(50% - 60px - min(200px,14vw));width:min(min(400px,28vw),calc(50% + 60px + min(200px,14vw) - var(--right-panel-w,340px) - 52px));
}
@media(max-width:900px){.topbar-search{position:static;transform:none;margin-left:auto;width:auto;flex:1}}

/* ── Notifications use the whole height ──────────────────────────────────────
   The rail started below the top bar and was cut off at the top. It runs the full height of
   the window now, and the bell travels with it so the control stays attached to the thing
   it opens. Help steps aside rather than being overlapped. */
.global-right-sidebar{top:0;bottom:0;height:100%}
body.grs-open .topbar-bell{transform:translateX(calc(var(--right-panel-w) * -1 + 8px))}
body.grs-open #helpBtn{opacity:0;pointer-events:none}
.topbar-bell,#helpBtn{transition:transform var(--dur-modal,300ms) var(--ease-std),opacity .18s ease}

/* ── Sidebar: a channel's # is the same size as everything beside it ─────────
   .sidebar-channel-icon was 20px wide with the glyph inside drawn at 14, against the 18px
   glyphs every other row uses — so the # read as the small one in the list. */
.sidebar-channel-icon{width:20px;height:20px;opacity:1}
.sidebar-channel-icon svg{width:18px !important;height:18px !important}

/* ── One unread badge ────────────────────────────────────────────────────────
   The DM list drew its count with the conversation gradient and the sidebar footer drew the
   same count in the error red. Same number, same meaning — one treatment. */
.dmx-row-badge{background:var(--color-error)}

/* "Delivered" said nothing a sent message does not already say by being there. */
.dmx-receipt{display:none}

/* The thread composer is the channel composer — the SAME column layout, untouched.
   align-items:flex-end predated the column composer; in a column it pushed every child
   to the RIGHT edge, which is why the thread's "Reply…" and tools sat mirrored. */
#crThreadPanel .cr-compose-tools{display:flex;align-items:center;gap:2px}

/* ── Unread is a dot, not a count ────────────────────────────────────────────
   Half the size and no number. The digit was never the point — you look at these to see
   THAT something is unread, and the exact figure is one glance away in the list itself.
   font-size:0 hides the glyph without removing it, so a screen reader still reads the count.
   Both surfaces together, because they are the same signal in two places. */
.sidebar-dm-dot.has-notif,
.dmx-row-badge{
  min-width:5px;width:5px;height:5px;padding:0;border-radius:50%;
  font-size:0;line-height:0;overflow:hidden;flex:none;
}

/* ── One pill, everywhere in a table row ─────────────────────────────────────
   These were four different components that happen to look alike: .prop-pill at 10px,
   .prop-person-pill at 11px with lopsided padding, .prop-person-more with its own height,
   .prop-num/.prop-count with neither. Side by side in one row that reads as random.
   One height, one radius, one type size, one default fill — a value keeps its OWN colour
   when it has one; only the fallback is shared. Scoped to the flat table so the card
   modal's chips, which sit in a different context, are left alone. */
.gv-flat-cell .prop-pill,
.gv-flat-cell .prop-person-pill,
.gv-flat-cell .prop-person-more,
.gv-flat-cell .prop-count,
.gv-flat-cell .ss-pending-chip,
.gv-flat-cell .cr-profile-role{
  display:inline-flex;align-items:center;gap:5px;
  height:22px;box-sizing:border-box;padding:0 9px;
  border:0;border-radius:11px;
  font:600 11px/1 var(--sans);white-space:nowrap;flex:none;
}
/* An avatar rides flush at the left, so that side loses its padding. */
.gv-flat-cell .prop-person-pill{padding-left:2px}
.gv-flat-cell .prop-person-pill .card-avatar,
.gv-flat-cell .prop-person-pill img{width:18px;height:18px;flex:none}

/* THE default. Anything without a colour of its own uses this one grey — there is no
   reason for a value with no colour to look different from another value with no colour. */
.gv-flat-cell .prop-pill:not([style*="background"]),
.gv-flat-cell .prop-person-more,
.gv-flat-cell .prop-count,
.gv-flat-cell .ss-pending-chip{
  background:var(--surface-raised);color:var(--text-2);
}
.gv-flat-cell .prop-num{font:600 11px/1 var(--sans);color:var(--text-2)}
.gv-flat-cell .gv-owner-empty{font:600 11px/1 var(--sans);color:var(--muted)}

/* People carry their own colour HERE too. The tint was scoped to the card modal and the
   subtask cell, so every person chip in a table row fell back to the neutral fill — which
   is why the assigned colours went missing in the List view specifically. */
.gv-flat-cell .prop-person-pill[style*="--pp-hue"]{
  background:hsla(var(--pp-hue,0),52%,50%,.16);color:var(--cream);border:0;box-shadow:none}

/* ── Help and the bell go back to the right edge ─────────────────────────────
   Centring the search took it out of the flex flow — and the search was the element carrying
   margin-left:auto, the one thing pushing everything after it to the right. With it absolute
   the two buttons fell back against the breadcrumb. The auto margin moves to the first button
   that is still in flow. On a workshop page the hoisted tab strip is flex:1, and flex-grow
   resolves before auto margins do, so this is a no-op there — exactly as it was before. */
#helpBtn{margin-left:auto}

/* ── One header control ──────────────────────────────────────────────────────
   The search in a channel, the Share button, the top-bar search, Upload and the search on
   Files are the same kind of thing — a control sitting in a header row — and they were drawn
   at three heights (34 / 36 / 44), three corner radii (9 / 10 / 11), four different "default"
   greys and three font weights, two of them wearing a 1px outline nothing else had. One size,
   one corner, one surface, one type ramp.

   36px is deliberately the height of the PILL inside a .m-pillbar rather than of the bar: a
   field beside the Messages / Pins / Files tabs then lines up with the selected tab, and the
   4px showing above and below is the track's padding doing its job. Every labelled pill bar
   in the app — Home, DMs, Settings, a channel — already agrees on that geometry; it was the
   loose controls beside them that did not. */
:root{
  --control-surface:var(--surface-container);
  --control-surface-hover:color-mix(in srgb,var(--surface-container) 100%,#fff 5%);
}
html[data-theme="light"]{--control-surface:var(--surface-inset);--control-surface-hover:rgba(0,0,0,.09)}

.topbar-search,
.cr-search-wrap,
.fm-search,
.ws-share-btn,
.fm-upload,
.fm-gear{box-sizing:border-box;height:36px;border:0;border-radius:10px;
  font-family:var(--sans);font-size:13px}
.topbar-search,.cr-search-wrap,.fm-search,.ws-share-btn,.fm-gear{background:var(--control-surface)}
.topbar-search:hover,.ws-share-btn:hover,.fm-gear:hover,
.cr-search-wrap:hover,.fm-search:hover,
.cr-search-wrap:focus-within,.fm-search:focus-within{background:var(--control-surface-hover)}

/* Fields — 15px glyph, 10px gap, 13px padding, so the magnifier sits the same distance from
   the left edge in all three and the text starts on the same line. */
.topbar-search,.cr-search-wrap,.fm-search{display:flex;align-items:center;gap:10px;
  padding:0 13px;font-weight:400;color:var(--text-3)}
.topbar-search svg,.cr-search-wrap svg,.fm-search svg{width:15px;height:15px;flex:none;opacity:1}
/* Files drew its magnifier with a hard-coded stroke colour; every other one takes the
   field's own, so all three dim and brighten together. */
.fm-search svg *{stroke:currentColor}
.cr-search-input,.fm-search input{font:400 13px var(--sans);color:var(--text-1)}
.cr-search-input::placeholder,.fm-search input::placeholder{color:var(--text-3)}
/* Same width as the channel's, at the same right edge of its own header row. */
.fm-search{width:210px}
@media(max-width:900px){.fm-search{width:150px}}

/* Buttons — the label carries the weight the tab pills use. Upload keeps its fill because it
   is the one control here that MAKES something; the rest is chrome. */
.ws-share-btn,.fm-upload{display:inline-flex;align-items:center;justify-content:center;
  padding:0 15px;font-weight:600}
.fm-gear{width:36px;padding:0}

/* ── Home tab row: the workspace, and the set of them ────────────────────────
   Four tabs are about the workspace you are standing in. Manage Workspaces is about the
   set of them, so it gets its own track at the far end rather than sitting fifth in a row
   of peers. Two tracks, not one with a gap: the sliding pill belongs to a track, and a
   pill that glides across dead space between unrelated groups reads as a bug. */
/* The row inherits the strip's old spacing (.home-tabs was margin:2px 0 20px). Zeroing the
   bar's margin without moving it to the wrapper is what collapsed the gap under the tabs. */
.home-tabs-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:2px 0 20px}
.home-tabs-row .home-tabs{margin:0}
/* Specificity matters here: the reset above is (0,2,0), so a bare .home-tabs-trailing
   rule loses to it and the trailing track never leaves the left edge. */
.home-tabs-row .home-tabs-trailing{margin-left:auto}
@media(max-width:760px){.home-tabs-row .home-tabs-trailing{margin-left:0}}

/* ── Home -> Social ──────────────────────────────────────────────────────────
   Publishing activity, not reach. The note says so on the page, because a page headed
   "Social" that shows no follower count should explain itself rather than look broken. */
.hsoc-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 20px}
.hsoc-pick{display:flex;align-items:center;gap:8px;font:600 12px var(--sans);color:var(--text-2)}
.hsoc-pick select{height:32px;padding:0 10px;border-radius:8px;border:0;
  background:var(--control-surface);color:var(--text-1);font:600 12px var(--sans);cursor:pointer;
  max-width:260px}
.hsoc-refresh{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;
  border:0;border-radius:8px;background:var(--control-surface);color:var(--text-2);
  font:600 12px var(--sans);cursor:pointer;transition:background .14s,color .14s}
.hsoc-refresh:hover{background:var(--control-surface-hover);color:var(--text-1)}
.hsoc-note{flex:1;min-width:200px;font:400 11.5px/1.45 var(--sans);color:var(--text-3)}

.hsoc-acct{display:flex;align-items:center;gap:9px;min-width:0}
.hsoc-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.hsoc-av{width:24px;height:24px;border-radius:50%;flex:none;object-fit:cover;display:block}
.hsoc-av-icon{display:inline-flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--pc,var(--purple)) 18%,transparent);color:var(--pc,var(--purple))}
.hsoc-av-icon svg{width:13px;height:13px}
.hsoc-av-sm{width:20px;height:20px}
.hsoc-av-sm svg{width:11px;height:11px}
.hsoc-plats{display:flex;align-items:center;gap:5px}
.hsoc-dim{color:var(--text-3)}

/* Same state vocabulary the Schedule tab uses (.sch-status-*), so one post reads the same
   in a task and on this page. */
.hsoc-st-posted{color:var(--green);background:color-mix(in srgb,var(--green) 16%,transparent)}
.hsoc-st-ready{color:var(--gold);background:color-mix(in srgb,var(--gold) 16%,transparent)}
.hsoc-st-draft-created{color:var(--gold);background:color-mix(in srgb,var(--gold) 16%,transparent)}
.hsoc-st-failed{color:var(--danger-text);background:color-mix(in srgb,var(--color-error) 16%,transparent)}
.hsoc-st-draft{color:var(--muted)}
.prop-pill.hsoc-ok{color:var(--green);background:color-mix(in srgb,var(--green) 16%,transparent)}
.prop-pill.hsoc-off{color:var(--muted)}

/* ── Unread messages read as unread ──────────────────────────────────────────
   The footer row carried a red dot while its label stayed the same dim grey as Files and
   Trash, so the one row with something waiting looked identical to the two without. */
/* Unread pulls this row forward. --white is literally #fff, which does that on the dark
   sidebar and erases the label on the light one — the icon and the count stayed, the word
   "Messages" did not. --off-white is the same emphasis expressed as a theme-aware token. */
#sidebarFooterNav a:has(.sidebar-dm-dot.has-notif){color:var(--off-white)}
#sidebarFooterNav a:has(.sidebar-dm-dot.has-notif) svg{opacity:1}


/* Adding an account is the Schedule tab's dashed + square, reused verbatim — the same job
   should not have two button styles depending on which page you are standing on. */
.ss-section > .sch-accounts{margin:14px 0 18px}
/* When the table follows the + row it supplies its own top edge, so the row's own bottom
   margin is the only gap — without it the + sat flush against the table header. */
.ss-section > .sch-accounts + .group-view{margin-top:0}

/* The workspace picker is Henshu's dropdown, so the label only has to hold it. */
.hsoc-pick-mount{display:inline-flex;align-items:center}
.hsoc-pick-mount .ms-dropdown{width:220px}

/* The workspace picker sits beside Refresh, so it is that button with a chevron — not the
   outlined field the same component draws inside a task modal. Scoped to this page on
   purpose: the outline and focus ring are right where the dropdown IS a form field.
   Base rule sets background, border, colour and a focus ring, so each is answered here. */
.hsoc-pick-mount .ms-dropdown-trigger{
  height:32px;padding:0 12px;border:0;border-radius:8px;
  background:var(--control-surface);color:var(--text-2);
  font:600 12px var(--sans);box-shadow:none;
  transition:background .14s,color .14s}
.hsoc-pick-mount .ms-dropdown-trigger:hover,
.hsoc-pick-mount .ms-dropdown-trigger:focus,
.hsoc-pick-mount .ms-dropdown.open .ms-dropdown-trigger{
  border:0;box-shadow:none;background:var(--control-surface-hover);color:var(--text-1)}
.hsoc-pick-mount .ms-dropdown-trigger-chevron{color:var(--text-3)}


/* Heading with a control on the same line (Analytics scope note, Recent posts view seg). */
.hsoc-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.hsoc-head h3{margin:0}
.hsoc-scope-note{font:500 11.5px var(--sans);color:var(--text-3)}
.hsoc-seg{flex:none}

/* Publish entry point — the one thing on the bar that MAKES something, so it is the one
   thing with a fill. */
.hsoc-pub{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 13px;border:0;
  border-radius:8px;background:var(--purple);color:#fff;font:600 12px var(--sans);cursor:pointer;
  transition:filter .14s}
.hsoc-pub:hover{filter:brightness(1.08)}
.hsoc-pub svg{flex:none}

/* Account toggle: what is on feeds the Analytics section. */
.hsoc-tog{width:20px;height:20px;padding:0;border-radius:6px;cursor:pointer;display:inline-flex;
  align-items:center;justify-content:center;border:1.5px solid var(--border-d);
  background:transparent;color:transparent;transition:background .12s,border-color .12s,color .12s}
.hsoc-tog svg{width:12px;height:12px}
.hsoc-tog:hover{border-color:color-mix(in srgb,var(--purple) 60%,var(--border-d))}
.hsoc-tog.on{background:var(--purple);border-color:var(--purple);color:#fff}
.gv-flat-row.hsoc-row-off{opacity:.5}

/* Task picker for publishing. */
.hsoc-pick-list{display:flex;flex-direction:column;gap:6px;max-height:52vh;overflow-y:auto}
.hsoc-pick-row{display:flex;flex-direction:column;gap:2px;text-align:left;padding:9px 11px;
  border:0;border-radius:9px;background:var(--surface-raised);color:var(--text-1);cursor:pointer;
  font-family:var(--sans);transition:background .12s}
.hsoc-pick-row:hover{background:var(--state-hover)}
.hsoc-pick-row b{font:600 12.5px var(--sans)}
.hsoc-pick-row small{font:500 11px var(--sans);color:var(--text-3)}

/* Month view of what went out. Read-only, so no drag targets and no day chrome beyond
   the number and the posts themselves. */
.hsoc-cal{margin-top:14px}
.hsoc-cal-nav{display:flex;align-items:center;justify-content:center;gap:14px;margin-bottom:10px}
.hsoc-cal-nav b{font:700 13px var(--sans);color:var(--text-1);min-width:150px;text-align:center}
.hsoc-cal-nav button{width:26px;height:26px;border:0;border-radius:7px;cursor:pointer;
  background:var(--control-surface);color:var(--text-2);font-size:15px;line-height:1}
.hsoc-cal-nav button:hover{background:var(--control-surface-hover);color:var(--text-1)}
.hsoc-cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:5px}
.hsoc-cal-dow{font:600 10px var(--sans);text-transform:uppercase;letter-spacing:.5px;
  color:var(--text-3);text-align:center;padding-bottom:2px}
.hsoc-cal-cell{min-height:82px;border-radius:9px;background:var(--surface-container);
  padding:6px;display:flex;flex-direction:column;gap:3px;overflow:hidden}
.hsoc-cal-cell.is-blank{background:transparent}
.hsoc-cal-cell.is-today{box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--purple) 55%,transparent)}
.hsoc-cal-num{font:600 11px var(--sans);color:var(--text-3)}
.hsoc-cal-cell.is-today .hsoc-cal-num{color:var(--purple)}
.hsoc-cal2 .calendar-day{min-height:118px}
.hsoc-cal2 .calendar-day .hsoc-cal-post{margin:0}
.hsoc-cal2 .calendar-day.drag-over{outline:2px dashed var(--purple);outline-offset:-2px;background:rgba(124,92,255,.08)}
.hsoc-cal-post[draggable="true"]{cursor:grab}
.hsoc-cal-post.is-dragging{opacity:.35}
.hsoc-cal-post{display:flex;align-items:center;gap:4px;padding:2px 5px;border-radius:6px;
  font:600 10px var(--sans);white-space:nowrap;overflow:hidden}
.hsoc-cal-post span{overflow:hidden;text-overflow:ellipsis}
.hsoc-cal-more{font:600 9.5px var(--sans);color:var(--text-3);padding-left:4px}
.hsoc-av-xs{width:14px;height:14px}
.hsoc-av-xs svg{width:8px;height:8px}
@media(max-width:760px){.hsoc-cal-cell{min-height:60px}.hsoc-cal-post span{display:none}}

/* Title is a YouTube-only field. Dimmed rather than hidden when no YouTube account is
   selected: it still tells you the field exists and what turns it on. */
.sch-row.sch-row-off label{opacity:.55}
.sch-row.sch-row-off .sch-in{opacity:.5;cursor:not-allowed}

/* The attached cut plays here. Same box it already occupied — controls, not a bigger
   preview — and the native controls need a dark ground to sit on. */
.sch-media-el[controls]{background:#000;cursor:pointer}

/* ── A wide tab grows the modal from its centre, and the tabs hold still ─────
   Review already widened the modal and Schedule now does too. Widening from the centre
   slides the tab strip ~270px left, so the tab you just clicked jumps out from under the
   cursor. The modal STAYS CENTRED — it should grow both ways — and the strip is pushed
   back by exactly half the growth, which is the distance the left edge travels.

   MAX-WIDTH is the only thing animated, and both ends of it are explicit lengths. The
   first version animated `width` and set `max-width:none` on the wide state, which played
   the move BACKWARDS: `none` is not an animatable value so the cap vanished on frame one,
   the base `width:100%` immediately resolved against the whole overlay (~1926px), and the
   transition then ran 1926 -> 1360. It snapped huge, then shrank. With `width:100%` left
   alone and the cap moving 820px -> 1360px, the used width is the cap the entire way, so
   the box opens outward and lands exactly where it stops. */
.card-modal{
  --cm-narrow:820px;
  --cm-wide:min(1360px, 96vw);
  transition:max-width var(--dur-modal,300ms) var(--ease-std);
}
.card-modal.cm-wide-tab{max-width:var(--cm-wide) !important}
#cardModalTabs{transition:transform var(--dur-modal,300ms) var(--ease-std)}
/* The strip stays at the modal's left edge as the modal grows; Review/Publish's action
   tabs (Share For Review, Settings) sit at the right end of the same row. */
.card-modal.cm-wide-tab #cardModalTabs{transform:none}
.card-modal-tabs .card-modal-tab:not(.rev-extra-tab)+.rev-extra-tab{margin-left:auto}
/* Below the narrow width the modal already fills the viewport, so there is no growth to
   compensate for and the strip must not be pushed off the edge. */
@media(max-width:900px){
  .card-modal.cm-wide-tab{max-width:96vw !important}
}
@media(prefers-reduced-motion:reduce){
  .card-modal,#cardModalTabs{transition:none}
}

/* ── Schedule: no boxes around the boxes ─────────────────────────────────────
   Every field carried its own 1px outline, so the pane read as a stack of framed cards
   rather than one composer. The fill already separates a field from the ground. */
#cardModalTabSchedule .sch-in,
#cardModalTabSchedule .sch-caption,
#cardModalTabSchedule .sch-option-card,
#cardModalTabSchedule .sch-drop-locked,
#cardModalTabSchedule .sch-media{border:0}
#cardModalTabSchedule .sch-in:focus,
#cardModalTabSchedule .sch-caption:focus{
  border:0;box-shadow:0 0 0 2px color-mix(in srgb,var(--purple) 45%,transparent)}
/* The drop zone keeps its dashed edge — that IS the affordance, not decoration. */
#cardModalTabSchedule .sch-drop{border-style:dashed}

/* ── The attached cut shows at its own shape ─────────────────────────────────
   max-width:240px + max-height:240px + object-fit:cover is a square that CROPS: a 16:9
   clip lost its sides, a vertical lost its top and bottom. Contain, and let the box take
   the video's aspect the way the Review player does. */
/* Centred in the composer. .sch-wrap is a column flex, so its children stretch and a
   max-width alone just pins the box to the left edge — align-self is what actually
   centres a capped flex item on the cross axis. */
.sch-media{max-width:min(560px,100%);width:100%;display:block;background:#000;align-self:center}
.sch-media-el{width:100%;height:auto;max-height:none;object-fit:contain;background:#000}
/* A vertical clip would otherwise run the length of the pane. ONE constraint — the
   wrapper's width — and the video fills it at height:auto from the base rule. Capping the
   video's height as well made it compute a width from that height and overflow the box. */
.sch-media[data-portrait="1"]{max-width:min(320px,100%)}

/* The + drops a menu rather than opening a modal. Parented to <body> and positioned
   against the viewport, so the scrolling composer cannot clip it. */
.sch-add-menu{min-width:190px;z-index:10500}
.sch-add-menu .sch-add-menu-ic{width:20px;height:20px;border-radius:6px;flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--pc,var(--purple)) 18%,transparent);color:var(--pc,var(--purple))}
.sch-add-menu .sch-add-menu-ic svg{width:12px;height:12px}
.sch-add-menu-sep{height:1px;margin:4px 0;background:var(--border-d)}

/* ── Cover: an image, or a frame from the video ──────────────────────────────
   Two mechanisms because the platforms differ — YouTube and Facebook take an image,
   TikTok takes a frame offset, Instagram takes either. Both live under the player they
   describe, so "the frame showing now" means the one you can see. */
.sch-cover{display:flex;flex-direction:column;gap:10px;padding:12px 13px;border-radius:11px;
  background:var(--surface-raised)}
.sch-cover-head{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.sch-cover-head b{font:700 12px var(--sans);color:var(--cream)}
.sch-cover-head span{font:500 10.5px var(--sans);color:var(--muted)}
.sch-cover-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sch-cover-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 12px;font-size:12px;
  font-weight:600;cursor:pointer;flex:none;width:auto}
.sch-cover-btn:disabled{opacity:.5;cursor:not-allowed}
.sch-cover-note{font:500 10.5px/1.45 var(--sans);color:var(--muted);flex:1;min-width:160px}
.sch-cover-chip{display:inline-flex;align-items:center;gap:6px;padding:5px 6px 5px 11px;
  border-radius:999px;background:color-mix(in srgb,var(--purple) 16%,transparent);
  color:var(--cream);font:600 11px var(--sans)}
.sch-cover-chip button{width:17px;height:17px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(255,255,255,.12);color:var(--cream);font-size:12px;line-height:1;padding:0}
.sch-cover-chip button:hover{background:rgba(255,255,255,.22)}
.sch-cover-thumb{position:relative;display:inline-block;flex:none}
.sch-cover-thumb img{width:104px;height:59px;object-fit:cover;border-radius:8px;display:block;background:#000}
.sch-cover-thumb button{position:absolute;top:-6px;right:-6px;width:20px;height:20px;border:0;
  border-radius:50%;background:rgba(0,0,0,.75);color:#fff;cursor:pointer;font-size:13px;line-height:1;padding:0}

/* YouTube's own settings — the pipeline validated these all along. */
.sch-yt{flex-direction:column;gap:12px}
.sch-yt-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.sch-yt-row label{font:600 12px var(--sans);color:var(--cream)}
.sch-seg{display:inline-flex;gap:3px;padding:3px;border-radius:9px;background:var(--bg-inset)}
.sch-seg-btn{padding:5px 12px;border:0;border-radius:7px;background:transparent;cursor:pointer;
  color:var(--muted);font:600 11.5px var(--sans);transition:background .12s,color .12s}
.sch-seg-btn:hover{color:var(--cream)}
.sch-seg-btn.on{background:var(--purple);color:#fff}
.sch-seg-btn:disabled{opacity:.5;cursor:not-allowed}
.sch-yt-check{display:flex;align-items:flex-start;gap:9px;cursor:pointer}
.sch-yt-check input{margin-top:2px;flex:none}
.sch-yt-check b{display:block;font:600 12px var(--sans);color:var(--cream)}
.sch-yt-check small{display:block;margin-top:2px;font:500 10px/1.4 var(--sans);color:var(--muted)}

/* ── The people picker's pixel avatars are not menu glyphs ────────────────────
   .server-dropdown-item svg (16px, opacity .5) was written for the dropdown's little
   icons and hit the avatar SVG inside .dm-sb-av too — half-transparent over a dark menu
   is the "weird tint": whites went tan, every colour went muddy. */
.server-dropdown-item .dm-sb-av svg{width:100%;height:100%;opacity:1}

/* ── Muted rooms ──────────────────────────────────────────────────────────────
   A muted room shows no badge (the counts skip it), and the row itself says so quietly:
   dimmed name, no other ceremony. */
.dmx-row.is-muted .dmx-row-name{opacity:.55}
.dmx-row.is-muted .dmx-row-prev{opacity:.55}
[data-sidebar-id] > a.is-muted, .sidebar-cat-item.is-muted{opacity:.62}

/* ── Workspace card hover: the resting house steps back to a dot ─────────────
   Off Home the caret rests as a HOUSE. Hovering anywhere on the card softens it to a
   dot — the affordance stays present without a second house glyph shouting from the
   corner — and hovering the button itself still crossfades to the chevron exactly as
   before (those rules are untouched; the dot only has to get out of their way, which
   is why the hide rules below repeat the .sidebar-ws-card:hover prefix — they must
   outrank the show rule, and .sidebar-ws-caret:hover alone is one class short). */
.sidebar-ws-caret .swc-dot{opacity:0}
body:not(.is-home) .sidebar-ws-card:hover .sidebar-ws-caret .swc-house{opacity:0}
body:not(.is-home) .sidebar-ws-card:hover .sidebar-ws-caret .swc-dot{opacity:1}
body:not(.is-home) .sidebar-ws-card:hover .sidebar-ws-caret:hover .swc-dot,
body:not(.is-home) .sidebar-ws-card:hover .sidebar-ws-caret.open .swc-dot{opacity:0}
body.is-home .sidebar-ws-caret .swc-dot{opacity:0}


/* ── Publish tab: Review's geometry, to the pixel ────────────────────────────
   The SAME numbers Review uses — .rev-wrap's 16px gap, the stage as flex:1, the rail at
   380px (the wide-modal .rev-side width), and the player as a 16:9 stage capped at 56vh
   with the video absolutely filling it, object-fit:contain (.rev-player/.rev-video,
   verbatim). Contain letterboxes a vertical clip exactly the way Review does, so the two
   tabs show one video in one place at one size. */
.sch-cols{display:flex;gap:16px;align-items:flex-start}
.sch-col-media{flex:1;min-width:0;display:flex;flex-direction:column;gap:12px}
.sch-col-fields{width:380px;flex:0 0 380px;display:flex;flex-direction:column;gap:14px}
.sch-col-fields .sch-row{margin:0}
.sch-col-media .sch-media,
.sch-col-media .sch-drop{align-self:stretch;max-width:none;width:100%}
.sch-col-media .sch-media{position:relative;aspect-ratio:16/9;max-height:56vh;border-radius:12px;background:#000;overflow:hidden;display:block}
.sch-col-media .sch-media-el{position:absolute;inset:0;width:100%;height:100%;max-height:none;object-fit:contain;background:#000;margin:0}
/* Portrait needs no special case in a 16:9 stage — contain centres it, like Review. */
.sch-col-media .sch-media[data-portrait="1"]{align-self:stretch;max-width:none}
/* The filename chip floats on the stage the way Review's version chip does. */
.sch-col-media .sch-media-meta{position:absolute;left:10px;bottom:10px;background:rgba(0,0,0,.62);
  border-radius:8px;padding:5px 10px;max-width:70%;pointer-events:none}
.sch-col-media .sch-drop{aspect-ratio:16/9;max-height:56vh;min-height:0}
@media(max-width:900px){.sch-cols{flex-direction:column}.sch-col-media{width:100%}.sch-col-fields{width:100%;flex:1 1 auto}}

/* Recent Activity: the task's own glyph, bare — the glyph already carries its own rounded
   plate (the same one it wears on the board), so a container behind it was a box in a box. */
.ha-ic-task{background:none;border:none}
.ha-ic-task svg,.ha-ic-task img{width:18px;height:18px;display:block}


/* ── System notices from the agent ────────────────────────────────────────────
   An error is not something Shu SAID — muted, marked with the info glyph, set apart from
   his voice. Same mechanism as the pending sentinel. */
.cr-sys-error{display:flex;align-items:flex-start;gap:7px;padding:7px 10px;border-radius:9px;
  background:color-mix(in srgb,var(--color-error) 9%,transparent);
  color:var(--danger-text,#ff8f8f);font-size:12.5px;font-style:italic}
.cr-sys-error svg{flex:none;margin-top:2px;opacity:.8}

/* ── Muted rooms say so ───────────────────────────────────────────────────────
   A struck bell beside the name, and the NAME wears the same colour as the bell — one
   dimmed voice, not a dim icon next to bright text. The DM row's bell hangs off the TIME
   cell, not the name: the name ellipsizes, and a pseudo-element inside an ellipsized span
   is the first thing a long name swallows. */
.is-muted .sidebar-channel-name,
.dmx-row.is-muted .dmx-row-name,
.dmx-row.is-muted .dmx-row-prev{color:var(--text-3);opacity:1}
.sidebar-channel-name{display:inline-flex;align-items:center;gap:6px;min-width:0}
.dmx-row.is-muted .dmx-row-time{display:inline-flex;align-items:center;gap:5px;color:var(--text-3)}
.is-muted .sidebar-channel-name::after,
.dmx-row.is-muted .dmx-row-time::before{
  content:'';display:inline-block;width:12px;height:12px;flex:none;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13.73 21a2 2 0 0 1-3.46 0'/%3E%3Cpath d='M18.63 13A17.9 17.9 0 0 1 18 8'/%3E%3Cpath d='M6.26 6.26A5.86 5.86 0 0 0 6 8c0 7-3 9-3 9h14'/%3E%3Cpath d='M18 8a6 6 0 0 0-9.33-5'/%3E%3Cline x1='1' y1='1' x2='23' y2='23'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13.73 21a2 2 0 0 1-3.46 0'/%3E%3Cpath d='M18.63 13A17.9 17.9 0 0 1 18 8'/%3E%3Cpath d='M6.26 6.26A5.86 5.86 0 0 0 6 8c0 7-3 9-3 9h14'/%3E%3Cpath d='M18 8a6 6 0 0 0-9.33-5'/%3E%3Cline x1='1' y1='1' x2='23' y2='23'/%3E%3C/svg%3E") center/contain no-repeat}

/* ── Notifications own the full right edge while open ────────────────────────
   Above the topbar (z 50) so the rail covers search and settings too — a panel that
   stops short of the chrome reads as broken glass, not a drawer. */
.global-right-sidebar{z-index:60}
body.grs-open #notifBell{z-index:61}

/* ── Home ask: the field never leaves; busy dims it and overlays the dots ────
   Hiding the input swapped a different-height element in and the whole card jumped. */
.hh-ask-field{position:relative}
.hh-ask-input.is-busy{opacity:.35;pointer-events:none}
.hh-ask-field .hh-ask-thinking{position:absolute;left:2px;top:50%;transform:translateY(-50%);margin:0}


/* ── Review: the rest of the outline sweep + still images + extra tabs ────────
   Every decorative border inside the tab goes; the dark room and spacing already
   separate the regions. */
#cardModalTabReview .rev-side{border:none}
#cardModalTabReview .rev-anchor-row .rev-anchor,
#cardModalTabReview .rev-anchor-row button{border:none}
#cardModalTabReview .rev-input-row.cmt-bar{background:rgba(255,255,255,.06);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:none;border-radius:12px;align-items:center;padding:6px 8px 6px 12px;box-shadow:inset 0 1px 0 rgba(255,255,255,.08)}
#cardModalTabReview .rev-input-row.cmt-bar:focus-within{background:rgba(255,255,255,.09)}
/* The base .cmt-field geometry (6px/0, !important) is the main tab's — keep it and only
   drop the rev2 44px min-height, which top-aligned the text against centered icons. */
#cardModalTabReview .rev-input-row .rev-input.cmt-field{min-height:0}
/* A photo under review: the transport is all video verbs, so it stands down. */
.rev-main.rev-still .rev-transport{display:none}
.rev-main.rev-still .rev-player{max-height:60vh}
/* A still has nothing to play: no big play button, no tap-to-seek zones, no seek
   flashes, no buffering pill. (Publish showed a play button over a PNG.) */
.rev-main.rev-still .rev-bigplay,.rev-main.rev-still .rev-tapzone,.rev-main.rev-still .rev-seekflash,.rev-main.rev-still .rev-buffer-indicator{display:none}
.rev-main.rev-still .rev-player{cursor:default}
img.rev-video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#000;display:block}
/* The action tabs after History: tabs in dress, verbs in behaviour — no active state. */
.rev-extra-tab{opacity:.85}
.pub-settings-pop .pub-settings-lock{padding:10px 14px 0;font:600 12px var(--sans);color:var(--muted);line-height:1.4}
.pub-settings-pop .rev-set-group.is-locked{opacity:.5}
.pub-settings-pop .rev-set-group.is-locked .rev-seg{cursor:not-allowed}
.rev-extra-tab:hover{opacity:1}


/* Review fits, so nothing scrolls: the modal is a scroller for the form-like tabs, but on
   Review the content is height-budgeted to the modal — the leftover few px of scrollable
   slack (and a stray horizontal bar) were the only thing the scrollbars had to say. The
   rail's own list still scrolls internally. */
.card-modal.cm-review-active{overflow:hidden}
#cardModalTabReview{overflow:hidden}


/* ── Player settings as a dropdown ───────────────────────────────────────────
   The same popover chassis as quality/guides. Slide-up chrome (grip, Done) went with the
   sheet; groups keep their soft fill, no borders anywhere. The selection is the app's
   sliding pill, tinted by the task's status like the scrub line. */
.rev-settings-pop{width:380px;max-width:92vw;padding:12px}
.rev-settings-pop .rev-sheet-body{padding:0}
.rev-settings-pop .rev-set-group{margin-bottom:10px}
.rev-settings-pop .rev-set-group:last-child{margin-bottom:0}
.rev-seg-group{position:relative}
.rev-seg-group .rev-seg{position:relative;z-index:1}
.rev-seg-group .m-pill-thumb{background:var(--modal-col-color,var(--purple));border:0;border-radius:7px}
/* With the pill as the highlight, a static fill would stack a second one under it. */
.rev-settings-pop .rev-seg.on{background:transparent;color:#fff}

/* ── Review consistency pass ─────────────────────────────────────────────────
   One left edge (14px) and one type ramp for the rail: 12.5px body, 12px controls. The
   transport's delete keeps the danger hover the old link had. */
#cardModalTabReview .rev-subtabs,
#cardModalTabReview .rev-filterbar{padding-left:14px;padding-right:14px}
#cardModalTabReview .rev-list{padding-left:14px;padding-right:14px}
#cardModalTabReview .rev-empty{font-size:12.5px;line-height:1.5}
#cardModalTabReview .rev-inputbar{padding-left:14px;padding-right:14px;padding-bottom:0}
.rev-cbtn-del:hover{background:rgba(255,107,107,.12);color:#ff6b6b}

/* Recent/scheduled posts link back to their task. */
.hsoc-row-open{cursor:pointer}
.hsoc-cal-post.hsoc-row-open:hover{filter:brightness(1.25)}


/* ── Review: send-to-Publish button + player entrance ────────────────────────
   A disabled transport button reads as "not now" rather than vanishing. */
.rev2 .rev-ctrlrow .rev-cbtn:disabled{opacity:.35;cursor:default}
.rev2 .rev-ctrlrow .rev-cbtn:disabled:hover{background:transparent;color:rgba(235,235,245,.82)}

/* The media fades in over the same shimmer every other loading surface uses,
   inside a box already shaped like the media (cached ratio), so nothing jumps. */
.rev-player .rev-video{transition:opacity .35s ease}
.rev-player.rev-loading .rev-video{opacity:0}
.rev-player::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;opacity:0;transition:opacity .3s ease;
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi,rgba(255,255,255,.13)) 50%,var(--bg-inset) 75%);
  background-size:200% 100%}
.rev-player.rev-loading::after{opacity:1;animation:skelShimmer 1.4s linear infinite}


/* Filter menu's By-person rows: the face beside the name, name in its owner's colour. */
.rev-menu-item.rev-menu-person{display:flex;align-items:center;gap:8px}
.rev-menu-person-av{width:18px;height:18px;border-radius:50%;overflow:hidden;flex:none;display:inline-flex;align-items:center;justify-content:center;background:var(--bg-inset);font-size:9px}
.rev-menu-person-av img,.rev-menu-person-av svg{width:100%;height:100%;object-fit:cover;display:block}


/* ── Review fills the modal ──────────────────────────────────────────────────
   The wrap's fixed height cap left a dead band under the rail: the comments and the
   composer stopped ~90px short of the modal's bottom. In the review modal the pane is
   a flex column and the wrap takes all of it, so the dark room, the list and the
   composer all reach the bottom edge together. */
.card-modal.cm-review-active #cardModalTabReview{flex:1;min-height:0;display:flex;flex-direction:column}
.card-modal.cm-review-active .rev-wrap.rev2{height:auto;flex:1;min-height:0}
.card-modal.cm-review-active .rev-list{max-height:none}
/* The composer floats OVER the list's tail, so scrolling comments pass behind its glass.
   The bar itself is click-through (only its pills catch the pointer), and the list gets
   matching tail padding so the last comment can clear the glass. */
.card-modal.cm-review-active .rev-side{position:relative}
.card-modal.cm-review-active .rev-inputbar{position:absolute;left:0;right:0;bottom:0;z-index:3;background:transparent;pointer-events:none}
.card-modal.cm-review-active .rev-inputbar > *{pointer-events:auto}
.card-modal.cm-review-active .rev-list{padding-bottom:112px}
/* Selecting a comment to copy it is a first-class gesture. */
#cardModalTabReview .rev-cm-text{user-select:text;-webkit-user-select:text;cursor:text}

/* The anchor pill matches the composer's glass; its .on tint stays and now sits on blur. */
.rev2 .rev-anchor-toggle{backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:none;box-shadow:inset 0 1px 0 rgba(255,255,255,.08)}
.rev2 .rev-anchor-toggle:not(.on){background:rgba(255,255,255,.06)}
/* On: the status tint stays, now sitting on the blur. */


/* ── Publish wears the Review shell ──────────────────────────────────────────
   Same wrap, same dark stage, same player, same geometry: the rev-wrap fills the modal
   exactly as it does on Review, and the fields rail sits where Review keeps comments. */
.card-modal.cm-schedule-active{overflow:hidden}
.card-modal.cm-schedule-active #cardModalTabSchedule{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}
.card-modal.cm-schedule-active .rev-wrap.rev2{height:auto;flex:1;min-height:0}
.pub2 .rev-side{overflow:hidden;padding:0}
.pub2 .rev-side .sch-wrap{overflow-y:auto;height:100%;box-sizing:border-box;padding:2px 14px 16px}
/* The empty state floats in the dark room instead of spanning a full-width band. */
.pub2 .rev-stage .sch-drop-locked{width:auto;min-height:0;border:none;background:transparent;color:var(--text-3)}
/* Media row in the rail: name + remove on one line under its label. */
.sch-media-row .sch-media-meta{display:flex;align-items:center;gap:10px;background:transparent;padding:0;font-size:12px;white-space:normal}
.sch-media-row .rev-link{flex:none}


/* ── Publish rail: account strip, merged when-control, rich description, variants ── */
/* One horizontal row of profile chips + the add button; overflow scrolls sideways. */
.pub-side .sch-accounts-strip{flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;padding:2px 2px 6px;scrollbar-width:thin}
.pub-side .sch-accounts-strip::-webkit-scrollbar{height:6px}
.pub-side .sch-accounts-strip::-webkit-scrollbar-thumb{background:var(--hairline-2);border-radius:3px}
.pub-side .sch-accounts-strip .sch-account-chip{flex:0 0 auto}
.pub-side .sch-accounts-strip .sch-account-add{flex:0 0 auto}

/* Date · hour : minute wear one shell. */
.sch-when-merged{display:inline-flex;align-items:stretch;gap:0;background:#1c1c20;border:1px solid var(--border-d);border-radius:12px;overflow:hidden;max-width:100%}
.sch-when-merged.is-locked{opacity:.6}
.sch-when-date{display:flex;align-items:center;gap:10px;background:transparent;border:none;color:var(--white);font:inherit;font-size:13px;padding:9px 12px;cursor:pointer;white-space:nowrap}
.sch-when-date:disabled{cursor:default;color:var(--muted)}
.sch-when-div{width:1px;background:var(--hairline-2);margin:7px 0}
.sch-when-seg{display:flex;align-items:center}
.sch-when-seg .ms-dropdown-trigger{background:transparent;border:none;border-radius:0;height:100%;padding:9px 10px}
.sch-when-colon{align-self:center;color:var(--muted);font-weight:700}

/* Rich description: same box as the old textarea, chips render inline. */
.sch-desc-rich{min-height:120px;white-space:pre-wrap;overflow-y:auto;cursor:text}
.sch-desc-rich:empty::before{content:attr(data-placeholder);color:var(--text-3);pointer-events:none}
.sch-desc-rich[data-disabled="1"]{opacity:.6;cursor:default}
.sch-desc-rich .link-chip{margin:0 2px}

/* #hashtags read platform-blue, like the example. */
.tag-chip{color:#6ea8ff;font-weight:600}

/* Platform videos: one row per selected platform. */
.sch-variants .sch-var-row{display:flex;align-items:center;gap:9px;padding:7px 0;border-bottom:1px solid var(--hairline-2);font-size:12.5px}
.sch-variants .sch-var-row:last-child{border-bottom:none}
.sch-var-ico{width:22px;height:22px;border-radius:6px;flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--pc,var(--muted));background:color-mix(in srgb,var(--pc,#888) 14%,transparent)}
.sch-var-ico svg{width:13px;height:13px}
.sch-var-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--cream)}
.sch-var-name.sch-var-main{color:var(--muted)}


/* A publishing job in flight animates exactly like an upload: the 4px track with the
   canonical shimmer sweep (same recipe as .hd-tray-bar.is-phase). */
.sch-job-bar{position:relative;display:block;height:4px;border-radius:3px;background:var(--bg-inset);margin-top:6px;overflow:hidden}
.sch-job-bar::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi,rgba(255,255,255,.13)) 50%,var(--bg-inset) 75%);
  background-size:200% 100%;animation:skelShimmer 1.4s linear infinite}

.sch-job-bar.sch-job-bar-det::after{display:none}
.sch-job-fill{position:absolute;left:0;top:0;bottom:0;border-radius:3px;background:var(--purple);transition:width .9s ease}

/* Zone segment: long IANA names ellipsize inside the merged shell. */
.sch-when-tz{max-width:170px;min-width:96px}
.sch-when-tz .ms-dropdown-trigger-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px}

/* The Review empty state floats its drop card in the dark room, same as Publish. */
.rev2 .rev-stage .rev-drop,#cardModalTabReview .rev-stage .rev-drop,#cardModalTabSchedule .rev-stage .rev-drop{width:min(520px,86%);background:transparent;border:none;min-height:280px;padding:32px;gap:10px}
/* The drag-over glow keeps working without a resting border. */
#cardModalTabReview .rev-stage .rev-drop.drag,#cardModalTabSchedule .rev-stage .rev-drop.drag{background:color-mix(in srgb,var(--purple) 8%,transparent);border:none;border-radius:14px}
/* The Publish drop wears .sch-drop too; its 30px icon rule must not shrink the shared glyph. */
#cardModalTabSchedule .rev-stage .rev-drop svg{width:46px;height:46px;opacity:.6}


/* ── Publish bottom bar: the schedule control + actions float where Review's composer
   floats — same geometry (absolute bottom, 14px sides, glass shell), so the two tabs'
   bottom edges line up exactly. The rail scrolls behind it. */
.card-modal.cm-schedule-active .pub-side{position:relative}
.card-modal.cm-schedule-active .sch-pubbar{position:absolute;left:0;right:0;bottom:0;z-index:3;padding:10px 14px 0;pointer-events:none}
.card-modal.cm-schedule-active .sch-pubbar > *{pointer-events:auto}
.card-modal.cm-schedule-active .pub-side .sch-wrap{padding-bottom:110px}
.sch-pubbar-one{display:flex;align-items:center;justify-content:flex-end;gap:6px;min-height:44px;background:rgba(255,255,255,.06);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border-radius:12px;padding:5px 6px 5px 12px;box-shadow:inset 0 1px 0 rgba(255,255,255,.08)}
.sch-pubbar-one .sch-when-merged{background:transparent;border:none;flex:1;min-width:0;gap:0}
.sch-pubbar-one .sch-when-date{padding:6px 6px 6px 8px;gap:6px;font-size:12.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-pubbar-one .sch-when-seg .ms-dropdown-trigger{padding:6px 5px;font-size:12.5px}
.sch-pubbar-one .sch-when-colon{margin:0 -1px}
.sch-pubbar-one .sch-when-div{margin:6px 2px}
.sch-pubbar-one .sch-when-tz{max-width:96px;min-width:0}
.sch-pubbar-one .sch-when-tz .ms-dropdown-trigger-label{max-width:64px}
.sch-pubbar-foot{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:6px}
.sch-pubbar-foot .sch-foot{border-top:none;display:flex;align-items:center;gap:8px;background:transparent;padding:0;width:100%;min-width:0}
.sch-pubbar-foot .sch-status{margin-right:auto;white-space:nowrap}
.sch-pubbar-foot .sch-actions{margin-left:auto;flex-wrap:wrap;justify-content:flex-end;min-width:0}
.sch-pubbar-foot .sch-status{padding-left:4px}
.sch-pubbar-foot .sch-actions{display:flex;align-items:center;gap:6px}
.sch-when-clear{width:26px;height:26px;flex:none;border:none;border-radius:8px;background:rgba(255,255,255,.08);color:var(--muted);font-size:15px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.sch-when-clear:hover{background:rgba(255,255,255,.14);color:var(--cream)}

/* Description toolbar row + the Main-description popup. */
.sch-desc-bar{margin:0;position:static;border-radius:0}
.sch-desc-bar .desc-tb-btn{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;padding:5px 9px}
.pub-desc-pop{width:440px;max-width:92vw;max-height:60vh;overflow-y:auto;padding:12px 14px}
.pub-desc-pop .rev-menu-head{padding:0;margin:0 0 8px}
.pub-desc-body{font-size:13px;line-height:1.7;color:var(--text-1);user-select:text;-webkit-user-select:text;white-space:pre-wrap}
.pub-desc-body .mention-chip{margin:1px 3px 1px 0;vertical-align:middle}
.pub-desc-body img.custom-emote,.pub-desc-body img[data-emote]{vertical-align:middle}
.pub-desc-none{color:var(--text-3);font-style:italic}
.pub-settings-pop{width:400px}

/* Grayed-out past days: visibly unavailable, silently inert. */
.gv-cal-day.is-past{opacity:.26;pointer-events:none}
/* The description holds its size; long text scrolls inside. */
.sch-desc-rich{height:150px;min-height:0;max-height:150px}
/* Icon-only toolbar button above the description. */
.sch-desc-bar .desc-tb-btn{width:28px;height:26px;padding:0;display:inline-flex;align-items:center;justify-content:center}


/* ── The one schedule panel: calendar + time + zone, one type ramp, one color. ── */
.sch-when-pop{width:300px;padding:12px 12px 10px}
.sch-when-pop .gv-cal-head{margin-bottom:4px}
.sch-when-pop .gv-cal-month{font-size:13px;font-weight:600;color:var(--cream)}
.sch-when-pop .gv-cal-dow span{font-size:11px;color:var(--muted);font-weight:600}
.sch-when-pop .gv-cal-day{font-size:13px;color:var(--cream)}
.sch-when-pop .gv-cal-day.is-other{color:var(--text-3)}
.sch-when-pop .gv-cal-foot{display:none}
.sch-wp-row{display:flex;align-items:center;gap:5px;margin-top:10px}
.sch-wp-row .ms-dropdown-trigger{font-size:13px;color:var(--cream);padding:7px 8px}
.sch-wp-row .sch-when-colon{color:var(--muted);font-weight:700}
.sch-wp-gap{flex:1}
.sch-wp-row .sch-when-tz{max-width:132px}
.sch-wp-row .sch-when-tz .ms-dropdown-trigger-label{max-width:96px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-wp-foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:12px}
.sch-wp-foot .sch-act{font-size:12px}

/* Split action: [ Publish | v ] — one shape, a hairline seam between the halves. */
.sch-split{display:inline-flex;align-items:stretch}
.sch-split .sch-split-main{border-radius:9px 0 0 9px}
.sch-split .sch-split-arrow{border-radius:0 9px 9px 0;padding:7px 8px;border-left:1px solid rgba(0,0,0,.25)}
.sch-split-when{font-weight:500;opacity:.85;font-size:11px;margin-left:6px}


/* The split action is part of the bar, not a purple pill on it. */
.sch-split .sch-split-main,.sch-split .sch-split-arrow{background:transparent;color:var(--cream);border:none;box-shadow:none}
.sch-split .sch-split-main{font-weight:700}
.sch-split .sch-split-main:hover,.sch-split .sch-split-arrow:hover{background:rgba(255,255,255,.08);color:#fff;filter:none}
.sch-split .sch-split-arrow{border-left:1px solid var(--hairline-2);color:var(--muted)}
.sch-split .sch-split-main.is-disabled,.sch-split .sch-split-main:disabled{opacity:.45;background:transparent}
.sch-split .sch-split-main.is-disabled:hover,.sch-split .sch-split-main:disabled:hover{background:transparent}
.sch-split-when{color:var(--muted);font-weight:500}

/* The name chip over the player is ONE size in both tabs — Review's version nav set its
   height; Publish's name-only chip matches it instead of shrinking. */
.rev2 .rev-topright{min-height:36px;box-sizing:border-box;align-items:center}


/* Top-left stage chip — the name chip's twin, on the other corner. */
.rev2 .rev-stage>.rev-topleft{position:absolute;left:18px;top:16px;z-index:9;display:flex;align-items:center;max-width:calc(50% - 36px)}
.sch-varchip-btn{display:inline-flex;align-items:center;gap:8px;min-height:36px;box-sizing:border-box;background:rgba(0,0,0,.55);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.1);border-radius:9px;padding:5px 8px 5px 10px;font:600 12px var(--sans);color:#fff;cursor:pointer}
.sch-varchip-btn:hover{background:rgba(0,0,0,.7)}
.sch-varchip-btn svg{flex:none;opacity:.85}
.sch-var-pop{width:340px;padding:8px 12px 10px}
.sch-var-empty{font-size:12.5px;color:var(--text-3);font-style:italic;padding:6px 0}


/* iPhone-style trim over the scrub: darkened outsides, a gold-framed window, grabbable
   end handles. The bar above carries the range and Done/Cancel/Reset. */
.pub-trim{position:absolute;inset:-6px 0;z-index:6;display:flex;pointer-events:none}
.pub-trim-shade{background:rgba(0,0,0,.55);border-radius:4px;flex:none}
.pub-trim-win{position:absolute;top:0;bottom:0;border:2px solid var(--gold);border-left-width:12px;border-right-width:12px;border-radius:7px;box-sizing:border-box;pointer-events:none}
.pub-trim-handle{position:absolute;top:-6px;bottom:-6px;width:22px;pointer-events:auto;cursor:ew-resize;touch-action:none}
.pub-trim-handle-l{left:-17px}
.pub-trim-handle-r{right:-17px}
.pub-trim-handle::after{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:3.5px;height:12px;border-radius:2px;background:#1b1b1b}
.pub-trim-handle-l::after{margin-left:-2.5px}
.pub-trim-handle-r::after{margin-left:2.5px}
.pub-trim-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:0 18px 8px}
.pub-trim-label{font:600 12px var(--mono,monospace);color:var(--gold);font-variant-numeric:tabular-nums}
.pub-trim-acts{display:flex;align-items:center;gap:6px}
/* The coming-soon captions button reads unavailable but still tips on hover. */
.rev-cbtn.is-off{opacity:.38;cursor:default}
.rev-cbtn.is-off:hover{background:transparent;color:rgba(235,235,245,.82)}
#pubTrimBtn.on{color:var(--gold)}

/* The task-files tree inside the Platform videos dropdown. */
.sch-var-tree{margin:2px 0 6px;padding:6px 8px;background:rgba(255,255,255,.04);border-radius:9px}
.sch-var-tree-folder{display:flex;align-items:center;gap:6px;font:700 10.5px var(--sans);letter-spacing:.4px;text-transform:uppercase;color:var(--muted);padding:5px 2px 3px}
.sch-var-tree-file{display:flex;align-items:center;gap:7px;width:100%;text-align:left;background:transparent;border:none;border-radius:7px;color:var(--cream);font:500 12.5px var(--sans);padding:6px 8px;cursor:pointer}
.sch-var-tree-file:hover{background:var(--state-hover)}
.sch-var-tree-file.on{color:var(--modal-col-color,var(--purple))}
.sch-var-tree-file span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-var-tree-tag{flex:none;font-size:10px;font-weight:700;color:var(--muted);background:rgba(255,255,255,.08);border-radius:8px;padding:1px 7px}
.sch-var-tree-tag.on{color:var(--modal-col-color,var(--purple));background:color-mix(in srgb,var(--modal-col-color,var(--purple)) 16%,transparent)}
.sch-var-tree-note{font-size:12px;color:var(--text-3);font-style:italic;padding:6px 2px}
.sch-var-tree-upload{display:block;padding:7px 2px 3px;font-size:12px}

/* Published: the composer is a record now — everything grays and locks except the job
   rows, whose View-post links are the point. */
.sch-wrap.sch-locked-published > *{opacity:.4;pointer-events:none;filter:saturate(.6)}
.sch-postlinks{display:flex;flex-direction:column;gap:2px;padding:6px;min-height:150px;max-height:150px;overflow-y:auto}
.sch-postlink-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;color:var(--cream);text-decoration:none}
.sch-postlink-row:hover{background:rgba(255,255,255,.05)}
.sch-postlink-main{display:flex;flex-direction:column;min-width:0}
.sch-postlink-main b{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sch-postlink-main small{font-size:11px;color:var(--muted)}
.sch-postlink-ext{margin-left:auto;flex:none;color:var(--muted)}
.sch-postlink-row:hover .sch-postlink-ext{color:var(--cream)}
.sch-postlinks-empty{padding:10px;font-size:12px;color:var(--muted);font-style:italic}
.sch-wrap.sch-locked-published > .sch-row-postlinks{opacity:1;pointer-events:auto;filter:none}
.sch-wrap.sch-locked-published > .sch-batch{opacity:1;pointer-events:auto;filter:none}
.sch-wrap.sch-locked-published > .sch-job-list{opacity:1;pointer-events:auto;filter:none}
/* The per-platform video links in the bar. */
.sch-post-link{display:inline-flex;align-items:center;gap:5px;color:var(--cream);text-decoration:none}
.sch-post-link:hover{background:var(--state-hover);color:#fff}

/* Inside the Main-tab chassis the field brings no box of its own — the wrap is the box. */
.sch-desc-wrap .sch-desc-rich{background:transparent;border:none;border-radius:0}
.sch-desc-wrap .sch-desc-rich:focus{border:none}

/* ── Light mode sweep ─────────────────────────────────────────────────────────
   Surfaces that were still black, white-alpha text that vanished on white, and shadows
   tuned for a dark canvas. Everything here is scoped to the light theme. */
html[data-theme="light"] .sidebar{box-shadow:1px 0 0 var(--hairline-2)}
html[data-theme="light"] .ws-view-tabs,html[data-theme="light"] .hi-seg{border:1px solid var(--hairline-2)}
html[data-theme="light"] .ws-view-tab-label{color:inherit}
/* A segment without a sliding thumb still needs its selected state painted. */
html[data-theme="light"] .hi-seg:not(:has(.m-pill-thumb)) button.on{background:var(--purple);color:#fff}
html[data-theme="light"] .ws-share-btn{background:rgba(0,0,0,.05);color:var(--off-white)}
html[data-theme="light"] .ws-share-btn:hover{background:rgba(0,0,0,.09)}
html[data-theme="light"] .fm-crumb-cur{color:var(--off-white)}
html[data-theme="light"] .fm-lhead{border-bottom-color:var(--hairline-2);color:var(--muted)}
html[data-theme="light"] .fm-lc,html[data-theme="light"] .fm-lsort,html[data-theme="light"] .fm-lby-name,html[data-theme="light"] .fm-meter-txt{color:var(--sec)}
html[data-theme="light"] .fm-meter-txt em{color:var(--muted)}
html[data-theme="light"] .sidebar-section-name{color:var(--off-white)}
html[data-theme="light"] .trash-purge-label{color:var(--sec)}
html[data-theme="light"] .hh-overdue{color:var(--color-error-text,#c92f2f)}
/* Per-person colours are picked for a dark canvas; darken them where they carry text. */
html[data-theme="light"] .cr-msg-author,html[data-theme="light"] .prop-pill{filter:brightness(.72) saturate(1.15)}
html[data-theme="light"] .sidebar-ws-card.ws-open .server-dropdown.open,html[data-theme="light"] .cr-profile-idcard.acct-open .server-dropdown.open{background:rgba(255,255,255,.92);border-color:var(--border-d);box-shadow:0 18px 36px rgba(0,0,0,.14)}
/* Customize previews: one window chassis, one shadow, for both cards. */
html[data-theme="light"] .ss-app-preview,html[data-theme="light"] .ss-kb-prev{box-shadow:0 8px 24px rgba(0,0,0,.12)}
html[data-theme="light"] .ss-ap-titlebar{background:rgba(0,0,0,.03);border-bottom-color:var(--hairline)}
html[data-theme="light"] .ss-ap-sidebar{border-right-color:var(--hairline)}
html[data-theme="light"] .ss-ap-topbar,html[data-theme="light"] .ss-kb-top{border-bottom-color:var(--hairline)}
html[data-theme="light"] .ss-ap-widget,html[data-theme="light"] .ss-kb-t{background:#fff;border-color:var(--hairline)}
html[data-theme="light"] .ss-ap-list-row{border-bottom-color:var(--hairline)}
/* Pass two: board toolbar, calendar, automations, list dates, coloured sidebar sections. */
html[data-theme="light"] .ws-toolbar-btn,html[data-theme="light"] .workshop-view-btn{color:var(--sec)}
html[data-theme="light"] .ws-toolbar-btn:hover,html[data-theme="light"] .workshop-view-btn:hover{color:var(--off-white)}
html[data-theme="light"] .calendar-day-label{color:var(--muted)}
html[data-theme="light"] .cal-view-toggle button{color:var(--sec)}
html[data-theme="light"] .cal-view-toggle button.is-active{color:var(--purple)}
html[data-theme="light"] .azp-pixlabel{color:var(--muted)}
html[data-theme="light"] .azp-recipe-txt{color:var(--off-white)}
/* .sidebar-section-name dropped from this list: a brightness/saturate filter darkened a
   folder label by different maths than the colour mix its own children use, so one
   --cat-color came out as two different reds a line apart. It also dimmed labels with no
   custom colour at all. Coloured folders now use the children's mix, below. */
html[data-theme="light"] .azp-kw,html[data-theme="light"] .gv-flat-cell-date{filter:brightness(.78) saturate(1.15)}
/* Shu QC button in the review transport */
.rev-cbtn-shu .shu-av{width:20px;height:20px;image-rendering:pixelated}
.rev-cbtn-shu.is-busy{opacity:.85;cursor:progress}
.rev-cbtn-shu.is-busy .shu-av{animation:revShuBob .9s ease-in-out infinite}
@keyframes revShuBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
/* These three lose to more specific dark rules; the light value has to win outright. */
html[data-theme="light"] .azp-pixlabel{color:var(--muted) !important}
html[data-theme="light"] .calendar-day-label{color:var(--muted) !important}
html[data-theme="light"] .cal-view-toggle button.is-active{color:var(--purple) !important}

/* ── Light mode, round three ─────────────────────────────────────────────────── */
html[data-theme="light"] .board-canvas{background-color:rgba(0,0,0,.02);background-image:radial-gradient(rgba(0,0,0,.16) 1px,transparent 1px);border-color:var(--border-d)}
html[data-theme="light"] .mp-eye-btn{background:rgba(0,0,0,.05);color:var(--off-white)}
html[data-theme="light"] .mp-eye-btn:hover{background:rgba(0,0,0,.09)}
html[data-theme="light"] .server-dropdown-item{color:var(--off-white);font-weight:600}
html[data-theme="light"] .server-dropdown-item svg{color:var(--sec)}
html[data-theme="light"] .cr-profile-popout{background:#ffffff;color:var(--off-white)}
html[data-theme="light"] .cr-profile-popout strong,html[data-theme="light"] #popoutHeaderName{color:var(--off-white)}
html[data-theme="light"] .cr-profile-section-label{color:var(--sec)}
html[data-theme="light"] .theme-toggle:not(:has(.m-pill-thumb.show)) .theme-seg.on{background:var(--purple);color:#fff}
html[data-theme="light"] .us-card label{color:var(--off-white)}
html[data-theme="light"] .us-card label + div,html[data-theme="light"] .us-card label div + div,html[data-theme="light"] .us-card .us-toggle-desc{color:var(--sec)}
html[data-theme="light"] .rev-bigplay,html[data-theme="light"] .rev2 .rev-bigplay,html[data-theme="light"] .fm-bigplay{background:rgba(255,255,255,.92);color:#17171c;border:1px solid rgba(0,0,0,.08);backdrop-filter:none;-webkit-backdrop-filter:none}
html[data-theme="light"] .card-modal-tab{color:var(--sec)}
html[data-theme="light"] .card-modal-tab:hover{color:var(--off-white)}
html[data-theme="light"] .kanban-card-due{filter:brightness(.8) saturate(1.2)}
html[data-theme="light"] .kanban-card-due span[style*="opacity"]{opacity:.85 !important}
html[data-theme="light"] .ws-view-tabs,html[data-theme="light"] .hi-seg,html[data-theme="light"] .card-modal-tabs{box-shadow:0 1px 2px rgba(0,0,0,.04)}
/* Review side panel: the input bar floats over the list, so it needs a ground; the list
   scrolls its last comment clear of it. Shu's own face in the comment list. */
.card-modal.cm-review-active .rev-inputbar{background:linear-gradient(to bottom,transparent 0,var(--modal-bg,#0c0c0e) 26px)}
.rev2 .rev-list{padding-bottom:112px}
.rev2 .rev-side{overflow:hidden}
.rev2 .rev-send.rev-send-sm{width:30px;height:30px;border-radius:8px}
.rev2 .rev-send.rev-send-sm svg{width:14px;height:14px}
.rev-cm-av .rev-shu-av{width:100%;height:100%;image-rendering:pixelated}
/* Round four: icon weight. Sidebar glyphs and the folder/padlock read in the secondary
   ink, not the text colour; the "+" pill beside tab pills is a light control. */
html[data-theme="light"] .sidebar-nav a svg{color:var(--sec)}
html[data-theme="light"] .sidebar-nav a.active svg{color:var(--purple)}
html[data-theme="light"] .sidebar-section-folder{stroke:var(--muted)}
/* Direct child: .fav-icon also holds the .sb-lock badge, whose glyph must keep taking
   the colour of the item it sits on (see the note on .sidebar-nav-scroll .sb-lock).
   The badge falls back to a neutral only when nothing gave it a colour to inherit. */
html[data-theme="light"] .fav-icon > svg{color:var(--sec)}
html[data-theme="light"] .sidebar-nav-scroll .sb-lock{color:var(--sec)}
html[data-theme="light"] .sidebar-nav-scroll .sb-lock svg{color:inherit;stroke:currentColor}
html[data-theme="light"] .azp-plus-sm{background:rgba(0,0,0,.06);color:var(--sec)}
html[data-theme="light"] .azp-plus-sm:hover{background:rgba(0,0,0,.1);color:var(--off-white)}
html[data-theme="light"] .mp-eye-btn{color:var(--sec)}
/* Sidebar hover in light: the row tints were white-alpha on a white sidebar. */
html[data-theme="light"] .sidebar-nav-scroll .sidebar-fav-nav a:hover,
html[data-theme="light"] .sidebar-nav-scroll .sidebar-cat-item:hover,
html[data-theme="light"] .sidebar-nav-scroll .sidebar-section-nav a:hover,
html[data-theme="light"] .sidebar-section-nav a:hover,
html[data-theme="light"] .sidebar-fav-nav a:hover,
html[data-theme="light"] .sidebar-cat-item:hover,
html[data-theme="light"] .sidebar-nav a:hover,
html[data-theme="light"] #sidebarFooterNav a:hover{background:rgba(0,0,0,.06);--sb-row-tint:rgba(0,0,0,.06)}
html[data-theme="light"] .sidebar-nav-scroll .sidebar-section-label:hover,
html[data-theme="light"] .sidebar-nav-scroll .sidebar-cat-label:hover{background:rgba(0,0,0,.045);--sb-row-tint:rgba(0,0,0,.045)}
/* Search fields: one control surface, like the top bar; the inner input never paints its own white box. */
html[data-theme="light"] .fm-search{background:var(--control-surface);border:0;box-shadow:none}
html[data-theme="light"] .fm-search:hover,html[data-theme="light"] .fm-search:focus-within,html[data-theme="light"] .cr-search-wrap:hover,html[data-theme="light"] .cr-search-wrap:focus-within{background:var(--control-surface-hover)}
html[data-theme="light"] .fm-search input,html[data-theme="light"] .cr-search-wrap input,html[data-theme="light"] .cr-search-wrap .cr-search-input{background:transparent !important;border:0 !important;box-shadow:none !important;color:var(--off-white)}
/* White text and white-alpha icons that survived on light surfaces. */
html[data-theme="light"] .ha-title{color:var(--off-white)}
html[data-theme="light"] .sidebar-ws-switch{color:var(--sec)}
html[data-theme="light"] .sidebar-ws-switch:hover{background:rgba(0,0,0,.06);color:var(--off-white)}
html[data-theme="light"] .cal-view-toggle button{color:var(--sec) !important}
html[data-theme="light"] .cal-view-toggle button.is-active{color:var(--purple) !important}
/* Padlocks and folder glyphs wear the item's own tint (inline), darkened like its name. */
/* Emoji favicons wash out on a light ground, so they get pulled down a touch. The
   folder glyph shares the same span but is a stroked SVG already painted in the exact
   category colour — the same filter turned its #ff6b6b into a visibly darker red than
   the channel icon next to it, which the owner read as "the wrong colour". Exempt it. */
html[data-theme="light"] .sidebar-section-label .fav-icon{filter:brightness(.78) saturate(1.15)}
html[data-theme="light"] .sidebar-section-label .fav-icon:has(> .sidebar-section-folder){filter:none}
/* Ask Shu from the multi-select bar: expands up from the bar, stays on the board. */
.multi-select-ask{display:inline-flex;align-items:center;gap:6px}
.multi-select-ask .shu-av{width:16px;height:16px;image-rendering:pixelated}
.multi-select-ask.on{background:color-mix(in srgb,var(--purple) 22%,transparent);color:var(--off-white)}
.ms-ask-pop{position:fixed;left:50%;transform:translateX(-50%);z-index:9200;width:min(520px,calc(100vw - 32px))}
.ms-ask-chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px}
.ms-ask-chip{font:600 11.5px var(--sans);color:var(--cream);background:var(--bg-inset,rgba(255,255,255,.06));border:1px solid var(--hairline,rgba(255,255,255,.08));border-radius:999px;padding:3px 9px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms-ask-chip.ms-ask-more{color:var(--muted)}
/* Files preview column in light: same ground as the page, and a divider you can see. */
html[data-theme="light"] .fm-drive .fm-col3,html[data-theme="light"] .fm-drive .fm-col3-wrap{background:transparent}
html[data-theme="light"] .fm-col-resizer::before{background:linear-gradient(to bottom,transparent 0,rgba(0,0,0,.16) 120px,rgba(0,0,0,.16) 100%)}
/* Profile popout: the bio box takes the same well as the other fields. */
html[data-theme="light"] .cr-profile-popout textarea.cr-profile-msg-input{background:rgba(0,0,0,.05);border-color:transparent}
/* Files storage bar: inline, right after the folder title. It used to own a full-width
   line above the title (order:-1), which read as a page-level banner about a number that
   only describes the drive whose name sits just under it. The crumbs stop claiming the
   whole row so the bar hugs the name; the actions keep their margin-left:auto seat. */
.fm-meter-row{flex:none;order:0;width:auto;margin:0 0 0 18px;display:flex;align-items:center;padding:0}
.fm-topbar .fm-crumbs{flex:0 1 auto}
.fm-meter{flex:none;display:flex;align-items:center;gap:10px;padding:0;margin:0;border:0}
.fm-meter-track{flex:none;width:200px;height:6px;border-radius:4px;background:rgba(255,255,255,.08);overflow:hidden}
.fm-meter.is-unlimited .fm-meter-fill{background:linear-gradient(90deg,color-mix(in srgb,var(--purple) 55%,transparent),color-mix(in srgb,var(--purple) 25%,transparent))}
.fm-meter-fill.is-amber{background:linear-gradient(90deg,#f0b34a,#d99a2b)}
.fm-meter-fill.is-red{background:linear-gradient(90deg,#f06a6a,#d94b4b)}
.fm-meter-txt{font:500 12px var(--sans);color:var(--muted);white-space:nowrap}
.fm-meter-txt b{font-weight:700;color:var(--off-white)}
html[data-theme="light"] .fm-meter-track{background:rgba(0,0,0,.08)}
.fm-src-note{margin:-4px 0 10px 54px;font:500 12px/1.45 var(--sans);color:var(--muted)}

/* ── Review/Publish player, light mode (owner decision 2026-09-04) ─────────────
   `.rev2 .rev-main` redeclares the dark token set locally so the player column stayed
   a dark room in both themes. On light the owner wants the stage, the empty drop
   target (icon + text), the transport and the name pill to follow the theme. `inherit`
   hands each island token back to the page's light value, so this block never drifts
   from the global light palette; the literal dark colours inside the island are
   remapped below. The video box itself stays black: letterboxing is black in every
   player, in every theme, and the big play button was already themed light. */
html[data-theme="light"] .rev2 .rev-main{color-scheme:light;background:var(--black);color:var(--off-white);
  --white:inherit;--off-white:inherit;--cream:inherit;--sec:inherit;--muted:inherit;
  --text-1:inherit;--text-2:inherit;--text-3:inherit;
  --hairline:inherit;--hairline-2:inherit;--hairline-3:inherit;--border-d:inherit;--bg-inset:inherit;
  --surf-1:inherit;--surf-2:inherit;--surf-3:inherit;--dark:inherit;
  --purple:inherit;--purple-soft:inherit;--gold:inherit;--green:inherit;--blue:inherit;--danger-text:#c0392b}
html[data-theme="light"] .rev2 .rev-stage{background:radial-gradient(80% 60% at 50% 40%,#f4f5f7,#e6e8ec 82%)}
html[data-theme="light"] .rev2 .rev-player{box-shadow:0 18px 44px rgba(0,0,0,.18)}
html[data-theme="light"] .rev-wrap.rev-show-upload .rev-player{box-shadow:0 18px 44px rgba(0,0,0,.18),0 0 0 2px rgba(122,95,214,.5)}
html[data-theme="light"] .rev-dropping .rev-stage{background:rgba(122,95,214,.08)}
/* empty state: icon + copy sit on the light stage */
html[data-theme="light"] .rev2 .rev-drop{color:var(--muted);border-color:rgba(0,0,0,.16)}
html[data-theme="light"] .rev2 .rev-drop-title{color:var(--off-white)}
/* name / version pill and the Publish "Platform videos" chip */
html[data-theme="light"] .rev2 .rev-stage>.rev-topright,html[data-theme="light"] .rev-topright,html[data-theme="light"] .sch-varchip-btn{background:rgba(255,255,255,.9);border-color:rgba(0,0,0,.1);box-shadow:0 2px 10px rgba(0,0,0,.08)}
html[data-theme="light"] .sch-varchip-btn:hover{background:#fff}
html[data-theme="light"] .rev-tr-name,html[data-theme="light"] .sch-varchip-btn{color:var(--off-white)}
html[data-theme="light"] .rev-tr-name[onclick]:hover{background:rgba(122,95,214,.16)}
html[data-theme="light"] .rev-tr-arrow{color:rgba(0,0,0,.55)}
html[data-theme="light"] .rev-tr-arrow:hover:not([disabled]){background:rgba(0,0,0,.07);color:var(--off-white)}
html[data-theme="light"] .rev-tr-count{color:rgba(0,0,0,.75)}
/* transport */
html[data-theme="light"] .rev2 .rev-transport .rev-scrub-track{background:rgba(0,0,0,.14)}
html[data-theme="light"] .rev-scrub-buffer span{background:rgba(0,0,0,.16)}
html[data-theme="light"] .rev-knob{box-shadow:0 1px 4px rgba(0,0,0,.45),0 0 0 1px rgba(0,0,0,.08)}
html[data-theme="light"] .rev2 .rev-ctrlrow .rev-cbtn{color:var(--sec)}
html[data-theme="light"] .rev2 .rev-ctrlrow .rev-cbtn:hover{background:rgba(0,0,0,.06);color:var(--off-white)}
html[data-theme="light"] .rev2 .rev-ctrlrow .rev-cbtn:disabled:hover,html[data-theme="light"] .rev2 .rev-ctrlrow .rev-cbtn.is-off:hover{background:transparent;color:var(--sec)}
html[data-theme="light"] .rev2 .rev-ctrlrow .rev-cbtn.on{background:var(--purple);color:#fff}
html[data-theme="light"] .rev2 .rev-ctrlrow .rev-cbtn-del:hover{background:rgba(210,59,59,.1);color:#c0392b}
html[data-theme="light"] .rev2 .rev-tcwrap .rev-tc{color:var(--off-white)}
html[data-theme="light"] .rev-tc-dur{color:rgba(0,0,0,.4)}
/* version strip, transcript drawer, annotate toolbar */
html[data-theme="light"] .rev2 .rev-verbar{border-bottom-color:var(--hairline)}
html[data-theme="light"] .rev2 .rev-verbar-file,html[data-theme="light"] .rev2 .rev-verbar-count{color:var(--off-white)}
html[data-theme="light"] .rev2 .rev-verbar-proj{color:var(--sec);background:rgba(0,0,0,.06)}
html[data-theme="light"] .rev2 .rev-verbar-arrow{color:var(--sec)}
html[data-theme="light"] .rev2 .rev-verbar-arrow:hover:not([disabled]){background:rgba(0,0,0,.06);color:var(--off-white)}
html[data-theme="light"] .rev-transcript{background:#fff;border-color:var(--border-d)}
html[data-theme="light"] .rev-annot-tools{background:rgba(255,255,255,.92);border-color:rgba(0,0,0,.1);color:var(--off-white);box-shadow:0 4px 14px rgba(0,0,0,.12)}
html[data-theme="light"] .rev-annot-tools button:not(.on){color:var(--off-white)}
html[data-theme="light"] .rev-annot-sw{border-color:rgba(0,0,0,.18)}
html[data-theme="light"] .rev-annot-sw.on{border-color:var(--off-white);box-shadow:0 0 0 2px rgba(0,0,0,.14)}
html[data-theme="light"] .rev-annot-tbtn{background:rgba(0,0,0,.06)}
html[data-theme="light"] .rev-annot-tbtn:hover{background:rgba(0,0,0,.12)}
html[data-theme="light"] .rev-transcript-edit,html[data-theme="light"] .rev-transcript-empty-add,html[data-theme="light"] .rev-transcript-import{background:rgba(0,0,0,.06)}
html[data-theme="light"] .rev-transcript-edit:hover,html[data-theme="light"] .rev-transcript-empty-add:hover,html[data-theme="light"] .rev-transcript-import:hover{background:rgba(0,0,0,.11)}
html[data-theme="light"] .rev-transcript-cue:hover{background:rgba(0,0,0,.04)}
html[data-theme="light"] .rev-transcript-x:hover{background:rgba(0,0,0,.06)}

/* ── Files toolbar: the new-folder glyph ──────────────────────────────────────
   `.fm-gear svg` pins every icon in that toolbar to 16px, so the size passed to
   _fmIco() is inert there. The folder is an open outline next to the gear's dense
   disc and read smaller at the same box; give it its own two pixels back. */
.fm-gear-nf svg{width:20px;height:20px}
/* The Files settings row sits at half opacity like the rest of the dropdown, which
   made the same gear look thinner than the one in the sidebar footer it is meant to
   match. The glyph is now identical; let it carry the same weight too. */
.server-dropdown-item .dd-hop-row svg{opacity:1}

/* ── Column resize handles ────────────────────────────────────────────────────
   These painted nothing at rest, so the only way to discover a column could be
   resized was to sweep the pointer along the header and notice the cursor change.
   Give them a quiet resting line — which doubles as the column divider the header
   lost — then a firm purple grip under the pointer. The hit area is widened to 10px
   because an 8px target straddling a border is below what a hand reliably lands on. */
.gv-col-resize{width:10px;right:-4px}
/* Hidden until the pointer is in the header, and then only on the nearest divider —
   see the pointermove handler that assigns .is-near. */
.gv-col-resize::after{left:4px;width:2px;background:var(--purple);border-radius:2px;opacity:0;transition:opacity .12s ease}
.gv-col-resize.is-near::after{opacity:.5}
.gv-col-resize.is-near:hover::after,.gv-col-resize:hover::after{opacity:1;box-shadow:0 0 0 1px color-mix(in srgb,var(--purple) 22%,transparent)}
.gv-flat-header .gv-flat-col:last-child .gv-col-resize::after{opacity:0 !important}
/* No grip pill. A short rounded block behind the line sat at a lighter tint than the
   line itself, so at a glance it read as a second, off-centre element in a different
   colour rather than as part of the divider. The line alone carries the affordance —
   it appears only under the pointer, which is signal enough. */
@media(prefers-reduced-motion:reduce){
  .gv-col-resize::after{transition:none}
}

/* ── Files list: the same table as a project's List view ──────────────────────
   Both are a header row over a grid of rows, but they were drawn by different
   hands: the Files header sat transparent and scrolled away, its labels were
   sentence-case body text rather than the small uppercase column headings used
   everywhere else, rows carried no separator at all, and file names were set at
   the same weight and grey as the metadata beside them — so nothing in the table
   told you what to read first.
   Scoped by #page-files because the light-theme rules for .fm-lc are (0,2,1) and
   would otherwise keep their colour; header and rows share one horizontal padding
   value, which is what keeps their columns aligned. The preview pane is untouched. */
#page-files .fm-lhead{
  position:sticky;top:0;z-index:2;
  background:var(--surface-container);
  height:40px;padding:0 18px;margin-bottom:0;
  border-bottom:1px solid var(--border-d)
}
#page-files .fm-lsort{
  font:700 11px var(--sans);
  text-transform:uppercase;letter-spacing:.7px;
  color:var(--text-2)
}
#page-files .fm-lsort.on,#page-files .fm-lsort:hover{color:var(--text-1)}
#page-files .fm-crow.fm-lrow{
  height:auto;min-height:43px;padding:0 18px;
  border-radius:0;
  border-bottom:1px solid var(--border-d)
}
#page-files .fm-crow.fm-lrow:last-child{border-bottom:none}
#page-files .fm-crow.fm-lrow:hover{background:rgba(255,255,255,.04)}
html[data-theme="light"] #page-files .fm-crow.fm-lrow:hover{background:rgba(0,0,0,.035)}
/* Name is the thing you scan; everything else is support. */
#page-files .fm-lc{font:500 13px var(--sans);color:var(--text-2)}
#page-files .fm-lc-name{font:600 14px var(--sans);color:var(--text-1)}

/* ── Files list, part 2: a floating table with dividers and draggable columns ──
   Matching a project's List view means four things this list did not have: the table
   floats as its own rounded card instead of sitting flush on the page; every column
   heading gets the same small uppercase treatment (By was bare text in a cell, so it
   kept body styling); cells are divided by vertical hairlines, which needs gap:0 and
   per-cell padding rather than a grid gap; and the fixed columns can be dragged. */
/* The table is the ONE scroll container. Previously the outer column scrolled too,
   so the card never overflowed, its sticky header had nothing to stick to and rode
   away with the rows, and the resize grips went with it — which is why neither the
   grips nor this scrollbar could be reached. */
#page-files .fm-col2{overflow:hidden;display:flex;flex-direction:column;min-height:0}
#page-files .fm-ltable{
  background:var(--surface-container);
  border-radius:14px;
  overflow:auto;overscroll-behavior:contain;
  flex:0 1 auto;min-height:0;
  margin:0 0 8px;
  /* Reserve the gutter so rows do not reflow the moment the bar appears. */
  scrollbar-gutter:stable;
  scrollbar-width:thin;
  scrollbar-color:var(--fm-sb,transparent) transparent;
  transition:scrollbar-color .28s cubic-bezier(.4,0,.2,1)
}
/* Custom bar: absent until you interact, then eased in. Firefox gets the same via the
   scrollbar-color transition above; WebKit needs the pseudo-elements. */
#page-files .fm-ltable:hover,#page-files .fm-ltable:focus-within{--fm-sb:rgba(0,0,0,.26)}
html[data-theme="light"] #page-files .fm-ltable:hover{--fm-sb:rgba(0,0,0,.26)}
#page-files .fm-ltable::-webkit-scrollbar{width:10px;height:10px}
#page-files .fm-ltable::-webkit-scrollbar-track{background:transparent}
#page-files .fm-ltable::-webkit-scrollbar-corner{background:transparent}
#page-files .fm-ltable::-webkit-scrollbar-thumb{
  background:transparent;border-radius:999px;
  /* The border is what insets the thumb from the card edge without shrinking the
     hit area — the track stays 10px wide and remains easy to grab. */
  border:3px solid transparent;background-clip:padding-box;
  transition:background-color .28s cubic-bezier(.4,0,.2,1)
}
#page-files .fm-ltable:hover::-webkit-scrollbar-thumb,
#page-files .fm-ltable:focus-within::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.26)}
#page-files .fm-ltable::-webkit-scrollbar-thumb:hover{background-color:rgba(0,0,0,.42)}
#page-files .fm-ltable::-webkit-scrollbar-thumb:active{background-color:var(--purple)}
html[data-theme="dark"] #page-files .fm-ltable:hover::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.22)}
html[data-theme="dark"] #page-files .fm-ltable::-webkit-scrollbar-thumb:hover{background-color:rgba(255,255,255,.34)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) #page-files .fm-ltable:hover::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.22)}
  :root:not([data-theme="light"]) #page-files .fm-ltable::-webkit-scrollbar-thumb:hover{background-color:rgba(255,255,255,.34)}
}
@media(prefers-reduced-motion:reduce){
  #page-files .fm-ltable,#page-files .fm-ltable::-webkit-scrollbar-thumb{transition:none}
}
/* The header can only stick once the table is the thing that scrolls. */
#page-files .fm-lhead{position:sticky;top:0;z-index:3;background:var(--surface-container)}
/* .page is height:100% of .main, but .main is a column flex whose first child is the
   52px top bar — so every page resolves 52px taller than the room it actually has and
   hangs that much below the fold, clipped by .main's overflow:hidden. Nothing showed it
   while the outer column had its own scrollbar to absorb the excess. Now that the table
   is the scroller, those 52px were the last rows, permanently out of reach. Let this
   page take the remaining space instead of a percentage of the whole. */
#page-files.page.active{height:auto;flex:1 1 auto;min-height:0}
/* One template, read by the header and every row, so their columns cannot drift. */
#page-files .fm-lhead,
#page-files .fm-crow.fm-lrow{
  grid-template-columns:var(--fm-cols,minmax(120px,1fr) 130px 150px 90px 44px);
  gap:0;padding:0;
  min-width:min-content
}
#page-files .fm-lhead{height:auto}
/* Cells own their padding now that the grid gap is gone, and carry the divider. */
#page-files .fm-lc{
  padding:10px 14px;
  border-right:1px solid var(--hairline);
  min-width:0
}
#page-files .fm-lc-act{border-right:none}
#page-files .fm-lhead .fm-lc{
  font:700 11px var(--sans);
  text-transform:uppercase;letter-spacing:.7px;
  color:var(--text-2);
  position:relative
}
#page-files .fm-lhead .fm-lsort{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;padding:0;margin:0}
#page-files .fm-lhead .fm-lsort.on,#page-files .fm-lhead .fm-lsort:hover{color:var(--text-1);background:none}
/* Nothing to override: the grip keeps .gv-col-resize's own trailing-edge position so it
   behaves identically to a project's List view — same offset, same reveal, same drag. */
#page-files .fm-ltable.is-col-resizing{cursor:col-resize;user-select:none}
#page-files .fm-ltable.is-col-resizing *{cursor:col-resize !important}

/* ── Filter chips sit beside Ask Shubot, so they share its shell ──────────────
   The chips were 32px tall on an 8px radius next to a 36px button on a 10px one:
   close enough to look like a mistake rather than a distinction. They stay outlined
   because they are filters, not the primary action, but the box now matches. */
#page-files .fm-chip{
  height:36px;
  border-radius:10px;
  padding:0 12px 0 14px
}

/* ── Sidebar colour, light mode (owner decision) ──────────────────────────────
   A folder's colour is the colour the owner picked. It was being mixed 32% toward a
   dark grey to buy contrast on white, which made Agent Stuff read as a muddy brick
   instead of the coral it is set to. Show the real value — everywhere it appears, so a
   folder, its children and its padlock are one hue rather than three shades of one.
   The label and icon are painted inline by the sidebar renderer, hence the weight. */
html[data-theme="light"] .sidebar-cat-colored .sidebar-section-name{color:var(--cat-color) !important}
html[data-theme="light"] .sidebar-cat-colored .sidebar-section-folder{stroke:var(--cat-color) !important}
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-item,
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-child .sidebar-channel-name{color:var(--cat-color)}
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-child .sidebar-channel-icon svg{stroke:var(--cat-color)}
/* Uncoloured rows: a folder was the one thing drawing its glyph in --muted while every
   project and channel beside it drew in the row's own ink, so the top folder read grey
   against black siblings. One neutral for all of them. */
html[data-theme="light"] .sidebar-section-folder{stroke:var(--text-1)}
/* No colour override here on purpose. _syncSidebarLocks already reads the computed
   colour of the glyph each padlock sits on and mirrors it inline — that is what makes a
   lock purple on a purple project and coral on a coral folder. Forcing currentColor from
   CSS beat that inline value and flattened every lock to the row's ink. The only thing
   this theme needs to guarantee is a sane fallback when nothing has been mirrored. */
html[data-theme="light"] .sidebar-nav-scroll .sb-lock{color:var(--text-1)}
/* The padlock is painted inline by _syncSidebarLocks with the folder's raw colour, so on
   white it stayed the bright pick while the icon it sits on had already been taken down —
   the badge read as a different colour from its own folder. Same mix as that icon. */
html[data-theme="light"] .sidebar-cat-colored .sidebar-section-label .sb-lock,
html[data-theme="light"] .sidebar-cat-colored .sidebar-section-label .sb-lock svg{
  color:var(--cat-color) !important
}

/* ── Mention chips in light mode ──────────────────────────────────────────────
   The chip colours are picked for the dark UI: #cbbdff lettering on a purple wash,
   and cream on a white wash for tasks. On a light panel the first is a pale mauve
   that barely separates from its own background, and the second is invisible. Use
   the same purple the author's name uses, so a mention of Shu and a line from Shu
   are recognisably the same colour. The base rules are !important, so these are too. */
html[data-theme="light"] .mention-person,
html[data-theme="light"] .mention-chip[data-type="person"],
html[data-theme="light"] .mention-chip[data-type="bot"]{
  color:var(--purple) !important;
  background:color-mix(in srgb,var(--purple) 14%,transparent) !important
}
html[data-theme="light"] .mention-person:hover,
html[data-theme="light"] .mention-chip[data-type="person"]:hover,
html[data-theme="light"] .mention-chip[data-type="bot"]:hover{
  background:color-mix(in srgb,var(--purple) 22%,transparent) !important
}
html[data-theme="light"] .mention-project,
html[data-theme="light"] .mention-chip[data-type="project"]{
  color:var(--purple) !important;
  background:color-mix(in srgb,var(--purple) 12%,transparent) !important
}
html[data-theme="light"] .mention-project:hover,
html[data-theme="light"] .mention-chip[data-type="project"]:hover{
  background:color-mix(in srgb,var(--purple) 20%,transparent) !important
}
html[data-theme="light"] .mention-task,
html[data-theme="light"] .mention-chip[data-type="task"]{
  color:var(--text-1) !important;
  background:rgba(0,0,0,.06) !important
}
html[data-theme="light"] .mention-task:hover,
html[data-theme="light"] .mention-chip[data-type="task"]:hover{
  background:rgba(0,0,0,.1) !important
}

/* ── DM composer = channel composer ───────────────────────────────────────────
   Same markup either side, but DMs wrapped the send button in a split control that
   filled purple once you typed and grew a divider and a caret, while a channel keeps
   a plain send glyph. The bar also carried a visible border a channel does not have.
   NOTE: the caret was the only way into Schedule send from a DM. Matching the channel
   exactly means it is no longer reachable — see the commit message. */
#dmInputRow .chatroom-input-bar{border-color:transparent}
#dmInputRow .dmx-send-split,
.dmx-composer-wrap.has-content #dmInputRow .dmx-send-split{
  margin-left:0;border-radius:0;overflow:visible;
  background:none !important;opacity:1;pointer-events:auto
}
#dmInputRow .dmx-send-caret{display:none}
#dmInputRow .dmx-send-split .cr-send{width:auto;height:auto}

/* ── Home → Social: consistent rhythm, and an account row you can act on ──────
   Section headings were spaced two ways: a bare <h3> took .ss-section h3's 10px, while
   the ones wrapped in .hsoc-head took none, so Connected accounts breathed and Analytics
   sat on top of its own table. One rule for both, and one type size for the headings. */
.hsoc-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:10px}
.hsoc-head h3{margin-bottom:0}
.ss-section > .hsoc-head + .group-view,
.ss-section > .hsoc-head + .ss-stats{margin-top:0}
.hsoc-scope-note{font:500 12px var(--sans);color:var(--text-2)}

/* The view switch matches the tab strip at the top of the page: muted when off, purple
   when on, and the moving pill supplies the wash rather than a solid fill. Icon-only, so
   the padding is square instead of the word-width padding it inherited. */
.hsoc-seg button{padding:6px 9px;display:inline-flex;align-items:center;justify-content:center}
.hsoc-seg button svg{display:block}
.hsoc-seg button{color:var(--muted)}
.hsoc-seg button.on{color:var(--purple)}
.hsoc-seg .m-pill-thumb{background:var(--purple-soft)}
html[data-theme="light"] .hsoc-seg{background:var(--surface-inset,rgba(0,0,0,.05))}

/* Row menu — the same three dots a person's row carries. */
.hsoc-rowmenu-cell{justify-content:flex-end}
.hsoc-rowmenu{width:28px;height:28px;border:0;background:none;color:var(--text-2);border-radius:7px;
  display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s,color .12s}
.hsoc-rowmenu:hover{background:var(--state-hover,rgba(255,255,255,.08));color:var(--text-1)}
html[data-theme="light"] .hsoc-rowmenu:hover{background:rgba(0,0,0,.06)}
.hsoc-acct-menu{position:fixed;z-index:100000;min-width:200px}

/* These two lose to dark-mode rules that appear later in this file — a footer-nav colour
   bundled into a long shared selector, and .hi-seg button.on pinning the active label to
   white. Restate them in the light theme, after both. */
html[data-theme="light"] #sidebarFooterNav a{color:var(--text-1)}
html[data-theme="light"] #sidebarFooterNav a:has(.sidebar-dm-dot.has-notif){color:var(--off-white)}
html[data-theme="light"] .hsoc-seg button{color:var(--muted)}
html[data-theme="light"] .hsoc-seg button.on{color:var(--purple)}
/* .hi-seg:not(:has(.m-pill-thumb)) button.on pins the active label to white for segments
   that have no sliding pill — correct where the button itself is filled purple, wrong
   here, where we want the tab strip's treatment: a lavender wash under purple lettering.
   Doubling the class clears that rule's weight. */
html[data-theme="light"] .hi-seg.hsoc-seg button.on,
html[data-theme="light"] .hi-seg.hsoc-seg:not(:has(.m-pill-thumb)) button.on{
  color:var(--purple);
  background:var(--purple-soft)
}
/* Measured off #homeTabs so this is the same control, not an approximation of it: the
   strip is the raised surface at an 11px radius, the active pill is the raw brand purple
   at 16% (what .m-pill-thumb paints there, not --purple-soft), and the lettering is the
   light-theme purple. This segment has no sliding thumb, so the active button carries the
   wash itself. */
html[data-theme="light"] .hi-seg.hsoc-seg{background:var(--surface-raised,#fff);border-radius:11px;padding:4px}
html[data-theme="light"] .hi-seg.hsoc-seg button{border-radius:9px}
html[data-theme="light"] .hi-seg.hsoc-seg button.on,
html[data-theme="light"] .hi-seg.hsoc-seg:not(:has(.m-pill-thumb)) button.on{
  color:#7a5fd6;
  background:rgba(124,92,255,.16)
}

/* ── Publishing activity, last 30 days ────────────────────────────────────────
   Replaces four count tiles that answered a question nobody asked ("how many posts
   exist?") with the one people actually look for: is anything going out, and is that
   more or less than it was. Counts that still matter sit as chips beside the number
   rather than each claiming a card of its own. */
.hsoc-chart-card{background:var(--surface-container);border-radius:14px;padding:18px 20px 12px}
.hsoc-chart-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}
.hsoc-chart-label{font:700 11px var(--sans);letter-spacing:.6px;text-transform:uppercase;color:var(--text-2)}
.hsoc-chart-value{font:700 30px/1.1 var(--sans);color:var(--text-1);font-variant-numeric:tabular-nums;margin-top:4px;display:flex;align-items:baseline;gap:9px}
.hsoc-chart-sub{font:500 12px var(--sans);color:var(--text-2);margin-top:5px}
.hsoc-delta{font:700 12px var(--sans);padding:2px 7px;border-radius:999px}
.hsoc-delta.up{color:var(--green);background:color-mix(in srgb,var(--green) 14%,transparent)}
.hsoc-delta.down{color:var(--danger-text,#c0392b);background:color-mix(in srgb,var(--danger-text,#c0392b) 12%,transparent)}
.hsoc-chart-side{display:flex;gap:8px;flex-wrap:wrap}
.hsoc-chip{font:500 12px var(--sans);color:var(--text-2);background:var(--bg-inset);border-radius:999px;padding:5px 10px;white-space:nowrap}
.hsoc-chip b{font-weight:700;color:var(--text-1);font-variant-numeric:tabular-nums}
.hsoc-chip.is-bad b{color:var(--danger-text,#c0392b)}
.hsoc-chart{display:block;width:100%;height:150px;margin-top:14px;overflow:visible}
.hsoc-grid{stroke:var(--hairline);stroke-width:1;vector-effect:non-scaling-stroke}
.hsoc-line{fill:none;stroke:var(--purple);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}
.hsoc-dot{fill:var(--purple);stroke:var(--surface-container);stroke-width:2;vector-effect:non-scaling-stroke}
.hsoc-g0{stop-color:var(--purple);stop-opacity:.26}
.hsoc-g1{stop-color:var(--purple);stop-opacity:0}
/* A marker on the line, not a tinted column: a filled rectangle draws the eye to the
   band instead of the value, and reads as a selection the user did not make. */
.hsoc-cursor-line{opacity:0;transition:opacity .12s ease;stroke:var(--hairline-3);stroke-width:1;vector-effect:non-scaling-stroke}
.hsoc-chart.is-hovering .hsoc-cursor-line{opacity:1}
/* A real circle: it lives outside the svg because that element is stretched to the
   container, which would draw any circle inside it as an ellipse. No ring — the outline
   only existed to lift an SVG dot off the line, and a solid dot reads cleaner. Position
   is animated through transform so it glides on the compositor instead of relayouting. */
.hsoc-cursor-dot{position:absolute;top:0;left:0;width:10px;height:10px;border-radius:50%;
  background:var(--purple);border:0;pointer-events:none;opacity:0;z-index:5;
  transition:transform .13s cubic-bezier(.22,1,.36,1),opacity .13s ease}
.hsoc-cursor-dot.show{opacity:1}
.hsoc-readout{position:absolute;top:0;left:0;pointer-events:none;opacity:0;
  transition:transform .13s cubic-bezier(.22,1,.36,1),opacity .13s ease;
  background:var(--surface-raised,#fff);border:1px solid var(--hairline-2);border-radius:9px;
  padding:6px 10px;white-space:nowrap;box-shadow:0 6px 20px rgba(0,0,0,.14);
  font:500 12px var(--sans);color:var(--text-2);z-index:6}
.hsoc-readout.show{opacity:1}
@media(prefers-reduced-motion:reduce){
  .hsoc-cursor-dot,.hsoc-readout{transition:opacity .1s ease}
}
.hsoc-readout b{font:700 13px var(--sans);color:var(--text-1);margin-right:6px}
.hsoc-readout span{display:block;font-size:11px;color:var(--text-2);margin-top:1px}
.hsoc-chart-card{position:relative}
.hsoc-chart-empty{font:500 12.5px var(--sans);color:var(--text-2);padding:0 0 6px}

/* Containers on this page were outlined twice over in light mode: a hairline border on
   the tab strip and a soft drop shadow under it and the tables. On a light canvas each
   card already separates by its own surface colour, so the outline just adds noise. */
html[data-theme="light"] .ws-view-tabs{border-color:transparent;box-shadow:none}
html[data-theme="light"] .gv-flat-table{box-shadow:none}
html[data-theme="light"] .hsoc-chart-card{box-shadow:none}
/* One black in the sidebar. Labels were split between --text-1 (#17171c) and --off-white
   (#1c1c1e): close enough to look like a rendering artefact, far enough that a channel
   never quite matched the project above it. */
html[data-theme="light"] .sidebar-section-name,
html[data-theme="light"] .sidebar-channel-name,
html[data-theme="light"] .sidebar-cat-item,
html[data-theme="light"] .sidebar-fav-nav a,
html[data-theme="light"] .sidebar-section-nav a{color:var(--text-1)}
html[data-theme="light"] .sidebar-cat-colored .sidebar-section-name{color:var(--cat-color) !important}
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-item,
html[data-theme="light"] .sidebar-cat-colored .sidebar-cat-child .sidebar-channel-name{color:var(--cat-color)}

/* ── Account avatars load from the provider's CDN ─────────────────────────────
   They are always a beat behind the row that frames them, and with nothing beneath
   them that beat reads as a blank box that pops. Hold the same skeleton sweep the
   rest of the app uses, then fade the picture in over it. .skel-avatar supplies the
   gradient and the reduced-motion opt-out, so this adds no second loader. */
.hsoc-av.is-loading{
  background:linear-gradient(90deg,var(--bg-inset) 25%,var(--skel-hi,rgba(255,255,255,.13)) 50%,var(--bg-inset) 75%);
  background-size:200% 100%;
  animation:skelShimmer 1.4s linear infinite;
  /* The element keeps its box so the row never reflows when the picture lands. */
  color:transparent
}
/* No opacity trick on the <img> itself: an image and its own background share one
   opacity, so fading the element out to reveal "the skeleton underneath" hides the
   skeleton too. The background IS the skeleton, and the picture paints over it the
   moment it decodes — so the box is never empty, which is the whole point. */
/* A 404 avatar keeps the circle rather than an alt-text stub or an endless shimmer. */
img.hsoc-av.is-broken{background:var(--bg-inset);animation:none}
@media(prefers-reduced-motion:reduce){
  .hsoc-av.is-loading{animation:none}
}

/* ── Review / Publish action tabs, entering and leaving ───────────────────────
   Share For Review and Settings appear only on the tabs that own them, so they
   arrive and depart while the row is on screen. Popping in and out at full size
   made the whole tab strip twitch; easing width and opacity together lets the
   neighbours slide rather than jump. Settings survives a Review↔Publish switch
   and is deliberately left untouched by both animations — see switchCardModalTab. */
@keyframes revExtraIn{
  from{opacity:0;transform:translateX(-4px) scale(.96);max-width:0;padding-left:0;padding-right:0}
  to{opacity:1;transform:none;max-width:220px}
}
@keyframes revExtraOut{
  from{opacity:1;transform:none;max-width:220px}
  to{opacity:0;transform:translateX(-4px) scale(.96);max-width:0;padding-left:0;padding-right:0}
}
.rev-extra-tab{max-width:220px;overflow:hidden;white-space:nowrap}
.rev-extra-tab.is-entering{animation:revExtraIn .22s cubic-bezier(.22,1,.36,1) both}
.rev-extra-tab.is-leaving{animation:revExtraOut .2s cubic-bezier(.4,0,1,1) both;pointer-events:none}
@media(prefers-reduced-motion:reduce){
  .rev-extra-tab.is-entering,.rev-extra-tab.is-leaving{animation-duration:.001ms}
}

/* A hashtag that names a real channel is a chip like the task and person ones: it opens a
   card on click. Only the resolved ones get the hand — an unresolved #word stays text. */
.mention-hash.mention-channel{cursor:pointer}
.mention-hash.mention-channel:hover{filter:brightness(1.08)}

/* Uncoloured folders draw their glyph in these; the tree lines under them use the same. */
.sidebar-cat-wrapper{--sb-tree:rgba(235,235,245,.82)}
html[data-theme="light"] .sidebar-cat-wrapper{--sb-tree:var(--text-1)}

/* DM list preview of an agent error: the message's colour and glyph, on one line. */
.dmx-row-prev.is-error{color:var(--danger-text,#ff8f8f);font-style:italic;display:inline-flex;align-items:center;gap:5px;min-width:0}
.dmx-row-prev.is-error svg{flex:none;opacity:.8}

/* ── Canvas tool rail ───────────────────────────────────────────────────────
   Floats at the left of the canvas, its top on the same line as the view tabs, and wears
   the tabs' own surface, radius and padding so the two read as one set of controls. */
/* Fallback geometry = tabs at 16px/40px, 46px tall, plus the 10px gap; JS measures the real thing. */
.cv-rail{position:absolute;left:16px;top:var(--cv-rail-top,96px);z-index:6;display:flex;flex-direction:column;gap:10px}
.cv-rail-group{display:flex;flex-direction:column;gap:2px;padding:4px;background:var(--surface-container);border-radius:11px;box-shadow:0 1px 2px rgba(0,0,0,.05),0 6px 18px rgba(0,0,0,.07)}
.cv-tool{width:38px;height:38px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:9px;background:transparent;color:var(--text-1);cursor:pointer;transition:background .12s ease,color .12s ease}
.cv-tool svg{width:20px;height:20px}
.cv-tool:hover{background:var(--bg-inset)}
.cv-tool:focus-visible{outline:2px solid var(--purple);outline-offset:-2px}
.cv-tool.active{background:color-mix(in srgb,var(--ws-accent,var(--purple)) 16%,transparent);color:var(--ws-accent,var(--purple))}
.cv-tool .cv-ink{stroke:var(--surface-container)}
.cv-rail-sep{height:1px;margin:4px 6px;background:color-mix(in srgb,var(--text-1) 12%,transparent)}

/* Undo/redo are gated by the board's history; a dead end looks like one. */
.cv-tool:disabled{opacity:.35;cursor:default}
.cv-tool:disabled:hover{background:transparent}
/* ── Zoom, bottom-left of the whiteboard. Fixed so it stays put while the board scrolls;
   its left is set from the view tabs' left edge, the same line the rail hangs on. ── */
.cv-zoom{position:fixed;left:16px;bottom:16px;z-index:6;display:inline-flex;align-items:center;gap:2px;padding:4px;background:var(--surface-container);border-radius:11px;box-shadow:0 1px 2px rgba(0,0,0,.05),0 6px 18px rgba(0,0,0,.07)}
.cv-zoom-btn{width:34px;height:34px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:9px;background:transparent;color:var(--text-1);cursor:pointer}
.cv-zoom-btn svg{width:16px;height:16px}
.cv-zoom-btn:hover{background:var(--bg-inset)}
.cv-zoom-val{min-width:54px;height:34px;padding:0 6px;border:0;border-radius:9px;background:transparent;color:var(--text-2);font:600 12.5px var(--sans);font-variant-numeric:tabular-nums;cursor:pointer}
.cv-zoom-val:hover{background:var(--bg-inset);color:var(--text-1)}
.cv-zoom-btn:focus-visible,.cv-zoom-val:focus-visible{outline:2px solid var(--purple);outline-offset:-2px}

/* Shortcut keycaps inside the app tooltip (data-tip-keys), and the side placement. */
.app-tip.is-side{transform:none}
.app-tip-keys{display:inline-flex;gap:3px;margin-left:9px;vertical-align:middle}
.app-tip kbd{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:5px;background:color-mix(in srgb,currentColor 18%,transparent);color:inherit;font:600 11px var(--sans);letter-spacing:.02em}
/* The history group runs to the default note's bottom edge: a note is 10 rows of 40px,
   the first group is 297px and the gap 10px, so this group is 93px. */
.cv-rail-history{padding:7px 4px 8px}

/* Settings fields sit on the card's fill alone — no outline at rest, and focus shows as a
   lift of the fill rather than a ring. */
.profile-input,.profile-textarea{border-color:transparent}
.profile-input:focus,.profile-textarea:focus{border-color:transparent;background:color-mix(in srgb,var(--purple) 8%,var(--bg-inset,rgba(255,255,255,.06)))}
#usFbEmail,#usFbText{border-color:transparent !important}
#usFbEmail:focus,#usFbText:focus{background:color-mix(in srgb,var(--purple) 8%,var(--bg-inset,rgba(255,255,255,.06))) !important}

/* The "no colour" swatch is a container in both themes: faint white on dark, grey on paper. */
.eim-swatch-none{background:rgba(255,255,255,.12)}
html[data-theme="light"] .eim-swatch-none{background:rgba(0,0,0,.09)}

/* ── Tool flyouts: beside the rail, the rail's own surface. ── */
.cv-fly{position:fixed;z-index:1150;min-width:236px;padding:10px 12px 12px;border-radius:12px;background:var(--surface-container);box-shadow:0 1px 2px rgba(0,0,0,.06),0 10px 28px rgba(0,0,0,.14);opacity:0;pointer-events:none;transform:translateX(-4px);transition:opacity .14s ease,transform .14s ease}
.cv-fly.show{opacity:1;pointer-events:auto;transform:none}
.cv-fly-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px;color:var(--text-1);font:600 13px var(--sans)}
.cv-fly-head .app-tip-keys{margin-left:0}
.cv-fly-head kbd{background:var(--bg-inset);color:var(--text-2)}
.cv-fly-label{font:600 10.5px var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--text-3);margin:8px 0 6px}
.cv-fly-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.cv-fly-row .eim-color-swatch{width:24px;height:24px}
.cv-fly-none{position:absolute;top:50%;left:50%;width:140%;height:2px;background:var(--muted);transform:translate(-50%,-50%) rotate(-45deg)}
.cv-fly-row .eim-swatch-none{position:relative;overflow:hidden}
.cv-fly-segs{gap:4px}
.cv-fly-seg{min-width:34px;height:30px;padding:0 10px;border:0;border-radius:8px;background:var(--bg-inset);color:var(--text-2);font:600 12.5px var(--sans);cursor:pointer}
.cv-fly-seg:hover{color:var(--text-1)}
.cv-fly-seg.on{background:color-mix(in srgb,var(--purple) 16%,transparent);color:var(--purple)}
@media(prefers-reduced-motion:reduce){.cv-fly{transition:none}}

/* ── Insert picker: a short searchable list beside the + ── */
.cv-picker{position:fixed;z-index:1200;width:300px;max-height:380px;display:flex;flex-direction:column;border-radius:12px;background:var(--surface-container);box-shadow:0 1px 2px rgba(0,0,0,.06),0 10px 28px rgba(0,0,0,.16);overflow:hidden}
.cv-picker-head{padding:10px 12px 6px;font:600 13px var(--sans);color:var(--text-1);display:flex;align-items:center;justify-content:space-between;gap:8px}
.cv-picker-x{width:24px;height:24px;flex:none;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:7px;background:transparent;color:var(--text-3);cursor:pointer}
.cv-picker-x svg{width:13px;height:13px}
.cv-picker-x:hover{background:var(--bg-inset);color:var(--text-1)}
.cv-picker-q{margin:0 10px 8px;padding:8px 10px;border:0;border-radius:8px;background:var(--bg-inset);color:var(--text-1);font:500 13px var(--sans);outline:none}
.cv-picker-q:focus{box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--purple) 55%,transparent)}
.cv-picker-list{overflow-y:auto;padding:0 6px 8px;display:flex;flex-direction:column;gap:2px}
.cv-picker-item{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:7px 10px;border:0;border-radius:8px;background:transparent;text-align:left;cursor:pointer;color:var(--text-1)}
.cv-picker-item:hover,.cv-picker-item:focus-visible{background:var(--bg-inset);outline:none}
.cv-picker-label{font:600 13px var(--sans);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.cv-picker-sub{font:500 11.5px var(--sans);color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.cv-picker-empty{padding:12px;font:500 12.5px var(--sans);color:var(--text-3)}

/* The shape picker's two buttons hold an icon rather than a letter. */
.cv-fly-shape{display:inline-flex;align-items:center;justify-content:center;min-width:40px}
.cv-fly-shape svg{width:17px;height:17px}

/* Fit sits with the zoom controls and takes the same treatment. */
.cv-zoom-fit svg{width:15px;height:15px}
