/* ============================================================
   DS WORKSPACE OS V3 — Kliktron Advertising Platform
   Design: clear, minimalist, modern, professional.
   Theme: light (default) + dark via [data-theme="dark"]
   ============================================================ */

:root{
  /* surfaces are white in light mode; borders carry the separation */
  /* greys are neutral (no blue cast) and a shade lighter; white surfaces stay white */
  --bg:#ffffff; --panel:#ffffff; --sidebar:#fafafa; --ink:#12181f; --sub:#6b7280;
  --line:#e9e9e9; --line2:#f1f1f1; --soft:#f7f7f7; --accent:#2f6bed; --accent-soft:#eaf0fe;
  --ok:#16a34a; --okb:#e7f6ec; --warn:#c77a18; --warnb:#fbf1e2; --dang:#dc2626; --dangb:#fbeaea;
  --slate:#64748b; --slateb:#f2f2f2; --violet:#7a4fd1; --teal:#0d9488; --gold:#b08900;
  --radius:10px; --sh:0 1px 2px rgba(16,24,40,.04),0 1px 3px rgba(16,24,40,.06);
  --shl:0 8px 30px rgba(16,24,40,.14);
  --side-w:250px; --rail-w:58px;
}
[data-theme="dark"]{
  --bg:#0f1115; --panel:#14171d; --sidebar:#101318; --ink:#e8eaee; --sub:#98a1ae;
  --line:#242a33; --line2:#1c2129; --soft:#181c23; --accent:#5b8cff; --accent-soft:#182642;
  --ok:#3fbf6f; --okb:#12261a; --warn:#d99a3d; --warnb:#2a2113; --dang:#f06565; --dangb:#2c1618;
  --slate:#8794a5; --slateb:#1b2028; --violet:#9b74e8; --teal:#2bb6a8; --gold:#d4ac3a;
  --sh:0 1px 2px rgba(0,0,0,.4),0 1px 3px rgba(0,0,0,.3);
  --shl:0 10px 34px rgba(0,0,0,.55);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
/* §88 — the workspace draws **below 1:1** — 90% today (§88b; it shipped at 80% and
   read too small) — the way a reader who had pressed Ctrl+- once
   was already using it. `zoom` and not `transform:scale()`: zoom re-lays the page
   out at the smaller size, so nothing about the structure changes — the sidebar is
   still the sidebar, the grid still wraps where it wrapped, and a `position:fixed`
   panel still sits where it was told to. A transform would paint a shrunken picture
   of a full-size page and leave the hit areas behind it.

   One number, `--ui-zoom`. ⚠ Three things follow from it and all three are done:

   1. the **print sheet resets to 1** — an export must not shrink with the screen.
      Setting the token in `@media print` is enough; everything below reads it.
   2. every popover measures itself with `getBoundingClientRect()` rather than
      `offsetWidth` — under a zoom the first is viewport space, like `innerWidth`,
      and the second is not. `zpx()` in ui.js writes the number back the other way.
   3. **a viewport unit is not zoomed.** `100vh` stays the height of the window and
      is then scaled with everything else, so a full-height shell drew at the zoom's
      share of the screen and left the rest of it empty (§88a). `--vh` / `--vw` are the units this
      workspace uses instead: one hundredth of the window *in the space the page is
      laid out in*. Same for the breakpoints — below 1:1 the layout is wider than
      the window, so every `@media` width is the design width × the zoom, which is
      exactly what browser zoom does to them. */
:root{--ui-zoom:.9; --vh:calc(1vh / var(--ui-zoom)); --vw:calc(1vw / var(--ui-zoom))}
body{font-family:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;color:var(--ink);
  background:var(--bg);-webkit-font-smoothing:antialiased;font-size:13px;line-height:1.5;
  zoom:var(--ui-zoom);
  transition:background .18s,color .18s}
button{font-family:inherit;cursor:pointer;color:inherit}
input,select,textarea{font-family:inherit;color:inherit}
a{color:inherit}
::selection{background:var(--accent-soft)}

/* ---------- LOGIN ---------- */
.login{position:fixed;inset:0;z-index:200;display:grid;place-items:center;background:var(--bg)}
.login-card{width:360px;max-width:calc(92 * var(--vw));border:1px solid var(--line);border-radius:16px;background:var(--panel);
  box-shadow:var(--shl);padding:30px 28px}
.login-logo{width:40px;height:40px;border-radius:11px;background:var(--ink);display:flex;align-items:center;justify-content:center;margin-bottom:16px;overflow:hidden;line-height:0}
.login-logo img{width:25px;height:25px;display:block;object-fit:contain;filter:invert(1)}
[data-theme="dark"] .login-logo{background:#fff}
[data-theme="dark"] .login-logo img{filter:none}
.login h1{font-size:19px;margin:0 0 4px;letter-spacing:-.4px}
.login p{margin:0 0 20px;color:var(--sub);font-size:12.5px}
.login .field{margin-bottom:12px}
.login .btn{width:100%;justify-content:center;margin-top:6px}
.login .hint2{font-size:11px;color:var(--sub);margin-top:14px;line-height:1.7}
.login .hint2 code{background:var(--soft);border:1px solid var(--line2);border-radius:5px;padding:1px 5px;font-size:10.5px}

/* ---------- APP SHELL ---------- */
.app{display:grid;grid-template-columns:var(--side-w) 1fr;height:calc(100 * var(--vh));overflow:hidden;transition:grid-template-columns .2s}
.app.side-collapsed{grid-template-columns:var(--rail-w) 1fr}

/* ---------- SIDEBAR ---------- */
.side{background:var(--sidebar);border-right:1px solid var(--line);display:flex;flex-direction:column;overflow:hidden}

/* ---- collapsed = icon rail; hovering the rail opens it temporarily ---- */
.app.side-collapsed .side{position:fixed;top:0;left:0;height:calc(100 * var(--vh));width:var(--rail-w);z-index:45;
  transition:width .18s ease,box-shadow .18s ease}
/* the fixed rail leaves the grid flow — pin main to the second track so it
   keeps its own column instead of sliding into the rail track */
.app.side-collapsed .main{grid-column:2}
.app.side-collapsed .side:hover{width:var(--side-w);box-shadow:6px 0 26px rgba(16,24,40,.13)}
[data-theme="dark"] .app.side-collapsed .side:hover{box-shadow:6px 0 26px rgba(0,0,0,.55)}
.app.side-collapsed .side .lbl,
.app.side-collapsed .side .gh,
.app.side-collapsed .side .brand-txt,
.app.side-collapsed .side .side-foot,
.app.side-collapsed .side .chev,
.app.side-collapsed .side .badge,
.app.side-collapsed .side .side-collapse{opacity:0;transition:opacity .12s}
.app.side-collapsed .side:hover .lbl,
.app.side-collapsed .side:hover .gh,
.app.side-collapsed .side:hover .brand-txt,
.app.side-collapsed .side:hover .side-foot,
.app.side-collapsed .side:hover .chev,
.app.side-collapsed .side:hover .badge,
.app.side-collapsed .side:hover .side-collapse{opacity:1}
.app.side-collapsed .side .side-collapse{pointer-events:none}
.app.side-collapsed .side:hover .side-collapse{pointer-events:auto}
.app.side-collapsed .side .subitems{display:none}
.app.side-collapsed .side:hover .divgrp.open .subitems{display:block}
.app.side-collapsed .side .nav{overflow-y:auto;overflow-x:hidden}
.app.side-collapsed .side .item,
.app.side-collapsed .side .dh{white-space:nowrap}
/* rail: keep the icon column fixed so nothing jitters on hover-expand */
.app.side-collapsed .side .item,
.app.side-collapsed .side .divgrp>.dh{padding-left:11px;padding-right:11px}
.app.side-collapsed .side .grp>.gh{height:0;padding-top:0;padding-bottom:0;overflow:hidden;transition:height .12s,padding .12s,opacity .12s}
.app.side-collapsed .side:hover .grp>.gh{height:auto;padding:4px 10px}
.app.side-collapsed .side .brand{padding-left:15px}
.app.side-collapsed .side:hover .brand{padding-left:12px}
.app.side-collapsed .side .brand-txt{white-space:nowrap}
/* while the rail is only previewing, the foot must not steal pointer events */
.app.side-collapsed .side .side-foot{pointer-events:none}
.app.side-collapsed .side:hover .side-foot{pointer-events:auto}
.brand{display:flex;align-items:center;gap:9px;padding:14px 12px 10px;position:relative}
.brand-btn{display:flex;align-items:center;gap:9px;flex:1;border:0;background:transparent;padding:4px 6px;border-radius:9px;text-align:left}
.brand-btn:hover{background:var(--soft)}
.logo{width:27px;height:27px;border-radius:8px;background:var(--ink);display:flex;align-items:center;justify-content:center;overflow:hidden;flex:0 0 27px;line-height:0}
.logo img{width:17px;height:17px;display:block;margin:0;object-fit:contain;filter:invert(1)}
[data-theme="dark"] .logo{background:#fff}
[data-theme="dark"] .logo img{filter:none}
/* ---- the mark wears the space it is standing in (BOARD OFFICE V1A) ----
   A coloured block with a white icon, one colour per space. The icon stays
   white in **both** themes here, so the dark-theme rule above — which flips the
   block white and the icon dark — has to be overridden for a toned mark. */
/* the fallback matters: an unknown or missing tone must still paint a solid
   block with a white icon. Without it `var(--wsc)` resolves to nothing, the
   background falls back to transparent, and the mark reads as a white tile with
   a dark icon — which is exactly what a half-updated cache used to show. */
.logo{--wsc:var(--ink)}
.tone-blue{--wsc:#2f6bed}
.tone-gold{--wsc:#c8930a}
.tone-green{--wsc:#12855a}
.tone-red{--wsc:#d63b3b}
.logo{background:var(--wsc)}
.logo img{filter:invert(1) brightness(2.2)}
[data-theme="dark"] .logo{background:var(--wsc)}
[data-theme="dark"] .logo img{filter:invert(1) brightness(2.2)}
/* the same four colours as a dot beside each row of the switcher */
.wsdot{width:9px;height:9px;border-radius:3px;flex:0 0 9px;background:var(--wsc)}
.brand-txt b{font-size:13.5px;letter-spacing:-.2px;display:block}
.brand-txt span{font-size:10.5px;color:var(--sub);display:block;margin-top:-2px}
.side-collapse{border:1px solid var(--line);background:var(--bg);border-radius:7px;width:26px;height:26px;
  display:grid;place-items:center;font-size:11px;color:var(--sub);flex:0 0 26px}
.side-collapse:hover{background:var(--soft);color:var(--ink)}
.side-open-btn{display:none;border:1px solid var(--line);background:var(--bg);border-radius:8px;width:30px;height:30px;
  align-items:center;justify-content:center;color:var(--sub);flex:0 0 30px}
.app.side-collapsed .side-open-btn{display:inline-flex}
.side-open-btn:hover{background:var(--soft);color:var(--ink)}

.nav{flex:1;overflow-y:auto;padding:4px 8px 8px}
.nav::-webkit-scrollbar{width:8px}
.nav::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.grp{margin-top:11px}
.grp>.gh{font-size:9.5px;text-transform:uppercase;letter-spacing:.8px;color:var(--sub);opacity:.85;font-weight:700;padding:4px 10px}
.item{display:flex;align-items:center;gap:9px;padding:7px 10px;border-radius:8px;font-size:12.5px;color:var(--ink);
  opacity:.86;user-select:none;cursor:pointer}
.item:hover{background:var(--soft);opacity:1}
.item.active{background:var(--bg);opacity:1;font-weight:600;box-shadow:var(--sh);border:1px solid var(--line2)}
.item .ic{width:15px;height:15px;flex:0 0 15px;stroke:var(--sub);stroke-width:1.8;fill:none}
.item.active .ic{stroke:var(--accent)}
.item .lbl{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.item .badge{margin-left:auto;font-size:10px;background:var(--soft);color:var(--sub);border-radius:20px;padding:1px 7px;font-weight:600}
.divgrp>.dh{display:flex;align-items:center;gap:9px;padding:7px 10px;border-radius:8px;font-size:12.5px;font-weight:600;
  color:var(--ink);opacity:.9;user-select:none;cursor:pointer}
.divgrp>.dh:hover{background:var(--soft)}
.divgrp>.dh.active{background:var(--bg);box-shadow:var(--sh);border:1px solid var(--line2)}
.divgrp>.dh .ic{width:15px;height:15px;flex:0 0 15px;stroke:var(--sub);stroke-width:1.8;fill:none}
.divgrp>.dh.active .ic{stroke:var(--accent)}
.divgrp>.dh .lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
/* the chevron is its own button now — it folds the division without opening it */
.divgrp .chevbtn{margin-left:auto;flex:0 0 auto;display:grid;place-items:center;width:20px;height:20px;
  border:0;background:transparent;border-radius:6px;padding:0;cursor:pointer}
.divgrp .chevbtn:hover{background:var(--line2)}
.divgrp .chev{flex:0 0 13px;width:13px;height:13px;stroke:var(--sub);transition:transform .15s;fill:none;stroke-width:2}
.divgrp.open .chev{transform:rotate(90deg)}
.divgrp .chevbtn:hover .chev{stroke:var(--ink)}
/* on the collapsed rail the chevron fades out with the labels — and stops being
   clickable while it is invisible, or the rail would fold groups by accident */
.app.side-collapsed .side .chevbtn{opacity:0;pointer-events:none;transition:opacity .12s}
.app.side-collapsed .side:hover .chevbtn{opacity:1;pointer-events:auto}
.subitems{display:none;margin:2px 0 4px 9px;padding-left:9px;border-left:1px solid var(--line)}
.divgrp.open .subitems{display:block}
/* a personnel name lines up with its division's name, not with the guide rail:
   the division text starts at 10px of padding + a 15px icon + a 9px gap, so the
   6px the sub-items were short by is given back here (9 + 1 border + 9 + 15 = 34) */
.subitems .item{padding:6px 9px 6px 15px;font-size:12px}
.side-foot{padding:10px 16px 12px;font-size:9.5px;line-height:1.45;color:var(--sub);opacity:.5;border-top:1px solid var(--line2)}

/* brand dropdown */
.brandmenu{position:absolute;top:52px;left:12px;right:12px;background:var(--panel);border:1px solid var(--line);
  border-radius:11px;box-shadow:var(--shl);padding:6px;z-index:70;display:none}
.brandmenu.on{display:block}
.brandmenu .mh{font-size:9.5px;text-transform:uppercase;letter-spacing:.7px;color:var(--sub);font-weight:700;padding:7px 9px 4px}
.brandmenu button{display:flex;align-items:center;gap:9px;width:100%;border:0;background:transparent;padding:8px 9px;
  border-radius:7px;font-size:12.5px;text-align:left}
.brandmenu button:hover{background:var(--soft)}
.brandmenu button[disabled]{opacity:.4;cursor:not-allowed}
.brandmenu button .r{margin-left:auto;font-size:10.5px;color:var(--sub)}
.brandmenu hr{border:0;border-top:1px solid var(--line2);margin:5px 2px}
.brandmenu .wshead .chev{width:13px;height:13px;stroke:var(--sub);transition:transform .15s;flex:0 0 13px;margin-left:2px}
.brandmenu .wsgrp.open .wshead .chev{transform:rotate(90deg)}
.brandmenu .wshead .r{margin-left:auto}
.brandmenu .wssub{display:none;margin:2px 0 2px 10px;padding-left:8px;border-left:1px solid var(--line)}
.brandmenu .wsgrp.open .wssub{display:block}
.brandmenu .wssub button{font-size:12px}
/* V1A — the four spaces are equals: one flat list, no parent row, no indent */
.brandmenu .wsrow{display:flex;align-items:center;gap:8px}
.brandmenu .wsrow .r{margin-left:auto}
.brandmenu .wsrow.on{font-weight:600}
.seg{display:inline-flex;background:var(--soft);border-radius:7px;padding:2px;margin-left:auto}
.seg button{padding:3px 9px;border-radius:5px;font-size:11px;font-weight:600;color:var(--sub);width:auto}
.seg button.on{background:var(--bg);color:var(--ink);box-shadow:var(--sh)}

/* ---------- MAIN ---------- */
.main{display:flex;flex-direction:column;overflow:hidden;min-width:0}
.topbar{height:54px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;padding:0 18px;
  background:var(--bg);flex:0 0 54px}
.icobtn{border:1px solid var(--line);background:var(--bg);border-radius:8px;width:30px;height:30px;display:inline-flex;
  align-items:center;justify-content:center;color:var(--sub);flex:0 0 30px}
.icobtn:hover{background:var(--soft);color:var(--ink)}
.icobtn svg{width:16px;height:16px;stroke:currentColor;stroke-width:2;fill:none}
.icobtn:disabled{opacity:.35;cursor:default}
.tsearch{flex:1;max-width:420px;position:relative}
.tsearch input{width:100%;border:1px solid var(--line);border-radius:8px;padding:7px 10px 7px 30px;font-size:12px;
  outline:none;background:var(--soft)}
.tsearch input::placeholder{font-style:italic;color:var(--sub);opacity:.65}
.tsearch input:focus{border-color:var(--accent);background:var(--bg)}
.tsearch svg{position:absolute;left:9px;top:8px;width:14px;height:14px;stroke:var(--sub);fill:none;stroke-width:2}
.top-actions{margin-left:auto;display:flex;align-items:center;gap:10px;position:relative}
.user{display:flex;align-items:center;gap:9px;padding-left:11px;border-left:1px solid var(--line);cursor:pointer;
  border-radius:8px;padding-right:6px;padding-top:3px;padding-bottom:3px}
.user:hover{background:var(--soft)}
.avatar{width:30px;height:30px;border-radius:50%;background:linear-gradient(135deg,#2f6bed,#7a4fd1);color:#fff;
  display:grid;place-items:center;font-weight:700;font-size:12px;overflow:hidden;flex:0 0 30px}
.avatar img{width:100%;height:100%;object-fit:cover}
.user .un{font-size:12.5px;font-weight:600;line-height:1.15}
.user .ur{font-size:10.5px;color:var(--sub)}
/* the gutter is reserved whether or not a page scrolls, so switching to a tall
   tab (the board) no longer shifts every margin by the scrollbar's width */
.content{flex:1;overflow-y:auto;scrollbar-gutter:stable;padding:22px 26px 70px;background:var(--bg)}
.content::-webkit-scrollbar{width:10px}
.content::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}

/* generic dropdown menu */
.menu{position:absolute;top:44px;right:0;background:var(--panel);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shl);padding:6px;z-index:60;display:none;min-width:190px}
.menu.on{display:block}
.menu .mh{font-size:9.5px;text-transform:uppercase;letter-spacing:.7px;color:var(--sub);font-weight:700;padding:6px 9px 3px}
.menu button{display:flex;align-items:center;gap:9px;width:100%;border:0;background:transparent;padding:8px 10px;
  border-radius:7px;font-size:12.5px;text-align:left}
.menu button:hover{background:var(--soft)}
.menu hr{border:0;border-top:1px solid var(--line2);margin:5px 2px}

/* ---------- notification bell (V4 NOTIF V1) ----------
   The badge is a red circle, bigger than the old dot; past one notification it
   carries the number, and once the oldest unopened one has waited ten minutes it
   breathes — a slow siren, not a flash. */
.notif-dot{position:absolute;top:-4px;right:-4px;min-width:13px;height:13px;border-radius:999px;background:var(--dang);
  border:2px solid var(--bg);box-sizing:border-box;display:block}
.notif-dot.num{min-width:19px;height:19px;padding:0 4px;color:#fff;font-size:10.5px;font-weight:800;
  line-height:15px;text-align:center;letter-spacing:-.2px}
@keyframes notifPulse{
  0%{transform:scale(1);box-shadow:0 0 0 0 rgba(220,38,38,.55)}
  50%{transform:scale(1.18);box-shadow:0 0 0 6px rgba(220,38,38,0)}
  100%{transform:scale(1);box-shadow:0 0 0 0 rgba(220,38,38,0)}}
.notif-dot.pulse{animation:notifPulse 1.7s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){.notif-dot.pulse{animation:none;box-shadow:0 0 0 3px rgba(220,38,38,.35)}}
.notifwrap{position:relative}
/* the three segments */
.ntabs{display:flex;gap:4px;padding:2px 4px 6px;border-bottom:1px solid var(--line2);margin-bottom:5px}
/* each segment has a colour of its own: Assign orange, Event blue, Activity
   green — on the label itself, not only on the line under it */
.ntabs .ntab{flex:1;display:flex;align-items:center;justify-content:center;gap:5px;padding:6px 4px;border:0;
  background:transparent;border-radius:7px;font-size:11.5px;font-weight:600;color:var(--nsc,var(--sub));
  opacity:.72;cursor:pointer}
.ntabs .ntab:hover{background:var(--nsb,var(--soft));opacity:1}
/* no underline: the colour and the tint say which tab is open on their own */
.ntabs .ntab.on{background:var(--nsb,var(--soft));color:var(--nsc,var(--ink));opacity:1;font-weight:700}
.ntabs .ns-assign{--nsc:#d97706;--nsb:#fdf1e0}
.ntabs .ns-event{--nsc:#2f6bed;--nsb:#eaf0fe}
.ntabs .ns-activity{--nsc:#16a34a;--nsb:#e7f6ec}
[data-theme="dark"] .ntabs .ns-assign{--nsc:#e2a33f;--nsb:#2a2113}
[data-theme="dark"] .ntabs .ns-event{--nsc:#5b8cff;--nsb:#182642}
[data-theme="dark"] .ntabs .ns-activity{--nsc:#3fbf6f;--nsb:#12261a}
.nbadge{background:var(--dang);color:#fff;border-radius:999px;font-size:10px;font-weight:800;line-height:1}
.nbadge.sm{min-width:9px;height:9px;display:inline-block}
.nbadge.sm:not(:empty){min-width:15px;height:15px;line-height:15px;padding:0 4px;text-align:center}
.notiflist{max-height:340px;overflow-y:auto}
.notifitem{display:flex;gap:9px;align-items:flex-start;padding:9px 10px;border-radius:8px;cursor:pointer}
.notifitem:hover{background:var(--soft)}
.notifitem.unread{background:var(--accent-soft)}
/* not addressed to this reader: listed, never shouted */
.notifitem.flat{opacity:.72}
.notifitem.flat:hover{opacity:1}
.notifitem>div:first-child{flex:1;min-width:0}
.notifitem .nt{font-size:12px;line-height:1.4}
.nk{font-weight:700}
.nk-mention{color:var(--accent)}
.nk-assign{color:var(--dang)}
.nk-request{color:var(--ok)}
.nk-due{color:var(--warn)}
/* one quiet timestamp in every segment */
.notifitem .nw{display:inline-block;font-size:10.5px;color:var(--sub);margin-top:3px}
.notifitem .ndot{flex:0 0 7px;width:7px;height:7px;border-radius:50%;background:var(--dang);margin-top:5px}

/* the chip that replaced the create button: the clock, or who is online */
.topclock{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--sub);white-space:nowrap;
  padding:5px 10px;border:1px solid var(--line);border-radius:8px;background:var(--bg);cursor:pointer;
  font-variant-numeric:tabular-nums;min-height:30px;box-sizing:border-box}
.topclock:hover{border-color:var(--accent)}
.topclock b{color:var(--ink);font-weight:700;letter-spacing:.2px}
.topclock i{color:var(--line);font-style:normal}
.topclock.people{padding:3px 8px}
.tcstack{display:flex;align-items:center}
.tcav{width:22px;height:22px;border-radius:50%;background:linear-gradient(135deg,#2f6bed,#7a4fd1);color:#fff;
  display:grid;place-items:center;font-size:8.5px;font-weight:700;overflow:hidden;flex:0 0 22px;
  border:2px solid var(--bg);margin-left:-7px;box-sizing:border-box}
.tcav:first-child{margin-left:0}
.tcav img{width:100%;height:100%;object-fit:cover}
.tcav.me{background:linear-gradient(135deg,#16a34a,#0d9488)}
.tcav.more{background:var(--soft);color:var(--sub);font-size:9px}
/* narrow: the date goes, the time and the faces stay */
@media(max-width:1062px){.topclock .tcdate,.topclock i{display:none}}
@media(max-width:810px){.topclock{display:none}}

/* the workspace's own "show notifications" ask, centred */
/* the direction marks the spot: horizontally centred, just under the sticky top
   — where the browser puts its own prompt, only in the middle of the page */
.nask{position:fixed;inset:0;z-index:400;background:rgba(15,18,24,.42);display:grid;
  justify-items:center;align-items:start;padding:66px 20px 20px}
.nask-card{width:min(420px,calc(92 * var(--vw)));background:var(--panel);border:1px solid var(--line);border-radius:14px;
  box-shadow:var(--shl);padding:18px 18px 14px;animation:naskIn .16s ease-out}
@keyframes naskIn{from{opacity:0;transform:translateY(6px) scale(.985)}to{opacity:1;transform:none}}
.nask-h{display:flex;gap:12px;align-items:center}
.nask-logo{width:40px;height:40px;border-radius:10px;overflow:hidden;flex:0 0 40px;border:1px solid var(--line);background:#fff}
.nask-logo img{width:100%;height:100%;object-fit:contain}
.nask-t b{display:block;font-size:14px;letter-spacing:-.2px}
.nask-t span{font-size:11.5px;color:var(--sub)}
.nask p{margin:12px 0 14px;font-size:12.5px;line-height:1.65;color:var(--sub)}
.nask-f{display:flex;justify-content:flex-end;gap:8px}

/* ---------- PAGE HEAD ---------- */
.ph{margin-bottom:16px;display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap}
.ph h1{font-size:21px;letter-spacing:-.4px;margin:0;cursor:help}
.ph .ph-right{margin-left:auto;display:flex;align-items:center;gap:8px}
/* tabs on the left, filter controls trailing on the right */
.tabsrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px}
.tabsrow .tabs{margin:0}
.tabsrow #fText{min-width:190px}
.tabsrow #fStatus{min-width:120px}
.tabsrow .addwrap{position:relative;margin-left:auto}
/* the second writer sits right beside the first, not pushed to its own edge */
.tabsrow .addwrap.addwrap2{margin-left:0}
#pDocMenu{right:0;top:40px;min-width:170px}
/* multi-select filter dropdown beside the status select */
.fwrap{position:relative;display:inline-flex}
.fbtn{cursor:pointer;font-weight:600;color:var(--sub);white-space:nowrap}
.fbtn:hover{color:var(--ink)}
.fbtn.on{color:var(--ink);border-color:var(--ink)}
#fMenu{top:34px;left:0;min-width:190px;z-index:95;padding:6px}
.fopt{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:7px;font-size:12.5px;cursor:pointer}
.fopt:hover{background:var(--soft)}
.fopt input{width:14px;height:14px;accent-color:var(--accent)}
.fclear{width:100%;border:0;background:transparent;text-align:left;padding:7px 9px;border-radius:7px;
  font-size:12px;color:var(--sub);border-top:1px solid var(--line2);margin-top:4px;cursor:pointer}
.fclear:hover{background:var(--soft);color:var(--ink)}
.tabs{display:flex;gap:4px;margin:0 0 14px;background:var(--bg);border:1px solid var(--line);
  padding:3px;border-radius:9px;width:max-content;max-width:100%;overflow-x:auto}
.tabs button{border:0;background:transparent;padding:6px 13px;border-radius:7px;font-size:12px;font-weight:600;color:var(--sub);white-space:nowrap}
.tabs button:hover{color:var(--ink)}
.tabs button.on{background:var(--soft);color:var(--ink)}

/* ---------- BUTTONS / INPUTS ---------- */
.btn{border:1px solid var(--line);background:var(--bg);border-radius:8px;padding:7px 12px;font-size:12.5px;
  font-weight:600;display:inline-flex;align-items:center;gap:6px}
.btn:hover{background:var(--soft)}
.btn.primary{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.btn.primary:hover{opacity:.9}
.btn.sm{padding:5px 9px;font-size:11.5px}
.btn.ghost{border-color:transparent;background:transparent;color:var(--sub)}
.btn.ghost:hover{background:var(--soft);color:var(--ink)}
.btn.danger{color:var(--dang);border-color:var(--line)}
.mini-input{border:1px solid var(--line);border-radius:8px;padding:6px 9px;font-size:12px;outline:none;background:var(--bg)}
.mini-input:focus{border-color:var(--accent)}
.field{margin-bottom:12px}
.field label{display:block;font-size:10.5px;font-weight:700;color:var(--sub);text-transform:uppercase;
  letter-spacing:.4px;margin-bottom:4px}
.field input,.field select,.field textarea{width:100%;border:1px solid var(--line);border-radius:8px;padding:8px 10px;
  font-size:12.5px;outline:none;background:var(--bg)}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--accent)}
.field textarea{resize:vertical;min-height:60px}
/* DS-Config figures are typed, not spun — the grouped fields are text inputs and
   carry no arrows, so the two that stayed numeric must not carry them either */
.cfgnum{-moz-appearance:textfield;appearance:textfield}
.cfgnum::-webkit-outer-spin-button,.cfgnum::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* ---------- CARDS / TILES ---------- */
.tiles{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:18px}
.tiles.t3{grid-template-columns:repeat(3,1fr)}
.tiles.t5{grid-template-columns:repeat(5,1fr)}
.tile{border:1px solid var(--line);border-radius:var(--radius);padding:15px 16px;background:var(--panel);box-shadow:var(--sh)}
/* the caption stays on one line for the same reason as .td below — a wrapped
   label pushes its own value down and breaks the row of numbers */
.tile .tl{font-size:10.5px;color:var(--sub);font-weight:600;text-transform:uppercase;letter-spacing:.4px;
  display:flex;align-items:center;gap:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tile .tv{font-size:24px;font-weight:800;letter-spacing:-.6px;margin-top:6px}
/* the caption stays on one line — a wrap would make one tile taller than the
   rest, which is what the board tab exposed */
.tile .td{font-size:11px;margin-top:5px;color:var(--sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* a tile that also acts as a filter */
.tileclick{cursor:pointer;border-radius:var(--radius)}
.tileclick .tile{height:100%;transition:border-color .15s}
.tileclick:hover .tile{border-color:var(--sub)}
.tileclick.on .tile{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.tile .up{color:var(--ok);font-weight:700}
.tile .down{color:var(--dang);font-weight:700}
.bar{height:7px;border-radius:6px;background:var(--soft);overflow:hidden;margin-top:9px}
.bar>i{display:block;height:100%;background:var(--accent);border-radius:6px;transition:width .3s}
.bar.ok>i{background:var(--ok)}
.bar.warn>i{background:var(--warn)}
/* summary bars read their band at a glance: red → orange → blue → green */
.bar.t-lo>i{background:var(--dang)}
.bar.t-mid>i{background:var(--warn)}
.bar.t-hi>i{background:var(--accent)}
.bar.t-top>i{background:var(--ok)}
/* the task peek keeps a neutral bar — status colour lives in the status pill */
.bar.plain>i{background:var(--sub);opacity:.55}

.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.card{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);box-shadow:var(--sh);
  overflow:hidden;margin-bottom:16px}
.card>.ch{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid var(--line2);flex-wrap:wrap}
.card>.ch h3{margin:0;font-size:13.5px;font-weight:700}
.card>.ch .sub{font-size:11px;color:var(--sub)}
.card>.cb{padding:14px 16px}
.card>.cb.flush{padding:0}
.card.click{cursor:pointer}
.card.click:hover{border-color:var(--accent)}

/* ---------- TABLE ---------- */
table{width:100%;border-collapse:collapse;font-size:12px}
thead th{text-align:left;font-size:9.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--sub);font-weight:700;
  padding:9px 14px;border-bottom:1px solid var(--line2);background:var(--soft);position:sticky;top:0;z-index:1}
tbody td{padding:10px 14px;border-bottom:1px solid var(--line2);vertical-align:middle}
tbody tr:hover{background:var(--soft);cursor:pointer}
tbody tr:last-child td{border-bottom:0}
.n{text-align:right;white-space:nowrap}

/* ---------- PILLS / TAGS ---------- */
.pill{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:2px 9px;border-radius:20px;white-space:nowrap}
.dot{width:6px;height:6px;border-radius:50%}
.st-Done{background:var(--okb);color:var(--ok)}.st-Done .dot{background:var(--ok)}
.st-InProgress{background:var(--accent-soft);color:var(--accent)}.st-InProgress .dot{background:var(--accent)}
.st-Review{background:var(--warnb);color:var(--warn)}.st-Review .dot{background:var(--warn)}
.st-Blocked,.st-Hold{background:var(--dangb);color:var(--dang)}.st-Blocked .dot,.st-Hold .dot{background:var(--dang)}
.st-ToDo{background:var(--slateb);color:var(--slate)}.st-ToDo .dot{background:var(--slate)}
.st-Backlog{background:var(--soft);color:var(--sub)}.st-Backlog .dot{background:var(--sub)}
/* a project runs its own ladder — Planning and On Going are project-only states */
.st-Planning{background:var(--slateb);color:var(--slate)}.st-Planning .dot{background:var(--slate)}
.st-OnGoing{background:var(--accent-soft);color:var(--accent)}.st-OnGoing .dot{background:var(--accent)}
.pr{font-size:11px;font-weight:700}
.pr-Urgent{color:var(--dang)}.pr-High{color:var(--warn)}.pr-Medium{color:var(--accent)}.pr-Low{color:var(--slate)}
.tag{display:inline-block;font-size:10.5px;background:var(--soft);border:1px solid var(--line2);color:var(--sub);
  border-radius:6px;padding:1px 7px;margin:1px 2px 1px 0;white-space:nowrap}
.mini-av{width:22px;height:22px;border-radius:50%;background:var(--slateb);color:var(--slate);display:inline-grid;
  place-items:center;font-size:9.5px;font-weight:700;overflow:hidden}
.mini-av img{width:100%;height:100%;object-fit:cover}
/* the avatars carry initials, not faces — overlapping them cut the second letter
   off every chip, so they sit side by side with a ring to read as one group */
.avstack{display:inline-flex;align-items:center;gap:3px}
.avstack .mini-av{border:2px solid var(--bg);box-shadow:0 0 0 .5px var(--line)}
.avstack .mini-av:hover{z-index:2}
.progress-cell{display:flex;align-items:center;gap:8px;min-width:110px}
.progress-cell .bar{flex:1;margin:0}
.kv{display:grid;grid-template-columns:150px 1fr;gap:6px 10px;font-size:12px}
.kv .k{color:var(--sub);font-weight:600}
.linkrow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px;border-bottom:1px solid var(--line2)}
.linkrow:last-child{border-bottom:0}
.linkrow a{color:var(--accent);font-weight:600;text-decoration:none;font-size:12px}
.empty{padding:30px;text-align:center;color:var(--sub);font-size:12px}
.hint{font-size:11.5px;color:var(--sub);background:var(--soft);border:1px solid var(--line2);border-radius:8px;
  padding:9px 11px;margin-bottom:14px}
.rowbtn{display:flex;gap:8px;align-items:center;margin:0 0 12px;flex-wrap:wrap}
.chips{display:flex;gap:6px;flex-wrap:wrap}
.chip{font-size:11px;border:1px solid var(--line);border-radius:20px;padding:3px 10px;color:var(--sub);
  background:var(--bg);cursor:pointer}
.chip.on{background:var(--ink);color:var(--bg);border-color:var(--ink)}

/* ---------- FUNNEL / CHART ---------- */
.fnl{display:flex;align-items:center;gap:10px;margin-bottom:9px}
.fnl .fl{width:170px;font-size:11.5px;font-weight:600}
.fnl .fv{width:120px;text-align:right;font-size:11.5px;color:var(--sub)}
/* each i is the full-height track, b is the fill — the track has to stretch or
   the percentage height on b resolves against 0 and nothing draws */
.spark{display:flex;align-items:stretch;gap:3px;height:70px}
.spark i{flex:1;background:var(--accent-soft);border-radius:3px 3px 0 0;position:relative}
.spark i b{position:absolute;left:0;right:0;bottom:0;background:var(--accent);border-radius:3px 3px 0 0;display:block}
.donut{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.donut svg{flex:0 0 128px}
.donut .lg{font-size:11.5px}
.donut .lg div{display:flex;align-items:center;gap:7px;margin-bottom:6px}
.donut .lg i{width:9px;height:9px;border-radius:3px;display:inline-block}
.venn{position:relative}
.venn circle{opacity:.42}
.legend{display:flex;gap:14px;flex-wrap:wrap;font-size:11.5px;color:var(--sub);margin-top:8px}
.legend span{display:inline-flex;align-items:center;gap:6px}
.legend i{width:9px;height:9px;border-radius:3px}

/* ============================================================
   EVENT OVERVIEW (Calendar)
   The page fills the window: toolbar on top, calendar and the overview
   column below it, each scrolling inside its own box so the page itself
   never grows past one screen.
   ============================================================ */
.content.calpg{display:flex;flex-direction:column;overflow:hidden;padding-bottom:22px}
.content.calpg>.ph{flex:0 0 auto}
.calpage{flex:1;min-height:0;display:grid;grid-template-columns:1fr 316px;gap:16px}
.calmain{min-width:0;min-height:0;overflow:auto;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--panel);box-shadow:var(--sh);padding:10px}
.calside{min-height:0;overflow-y:auto;overflow-x:hidden;padding-right:2px}
.calmain::-webkit-scrollbar,.calside::-webkit-scrollbar{width:9px;height:9px}
.calmain::-webkit-scrollbar-thumb,.calside::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.calside .csec{margin-bottom:12px}
.calside .csec>.cb{padding:10px 12px}

/* ---- toolbar: one row, view tabs + search + Filter + Add Cal pushed right ---- */
.caltoolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 12px;flex:0 0 auto;--calwhen:168px}
.caltoolbar .calnav{display:inline-flex;gap:4px}
/* The period slot is a fixed width, sized to the longest thing that can sit in
   it — the two range date boxes. "July 2026" and "20 Jul – 26 Jul 2026" then
   occupy the same space, so the view tabs and everything right of them hold
   their position when the view changes. */
.caltoolbar .calwhen{flex:0 0 var(--calwhen);min-width:0;display:flex;align-items:center}
.caltoolbar .calperiod{font-size:14px;letter-spacing:-.2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* the right-hand controls travel together: when the row is too narrow they wrap
   as one block and stay right-aligned instead of dropping Add Cal to the left */
/* flex-basis 0 keeps the group on the first row whatever the language makes the
   labels — the search box inside it absorbs the difference */
.caltoolbar .calbarR{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;
  justify-content:flex-end;margin-left:auto;flex:1 1 0;min-width:0}
.caltoolbar .calviews{margin:0;flex:0 0 auto}
.caltoolbar .calbarR>.fwrap{flex:0 0 auto}
.caltoolbar .calbarR>.btn{flex:0 0 auto;white-space:nowrap}
/* the search box is the only elastic part — it gives up width before the row breaks */
.caltoolbar .calq{flex:1 1 200px;min-width:120px}
/* the range pair lives under the mini calendar, where there is room for the two
   date boxes at their natural width — squeezing them makes Chrome drop the
   picker icon and clip the year, and in the toolbar they moved everything else */
.calside .calrange{display:flex;align-items:center;justify-content:center;gap:6px;
  margin-top:9px;padding-top:9px;border-top:1px solid var(--line2);flex-wrap:wrap}
.calside .calrange .mini-input{flex:0 0 auto;padding:4px 6px;font-size:11.5px}
.calside .calrange i{color:var(--sub);font-style:normal}
.caltoolbar .fopt.allcal{font-weight:700}
.cdot{width:9px;height:9px;border-radius:3px;display:inline-block;flex:0 0 9px}

/* ---- category colours: one source for chips, dots and legend ---- */
.k-internal{--cc:var(--accent)} .k-meeting{--cc:var(--warn)} .k-project{--cc:var(--violet)}
.k-event{--cc:var(--ok)} .k-activity{--cc:var(--gold)} .k-marking{--cc:var(--slate)}
.k-promo{--cc:var(--teal)}
/* BOARD OFFICE V1 — the Office agenda, in the one colour nothing else uses */
.k-office{--cc:var(--dang)}
.m-holiday{--cc:var(--dang)} .m-birthday{--cc:var(--warn)} .m-city{--cc:var(--teal)}
.m-intl{--cc:var(--violet)} .m-national{--cc:var(--slate)} .m-local{--cc:var(--slate)} .m-due{--cc:var(--violet)}
.cdot{background:var(--cc,var(--sub))}

/* ---- event chip ---- */
.cev{display:flex;align-items:center;gap:4px;font-size:10.5px;line-height:1.5;border-radius:5px;padding:1px 6px;
  background:var(--cc,var(--ink));color:#fff;overflow:hidden;white-space:nowrap;cursor:pointer;
  max-width:100%;border:1px solid transparent;position:relative}
/* the day-span grip is absolute, so it adds nothing to the chip's size. Only
   the surfaces laid out one column per day switch it on. */
.cev-egrip{display:none;position:absolute;top:0;right:0;bottom:0;width:7px;cursor:ew-resize;z-index:2}
.calm .cev-egrip,.ct-bar .cev-egrip{display:block}
.cev-egrip::after{content:'';position:absolute;top:50%;right:1.5px;width:2px;height:9px;border-radius:2px;
  transform:translateY(-50%);background:currentColor;opacity:0;transition:opacity .12s}
.cev:hover .cev-egrip::after{opacity:.55}
.cev.resizing{filter:brightness(1.12)}
/* the days the drag would cover light up instead of the chip changing size */
.daybg.spanning,.ct-ad.spanning{background:color-mix(in srgb,var(--accent) 11%,transparent);
  outline:1px dashed var(--accent);outline-offset:-2px;border-radius:8px}
.cev .cn{overflow:hidden;text-overflow:ellipsis;font-weight:600}
.cev .ct{font-weight:700;opacity:.85;font-style:normal;flex:0 0 auto}
.cev .cs{font-style:normal;margin-left:auto;flex:0 0 auto}
.cev:hover{filter:brightness(1.08)}
.cev.active{outline:2px solid var(--ink);outline-offset:1px}
.cev.drag{opacity:.35}
.cev.draggable{cursor:grab}
.cev.drag-ghost{position:fixed;z-index:220;pointer-events:none;box-shadow:var(--shl);padding:3px 9px;font-size:11px}
/* markings read as a quiet layer, not as work */
.cev.ro{background:transparent;color:var(--cc,var(--sub));border-color:var(--cc,var(--line));
  background:color-mix(in srgb,var(--cc) 12%,transparent)}
.cev.m-holiday{font-weight:700}

/* ---- month grid ---- */
.calm{display:flex;flex-direction:column;height:100%;min-height:560px;gap:4px}
.calm-dow{display:grid;grid-template-columns:repeat(7,1fr);gap:5px;flex:0 0 auto}
.calm-dow span{font-size:9.5px;text-transform:uppercase;color:var(--sub);font-weight:700;text-align:center;padding-bottom:2px}
.wk{position:relative;flex:1 1 0;min-height:98px}
.wkbg{position:absolute;inset:0;display:grid;grid-template-columns:repeat(7,1fr);gap:5px}
.daybg{border:1px solid var(--line2);border-radius:8px;background:var(--bg);cursor:pointer}
.daybg:hover{background:var(--soft)}
.daybg.inweek{background:var(--soft)}
.daybg.today{border-color:var(--accent);background:var(--accent-soft)}
/* the foreground is only a layout layer — clicks fall through to the day */
.wkfg{position:relative;display:grid;grid-template-columns:repeat(7,1fr);gap:2px 5px;height:100%;
  padding:4px 0 4px;pointer-events:none;overflow:hidden}
.wkfg .cev,.wkfg .cmore{pointer-events:auto}
/* the all-day bars have to step aside mid-drag as well, or a drop on the strip
   hits the bar sitting over the day cell and finds no day to land on */
.calmain.dragging .wkfg,.calmain.dragging .cev,.calmain.dragging .tev,
.calmain.dragging .ct-bar{pointer-events:none}
.daybg.drop,.ct-slot.drop,.ct-ad.drop{outline:2px dashed var(--accent);outline-offset:-2px;border-radius:8px}
/* the day number sits top-left in every cell, filled or empty, so its position
   never shifts between a busy day and a blank one */
.dnum{display:flex;align-items:flex-start;justify-content:flex-start;font-size:10.5px;color:var(--sub);font-weight:700;padding:1px 0 0 6px}
.dnum.out{opacity:.38}
.dnum.today b{background:var(--accent);color:#fff;border-radius:20px;padding:1px 7px}
.dnum.hol b{color:var(--dang)}
.spanslot{display:flex;align-items:center;padding:0 4px;min-width:0}
.spanslot .cev{width:100%}
.dlist{display:flex;flex-direction:column;gap:2px;padding:0 4px;min-width:0;overflow:hidden}
.cmore{border:0;background:transparent;color:var(--sub);font-size:10px;font-weight:700;text-align:left;
  padding:1px 4px;border-radius:5px}
.cmore:hover{background:var(--soft);color:var(--ink)}

/* ---- week / day time grid ---- */
.calt{display:flex;flex-direction:column;height:100%;min-height:560px;--cols:7}
.ct-head,.ct-allday{display:grid;grid-template-columns:56px repeat(var(--cols),minmax(0,1fr));flex:0 0 auto}
.ct-head{border-bottom:1px solid var(--line2);padding-bottom:6px}
.ct-tz{font-size:9px;color:var(--sub);font-weight:700;text-transform:uppercase;display:flex;align-items:flex-end;
  justify-content:center;padding-bottom:3px}
.ct-dh{text-align:center;cursor:pointer;border-radius:8px;padding:2px 0}
.ct-dh:hover{background:var(--soft)}
.ct-dh .w{display:block;font-size:9.5px;text-transform:uppercase;color:var(--sub);font-weight:700}
.ct-dh b{font-size:19px;font-weight:600;letter-spacing:-.5px}
.ct-dh.today b{background:var(--accent);color:#fff;border-radius:50%;display:inline-block;width:30px;height:30px;line-height:30px}
.ct-allday{border-bottom:1px solid var(--line2);min-height:28px;padding:3px 0;row-gap:2px}
/* the day cells are the backdrop and the drop target; the bars sit on top of
   them and span whatever columns their event covers */
.ct-ad{grid-row:1/-1;display:flex;align-items:flex-end;justify-content:flex-end;padding:0 3px;
  border-left:1px solid var(--line2);cursor:pointer;min-width:0}
.ct-tz{grid-row:1/-1}
.ct-bar{padding:0 3px;min-width:0;display:flex;align-items:center;position:relative;z-index:1}
.ct-bar>.cev{width:100%;margin:0}
.ct-ad .cmore{font-size:9.5px;padding:0 4px;border:0;background:transparent;color:var(--sub);cursor:pointer;z-index:2}
.ct-ad .cmore:hover{color:var(--ink)}
/* the body always reserves its scrollbar and the head + all-day rows carry a
   matching gutter, so their column lines fall exactly on the body's columns */
.ct-head,.ct-allday{padding-right:9px}
.ct-body{flex:1;min-height:0;overflow-y:scroll;display:grid;grid-template-columns:56px repeat(var(--cols),minmax(0,1fr));
  align-items:start;position:relative}
.ct-body::-webkit-scrollbar{width:9px}
.ct-body::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.ct-hours .ct-h{height:52px;position:relative}
.ct-hours .ct-h span{position:absolute;top:-7px;right:8px;font-size:9.5px;color:var(--sub);font-weight:600}
.ct-col{position:relative;border-left:1px solid var(--line2)}
.ct-slot{height:52px;border-bottom:1px solid var(--line2);cursor:pointer}
.ct-slot:hover{background:var(--soft)}
.ct-now{position:absolute;left:0;right:0;height:2px;background:var(--dang);z-index:3}
.ct-now::before{content:'';position:absolute;left:-4px;top:-3px;width:8px;height:8px;border-radius:50%;background:var(--dang)}
.tev{position:absolute;z-index:2;display:block;padding:3px 6px;border-radius:6px;overflow:hidden;
  background:var(--cc,var(--accent));color:#fff;font-size:10.5px;line-height:1.35;cursor:pointer}
.tev b{display:block;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tev i{font-style:normal;opacity:.9;font-size:9.5px}
.tev.ro{background:color-mix(in srgb,var(--cc) 16%,transparent);color:var(--cc);border:1px solid var(--cc)}
.tev.resizing{opacity:.92;box-shadow:var(--sh)}
/* bottom grip drags to lengthen or shorten the block */
.tev-grip{position:absolute;left:0;right:8px;bottom:0;height:8px;cursor:ns-resize;z-index:3}
/* the right edge stretches the event across days; the bottom edge stays on hours */
.tev-egrip{position:absolute;top:0;bottom:0;right:0;width:8px;cursor:ew-resize;z-index:3}
.tev-egrip::after{content:'';position:absolute;top:50%;right:2px;width:3px;height:18px;border-radius:3px;
  transform:translateY(-50%);background:currentColor;opacity:0;transition:opacity .12s}
.tev:hover .tev-egrip::after{opacity:.5}
.tev-grip::after{content:'';position:absolute;left:50%;bottom:2px;width:20px;height:3px;border-radius:3px;
  transform:translateX(-50%);background:currentColor;opacity:0}
.tev:hover .tev-grip::after{opacity:.5}

/* ---- year ---- */
.caly{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.cym-h{font-size:12.5px;font-weight:700;margin-bottom:6px;cursor:pointer;border-radius:6px;padding:2px 4px}
.cym-h:hover{background:var(--soft)}
.cym-g{display:grid;grid-template-columns:repeat(7,1fr);gap:1px}
.cym-g .wd{font-size:9px;color:var(--sub);font-weight:700;text-align:center;padding-bottom:2px}
.yd,.md{border:0;background:transparent;font-size:10.5px;color:var(--ink);border-radius:50%;
  aspect-ratio:1;display:grid;place-items:center;padding:0}
.yd:hover,.md:hover{background:var(--soft)}
.yd.out,.md.out{color:var(--sub);opacity:.4}
.yd.has{font-weight:800;color:var(--accent)}
.yd.today,.md.today{background:var(--accent);color:#fff;font-weight:800}

/* ---- range agenda ---- */
.calr{display:flex;flex-direction:column}
.cr-day{display:grid;grid-template-columns:74px 1fr;gap:12px;padding:10px 4px;border-bottom:1px solid var(--line2)}
.cr-day.today .cr-d b{color:var(--accent)}
.cr-d{text-align:right;cursor:pointer;border-radius:8px;padding:2px 6px}
.cr-d:hover{background:var(--soft)}
.cr-d b{font-size:19px;font-weight:700;letter-spacing:-.5px;display:block}
.cr-d span{font-size:9.5px;text-transform:uppercase;color:var(--sub);font-weight:700}
.cr-d i{display:block;font-style:normal;font-size:10px;color:var(--sub)}
.cr-l{display:flex;flex-direction:column;gap:5px;min-width:0}
.cr-row{display:flex;align-items:center;gap:9px;min-width:0}
.cr-t{font-size:11px;color:var(--sub);font-weight:600;flex:0 0 96px}
.cr-row .cev{flex:0 1 auto}
.cr-w{margin-left:auto}

/* ---- side overview ---- */
/* the mini calendar is compact and always six rows tall, so the box keeps one
   size in every month */
.mini-h,.dph{display:flex;align-items:center;gap:4px}
.mini-h b{flex:1;font-size:12px}
.mini-h button{border:0;background:transparent;color:var(--sub);width:20px;height:20px;border-radius:6px}
.mini-h button:hover{background:var(--soft);color:var(--ink)}
.mini-g{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;margin-top:5px}
.mini-g .wd{font-size:8.5px;color:var(--sub);font-weight:700;text-align:center;padding-bottom:2px}
.mini .md{font-size:10px}
.mini-hint{font-size:10px;color:var(--sub);margin-top:6px;text-align:center}
.md.insel{background:var(--accent-soft);border-radius:0}
.md.insel.redge{background:var(--accent);color:#fff;border-radius:50%}
.md.rpick{outline:2px solid var(--accent);outline-offset:-2px}
.md.today{background:var(--accent);color:#fff;border-radius:50%}
.agn{display:flex;align-items:center;gap:8px;padding:5px 4px;border-radius:7px;font-size:12px;cursor:pointer}
.agn:hover{background:var(--soft)}
.agn input{width:14px;height:14px;accent-color:var(--cc,var(--accent))}
.agn span{flex:1}
.agn b{font-size:11px;color:var(--sub)}
.agn:not(.on) span{color:var(--sub)}
/* Agenda card header controls: All Cal / Clear / minimise */
.agnbtns{margin-left:auto;display:inline-flex;align-items:center;gap:2px}
.agnbtns .btn.sm{padding:3px 7px;font-size:11px}
.icobtn.sm{width:24px;height:24px;font-size:14px;flex:0 0 24px}
.agn-toggle{font-weight:700;line-height:1}
.cb.hide{display:none}
.srow2{display:flex;align-items:center;gap:9px;width:100%;border:0;background:transparent;text-align:left;
  padding:9px 12px;border-bottom:1px solid var(--line2)}
.srow2:last-child{border-bottom:0}
.srow2:hover{background:var(--soft)}
.srow2 .sx{min-width:0;flex:1}
.srow2 .sx b{display:block;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srow2 .sl{display:block;font-size:10.5px;color:var(--sub);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srow2 .cs{font-style:normal;color:var(--warn)}

/* ---- quick add card (Tampilan 1) ---- */
.calpop{position:fixed;z-index:140;width:376px;max-width:calc(94 * var(--vw));background:var(--panel);border:1px solid var(--line);
  border-radius:14px;box-shadow:var(--shl);display:flex;flex-direction:column;max-height:calc(88 * var(--vh))}
.calpop.moving{user-select:none}
.cq-h{display:flex;align-items:center;padding:8px 10px 0}
.cq-grip{color:var(--sub);cursor:grab;font-size:13px;padding:2px 4px;border-radius:6px}
.cq-grip:hover{background:var(--soft)}
.cq-x{margin-left:auto;width:26px;height:26px;font-size:12px}
.cq-b{padding:4px 16px 12px;overflow-y:auto}
.cq-title{width:100%;border:0;border-bottom:1px solid var(--line);background:transparent;font-size:19px;
  font-weight:700;letter-spacing:-.3px;padding:6px 2px 8px;outline:none}
.cq-title:focus{border-bottom-color:var(--accent)}
.cq-title::placeholder{color:var(--sub);opacity:.55;font-weight:600}
/* six categories read as an even 3 × 2 block instead of a ragged 4 + 2 wrap */
.cq-cats{display:grid;grid-template-columns:repeat(3,1fr);gap:5px;margin:12px 0 6px}
.cq-cat{border:1px solid var(--line);background:var(--bg);border-radius:20px;padding:3px 6px;font-size:11.5px;
  font-weight:600;color:var(--sub);text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cq-cat:hover{border-color:var(--cc,var(--sub));color:var(--ink)}
.cq-cat.on{background:var(--cc);border-color:var(--cc);color:#fff}
.cq-row{display:grid;grid-template-columns:24px 1fr;gap:8px;align-items:start;padding:7px 0;min-width:0}
.cq-row.sub2{padding-top:0}
.cq-row .ci{width:18px;height:18px;fill:none;stroke:var(--sub);stroke-width:1.7;stroke-linecap:round;margin-top:4px}
.cq-when{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0;position:relative}
.cq-when .wide{width:100%}
.cq-when textarea{resize:vertical;min-height:44px}
.cq-date,.cq-date2{cursor:pointer;font-weight:600}
.cq-times.hide,.cq-enddate.hide{display:none}
.cq-times i,.cq-enddate i{color:var(--sub);font-style:normal}
.cq-enddate{display:inline-flex;align-items:center;gap:5px}
/* the quick card's date popups open toward the left edge so the card, which may
   sit near the right of the window, never clips them */
.cq-pop2{top:32px;right:0;left:auto}
.cq-chk{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--sub)}
.cq-chk input{width:14px;height:14px;accent-color:var(--accent)}
.cq-tz{font-size:11px;color:var(--sub);border:1px solid var(--line2);border-radius:6px;padding:2px 7px}
.cq-link{border:0;background:transparent;color:var(--accent);font-size:11.5px;font-weight:600;padding:3px 4px;border-radius:6px}
.cq-link:hover{background:var(--soft)}
.cq-pop{top:32px;left:0}
.cq-f{display:flex;align-items:center;gap:8px;padding:10px 14px;border-top:1px solid var(--line2)}
.ntchip{display:inline-flex;align-items:center;gap:2px;border:1px solid var(--line2);border-radius:20px;
  background:var(--soft);padding:1px 3px 1px 8px;font-size:11px;margin:2px 4px 2px 0}
.ntchip button{border:0;background:transparent;font-size:11px;padding:1px 2px}
.ntchip .rm{color:var(--sub);border-radius:50%;width:16px;height:16px;line-height:1}
.ntchip .rm:hover{background:var(--dangb);color:var(--dang)}
/* the Cal Peek's time pair lines up with the rest of the meta row */
.cal-times,.cal-enddate{display:inline-flex;align-items:center;gap:5px}
.cal-times.hide,.cal-enddate.hide{display:none}
.cal-times i,.cal-enddate i{color:var(--sub);font-style:normal}
/* the meta-row date pickers open toward the panel's left so they stay inside it
   — the peek body's own scroll would otherwise clip them on the right */
.tk-meta .dpop{left:auto;right:0}

@media (max-width:1062px){
  /* on a narrow screen the group is allowed to break onto its own row again */
  .caltoolbar .calbarR{flex:0 1 auto;flex-wrap:wrap}
  .calpage{grid-template-columns:1fr}
  .content.calpg{overflow-y:auto;display:block}
  .calmain,.calside{overflow:visible;height:auto}
  .calm,.calt{min-height:520px}
  .caly{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:738px){
  .caly{grid-template-columns:repeat(2,1fr)}
  .caltoolbar .calq{margin-left:0;min-width:150px}
  .cr-day{grid-template-columns:56px 1fr}
}

/* ---------- DRAWER / PEEK ---------- */
.scrim{position:fixed;inset:0;background:rgba(16,24,40,.28);opacity:0;pointer-events:none;transition:opacity .18s;z-index:40}
.scrim.on{opacity:1;pointer-events:auto}
/* side peek: no tint and no click trap — the page underneath stays live, so
   picking another task or page jumps straight there */
.scrim.clear,[data-theme="dark"] .scrim.clear{background:transparent}
.scrim.clear{pointer-events:none}
[data-theme="dark"] .scrim{background:rgba(0,0,0,.55)}
/* `ghost` — invisible, but it still catches the click. The plain centred panel
   asks for both: no wash over the page (PIPELINE-2 §3) and clicking outside the
   box closes it, the way a dialog behaves.
   `.on` is in the selector deliberately: without it a closed scrim would keep
   `pointer-events:auto` and become the same invisible click-trap the closed
   centre panel was. */
.scrim.ghost,[data-theme="dark"] .scrim.ghost{background:transparent}
.scrim.on.ghost{pointer-events:auto}
.peek{position:fixed;background:var(--bg);z-index:50;display:flex;flex-direction:column;
  box-shadow:var(--shl);transition:transform .2s,opacity .16s}
.peek.side{top:0;right:0;height:calc(100 * var(--vh));width:var(--peekw,520px);max-width:calc(96 * var(--vw));transform:translateX(100%);border-left:1px solid var(--line)}
/* drag grip on the panel's left edge — widens the side peek up to 75% of the page */
.peek-grip{position:absolute;left:-3px;top:0;width:7px;height:100%;cursor:col-resize;z-index:2}
.peek-grip::after{content:'';position:absolute;left:2px;top:0;width:3px;height:100%;background:transparent;transition:background .15s}
.peek-grip:hover::after,.peek.sizing .peek-grip::after{background:var(--line)}
/* snapped to the default width — the grip reads a touch darker, still grey */
.peek.snapped .peek-grip::after{background:var(--sub);opacity:.45}
.peek.center .peek-grip,.peek:not(.on) .peek-grip{display:none}
.peek.sizing{transition:none;user-select:none}
.peek.center{top:50%;left:50%;width:820px;max-width:calc(94 * var(--vw));height:calc(86 * var(--vh));border-radius:14px;border:1px solid var(--line);
  transform:translate(-50%,-46%);opacity:0}
.peek.on{transform:none;opacity:1}
.peek.center.on{transform:translate(-50%,-50%)}
/* ⚠️ A CLOSED PANEL MUST NOT CATCH CLICKS.
   The side panel hides by sliding off the edge, so it was never in the way. The
   centre panel only fades — `opacity:0` and nothing else — so a closed one went
   on sitting in the middle of the page at 820px wide, invisible, swallowing
   every click that landed on it. That is the "suddenly can't click anything"
   the direction reports: it needed no particular sequence, only that the reader
   had used the centre panel once. */
.peek:not(.on){pointer-events:none}
/* PIPELINE-2 §3 — the plain centred panel: already where it belongs, no travel
   and no fade, and the page behind it keeps its own colours. It is opened and
   closed constantly while reading the board, and an animation on every open is
   what made that feel slow. */
.peek.center.plain{transition:none}
.peek.center.plain.on{transform:translate(-50%,-50%);opacity:1}
/* PIPELINE-3 — the entry panel is a property sheet, not a document: it is as
   tall as what it holds and no wider than its own two columns. At 820 × calc(86 * var(--vh)) it
   was mostly empty space to the right of every value and below the last row. */
.peek.center.plain{width:600px;height:auto;max-height:calc(86 * var(--vh))}
.peek.center.plain .peek-b{padding:16px 22px 22px}
.peek.center.plain .proprow{grid-template-columns:132px 1fr;min-height:30px}
.peek.center.plain .tk-title{font-size:20px}
.peek-h{display:flex;align-items:center;gap:8px;padding:11px 16px;border-bottom:1px solid var(--line2)}
.peek-h .ttl{font-size:11.5px;color:var(--sub);font-weight:600;flex:1}
/* collapse sits at the far left — the panel slides away in the direction it points */
.peek-h .peek-collapse{margin-right:2px;color:var(--sub)}
.peek-h .peek-collapse:hover{color:var(--ink)}
/* PRO-CAMPAIGN V1B — the way back to the panel this one was opened from. It
   sits beside Close, at the end the reader already looks to for "out of here",
   and it is drawn only when there is somewhere to go. */
.peek-h .peek-back{margin-left:-4px;color:var(--accent)}
.peek-h .peek-back:hover{background:var(--accent-soft)}
.peek.center .peek-h .peek-collapse svg{transform:rotate(90deg)}
.peek-b{flex:1;overflow-y:auto;padding:18px 26px 30px}
.peek-b::-webkit-scrollbar{width:9px}
.peek-b::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.peek-f{border-top:1px solid var(--line2);padding:10px 16px;display:flex;gap:8px;align-items:center}

/* task detail (clean, no boxes) */
.tk-title{font-size:22px;font-weight:800;letter-spacing:-.5px;border:0;outline:none;width:100%;background:transparent;padding:0 0 8px}
/* the untitled hint reads as a hint, and disappears the moment typing starts */
.tk-title::placeholder{color:var(--sub);opacity:.4;font-weight:800}
/* confirmation bubble under the control that opened it.
   §73a — **top of the ladder, above `.pickpop`'s 160.** It was 130, under
   `.memowin`'s 145, so Unpublish asked its question from behind the very window
   whose button was pressed. A confirm is the last thing opened and answers only
   Cancel / the act — it opens no picker of its own, so nothing can end up
   trapped behind it. Anything floating that a confirm can be asked from must
   stay below this. */
.confirmpop{position:fixed;z-index:170;min-width:236px;padding:12px;background:var(--panel);
  border:1px solid var(--line);border-radius:11px;box-shadow:var(--shl)}
.confirmpop .cq{font-size:12.5px;line-height:1.5;margin-bottom:10px}
.confirmpop .ca{display:flex;gap:8px;justify-content:flex-end}
.tk-meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.tk-meta .m{font-size:11.5px;color:var(--sub)}
/* date + reminder in one calendar popup */
.dpwrap{position:relative;display:inline-flex}
.dpbtn{cursor:pointer;text-align:left;min-width:118px}
.dpbtn.has-rem::after{content:'🔔';font-size:10px;margin-left:6px}
.dpop{position:absolute;top:30px;left:0;z-index:90;display:none;width:250px;padding:10px;
  background:var(--panel);border:1px solid var(--line);border-radius:11px;box-shadow:var(--shl)}
.dpop.on{display:block}
.dph{display:flex;align-items:center;gap:4px;margin-bottom:8px}
.dph b{flex:1;font-size:12.5px}
.dph button{border:0;background:transparent;color:var(--sub);border-radius:6px;padding:2px 6px;font-size:13px}
.dph button:hover{background:var(--soft);color:var(--ink)}
.dpg{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.dpg .wd{font-size:10px;color:var(--sub);text-align:center;padding:3px 0;font-weight:700}
.dpd{border:0;background:transparent;border-radius:7px;height:28px;font-size:11.5px;color:var(--ink)}
.dpd:hover{background:var(--soft)}
.dpd.out{color:var(--sub);opacity:.45}
.dpd.today{color:var(--accent);font-weight:700}
.dpd.sel{background:var(--accent);color:#fff;font-weight:700}
.dprem{display:flex;align-items:center;gap:6px;margin-top:9px;padding-top:9px;border-top:1px solid var(--line2)}
.dprem .ic{width:14px;height:14px;stroke:var(--sub);fill:none;stroke-width:1.8;flex:0 0 14px}
.dprem select,.dprem2 input{border:1px solid var(--line);background:var(--bg);color:var(--ink);
  border-radius:7px;font-size:11.5px;padding:4px 5px;outline:none}
.dprem>select{flex:1;min-width:0}
/* hour:minute as two selects — the native time popup rendered with odd gaps */
.tsel{display:inline-flex;align-items:center;gap:2px;flex:0 0 auto}
.tsel select{padding:4px 2px 4px 4px;font-variant-numeric:tabular-nums}
.tsel select:disabled{opacity:.4}
.tsel i{font-style:normal;color:var(--sub);font-size:11px}
.dprem2{display:flex;align-items:center;gap:6px;margin-top:6px;padding-left:20px;font-size:11.5px;color:var(--sub)}
.dprem2 input{flex:1;min-width:0}
.dpf{display:flex;justify-content:space-between;margin-top:8px}
.dpf button{border:0;background:transparent;color:var(--accent);font-size:11.5px;padding:3px 5px;border-radius:6px}
.dpf button:hover{background:var(--soft)}
/* peek header ⋯ menu */
.peekmorewrap{position:relative;display:inline-flex}
#peekMenu{top:36px;right:0;min-width:180px;z-index:95}
/* it is positioned by script from the anchor, so the base menu's right:0 must go —
   with both edges pinned the popover stretched across the page */
.rowmenupop{right:auto;min-width:190px;width:max-content;max-width:280px}
#peekMenu button,.rowmenupop button{display:flex;align-items:center;width:100%;border:0;background:transparent;
  padding:7px 9px;border-radius:7px;font-size:12.5px;text-align:left;color:var(--ink)}
#peekMenu button:hover,.rowmenupop button:hover{background:var(--soft)}
#peekMenu button.danger,.rowmenupop button.danger{color:var(--dang)}
#peekMenu .chev,.rowmenupop .chev{width:13px;height:13px;margin-left:auto;stroke:var(--sub);transition:transform .15s}
#peekMenu .subgrp.open .chev,.rowmenupop .subgrp.open .chev{transform:rotate(90deg)}
#peekMenu .subwrap,.rowmenupop .subwrap{display:none;max-height:210px;overflow-y:auto;margin:2px 0 2px 9px;
  padding-left:8px;border-left:1px solid var(--line)}
#peekMenu .subgrp.open .subwrap,.rowmenupop .subgrp.open .subwrap{display:block}
#peekMenu .subwrap button,.rowmenupop .subwrap button{font-size:12px;color:var(--sub)}
#peekMenu .subwrap button:hover,.rowmenupop .subwrap button:hover{color:var(--ink)}
/* §77 — and however tall a submenu makes it, the menu itself never grows past
   the window: it scrolls inside instead of being cut off by the edge */
.rowmenupop{max-height:calc(calc(100 * var(--vh)) - 20px);overflow-y:auto}
.icobtn.bkmk{border:1px solid var(--line);width:30px;height:30px;color:var(--sub)}
.icobtn.bkmk.on{color:var(--warn)}
.editor .mn{color:var(--accent);font-weight:600}
.bkmk{border:0;background:transparent;font-size:15px;color:var(--sub);padding:2px 4px;border-radius:6px;line-height:1}
.bkmk.on{color:var(--warn)}
.prop{margin-bottom:18px}
.prop>summary{list-style:none;cursor:pointer;font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;
  font-weight:800;color:var(--sub);padding:5px 0;display:flex;align-items:center;gap:7px}
.prop>summary::-webkit-details-marker{display:none}
/* real element, not ::before — the chevron and the label do different things */
.prop>summary .pchev{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;
  border-radius:5px;transition:transform .15s;font-size:14px;line-height:1;flex:0 0 16px}
.prop>summary .pchev:hover{background:var(--soft);color:var(--ink)}
.prop[open]>summary .pchev{transform:rotate(90deg)}
.prop>summary .plabel{cursor:pointer}
/* empty properties hide until the section's "more properties" toggle is used.
   Needs .proprow in the selector — a bare .prop-empty ties on specificity and loses. */
.proprow.prop-empty{display:none}
details.prop.show-empty .proprow.prop-empty{display:grid}
/* everything inside a section lines up with the first letter of its title
   (chevron 16px + the summary's 7px gap) */
.prop{--prop-ind:23px}
.prop>.proprow,.prop>.propmore,.prop>.subtasks,.prop>.addrow,.prop>#cmts,.prop>.cmtbox,.prop>.emptyval{
  margin-left:var(--prop-ind)}
.propmore{border:0;background:transparent;color:var(--sub);font-size:11.5px;padding:5px 0;
  border-radius:7px;margin-top:2px;display:block}
.propmore:hover{color:var(--ink)}
/* unfilled values read as a hint, never as content */
.emptyval,.proprow input::placeholder,.proprow textarea::placeholder{
  font-style:italic;color:var(--sub);opacity:.55}
.emptyval{font-size:12.5px;display:inline-block;padding:5px 7px}
.proprow select:has(option[value=""]:checked){font-style:italic;color:var(--sub);opacity:.75}
/* labels sit on the first line of the value, so multi-line rows (relations)
   keep the same top edge as single-line ones */
.proprow{display:grid;grid-template-columns:132px 1fr;gap:4px 12px;align-items:start;padding:3px 0}
.proprow>.pk{font-size:11.5px;color:var(--sub);font-weight:600;padding:6px 0}
.proprow>.pv{font-size:12.5px}
.proprow input,.proprow select,.proprow textarea{width:100%;border:1px solid transparent;border-radius:6px;
  padding:5px 7px;font-size:12.5px;outline:none;background:transparent}
.proprow input:hover,.proprow select:hover,.proprow textarea:hover{background:var(--soft)}
.proprow input:focus,.proprow select:focus,.proprow textarea:focus{background:var(--bg);border-color:var(--accent)}
.linklist a{display:block;color:var(--accent);font-size:12px;text-decoration:none;padding:2px 7px}
/* relation chips (roll-up task / event / sub-item) — every control fills the
   value column, so left and right edges line up down the whole panel */
.rel{display:flex;flex-wrap:wrap;gap:4px;width:100%}
.relchip{display:flex;align-items:center;gap:3px;background:var(--soft);border:1px solid var(--line);
  border-radius:7px;padding:0 4px 0 8px;flex:1 1 100%;min-width:0;min-height:28px}
.relchip button{border:0;background:transparent;color:var(--accent);font-size:11.5px;padding:2px 0;
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}
.relchip .rm{flex:0 0 auto;color:var(--sub);font-size:12px;padding:0 4px}
.relchip .rm:hover{color:var(--dang)}
/* the label never runs under the native arrow */
.proprow select.relsel{flex:1 1 100%;width:100%;font-size:11.5px;min-height:28px;
  padding-right:22px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rel select.relsel{color:var(--sub)}
/* ---------- ASSIGN FIELD ---------- */
/* every assignee sits on one line inside a single clickable box */
.asgline{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;width:100%;min-width:0;min-height:28px;
  padding:2px 6px;border-radius:7px;cursor:pointer}
.asgline:hover{background:var(--soft)}
.asgline:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}
.asgline .asgph{color:var(--sub);font-size:12px}
.asgchip{display:inline-flex;align-items:center;gap:5px;min-width:0;font-size:12px;color:var(--ink)}
.asgchip .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:130px}
.asgchip .mini-av{width:18px;height:18px;font-size:8px;flex:0 0 18px}
/* picker: chosen names as chips in the search box, the rest listed below */
.pickpop.asgpick{width:330px;min-width:330px}
.pickpop.asgpick .asgbox{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:2px}
/* one chip per row: the name gets the whole width, × parks at the right edge */
.pickpop.asgpick .asgchip.pick{flex:1 1 100%;width:100%;background:var(--soft);border:1px solid var(--line);
  border-radius:6px;padding:2px 4px 2px 5px;min-width:0}
.pickpop.asgpick .asgchip.pick .nm{flex:1;min-width:0;max-width:none}
/* width:auto beats the generic .pickpop button rule, which would eat the name */
.pickpop.asgpick .asgchip.pick .rm{flex:0 0 auto;width:auto;margin-left:auto;border:0;background:transparent;
  color:var(--sub);font-size:12px;padding:0 4px}
.pickpop.asgpick .asgchip.pick .rm:hover{color:var(--dang)}
.pickpop.asgpick .asgq{flex:1 1 100%;width:100%;min-width:0;border:0;background:transparent;outline:none;
  font-size:12.5px;padding:4px 4px;color:var(--ink)}
.pickpop.asgpick .prow{display:flex;align-items:center;gap:8px;width:100%;border:0;background:transparent;
  padding:6px 8px;border-radius:7px;font-size:12.5px;color:var(--ink);text-align:left}
.pickpop.asgpick .prow:hover{background:var(--soft)}
.pickpop.asgpick .prow .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------- SUB-ITEM FIELD ---------- */
.subrel{display:flex;flex-direction:column;gap:2px;width:100%;min-width:0}
/* inline variant (tags): chips on one line, same box behaviour as Assign */
.subrel.inline{flex-direction:row;flex-wrap:wrap}
.subrel.inline .s-ic{color:var(--sub);font-size:11px}
.subitem{display:flex;align-items:center;gap:6px;border-radius:7px;padding:1px 2px 1px 6px;min-height:28px}
.subitem:hover{background:var(--soft)}
.subitem .s-open{flex:1;min-width:0;display:flex;align-items:center;gap:6px;border:0;background:transparent;
  color:var(--ink);font-size:12px;padding:2px 0;text-align:left}
.subitem .s-open:hover .s-nm{text-decoration:underline}
/* values that lead nowhere (tags) read as text, not as a link */
.subitem .s-open.static{cursor:default}
.subitem .s-open.static:hover .s-nm{text-decoration:none}
.subitem .s-ic{color:var(--sub);font-size:11px;flex:0 0 auto}
.subitem .s-nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.subitem .s-ops{display:flex;align-items:center;gap:2px;opacity:0;flex:0 0 auto;transition:opacity .12s}
.subitem:hover .s-ops{opacity:1}
.subitem .s-op{border:0;background:transparent;color:var(--sub);font-size:14px;line-height:1;
  width:20px;height:20px;border-radius:5px}
.subitem .s-op:hover{background:var(--line2);color:var(--ink)}
.subrel .s-add{border:0;background:transparent;color:var(--sub);font-size:11.5px;text-align:left;
  padding:4px 6px;border-radius:7px;min-height:28px}
.subrel .s-add:hover{background:var(--soft);color:var(--ink)}
.subrel .s-none{color:var(--sub);font-size:11.5px;padding:4px 6px}
/* picker: search, current picks, candidates, then "New <title>" */
.pickpop.subpick{width:320px;min-width:320px}
.pickpop.subpick .prow{display:flex;align-items:center;gap:8px;width:100%;border:0;background:transparent;
  padding:6px 8px;border-radius:7px;font-size:12.5px;color:var(--ink);text-align:left}
.pickpop.subpick .prow:hover{background:var(--soft)}
.pickpop.subpick .prow .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pickpop.subpick .prow .mn{color:var(--sub);font-size:14px;line-height:1}
.pickpop.subpick .prow.mk{color:var(--accent);border-top:1px solid var(--line2);border-radius:0 0 7px 7px;margin-top:2px}
.pickpop.subpick .prow.mk b{font-weight:600}
.proprow>.pv,.proprow>.pk{min-width:0}
/* assignees flow inline like text — avatar + name, any number, no boxes */
.asgwrap{gap:4px 10px;align-items:center}
.asgwrap .relchip{flex:0 0 auto;width:auto;max-width:100%;background:transparent;border:0;
  border-radius:6px;padding:1px 2px 1px 0;min-height:22px}
.asgwrap .relchip:hover{background:var(--soft)}
.asgwrap .relchip .who{display:flex;align-items:center;gap:5px;flex:0 1 auto;min-width:0;color:var(--ink);
  border:0;background:transparent;font-size:12px;padding:1px 0;text-align:left}
.asgwrap .relchip .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:96px}
.asgwrap .relchip .mini-av{width:18px;height:18px;font-size:8px;flex:0 0 18px}
.asgwrap .relchip .rm{opacity:0;padding:0 2px}
.asgwrap .relchip:hover .rm{opacity:1}
.subtasks{margin:4px 0 0}
.subrow{display:flex;align-items:center;gap:6px;padding:2px 4px;border-radius:7px;font-size:12.5px;min-height:28px}
.subrow:hover{background:var(--soft)}
.subrow input[type=checkbox]{width:14px;height:14px;accent-color:var(--accent);flex:0 0 14px}
.subrow .stext{flex:1;min-width:0;border:1px solid transparent;border-radius:6px;background:transparent;
  padding:4px 6px;font-size:12.5px;outline:none;color:var(--ink)}
.subrow .stext:hover{background:var(--bg)}
.subrow .stext:focus{background:var(--bg);border-color:var(--accent)}
.subrow.done .stext{text-decoration:line-through;color:var(--sub)}
.subrow .sdrag{flex:0 0 12px;color:var(--sub);opacity:0;cursor:grab;font-size:11px;line-height:1;touch-action:none}
.subrow:hover .sdrag{opacity:.6}
.subrow.dragging{background:var(--soft);opacity:.75;box-shadow:var(--sh)}
.subrow.dragging .sdrag{cursor:grabbing;opacity:1}
.subrow .rm{flex:0 0 auto;border:0;background:transparent;color:var(--sub);opacity:0;padding:0 4px}
.subrow:hover .rm{opacity:1}
.subrow .rm:hover{color:var(--dang)}
/* pre-wrap so a typed tab actually shows up */
.editor{min-height:150px;border:0;outline:none;font-size:13px;line-height:1.75;padding:6px 0;
  white-space:pre-wrap;tab-size:4}
/* spelling suggestions */
.spellpop{position:fixed;z-index:130;min-width:170px;padding:5px;background:var(--panel);
  border:1px solid var(--line);border-radius:10px;box-shadow:var(--shl)}
.spellpop .sh{font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;color:var(--sub);
  font-weight:700;padding:5px 8px 6px}
.spellpop button{display:block;width:100%;text-align:left;border:0;background:transparent;
  padding:6px 9px;border-radius:7px;font-size:12.5px;color:var(--ink)}
.spellpop button:hover{background:var(--soft)}
.spellpop .ignore{color:var(--sub);border-top:1px solid var(--line2);border-radius:0 0 7px 7px;margin-top:3px;font-size:11.5px}
.editor:empty:before{content:attr(data-ph);color:var(--sub);opacity:.6}
.editor table{border:1px solid var(--line);margin:10px 0}
.editor td{border:1px solid var(--line);padding:6px 9px}
.editor img{max-width:100%;border-radius:8px;margin:8px 0;cursor:zoom-in}
.editor ul,.editor ol{margin:6px 0;padding-left:20px}
.editor li{margin:2px 0}
/* the rule spans the full editor width, flush with the text on both sides */
.editor hr{border:0;border-top:1px solid var(--line);margin:12px 0;width:100%;display:block}
.insmenu hr{border:0;border-top:1px solid var(--line2);margin:4px 2px}
.editor mark{border-radius:3px;padding:0 2px}
/* highlight palette — shared by the editor content and the toolbar swatches.
   Keep these at or above `.editor mark` specificity or the editor default wins. */
.editor mark[data-hl="yellow"],[data-hl="yellow"]{background:#fff2a8;color:#12181f}
.editor mark[data-hl="red"],[data-hl="red"]{background:#ffc9c9;color:#12181f}
.editor mark[data-hl="green"],[data-hl="green"]{background:#b8f0cd;color:#12181f}
.editor mark[data-hl="blue"],[data-hl="blue"]{background:#c4dcff;color:#12181f}
.editor mark[data-hl="purple"],[data-hl="purple"]{background:#e0d1ff;color:#12181f}
.editor mark[data-hl="black"],[data-hl="black"]{background:#12181f;color:#fff}
.editor mark:not([data-hl]){background:#fff2a8;color:#12181f}
.editor a[href^="data:"]{text-decoration:none}
.etoolbar{display:flex;gap:3px;margin-bottom:6px;flex-wrap:wrap;border-bottom:1px solid var(--line2);padding-bottom:6px}
.etoolbar button{border:0;background:transparent;border-radius:6px;padding:4px 8px;font-size:12px;color:var(--sub)}
.etoolbar button:hover{background:var(--soft);color:var(--ink)}
.etoolbar button.on{background:var(--ink);color:var(--bg)}
.etoolbar .hl{padding:0 3px;border-radius:3px}
.hlwrap{position:relative;display:inline-flex;align-items:center}
.etoolbar .hlcaret{padding:4px 3px;font-size:9px;margin-left:-4px}
/* swatches only, two columns */
.hlmenu{position:absolute;bottom:28px;left:0;z-index:80;display:none;padding:6px;
  grid-template-columns:repeat(2,auto);gap:4px;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;box-shadow:var(--shl)}
.hlmenu.on{display:grid}
.hlmenu button{display:grid;place-items:center;padding:3px;border-radius:6px}
.hlmenu button:hover{background:var(--soft)}
.hlmenu .sw{width:20px;height:20px;border-radius:5px;border:1px solid var(--line2);display:block}
.etoolbar .esize{border:1px solid var(--line);background:var(--bg);color:var(--sub);border-radius:6px;
  font-size:11.5px;padding:3px 6px;outline:none;margin-left:4px}
.etoolbar .esize:focus{border-color:var(--accent);color:var(--ink)}
.inswrap{position:relative;margin-left:4px}
.insbtn{font-size:14px;line-height:1;font-weight:700}
/* opens upward — the toolbar sits low in the peek and a downward menu gets clipped */
.insmenu{position:absolute;bottom:28px;left:0;z-index:80;display:none;min-width:158px;padding:5px;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;box-shadow:var(--shl)}
.insmenu.on{display:block}
.insmenu button{display:block;width:100%;text-align:left;font-size:12px;padding:6px 9px;color:var(--ink)}
.editor a{color:var(--accent);text-decoration:underline;text-underline-offset:2px;word-break:break-word}
.filechip{display:inline-flex;align-items:center;gap:5px;background:var(--soft);border:1px solid var(--line);
  border-radius:7px;padding:3px 4px 3px 8px;font-size:12px;text-decoration:none;color:var(--ink);cursor:pointer}
.filechip:hover{border-color:var(--accent)}
.filechip .fname{text-decoration:underline;text-underline-offset:2px}
.filechip .fdl{padding:0 5px;border-radius:5px;color:var(--sub);font-size:11px;text-decoration:none}
.filechip .fdl:hover{background:var(--bg);color:var(--accent)}
/* ---------- floating preview windows (several at once) ---------- */
.pvwin{position:fixed;inset:calc(5 * var(--vh)) calc(6 * var(--vw));z-index:120;display:flex;flex-direction:column;overflow:hidden;
  background:var(--bg);border:1px solid var(--line);border-radius:13px;box-shadow:var(--shl)}
.pvwin.min{inset:auto auto 0 14px;width:236px;height:38px;border-radius:11px 11px 0 0}
/* minimised: file name + controls only, so the restore target stays big */
.pvwin.min .pvb,.pvwin.min .pvf,.pvwin.min .pvsrc{display:none}
.pvwin.min .pvh{cursor:pointer}
.pvh{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--line2);flex:0 0 auto}
.pvh .pvname{font-size:12px;font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pvsrc{flex:0 0 auto;max-width:230px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pvh .icobtn{width:26px;height:26px;flex:0 0 26px;font-size:12px}
.pvb{flex:1;min-height:0;overflow:auto;background:var(--panel)}
.pvf{display:flex;align-items:center;gap:8px;padding:9px 12px;border-top:1px solid var(--line2);flex:0 0 auto}
.pvloading{padding:26px;text-align:center;color:var(--sub);font-size:12px}
/* the content fills the window — no empty gutters */
.pviframe{width:100%;height:100%;border:0;display:block;background:var(--bg)}
.pvimg{min-height:100%;display:grid;place-items:center;padding:10px}
.pvimg img{max-width:100%;max-height:100%;border-radius:8px;display:block}
.pvtext{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.65;padding:16px;margin:0}
.pvnone{display:grid;place-items:center;height:100%;text-align:center;color:var(--sub);padding:30px}
.pvnone .ic{font-size:40px;margin-bottom:10px}
.pvnone p{font-size:12px;max-width:330px;line-height:1.6;margin:0}
/* rendered office documents */
.pvdoc{background:var(--bg);padding:26px 30px;font-size:13px;line-height:1.75;min-height:100%}
.pvdoc h2{font-size:18px;margin:16px 0 6px}
.pvdoc h3{font-size:14.5px;margin:14px 0 5px}
.pvdoc p{margin:0 0 6px}
.pvdoc p.sp{height:8px;margin:0}
.pvdoc li{margin-left:20px}
.pvdoc .muted{color:var(--sub);font-size:12px}
.pvxls{padding:16px}
.pvsheet{margin-bottom:20px}
.pvsheet-h{font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;color:var(--sub);font-weight:700;margin-bottom:6px}
.pvxls table{border-collapse:collapse;width:100%;font-size:12px}
.pvxls td{border:1px solid var(--line);padding:5px 8px;white-space:nowrap;max-width:280px;overflow:hidden;text-overflow:ellipsis}
.pvslide{border:1px solid var(--line);border-radius:10px;padding:16px 18px;margin-bottom:14px;background:var(--panel)}
.pvslide-n{font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;color:var(--sub);font-weight:700;margin-bottom:6px}
.pvslide h3{margin:0 0 6px}
.pvpics{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.pvpics img,.pvdoc img{max-width:100%;border-radius:6px}
.pvtbl{border-collapse:collapse;margin:10px 0;width:100%}
.pvtbl td{border:1px solid var(--line);padding:6px 9px;vertical-align:top}
.pvtbl td p{margin:0}
.filechip.missing{opacity:.5;text-decoration:line-through}
@media(max-width:828px){.pvwin{inset:0;border-radius:0}.pvwin.min{inset:auto auto 0 8px;width:180px}}
.cmt{display:flex;gap:9px;margin-bottom:12px}
.cmt .mini-av{flex:0 0 26px;width:26px;height:26px}
.cmt .who{font-size:12px;font-weight:700}
.cmt .when{font-size:10.5px;color:var(--sub);margin-left:6px;font-weight:400}
.cmt .txt{font-size:12.5px;margin-top:2px;line-height:1.6}
.cmt .txt .mn{color:var(--accent);font-weight:600}
.cmtbox{display:flex;gap:8px;align-items:center;margin-top:10px}
.cmtbox input{flex:1;border:1px solid var(--line);border-radius:20px;padding:8px 13px;font-size:12.5px;outline:none;background:var(--bg)}
.cmtbox input:focus{border-color:var(--accent)}
.mnpop{position:absolute;background:var(--panel);border:1px solid var(--line);border-radius:9px;box-shadow:var(--shl);
  padding:5px;z-index:90;display:none;min-width:190px;max-height:280px;overflow-y:auto}
.mnpop.on{display:block}
.mnpop button{display:flex;gap:8px;align-items:center;width:100%;border:0;background:transparent;padding:6px 8px;
  border-radius:6px;font-size:12px;text-align:left}
.mnpop button:hover{background:var(--soft)}
/* PARTIAL TASK §2 — the "@" popup grew a second group, so each one is headed */
.mnpop{max-width:340px}
.mnpop .mnh{font-size:9.5px;text-transform:uppercase;letter-spacing:.6px;color:var(--sub);
  font-weight:700;padding:6px 8px 3px}
.mnpop .mnic{flex:0 0 auto;color:var(--accent);font-size:11px}
.mnpop .mntx{min-width:0;display:flex;flex-direction:column;line-height:1.25;text-align:left}
.mnpop .mntx b{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mnpop .mntx i{font-style:normal;font-size:10.5px;color:var(--sub);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* PARTIAL TASK §1 — a link to a record, wherever it was pasted. *"menggunakan
   icon panah link, underlined tipis, dan text hyperlink sesuai dengan
   tulisannya"* — the arrow is drawn rather than typed, so it never lands in the
   copied plain text or in a search index. */
/* ⚠ matched on the **href** as well as the class. A chip arrives by paste, and
   a sanitiser that drops `class` would leave a working link looking like plain
   text. The href is the one attribute nothing strips — the same reason the
   record reference lives there. */
.reclink,a[href*="#rl:"]{color:var(--accent);text-decoration:none;
  border-bottom:1px solid var(--accent-soft);cursor:pointer;padding-bottom:1px}
.reclink::before,a[href*="#rl:"]::before{content:'↗';font-size:.85em;margin-right:3px;opacity:.8}
.reclink:hover,a[href*="#rl:"]:hover{border-bottom-color:var(--accent)}

/* ---------- MODAL (meeting fullscreen w/ minimize) ---------- */
.modal{position:fixed;inset:24px;background:var(--bg);border:1px solid var(--line);border-radius:14px;z-index:55;
  display:none;flex-direction:column;box-shadow:var(--shl)}
.modal.on{display:flex}
.modal.min{inset:auto 24px 0 auto;width:330px;height:44px;border-radius:10px 10px 0 0;overflow:hidden}
.modal.min .modal-b,.modal.min .modal-f{display:none}
.modal-h{display:flex;align-items:center;gap:8px;padding:11px 16px;border-bottom:1px solid var(--line2)}
.modal-h .ttl{font-size:13px;font-weight:700;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.modal-b{flex:1;overflow-y:auto;padding:20px 26px}
.modal-f{border-top:1px solid var(--line2);padding:10px 16px;display:flex;gap:8px;justify-content:flex-end}

/* ---------- KANBAN ---------- */
/* flex, not grid: a folded lane has to take a narrower track than the rest.
   min-width:0 keeps the wide lane row from pushing the page — and the tiles — wider */
.kb{display:flex;gap:12px;overflow-x:auto;padding-bottom:10px;min-width:0}
.kb>.kbcol{flex:0 0 270px}
.kb>.kbcol.folded{flex:0 0 42px;padding:9px 4px;display:flex;justify-content:center}
/* the rail keeps the lane reachable — click it, or just drop a card on it */
.kfold{border:0;background:transparent;color:var(--sub);font-size:11.5px;font-weight:700;cursor:pointer;
  writing-mode:vertical-rl;text-orientation:mixed;padding:4px 0;letter-spacing:.4px}
.kfold:hover{color:var(--ink)}
.kfoldbtn{border:0;background:transparent;color:var(--sub);cursor:pointer;font-size:15px;line-height:1;padding:0 4px}
.kfoldbtn:hover{color:var(--ink)}
/* board scroller: a light grey slider, not the browser default */
.kb::-webkit-scrollbar{height:10px}
.kb::-webkit-scrollbar-track{background:transparent}
.kb::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.kb{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.kbcol{background:var(--soft);border-radius:11px;padding:9px;min-height:150px}
.kbcol.over{outline:2px dashed var(--accent);outline-offset:-3px}
.kbcol>.kh{display:flex;align-items:center;gap:7px;font-size:11.5px;font-weight:700;padding:3px 5px 9px}
.kbcol>.kh .c{margin-left:auto;font-size:10.5px;color:var(--sub);background:var(--bg);border-radius:20px;padding:1px 7px}
/* the board header reads quieter than the same pill in a list or the navigation */
.kbcol>.kh .pill{opacity:.6}
.kbadd{padding:8px 6px 4px;color:var(--sub);font-size:12px;cursor:pointer;border-radius:8px}
.kbadd:hover{background:var(--bg);color:var(--ink)}
.kbcard{background:var(--bg);border:1px solid var(--line2);border-radius:9px;padding:10px 11px;margin-bottom:8px;
  box-shadow:var(--sh);cursor:grab}
.kbcard:active{cursor:grabbing}
/* card tone: red for urgent, blue for work handed over by another personnel */
.kbcard.urg{background:color-mix(in srgb,var(--dang) 9%,var(--bg));border-color:color-mix(in srgb,var(--dang) 35%,var(--line2))}
.kbcard.asg{background:color-mix(in srgb,var(--accent) 9%,var(--bg));border-color:color-mix(in srgb,var(--accent) 35%,var(--line2))}
/* sub-item cards step in, like the sub rows in the task list */
.kbcard.sub{margin-left:14px}
/* a parent shown only for context, or a card out of step with its column */
.kbcard.dim{opacity:.45}
.kbcard.dim:hover{opacity:.8}
.kbcard.drag{opacity:.4}
.kbcard .t{font-size:12.5px;font-weight:600;line-height:1.4}
.kbcard .m{display:flex;align-items:center;gap:6px;margin-top:7px;font-size:10.5px;color:var(--sub)}

/* ---------- LIST ROWS (task list view) ---------- */
.trow{display:flex;align-items:center;gap:10px;padding:9px 12px;border-bottom:1px solid var(--line2);cursor:pointer}
.trow:hover{background:var(--soft)}
/* out-of-context rows: a closed sub-item in the Task tab, an open parent shown
   for context in the Done tab. Still clickable, just quiet. */
.trow.dim{opacity:.45}
.trow.dim:hover{opacity:.8}
/* the row whose peek is open reads as a boxed selection */
.trow.active{background:var(--soft);box-shadow:inset 0 0 0 1px var(--line);border-radius:8px;
  border-bottom-color:transparent}
.trow .tt{flex:1 1 auto;font-size:12.5px;font-weight:600;min-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* fixed columns so tags / assignee / priority / status / due line up down the list */
.trow .tm{display:grid;grid-template-columns:minmax(0,1fr) 62px 74px 104px 54px 26px;
  align-items:center;gap:8px;flex:0 0 auto;width:500px}
/* tags never spill: the newest ones drop behind a +N counter */
.trow .c-tags{display:flex;gap:5px;justify-content:flex-end;overflow:hidden;white-space:nowrap;min-width:0}
/* chips shrink before they clip, so a long label ends in "…" instead of losing its first letters */
.trow .c-tags .tag{flex:0 1 auto;min-width:0;max-width:110px;overflow:hidden;text-overflow:ellipsis}
.trow .c-tags .tag.more{flex:0 0 auto;background:var(--soft);color:var(--sub)}
/* "from <role>" — the hand-over source on rows the viewer does not own */
.trow .c-tags .tag.from{background:transparent;border-style:dashed;color:var(--sub);max-width:132px}
.trow .c-tags .tag.from i{font-style:normal;opacity:.65;margin-right:2px}
.trow .c-asg{display:flex;justify-content:flex-end}
.trow .c-prio,.trow .c-stat{justify-self:start;overflow:hidden}
.trow .c-due{color:var(--sub);font-size:11px;text-align:right;white-space:nowrap}
/* cells that can be changed without opening the task */
.trow .cell{cursor:pointer;border-radius:7px;padding:2px 4px;min-height:24px;display:flex;align-items:center}
.trow .cell:hover{background:var(--bg);box-shadow:inset 0 0 0 1px var(--line)}
.trow .cellph{color:var(--sub);opacity:0;font-size:11px}
.trow:hover .cellph{opacity:.7}
/* chooser popover */
/* above the quick-add card (z 140) so a tag / notification / guest picker
   opened from it is never trapped behind the box */
.pickpop{position:fixed;z-index:160;min-width:186px;max-height:340px;padding:5px;display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shl)}
.pickpop .plist{overflow-y:auto;min-height:0}
.pickpop .pt{padding:2px 4px 6px;border-bottom:1px solid var(--line2);margin-bottom:4px}
.pickpop .pt input{width:100%}
.pickpop .ph2{font-size:10px;text-transform:uppercase;letter-spacing:.6px;color:var(--sub);font-weight:700;padding:5px 8px}
.pickpop button{display:flex;align-items:center;gap:8px;width:100%;text-align:left;border:0;background:transparent;
  padding:6px 8px;border-radius:7px;font-size:12.5px;color:var(--ink)}
.pickpop button:hover{background:var(--soft)}
.pickpop button .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pickpop button .ck{margin-left:auto;color:var(--accent);font-weight:700}
.pickpop .pf{padding:5px 6px 3px;border-top:1px solid var(--line2);margin-top:4px}
.pickpop .pf input{width:100%}
@media(max-width:990px){.trow .tm{grid-template-columns:74px 104px 54px 26px;width:270px}
  .trow .c-tags,.trow .c-asg{display:none}}
/* HOME — a slim list. The two summary columns are ~460px wide while a task row
   asks for 768px (a 190px title plus a fixed 500px meta grid), so every row ran
   past the card and priority, status and due were clipped at the edge. In a slim
   list the row keeps what a summary is read for — title, priority, date — and
   drops the editing cells; tags, assignee and status are edited in the space
   itself, one click away on "Open my space". */
.cb.slim{overflow:hidden}
/* the three remaining cells size to their content and hug the right edge —
   a fixed track set left the "⋯" 4px past the card */
.cb.slim .trow .tm{grid-template-columns:auto auto auto;width:auto;gap:6px;justify-content:end}
.cb.slim .trow .c-tags,.cb.slim .trow .c-asg,.cb.slim .trow .c-stat{display:none}
.cb.slim .trow .tt{min-width:0}
/* the row "⋯" is a bare glyph wherever it appears — task row or note card */
.rowmenu{border:0;background:transparent;color:var(--sub);padding:2px 6px;border-radius:6px;font-size:15px;line-height:1}
.rowmenu:hover{background:var(--soft);color:var(--ink)}
.trow .rowmenu{opacity:0}
.trow:hover .rowmenu{opacity:1}
.grouph{font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;font-weight:800;color:var(--sub);
  padding:14px 12px 6px;display:flex;align-items:center;gap:8px}
/* outside a list card the group heading needs no row padding */
.grid3+.grouph,.rowbtn+.grouph{padding-left:2px;padding-right:2px}
/* a capped list ends on this row: it opens the rest and folds it back */
.viewmore{padding:9px 12px;color:var(--sub);font-size:12px;font-weight:600;cursor:pointer;
  border-bottom:1px solid var(--line2);text-align:center}
.viewmore:hover{background:var(--soft);color:var(--ink)}
/* inside a board lane it is a card-sized row, not a list divider */
.kbcol .viewmore{border-bottom:0;padding:6px;border-radius:8px}
.kbcol .viewmore:hover{background:var(--bg)}
.addrow{display:flex;align-items:center;gap:8px;padding:9px 12px;color:var(--sub);font-size:12.5px;cursor:pointer}
.addrow:hover{background:var(--soft);color:var(--ink)}

/* PARTIAL TASK §6 — the add row types. It wears whichever class its list gives
   it (`.addrow` in a list, `.kbadd` in a board lane) and only the writing state
   is dressed here, so a lane keeps its own padding and a list keeps its own. */
.qadd.writing{display:flex;align-items:center;gap:6px;cursor:default;background:transparent}
.qadd.writing:hover{background:transparent}
.qadd .qanew{flex:1 1 auto;min-width:0;max-width:340px;border:1px solid var(--accent);border-radius:7px;
  padding:4px 8px;font-size:12.5px;font-family:inherit;background:var(--panel);color:var(--ink);outline:none}
.qadd .qapeek{flex:0 0 auto;width:26px;height:26px;line-height:1;padding:0;font-size:13px;cursor:pointer;
  border:1px solid var(--line2);border-radius:7px;background:var(--panel);color:var(--sub)}
.qadd .qapeek:hover{background:var(--soft);color:var(--ink);border-color:var(--accent)}
/* a lane is narrow: the field takes what is there and the icon keeps its size */
.kbcol .qadd .qanew{max-width:none}

/* a title edited where it is read (§6). It replaces the element it renames, so
   it inherits that element's slot — the indent comes with `--lv` off the row. */
.inrename{border:1px solid var(--accent);background:var(--panel);color:var(--ink);border-radius:7px;
  padding:3px 8px;font-size:12.5px;font-weight:600;font-family:inherit;outline:none}
.trow .inrename{flex:1 1 auto;min-width:120px;margin-left:calc(var(--lv,0) * 20px)}
.sectbl .inrename{width:min(320px,90%);font-weight:600}
/* the title says it is writable without shouting about it */
.trow .tt[data-ttl],.sectbl b[data-ttl]{cursor:text}
.trow .tt[data-ttl]:hover,.sectbl b[data-ttl]:hover{text-decoration:underline dotted;text-underline-offset:3px}

/* ---------- SUB-ITEM TREE (list rows) ---------- */
/* the twisty only shows on hover unless the row already has sub-items */
.trow .twist{border:0;background:transparent;color:var(--sub);font-size:11px;line-height:1;padding:3px 2px;
  border-radius:5px;width:18px;flex:0 0 auto;opacity:0;transition:transform .12s,opacity .12s}
.trow:hover .twist,.trow .twist.has{opacity:.75}
.trow .twist:hover{background:var(--line2);opacity:1}
.trow .twist.on{transform:rotate(90deg);opacity:1}
.trow .twist.ghost{visibility:hidden;pointer-events:none}
/* rows keep their columns aligned; only the label side steps in */
.trow{padding-left:6px}
.trow .tt{padding-left:calc(var(--lv,0) * 20px)}
.trow.sub .tt{font-weight:500;color:var(--ink)}
.subadd{display:flex;align-items:center;padding:7px 12px 7px calc(67px + var(--lv,1) * 20px);
  color:var(--sub);font-size:12px;cursor:pointer;border-bottom:1px solid var(--line2)}
.subadd:hover{background:var(--soft);color:var(--ink)}
.subadd.writing{cursor:default}
.subadd .subnew{width:min(320px,60%);border:1px solid var(--accent);border-radius:7px;padding:4px 8px;
  font-size:12.5px;background:var(--panel);outline:none}

/* PARTIAL TASK §5 — sub-items on a project section's task table. The Teamspace
   list is a stack of flex rows; this is a real <table>, so the twisty and the
   writer are re-dressed here rather than borrowing `.trow` / `.subadd` — and the
   sub row must NOT reuse `.subrow`, which is the Sub Task checklist's flex row
   and would take a <tr> out of the table layout entirely. */
.sectbl .twist{border:0;background:transparent;color:var(--sub);font-size:11px;line-height:1;
  padding:2px 3px;border-radius:5px;width:16px;opacity:0;transition:transform .12s,opacity .12s}
.sectbl tr:hover .twist,.sectbl .twist.has{opacity:.75}
.sectbl .twist:hover{background:var(--line2);opacity:1}
.sectbl .twist.on{transform:rotate(90deg);opacity:1}
.sectbl .twist.ghost{visibility:hidden;pointer-events:none}
.sectbl tr.psrow>td:first-child{padding-left:30px}
.sectbl tr.psrow b{font-weight:500}
.sectbl tr.psadd>td,.sectbl tr.pswrite>td{padding:6px 12px 6px 30px}
.sectbl tr.psadd button{border:0;background:transparent;color:var(--sub);font-size:12px;
  padding:2px 4px;border-radius:6px;cursor:pointer}
.sectbl tr.psadd button:hover{background:var(--soft);color:var(--ink)}
.sectbl .subnew{width:min(320px,60%);border:1px solid var(--accent);border-radius:7px;
  padding:4px 8px;font-size:12.5px;background:var(--panel);outline:none}

/* ---------- SEARCH RESULTS ---------- */
.srow{display:flex;align-items:center;gap:10px;padding:9px 10px;border-bottom:1px solid var(--line2);cursor:pointer;border-radius:8px}
.srow:hover{background:var(--soft)}
.srow .sx{flex:1;min-width:0}
.srow .st{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srow .sl{font-size:11px;color:var(--sub);margin-top:2px;line-height:1.45}
.srow .sm{display:flex;align-items:center;gap:4px;flex:0 0 auto}
.srow mark{background:#fff2a8;color:#12181f;border-radius:3px;padding:0 1px}
[data-theme="dark"] .srow mark{background:#5c4a10;color:#ffe9a8}

/* ---------- NOTES / CARD GRID ---------- */
.ncard{border:1px solid var(--line);border-radius:11px;background:var(--panel);padding:14px 15px;cursor:pointer;
  box-shadow:var(--sh);display:flex;flex-direction:column;min-height:118px}
.ncard:hover{border-color:var(--accent)}
/* the card whose peek is open reads as a boxed selection, like a task row */
.ncard.active{background:var(--soft);box-shadow:inset 0 0 0 1px var(--line);border-color:var(--line)}
/* star, title and "⋯" on one line, like a task row */
.ncard .nh{display:flex;align-items:flex-start;gap:7px;margin-bottom:5px}
.ncard .nh .nt{margin:0;flex:1;min-width:0}
/* public / private switch — grey and left is public, red and right is private */
.privsw{width:30px;height:17px;border-radius:20px;border:1px solid var(--line);background:var(--soft);
  padding:0;position:relative;cursor:pointer;flex:0 0 auto;transition:background .16s,border-color .16s}
.privsw>i{position:absolute;top:1px;left:1px;width:13px;height:13px;border-radius:50%;
  background:var(--sub);opacity:.7;transition:transform .16s,background .16s}
.privsw.on{background:var(--dangb);border-color:var(--dang)}
.privsw.on>i{transform:translateX(13px);background:var(--dang);opacity:1}
.ncard .nf .privsw{margin-left:auto}
.ncard .nh .bkmk{flex:0 0 auto;margin-top:-1px}
/* a shared card keeps the star's width so every title lines up */
.ncard .nh .bkmk.ghost{width:23px;display:inline-block}
.ncard .nh .rowmenu{opacity:0;flex:0 0 auto}
.ncard:hover .nh .rowmenu{opacity:1}
.ncard .nt{font-size:13px;font-weight:700;margin-bottom:5px}
.ncard .nx{font-size:11.5px;color:var(--sub);flex:1;overflow:hidden;line-height:1.55}
.ncard .nf{font-size:10.5px;color:var(--sub);margin-top:9px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.ncard .nf .tag{flex:0 0 auto}
/* the quota list is scanned, not read: fixed columns keep every row one height and
   the address rides on a single line with the full text on hover */
.qptable{table-layout:fixed;width:100%}
.qptable .qaddr{color:var(--sub);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qptable td>b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.thumb{height:120px;background:var(--soft);background-size:cover;background-position:center;border-radius:9px;margin-bottom:10px;
  display:grid;place-items:center;color:var(--sub);font-size:11px}

/* ============================================================
   PROJECT SPACE
   Source: "DS WORKSPACE V3 PROJECT-1". The timeline is a column strip
   (one column = one day, week or month, depending on the tab) with the
   task bars placed into the same CSS grid as the cells behind them.
   ============================================================ */

/* ---- timeline: the toolbar is a strip of its own under the card header ----
   Six view tabs plus the period need more room than a card header can share with
   a title, so the strip owns its row and the title keeps the header. */
.pjtl>.ch{gap:8px}
.pjtl.closed>.cb{display:none}
/* the fold on a whole section reads as a control, not as punctuation */
.bigfold{border:1px solid var(--line);background:var(--bg);color:var(--sub);border-radius:7px;
  width:24px;height:24px;line-height:1;font-size:12px;cursor:pointer;flex:0 0 auto;
  display:inline-grid;place-items:center}
.bigfold:hover{border-color:var(--accent);color:var(--accent)}
.tltoolbar{display:flex;align-items:center;gap:8px;padding:10px 16px;flex-wrap:wrap;
  border-bottom:1px solid var(--line2)}
/* the period keeps a fixed slot so the view tabs land on the same x in every tab
   and in both languages. Left-aligned, as PROJECT-2 asks — a centred label drifts
   inside its own slot every time the month name changes length. */
.tltoolbar .tlwhen{min-width:186px;flex:0 0 auto;font-size:12px;font-weight:700;text-align:left;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tltoolbar .tabs{margin:0 0 0 auto}
/* Range keeps its two dates on the toolbar row itself */
.tlrange{display:inline-flex;align-items:center;gap:10px;font-size:11.5px;color:var(--sub)}
.tlrange label{display:flex;align-items:center;gap:5px}
.tlrange input{border:1px solid var(--line);background:var(--bg);border-radius:7px;padding:3px 6px;font-size:11.5px}

/* ---- the strip ---- */
/* PROJECT-2: the strip scrolls sideways only. Vertical belongs to the page, so
   the wheel is free to walk the columns (see bindTimeline) and the box can never
   trap the pointer. `overflow-x:scroll` keeps the gutter reserved, so switching
   between Weekly and Semester does not change the height of the box. */
/* no padding here: it would offset this pane against the names pane, and the two
   only stay in step because their rows start at the same y */
.tlwrap{overflow-x:scroll;overflow-y:hidden;flex:1 1 auto;min-width:0}
.tlwrap::-webkit-scrollbar{height:10px}
.tlwrap::-webkit-scrollbar-track{background:transparent}
.tlwrap::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.tlwrap{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
/* the tracks carry a floor, not a fixed width: a week fills the card and a month
   still fits, while a semester's 26 columns push past it and the wrapper scrolls.
   `width:max-content` cannot be used here — it makes every 1fr resolve to the
   widest content in the column, which blew each day out to ~180px. */
/* two panes: the names stand still, only the strip on the right scrolls.
   `position:sticky` was tried first and cannot do this — a grid item's
   containing block is its own grid area, so the cell could never travel further
   than the width of its own column. */
.tlsplit{display:flex;align-items:flex-start;--tlname:210px;--rowh:32px;--headh:38px}
.tlnames{flex:0 0 var(--tlname);width:var(--tlname);border-right:1px solid var(--line);
  background:var(--panel);position:relative;z-index:2}
.tlnrow{height:var(--rowh);display:flex;align-items:center;gap:6px;padding:0 10px;
  font-size:11.5px;min-width:0;box-sizing:border-box}
.tlnrow.head{height:var(--headh);border-bottom:1px solid var(--line);
  font-size:9.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--sub);font-weight:700}
.tlnrow.task{padding-left:22px}
.tlnrow.more{padding-left:22px}
/* the tracks are real lengths, set per render — see renderTimeline. Under
   `minmax(min, 1fr)` they were free to squeeze below their minimum and a
   day-grain strip could not be scrolled at all. */
.tl{min-width:100%;width:max-content;--tlcw:30px}
.tlrow{display:grid;grid-template-columns:repeat(var(--tln),var(--tlcw));
  align-items:stretch;height:var(--rowh);box-sizing:border-box}
.tlrow.head{height:var(--headh)}
.tlgo{border:0;background:transparent;padding:0;text-align:left;font:inherit;font-weight:600;
  color:var(--ink);cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
.tlgo:hover{color:var(--accent)}
/* a project reads in its own colour, so a bar and its title belong together */
.tlgo.pj{font-weight:800;color:var(--pjc,var(--ink))}
.tlgo.pj:hover{filter:brightness(1.15)}
.tlmore{border:0;background:transparent;padding:0;font:inherit;font-size:11px;color:var(--accent);cursor:pointer}
.tlnrow .c{font-size:10px;color:var(--sub);background:var(--bg);border-radius:20px;padding:0 6px;flex:0 0 auto}
.tlnrow .s{font-size:10px;color:var(--sub);flex:0 0 auto;max-width:74px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* the cursor's row is marked in the Project / Task panel only — the marker never
   runs on into the date columns */
.tlnrow:not(.head):hover{background:var(--soft)}
/* the project row folds its own tasks away — PROJECT-2 puts the control on the
   marker that was already sitting there */
.tlfold{border:0;background:transparent;color:var(--sub);cursor:pointer;font-size:11px;
  padding:0 2px;line-height:1;flex:0 0 auto}
.tlfold:hover{color:var(--accent)}
/* no column body is tinted any more — only today. The weekend and the holidays
   are carried by the header lettering instead, which keeps the grid clean. */
.tlcell{grid-row:1;border-right:1px solid var(--line2)}
.tlcell.today{background:var(--accent-soft)}
/* header cells carry the date and its day letter, stacked and centred */
.tlrow.head{background:var(--panel);border-bottom:1px solid var(--line)}
.tlrow.head .tlcell{display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:5px 0;border-bottom:1px solid var(--line)}
.tlrow.head .tlcell b{font-size:11px;font-weight:700;line-height:1.2}
.tlrow.head .tlcell i{font-size:9px;color:var(--sub);font-style:normal;line-height:1.2}
.tlrow.head .tlcell.today b{color:var(--accent)}
/* Saturday and Sunday: the day letter is red, the date stays black.
   A national holiday takes the date with it. */
.tlrow.head .tlcell.wknd i{color:var(--dang);font-weight:700}
.tlrow.head .tlcell.hol b,.tlrow.head .tlcell.hol i{color:var(--dang);font-weight:700}
/* the strip draws a period either side of the one named above it, so a task can
   be followed across the month boundary without stepping */
.tlrow.head .tlcell.pad b,.tlrow.head .tlcell.pad i{opacity:.4}

/* ---- the bars ---- */
.tlbar{grid-row:1;z-index:2;align-self:center;margin:4px 2px;height:22px;border-radius:6px;
  display:flex;align-items:center;gap:6px;padding:0 7px;font-size:10.5px;font-weight:600;
  cursor:grab;position:relative;overflow:hidden;min-width:0;
  background:var(--accent-soft);color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 35%,transparent)}
.tlbar:active{cursor:grabbing}
.tlbar.dragging{opacity:.75;box-shadow:var(--shl);z-index:6}
/* a bar running out of the window loses the rounding on the clipped side, so it
   reads as "continues past here" instead of "ends here" */
.tlbar.cl{border-top-left-radius:0;border-bottom-left-radius:0;border-left-style:dashed}
.tlbar.cr{border-top-right-radius:0;border-bottom-right-radius:0;border-right-style:dashed}
.tlbar .tlt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
.tlbar .tla{flex:0 0 auto;display:flex}
.tlbar .tla .mini-av{width:15px;height:15px;font-size:7.5px}
/* the summary bar is filled in the project's colour for the whole of its
   duration, with the progress read as a deeper band inside it */
.tlbar.sum{height:24px;color:var(--ink);cursor:default;
  background:color-mix(in srgb,var(--pjc,var(--accent)) 10%,var(--panel));
  border-color:color-mix(in srgb,var(--pjc,var(--accent)) 50%,transparent)}
.tlbar.sum>i{position:absolute;left:0;top:0;bottom:0;background:var(--pjc,var(--accent));opacity:.3}
.tlbar.sum>span{position:relative;font-size:10px;color:var(--sub)}
/* a task bar keeps its status colour but carries the project's colour as a
   left-edge marker, so one project's work reads as one family across the strip */
.tlbar:not(.sum)::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--pjc,var(--accent))}
/* status colours, same vocabulary as the pills */
.tlbar.st-Done{background:var(--okb);color:var(--ok);border-color:color-mix(in srgb,var(--ok) 35%,transparent)}
.tlbar.st-Review{background:var(--warnb);color:var(--warn);border-color:color-mix(in srgb,var(--warn) 35%,transparent)}
.tlbar.st-Hold,.tlbar.st-Blocked{background:var(--dangb);color:var(--dang);border-color:color-mix(in srgb,var(--dang) 35%,transparent)}
.tlbar.st-Backlog,.tlbar.st-ToDo{background:var(--slateb);color:var(--slate);border-color:color-mix(in srgb,var(--slate) 35%,transparent)}
/* the grips cost no width: they sit on top of the bar's own padding */
.tlg{position:absolute;top:0;bottom:0;width:8px;cursor:ew-resize;z-index:2}
.tlg-l{left:0}.tlg-r{right:0}
.tlg:hover{background:color-mix(in srgb,var(--ink) 18%,transparent)}
/* while a bar is being dragged nothing underneath may answer the pointer */
body.tl-dragging{cursor:ew-resize;user-select:none}
body.tl-dragging .tlcell,body.tl-dragging .tlnames{pointer-events:none}
/* a spanning grid item contributes its own min-content to the tracks it covers,
   so both the bars and this note have to be allowed to shrink — otherwise one
   long label widens every column underneath it */
.tloff{grid-row:1;align-self:center;font-size:10.5px;color:var(--sub);padding-left:8px;opacity:.7;
  min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}

/* ---- project list ----
   every control on this row is the same height, so the tabs, the search box, the
   two toggles and the add button read as one strip rather than a stack of boxes */
.pjbarR{display:flex;align-items:center;gap:8px;margin-left:auto;flex:1 1 0;justify-content:flex-end;flex-wrap:wrap;
  --ctl:32px}
.pjbarR .tabs{margin:0;height:var(--ctl);padding:0 3px;align-items:center}
.pjbarR .tabs button{height:26px;display:inline-flex;align-items:center}
.pjbarR .mini-input,.pjbarR .btn{height:var(--ctl);display:inline-flex;align-items:center}
.pjq{width:180px;min-width:120px}
/* a grid column is `minmax(auto, 1fr)`, and that `auto` is the card's own
   min-content — so one long PIC name pulled its column wider than its siblings.
   With the card free to shrink, the columns stay equal and the row inside it is
   the thing that has to give way. */
.pjcard{cursor:default;min-width:0}
.pjcard .thumb{position:relative;cursor:pointer}
/* the colour the project paints on the timeline, shown where it is chosen from */
.pjbarcol{position:absolute;left:0;right:0;bottom:0;height:4px;border-radius:0 0 9px 9px}
.pjdotcol{display:inline-block;width:8px;height:8px;border-radius:3px;margin-right:7px;vertical-align:middle}
.pjhead{display:flex;align-items:flex-start;gap:6px}
.pjhead .nt{flex:1;min-width:0;cursor:pointer}
.pjhead .nt:hover{color:var(--accent)}
.pjhead .rowmenu{opacity:0;flex:0 0 auto}
.pjcard:hover .pjhead .rowmenu{opacity:1}
/* two lines of description, no more and no less, so the cards below the text all
   line up. The ellipsis itself is put on by clampText() — see the note there. */
.pjcard .nx.clamp2{flex:0 0 auto;height:36px;overflow:hidden}
/* Status, role and PIC stay on one line. The PIC is the one allowed to give way
   — its name is the longest and the least fixed — so it shrinks and ellipses
   rather than dropping the row onto two lines. */
.pjctl{display:flex;align-items:center;gap:5px;flex-wrap:nowrap;margin-top:9px;min-width:0}
/* status and role never give way — both are short, fixed vocabularies. The PIC
   is the one that shrinks and ellipses, because a person's name is the longest
   and the least predictable thing on the row. */
.pjctl{overflow:hidden;gap:4px}
.pjctl .pjpill,.pjctl .pjsel{flex:0 0 auto}
.pjctl .pjsel.pic{flex:1 1 auto;min-width:78px}
/* the row is tight by design, so the chrome around the labels is trimmed —
   every pixel saved here is a pixel of the PIC's name that stays readable */
.pjctl .pjpill{padding:2px 8px}
.pjctl .pjsel{padding:2px 6px;gap:4px}
.pjctl .pjsel .mini-av{width:15px;height:15px;font-size:7px}
.pjpill{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:2px 9px;
  border-radius:20px;white-space:nowrap;border:1px solid transparent;cursor:pointer}
.pjpill .dot{width:6px;height:6px;border-radius:50%}
/* On Going green · Report orange · Done blue — the project ladder's own colours,
   kept apart from the task pills so a "Done" project never reads as a done task */
.pst-OnGoing{background:var(--okb);color:var(--ok)}.pst-OnGoing .dot{background:var(--ok)}
.pst-Report{background:var(--warnb);color:var(--warn)}.pst-Report .dot{background:var(--warn)}
.pst-Done{background:var(--accent-soft);color:var(--accent)}.pst-Done .dot{background:var(--accent)}
/* text-overflow does not reach the direct text of a flex container, so the label
   sits in its own span — that is the box the ellipsis is drawn on */
.pjsel{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--sub);background:var(--soft);
  border:1px solid var(--line2);border-radius:6px;padding:2px 8px;cursor:pointer;white-space:nowrap;
  max-width:100%;overflow:hidden;min-width:0}
.pjsel .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.pjsel .mini-av{flex:0 0 auto}
.pjsel:hover{border-color:var(--accent);color:var(--ink)}
.pjsel.big{font-size:17px;font-weight:800;letter-spacing:-.4px;color:var(--ink);background:transparent;
  border-color:transparent;padding:0}
.pjsel.big:hover{color:var(--accent)}
.pjsel .mini-av{width:16px;height:16px;font-size:7.5px}
.pjdur{font-size:10.5px;color:var(--sub);margin-top:8px}
.pjdur .late{color:var(--dang)}
.pjcard .nf .late{color:var(--dang);font-weight:700}
/* the colour swatches inside the project dialog */
.colorpick{display:inline-flex;gap:4px;align-items:center}
.csw{width:17px;height:17px;border-radius:5px;border:2px solid transparent;cursor:pointer;padding:0}
.csw.on{border-color:var(--ink);box-shadow:0 0 0 1px var(--bg) inset}
/* list view. Eight columns × the table's usual 14px side padding costs 224px of
   the row before a single value is drawn, which is what starved the name column
   — this table pays 8px instead. */
.pjtable{table-layout:fixed}
.pjtable td,.pjtable th{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  padding-left:9px;padding-right:9px}
.pjtable td:first-child,.pjtable th:first-child{padding-left:16px}
.pjtable td .c{font-size:10.5px;color:var(--sub)}
/* a time-group heading, read the way the task lists head their weeks */
.pjtable tr.pjgrp td{background:var(--soft);font-size:9.5px;text-transform:uppercase;letter-spacing:.5px;
  color:var(--sub);font-weight:700;padding-top:7px;padding-bottom:7px}
.pjtable tr.pjgrp:hover td{background:var(--soft)}
.pjtable tr.pjgrp .c{font-weight:600;opacity:.75}
.pjtable td:first-child{cursor:pointer}
.pjtable td:first-child:hover b{color:var(--accent)}
.pjtable th.rm,.pjtable td.rm{padding-left:0;padding-right:8px;text-align:right}
.pjtable .progress-cell{min-width:0}
.pjtable td.late{color:var(--dang);font-weight:600}
.pjtable .rowmenu{opacity:0}
.pjtable tr:hover .rowmenu{opacity:1}
.kbempty{font-size:11px;color:var(--sub);padding:8px 6px;opacity:.7}
/* page search results: every hit says what it is and where it lives */
.pjhits{margin:-2px 0 2px}
.pjhit{display:flex;align-items:center;gap:10px;width:100%;text-align:left;border:0;background:transparent;
  padding:9px 4px;border-bottom:1px solid var(--line2);cursor:pointer}
.pjhit:hover{background:var(--soft)}
.pjhit .ic{flex:0 0 auto;color:var(--sub);font-size:12px}
.pjhit .tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.pjhit .tx b{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pjhit .wh{font-size:10.5px;color:var(--sub);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pjhit .mt{flex:0 0 auto;display:flex;align-items:center;gap:8px}
.pjhit .dt{font-size:10.5px;color:var(--sub);white-space:nowrap}
/* a money field is typed, so it must not carry number-spinner arrows */
.proprow input.money{text-align:left}
.pjarch{display:flex;align-items:center;gap:12px;background:var(--warnb);color:var(--warn);
  border:1px solid color-mix(in srgb,var(--warn) 30%,transparent);border-radius:var(--radius);
  padding:10px 14px;font-size:12px;margin-bottom:16px}
.pjarch .btn{margin-left:auto}

/* the Project tab's group heading is a link back to the project it names */
.grouph .grouplink{border:0;background:transparent;padding:0;font:inherit;color:inherit;
  font-weight:700;cursor:pointer}
.grouph .grouplink:hover{color:var(--accent)}
.grouph .c{margin-left:6px;font-weight:600;opacity:.7}

/* ---- project page: Card Summary + mini calendar ----
   Five boxes across, both rows. `minmax(0,1fr)` and not plain `1fr`, or the
   description and the calendar would each pull their column wider than the rest. */
.pjsum{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;margin-bottom:16px}
.pjsum .tile{display:flex;flex-direction:column;min-width:0;padding:13px 14px}
/* a fifth of the row is narrow, so these captions wrap instead of being cut —
   "37 total days · 27 days left" is the whole point of the box */
.pjsum .tile .td{white-space:normal;overflow:visible;line-height:1.5}
.pjsum .tile .td+.td{margin-top:2px}
.pjsum .tile .td .late{color:var(--dang)}
/* the three status counts under the progress bar */
.pjprog .stcount{margin-top:10px;display:flex;flex-direction:column;gap:4px}
.strow{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--sub)}
.strow span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.strow b{font-size:11px;color:var(--ink)}
.strow .dot{width:6px;height:6px;border-radius:50%;flex:0 0 auto;background:var(--sub)}
.strow .dot.st-InProgress{background:var(--accent)}
.strow .dot.st-Review{background:var(--warn)}
.strow .dot.st-Done{background:var(--ok)}
/* the caption block sits on the floor of its box, so the row reads as one band
   with the headline at the top and the detail at the bottom */
.pjsum .tile .foot{margin-top:auto}
.pjrole .td.foot{margin-top:auto;display:flex;align-items:center;gap:6px;min-width:0}
/* the description box never changes size: the text is cut to a character budget
   and the box keeps its height whether it is full or empty */
/* the title flashes when Save is pressed on an empty one */
.tk-title.needs{box-shadow:inset 0 -2px 0 var(--dang)}
.pjdesc{cursor:pointer}
.pjdesc:hover{border-color:var(--accent)}
/* a fixed five lines: the character budget keeps the text short enough to fit and
   this height guarantees it, so the box is the same size whatever is written */
.pjdesc .dv{font-size:12px;line-height:1.5;height:90px;overflow:hidden}
.pjdesc .dv .ph{color:var(--sub);opacity:.6}
.pjdesc .td{margin-top:7px;font-size:11px;color:var(--sub)}
/* Team Involved sits in row 1 as a plain box — no fold, no card header rules.
   Five names are shown and the rest is scrolled to. */
.pjteam .tl .c{margin-left:auto;font-weight:600;text-transform:none;letter-spacing:0;opacity:.75}
.pjteam .tl{display:flex;align-items:center;gap:6px}
.pjteam .avrow{margin:8px 0 2px}
/* exactly five rows — 5 × 17px plus the four 5px gaps. A max-height that is not
   a whole number of rows leaves a sliced sixth row that reads as a glitch. */
.pjteam .teamlist{max-height:105px;overflow-y:auto;padding-right:2px}
.pjteam .teamlist::-webkit-scrollbar{width:6px}
.pjteam .teamlist::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
.pjteam .teamlist{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.pjsum .tv.late{color:var(--dang)}
.pjsum .pjrole .td{display:flex;align-items:center;gap:6px;white-space:normal}
.minical{padding:11px 12px}
.mch{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;margin-bottom:6px}
.mch b{flex:1;text-align:center;font-size:11.5px}
.mcnav{border:1px solid var(--line);background:var(--bg);color:var(--sub);border-radius:6px;
  width:20px;height:20px;line-height:1;cursor:pointer;padding:0}
.mcnav:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.mcnav:disabled{opacity:.35;cursor:default}
.mcdow,.mcgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px}
.mcdow span{font-size:8.5px;color:var(--sub);text-align:center;font-weight:700}
.mcd{font-size:9.5px;text-align:center;padding:2px 0;border-radius:4px;color:var(--ink)}
.mcd.out{opacity:.28}
/* the project's own span is blocked out, with the two ends marked */
.mcd.on{background:var(--accent-soft);color:var(--accent);font-weight:700}
.mcd.a{border-top-left-radius:9px;border-bottom-left-radius:9px}
.mcd.b{border-top-right-radius:9px;border-bottom-right-radius:9px}
.mcd.now{box-shadow:inset 0 0 0 1px var(--ink)}

/* ---- project page: the Project Information row ---- */
.pjinfohead{display:flex;align-items:center;gap:9px;margin:0 0 10px;font-size:12.5px}
.pjinforow.closed .pjinfogrid{display:none}
.pjinfo{margin-bottom:0}
.pjinfo.closed>.cb{display:none}
/* trimmed from 12px: Contact Info's four fields ran a few pixels past the box
   height row 1 sets, and a scrollbar on a four-line form reads as a fault */
.pjinfo>.cb{padding:8px 14px}
.pjinfo .proprow{grid-template-columns:74px 1fr;gap:2px 10px}
.pjinfo .proprow .pk{font-size:10.5px;padding:4px 0}
.pjinfo .proprow input,.pjinfo .proprow select{padding-top:5px;padding-bottom:5px}
/* row 2 reads the way row 1 does — label on top, content underneath — instead of
   a label column beside a value column, which starved both at a fifth of the row */
.pjinfo .proprow.stack{grid-template-columns:1fr;gap:2px}
.pjinfo .proprow.stack>.pk{padding:0;font-size:9.5px;text-transform:uppercase;letter-spacing:.4px}
.pjinfo .proprow.stack>.pv{font-size:12px}
.pjinfo .proprow.stack+.proprow.stack{margin-top:9px}
/* Relation reads tighter than a form: the links sit right under their label */
.pjinfo .proprow.tight{padding:0}
.pjinfo .proprow.tight .subitem{padding:1px 0}
/* the full figure, with its rounded reading directly beneath */
.pjinfo.flat .td.big{font-size:12.5px;font-weight:700;color:var(--ink);margin-top:3px}
.pjinfo.flat .tv{font-size:17px}
/* row 2 is exactly as tall as row 1 — `--pjbox` is measured off `.pjsum` after
   every render (syncInfoRowHeight), because two separate grids cannot see each
   other's height in CSS. Anything taller than the box scrolls inside it. */
.pjinfogrid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;align-items:stretch;margin-bottom:18px}
.pjinfo{min-width:0;margin-bottom:0;display:flex;flex-direction:column;height:var(--pjbox,auto)}
/* every body scrolls rather than clips — Relation is the one that always needs
   it (seven roll-up rows), but Contact Info can run a few pixels over too, and a
   clipped field is one nobody can reach */
.pjinfo>.cb{min-height:0;overflow-y:auto;padding-right:8px}
.pjinfo>.cb::-webkit-scrollbar{width:7px}
.pjinfo>.cb::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.pjinfo>.ch .relcount{margin-left:auto;font-size:10.5px;color:var(--sub);white-space:nowrap}
.pjinfo>.ch{display:flex;align-items:baseline;gap:8px}
/* no rule under the heading — five boxes each cut in half by a line read as a
   stack of tables rather than one row of cards */
.pjinfo>.ch{border-bottom:0;padding-bottom:2px}
.pjinfo>.cb{flex:1;display:flex;flex-direction:column}
.pjinfo>.cb>.foot{margin-top:auto}
/* the two value boxes carry no fold — there is nothing in them to hide */
.pjinfo.flat .tv{font-size:19px;font-weight:800;letter-spacing:-.5px}
.pjinfo.flat .td{font-size:11px;color:var(--sub);margin-top:5px}
/* ---- PRO-CAMPAIGN V1 ----
   Desc takes the width of two cards, so the four cards of Project Description
   still fill the same five-column band the Card Summary above them sits on. */
.pjinfogrid .pjinfo.span2{grid-column:span 2}
/* Target and Achievement are written where they are read: a plain field with no
   chrome of its own, filling whatever height the row settled on */
.pjnote{flex:1;width:100%;min-height:58px;resize:none;border:0;background:transparent;color:var(--ink);
  font:inherit;font-size:12px;line-height:1.55;outline:none;padding:0}
.pjnote::placeholder{color:var(--sub);opacity:.6}
/* the campaign page has no Our Role tile, so PIC moves under Team Involved */
.pjteam .td.foot{margin-top:auto;padding-top:8px;display:flex;align-items:center;gap:6px;
  font-size:11px;color:var(--sub);white-space:normal}
/* Total Task reads like Progress: a figure, a line under it, then the counts */
.pjtotal .stcount{margin-top:10px;display:flex;flex-direction:column;gap:4px}
/* the three states Total Task counts — the ladder's other end, so they carry the
   ladder's own colours rather than the grey a dot falls back to */
.strow .dot.st-ToDo{background:var(--slate)}
.strow .dot.st-Hold,.strow .dot.st-Blocked{background:var(--dang)}
/* the creator's face sits inside a table cell and a board card, neither of which
   is a flex row — `display:grid` there would take a whole line to itself */
.sectbl .bychip,.kbcard .t .bychip{display:inline-grid;vertical-align:-4px;margin-right:5px}

/* ---- PRO-CAMPAIGN V1A — the mini calendars open ----
   A day inside a campaign's span is a button. `button.mcd` is one class and one
   element (0,1,1), so `.mcd.on` / `.mcd.out` (0,2,0) still paint over it. */
button.mcd{border:0;background:transparent;font:inherit;cursor:pointer;line-height:inherit}
button.mcd:hover{box-shadow:inset 0 0 0 1px var(--accent)}
/* a day that actually holds work carries a dot under its number */
.mcd.has{position:relative;font-weight:700}
.mcd.has::after{content:'';position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.75}
/* the page calendar is a summary card, so it wears the tile's own heading */
.procal{display:flex;flex-direction:column}
.procal .tl{margin-bottom:7px}
.procal .td.foot{margin-top:auto;padding-top:7px;font-size:10.5px;color:var(--sub)}
/* the day peek: project card → section → task rows */
.pcdproj{margin:0 0 10px}
.pcdproj>.ch{display:flex;align-items:center;gap:8px}
.pcdproj>.ch h3{min-width:0}
.pcdgo{border:0;background:transparent;padding:0;font:inherit;color:var(--ink);cursor:pointer;text-align:left}
.pcdgo:hover{color:var(--accent)}
.pcdsec+.pcdsec{border-top:1px solid var(--line2)}
.pcdsh{display:flex;align-items:center;gap:7px;padding:7px 14px 3px;font-size:9.5px;font-weight:700;
  letter-spacing:.5px;text-transform:uppercase;color:var(--sub)}
.pcdsh .c{font-size:9.5px;opacity:.7}
.pcdrow{display:flex;align-items:center;gap:9px;width:100%;text-align:left;border:0;background:transparent;
  padding:7px 14px;cursor:pointer;font:inherit;border-radius:0}
.pcdrow:hover{background:var(--soft)}
.pcdrow .tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.pcdrow .tx b{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pcdrow .tx .wh{font-size:10.5px;color:var(--sub);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pcdrow .mt{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.pcdrow .mt .dt{font-size:11px;color:var(--sub);white-space:nowrap}
.pcdrow .mt .dt.late{color:var(--dang)}
/* the tick under the date picker, and the mark it leaves on the button */
.dpcal{display:flex;align-items:center;gap:8px;margin-top:8px;padding-top:8px;
  border-top:1px solid var(--line2);font-size:11.5px;color:var(--sub);cursor:pointer}
.dpcal input{width:14px;height:14px;accent-color:var(--accent);cursor:pointer;flex:0 0 auto}
.dpbtn.on-cal{border-color:var(--accent);color:var(--accent)}

/* every person on the project, with how far their own share has been carried */
.teamlist{margin-top:9px;display:flex;flex-direction:column;gap:5px}
.tmrow{display:flex;align-items:center;gap:6px;font-size:11px;min-width:0}
.tmrow .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--sub)}
.tmrow .bar{flex:0 0 34px;height:5px;margin:0}
.tmrow b{flex:0 0 auto;font-size:10.5px;width:30px;text-align:right}
.tmrow .mini-av{width:16px;height:16px;font-size:7px;flex:0 0 auto}

/* ---- project page: the section-view tab row ---- */
.secbar2{margin-bottom:14px}
.secbar2 .tabs{margin:0}
.secbar2 .btn{margin-left:0}
.secbar2 .btn:first-of-type{margin-left:auto}
.secadd{margin:-4px 0 18px}

/* ---- Board tab: section listing on the left, status lanes on the right ---- */
.pboard{display:grid;grid-template-columns:250px minmax(0,1fr);align-items:start}
.pbside{border-right:1px solid var(--line2);padding:10px 0;max-height:calc(70 * var(--vh));overflow:auto}
.pbh{font-size:9.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--sub);font-weight:700;
  padding:0 14px 8px}
.pbgrp{margin-bottom:8px}
.pbgh{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;color:var(--sub);
  padding:5px 14px;background:var(--soft)}
.pbgh .c{margin-left:auto;font-weight:600}
.pbrow{display:flex;align-items:center;gap:8px;width:100%;text-align:left;border:0;background:transparent;
  padding:7px 14px;font-size:11.5px;cursor:pointer;border-bottom:1px solid var(--line2)}
.pbrow:hover{background:var(--soft)}
.pbrow.active{background:var(--soft);box-shadow:inset 2px 0 0 var(--accent)}
/* not `.n` — that class is the table's right-aligned numeric cell, and the
   inherited text-align pushed every task name to the right of its row */
.pbrow .pbn{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;text-align:left}
.pjkb2{padding:10px 12px}
/* a lane is 232px wide unless it is folded, and then it is the same 42px rail
   the personnel board uses — the `.kb>.kbcol.folded` rule sets that, so this one
   must not out-specify it */
.pjkb2>.kbcol:not(.folded){flex:0 0 232px}

/* ---- sections on the project page ---- */
.pjsec>.ch{gap:9px}
.pjsec.closed>.cb{display:none}
.pjsec.over{outline:2px dashed var(--accent);outline-offset:-2px}
/* a maximised section is the page: it takes the height the content area has */
.pjsec.maxed{min-height:calc(calc(100 * var(--vh)) - 210px)}
/* a section's fold is the same boxed control as every other fold on the page —
   a bare chevron reads as punctuation, not as something to click */
.secfold{font-size:11px}
.secname{cursor:text}
.secname:hover{color:var(--accent)}
.secrename{border:1px solid var(--accent);background:var(--bg);border-radius:7px;padding:3px 8px;
  font-size:13.5px;font-weight:700;min-width:180px}
.secbar{width:120px;height:6px;border-radius:6px;background:var(--soft);overflow:hidden;flex:0 0 auto}
.secbar>i{display:block;height:100%;background:var(--accent);border-radius:6px;transition:width .3s}
.secops{margin-left:auto;display:flex;gap:2px}
.secop{border:0;background:transparent;color:var(--sub);cursor:pointer;font-size:13px;line-height:1;
  padding:3px 6px;border-radius:6px}
.secop:hover{background:var(--soft);color:var(--ink)}
.secempty{font-size:11.5px;color:var(--sub);padding:14px 16px}
/* the row is scanned, not read: every column holds one line so the rows keep a
   single height and the whole section reads as a list of equal steps */
.sectbl{table-layout:fixed}
.sectbl td,.sectbl th{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sectbl tbody tr.active{background:var(--soft);box-shadow:inset 2px 0 0 var(--accent)}
.sectbl td.late{color:var(--dang);font-weight:700}
/* the "⋯" column is fixed and inside the table, so the button never rides past
   the card's own edge the way it used to */
.sectbl th.rm,.sectbl td.rm{padding-left:0;padding-right:8px;text-align:right;overflow:visible}
.sectbl .rowmenu{opacity:0}
.sectbl tr:hover .rowmenu{opacity:1}
/* Owner, Output, Status and Due all write from the row itself */
.sectbl td.cell{cursor:pointer;border-radius:6px}
.sectbl td.cell:hover{box-shadow:inset 0 0 0 1px var(--line)}
.sectbl td.out .lnk{color:var(--accent)}
.sectbl .cellph{color:var(--sub);opacity:.6;font-size:11px}
.cellinput{width:100%;border:1px solid var(--accent);background:var(--bg);border-radius:6px;
  padding:3px 6px;font-size:11.5px}
/* the drag handle is the only place a row drag starts — clicking the row itself
   still opens the Task Peek, which is what the row is for */
.sechandle{color:var(--sub);opacity:0;cursor:grab;margin-right:7px;font-size:11px;user-select:none;
  display:inline-block;width:11px}
.sectbl tr:hover .sechandle{opacity:.65}
.sechandle:active{cursor:grabbing}
.secghost{position:fixed;z-index:200;pointer-events:none;background:var(--panel);border:1px solid var(--accent);
  border-radius:8px;padding:6px 11px;font-size:11.5px;font-weight:600;box-shadow:var(--shl);max-width:260px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* five across needs room; below this the project page folds to three, then two */
@media (max-width:1188px){
  .pjsum,.pjinfogrid{grid-template-columns:repeat(3,minmax(0,1fr))}
}
/* both rows still fit at a 1142px viewport with the sidebar open — measured, not
   guessed — so they only hand back to a stacked layout below 1024 */
@media (max-width:922px){
  .tltoolbar .tlwhen{flex:1 1 auto;width:auto;text-align:left}
  .tltoolbar .tabs{margin-left:0}
  .pjbarR{width:100%;justify-content:flex-start}
  .pjq{width:100%}
  .tlsplit{--tlname:150px}
  .pjsum,.pjinfogrid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .pboard{grid-template-columns:1fr}
  .pbside{border-right:0;border-bottom:1px solid var(--line2);max-height:230px}
}

/* ---------- TOAST ---------- */
.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--ink);
  color:var(--bg);padding:9px 16px;border-radius:9px;font-size:12.5px;opacity:0;transition:.2s;z-index:120;box-shadow:var(--shl)}
.toast.on{opacity:1;transform:translateX(-50%) translateY(0)}

/* tooltip on hover title */
[data-tip]{position:relative}
[data-tip]:hover::after{content:attr(data-tip);position:absolute;left:0;top:calc(100% + 7px);background:var(--ink);
  color:var(--bg);font-size:11px;font-weight:500;line-height:1.5;padding:7px 10px;border-radius:8px;white-space:normal;
  width:max-content;max-width:420px;z-index:100;box-shadow:var(--shl);letter-spacing:0}

/* ============================================================
   PRODUCT CATALOGUE (V4 PRODUCT CAT V1A)
   Three tabs over one database. Product is the shop window: a summary, then a
   cover per family, per campaign bundle and per media owner — each cover opens
   its own page of cards. Inventory is the same records as a working list, and
   Bundle is where a bundle is assembled. All three share the card, so a product
   looks the same wherever it is read.
   ============================================================ */
.pctools{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;margin:12px 0 6px}
.pctools .srch{flex:0 0 240px}
.pctools .segs,.pctools .pcview{margin-left:auto}
.pctools .tabs{margin:0}
.pctools .btn.primary.sm{white-space:nowrap}
/* the view switch and + Add Product travel together and sit on the right edge
   of the content box at every width — wrapped onto a second line they stay
   right-aligned rather than falling back to the left */
.pctools .pcright{display:flex;align-items:center;gap:8px;margin-left:auto;flex:0 0 auto}
.pctools .pcright .pcview{margin-left:0}

/* ---- the Asset Product summary ---- */
.pcsum{margin-top:12px}
/* two of the five tiles are a small table rather than one number */
.tile.pctilelist{display:flex;flex-direction:column}
.pctlrows{margin-top:7px;display:flex;flex-direction:column;gap:3px}
.pctlrow{display:flex;align-items:baseline;gap:8px;font-size:11px;color:var(--sub);white-space:nowrap}
.pctlrow .k{flex:0 0 62px;color:var(--ink);font-weight:600}
.pctlrow .v{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
.pctlrow .v b{color:var(--ink)}
.pctlrow .p{flex:0 0 auto;font-variant-numeric:tabular-nums}

/* ---- section bar: the heading, with its own control trailing right ---- */
.pcsecbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:18px}
.pcsecbar .grouph.pcsec{margin:0}
.pcsecbar .tabs,.pcsecbar .fbtn{margin:0 0 0 auto}
.pcmot{flex-wrap:wrap;max-width:100%}
.pcempty{border:1px dashed var(--line);border-radius:var(--radius);padding:26px 16px;text-align:center;
  color:var(--sub);font-size:12px;margin-top:10px}

/* ---- the cover card: one photo standing for everything inside it ---- */
/* §83 — the title reads **under** the picture, not on top of it. Laid over a
   photograph it was legible on a dark videotron at dusk and unreadable on a
   bundle cover made of a bright screenshot — and the "⋯" had to share the corner
   with it. The picture keeps its own band, the words get a solid one, and both
   are the same on every cover. */
.pccover{position:relative;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
  cursor:pointer;background:var(--panel);display:flex;flex-direction:column;align-items:stretch;margin-top:10px}
.pccover:hover{border-color:var(--accent)}
.pcvimg{position:relative;flex:0 0 auto;height:152px;background:var(--soft)}
.pcvimg img{width:100%;height:100%;object-fit:cover;display:block}
.pcvbody{position:relative;flex:1;padding:12px 14px;width:100%;color:var(--ink)}
.pcvt{font-size:16px;font-weight:800;letter-spacing:-.3px}
.pcvx{font-size:11.5px;color:var(--sub);margin-top:3px}
.pcvtags{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
.pcvtags .tag{background:var(--soft);border-color:var(--line2);color:var(--sub)}
/* the menu sits on the picture, where nothing else is now */
.pcvmenu{position:absolute;top:8px;right:8px;z-index:2;background:rgba(255,255,255,.92);
  border:1px solid var(--line);border-radius:8px;width:26px;height:26px;line-height:1}
.pcvmenu:hover{background:#fff}
.pccover.nophoto .pcvmenu{background:var(--panel)}

/* ---- the page a cover opens ---- */
.pccrumb{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--sub);margin:12px 0 2px}
.pccrumb b{color:var(--ink)}
.pcback{border:0;background:transparent;color:var(--accent);font-size:12px;font-weight:600;
  padding:2px 0;cursor:pointer}
.pcback:hover{text-decoration:underline}

/* ---- the filters, as dropdowns sitting on the search row ----
   A set filter reads its own value, so the row states what is being looked at;
   each button is capped so five of them plus the search box still fit one line */
.pctools .pcfd{max-width:170px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:0 1 auto}
.pctools .pcfd.on{color:var(--ink);border-color:var(--ink);font-weight:700}
.pctools .pcfclr{color:var(--accent);flex:0 0 auto}
.pctools .pcfclr:hover{color:var(--accent);border-color:var(--accent)}
.grouph.pcsec{display:flex;align-items:baseline;gap:8px;font-size:13.5px;margin-top:18px}
.grouph.pcsec .c,.pcfam .c,.pcsub .c{color:var(--sub);font-weight:500;font-size:11.5px}
/* ---- product cat v1b: the two Quota Config channels ----
   A tier or price row belonging to a channel the record is not sold through is
   greyed rather than hidden: the reader has to see that the field exists and
   what would switch it on, which is the tick above it. */
.pcform .proprow.off>.pk{opacity:.42}
.pcform .proprow.off select,.pcform .proprow.off input{opacity:.45;cursor:not-allowed;background:var(--soft)}
.hint.pcqthint{margin:2px 0 6px}
/* Active, then the channels it is active on — one row, and a channel the point
   is not sold through is greyed rather than hidden, the same as its tier */
.pcform .pcacts{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.pcform .pcacts .pcck{gap:6px;white-space:nowrap}
.pcform .pcacts .pcck.off{opacity:.42}
.pcform .pcacts .pcck.off input{cursor:not-allowed}
/* the drill page's Quota Type: two buttons, not a dropdown — pressed reads as
   the ink pill the tab rows use, so "which channel am I looking at" is visible
   without opening anything */
.pctools .pcqb{flex:0 0 auto}
.pctools .pcqb.on{background:var(--ink);color:var(--bg);border-color:var(--ink);font-weight:700}
.pctools .pcqb.on:hover{background:var(--ink);color:var(--bg)}
.pcform #pcSubNew{width:100%}
/* two channels, two prices: the Inventory list names each one above its figure */
.pctable .pcpz{display:flex;align-items:baseline;justify-content:flex-end;gap:8px;white-space:nowrap}
.pctable .pcpz span{font-size:10.5px;color:var(--sub);font-weight:600}
.pctable .pcpz+.pcpz{margin-top:2px}
.pctable .lname .tag{margin-left:6px}
/* stacked price lines on the sheet share one rule above them */
.pcshprice+.pcshprice{border-top:0;padding-top:2px;margin-top:0}
.pcshprice+.pcshprice b{font-size:16px}
.pcfam{display:flex;align-items:baseline;gap:8px;font-weight:700;font-size:12.5px;color:var(--ink);
  margin:12px 0 2px;padding-left:2px}
.pcsub{display:flex;align-items:baseline;gap:8px;font-size:11.5px;color:var(--sub);
  text-transform:uppercase;letter-spacing:.04em;margin:10px 0 6px;padding-left:2px}

.pcard{padding:0;overflow:hidden;cursor:pointer;display:flex;flex-direction:column}
/* accent = picked for export; ink = the record the peek is showing right now.
   Two different questions, so two different colours. */
.pcard.picked{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
.pcard.open,.pccover.open{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink) inset}
.pcard.open .pcthumb::after,.pccover.open::after{content:'';position:absolute;left:0;right:0;top:0;
  height:3px;background:var(--ink);z-index:2}
.pccover.open::after{border-radius:var(--radius) var(--radius) 0 0}
/* a word, not only a colour — the badge names the state the ring is showing.
   It is always in the markup so the marker can be moved without a redraw. */
.pcopenpill{display:none;position:absolute;bottom:8px;left:8px;font-size:10px;font-weight:700;
  padding:3px 8px;border-radius:999px;background:var(--ink);color:var(--bg);letter-spacing:.02em;z-index:2}
.pcard.open .pcopenpill,.pccover.open .pcopenpill{display:block}
/* on a cover the bottom-left corner belongs to the caption, so it sits up top */
.pccover .pcopenpill{bottom:auto;top:11px;left:12px}
.pcard>.nh,.pcard>.nx,.pcard>.pcind,.pcard>.nf{padding-left:12px;padding-right:12px}
.pcard>.nh{margin-top:10px}
.pcard>.nf{padding-bottom:12px;margin-top:auto}
.pcthumb{position:relative;aspect-ratio:16/10;background:var(--soft);overflow:hidden}
.pcthumb img{width:100%;height:100%;object-fit:cover;display:block}
.pcpick{position:absolute;top:8px;left:8px;width:22px;height:22px;border-radius:6px;background:var(--panel);
  border:1px solid var(--line);display:grid;place-items:center;box-shadow:var(--sh);cursor:pointer}
.pcpick input{width:14px;height:14px;accent-color:var(--accent);cursor:pointer}
.pctier{position:absolute;top:8px;right:8px;font-size:10px;font-weight:700;letter-spacing:.03em;
  padding:3px 8px;border-radius:999px;background:var(--panel);border:1px solid var(--line);color:var(--sub)}
.pctier.tier-growth{color:var(--teal);border-color:var(--teal)}
.pctier.tier-premium{color:var(--gold);border-color:var(--gold)}
/* the placement levels wear the same badge as the project tiers — a card shows
   whichever channel names one first, so both sets need a colour */
.pctier.tier-silver{color:var(--slate);border-color:var(--slate)}
.pctier.tier-gold{color:var(--gold);border-color:var(--gold)}
.pctier.tier-crystal{color:var(--violet);border-color:var(--violet)}
.pcpub{position:absolute;bottom:8px;left:8px;font-size:10px;font-weight:700;padding:3px 8px;border-radius:999px;
  background:var(--okb);color:var(--ok)}
.pcpub.off{background:var(--soft);color:var(--sub)}
.pcind{display:flex;flex-wrap:wrap;gap:5px;margin:6px 0 8px}
.pcind .tag.ok{background:var(--okb);color:var(--ok)}
/* these carry the table class as well: the generic .pltable .c-val / .c-menu
   widths are declared further down the sheet and would otherwise win the tie */
.pltable.pctable .c-kind{width:92px}.pltable.pctable .c-mo{width:15%}.pltable.pctable .c-area{width:20%}
/* wide enough for the two named channel prices, which is the widest this cell
   ever gets: "Placement  Rp 12.900.000" on its own line */
.pltable.pctable .c-val{width:168px}.pltable.pctable .c-when{width:96px}.pltable.pctable .c-menu{width:44px}
.pltable.pcbtab .c-qty{width:74px}.pltable.pcbtab .c-val{width:120px}.pltable.pcbtab .c-menu{width:40px}
.pltable.pcbtab td:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pltable.pcbtab td.mid .btn{padding:2px 6px;min-width:0}
.pltable.pcbltable .c-sec{width:16%}.pltable.pcbltable .c-mo{width:14%}.pltable.pcbltable .c-n{width:74px}
.pltable.pcbltable .c-val{width:135px}.pltable.pcbltable .c-st{width:86px}.pltable.pcbltable .c-menu{width:44px}

/* the editor is a centre popover, so its form scrolls inside the panel */
.pcform{margin-top:10px}
.pcform select,.pcform input:not([type=checkbox]){width:100%}
/* a property whose value is chosen in a picker, not typed */
.pcpickbtn{width:100%;text-align:left;border:1px solid transparent;border-radius:7px;background:transparent;
  padding:5px 7px;font-size:12.5px;color:var(--ink);cursor:pointer;min-height:28px}
.pcpickbtn:hover{background:var(--soft)}
.pcpickbtn.ph{color:var(--sub);font-style:italic}
.pcck{display:flex;align-items:center;gap:8px;padding:5px 7px;cursor:pointer;font-size:12px;color:var(--sub)}
.pcck input{width:14px;height:14px;accent-color:var(--accent);cursor:pointer;flex:0 0 auto}
/* start → end on one line, with the day count reading as the answer beside it */
.pcform .pbdates{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.pcform .pbdates input{flex:0 1 138px;width:auto;min-width:0}
.pcform .pbdates i{color:var(--sub);font-style:normal;flex:0 0 auto}
.pbdays{flex:0 0 auto;font-size:11.5px;font-weight:700;color:var(--ink);white-space:nowrap;padding-left:2px}
/* the bundle card's crossed-out normal price beside its bundle price */
.pcard .pcblnorm{font-size:11.5px;color:var(--sub);text-decoration:line-through}
/* the picker that can create what it cannot find */
.pickpop.pcnewpick{width:280px;min-width:280px}
.pcnewfoot:empty{display:none}
.pcnores{font-size:11.5px;color:var(--sub);text-transform:uppercase;letter-spacing:.5px;padding:6px 8px 2px}
.pcnewbtn{display:block;width:100%;text-align:left;border:0;background:transparent;color:var(--accent);
  font-size:12.5px;font-weight:600;padding:6px 8px;border-top:1px solid var(--line2);border-radius:0;cursor:pointer}
.pcnewbtn:hover{background:var(--soft)}
.pcbmode{display:flex;gap:8px;align-items:center}
.pcbmode select{flex:0 0 150px}
.qtotbox{margin-top:10px;border-top:1px solid var(--line);padding-top:8px}
.qtotbox .qrow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 0;font-size:12.5px}
.qtotbox .qrow.grand{border-top:1px solid var(--line);margin-top:4px;padding-top:9px;font-size:14px;font-weight:800}
.qtotbox .minus{color:var(--dang)}
.pickpop .ph2i{display:block;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--sub);padding:2px 0}

/* the export sheet — the same block on screen, on paper and inside the JPEG */
.pcsheet{background:var(--panel);color:var(--ink);font-size:13px;line-height:1.55}
.pcsh{display:flex;align-items:center;gap:10px;border-bottom:2px solid var(--accent);padding-bottom:10px;margin-bottom:14px}
.pcshlogo{height:26px;width:auto}
.pcshkind{margin-left:auto;font-size:11px;color:var(--sub);text-transform:uppercase;letter-spacing:.04em}
.pcshname{font-size:22px;font-weight:800;line-height:1.25;margin:0 0 2px}
.pcshsub{color:var(--sub);font-size:12.5px;margin-bottom:12px}
.pcshimg{width:100%;height:220px;border-radius:12px;overflow:hidden;background:var(--soft);margin-bottom:12px}
.pcshimg img{width:100%;height:100%;object-fit:cover;display:block}
.pcshnar{font-size:12.5px;line-height:1.7;color:var(--sub);margin:0 0 12px}
.pcshtab{width:100%;border-collapse:collapse;margin-bottom:12px}
.pcshtab td{padding:5px 0;border-bottom:1px solid var(--line2);font-size:12.5px;vertical-align:top}
.pcshtab td:first-child{width:150px;color:var(--sub)}
.pcshtab td.r{text-align:right;white-space:nowrap}
.pcshtab.bundle td:first-child{width:auto;color:var(--ink)}
.pcshtab tr.grand td{font-weight:800;font-size:14px;border-bottom:0;padding-top:8px}
.pcshprice{display:flex;align-items:baseline;justify-content:space-between;border-top:2px solid var(--ink);
  padding-top:10px;margin-top:4px}
.pcshprice span{color:var(--sub);font-size:12.5px}
.pcshprice b{font-size:20px;font-weight:800}
.pcshlink{font-size:11.5px;color:var(--accent);margin-top:8px;word-break:break-all}
.pcshfoot{margin-top:14px;padding-top:10px;border-top:1px solid var(--line2);font-size:10px;color:var(--sub)}
@media(max-width:1152px){
  /* every right-hand control now travels inside .pcright, which keeps its auto
     margin: the row wraps but the cluster stays together and stays right */
  .pctools{flex-wrap:wrap}.pctools .srch{flex:0 1 200px}
}
@media(max-width:990px){.tiles.t5{grid-template-columns:repeat(3,1fr)}}

/* ---------- PRINT (meeting notes → PDF A4) ---------- */
@media print{
  @page{size:A4;margin:1cm}
  /* §88 — the sheet is a sheet: the screen's comfort has nothing to do with paper, and
     leaving it on shrank every export by a fifth */
  :root{--ui-zoom:1}
  body{background:#fff;color:#000;zoom:1}
  .app,.peek,.scrim,.toast,.modal-h,.modal-f{display:none !important}
  .print-area{display:block !important;position:static;padding:0;font-size:11pt}
  .print-area .kop{display:flex;align-items:center;gap:12px;border-bottom:2px solid #000;padding-bottom:10px;margin-bottom:16px}
  .print-area .kop img{width:34px;height:34px}
  .print-area table{border-collapse:collapse;width:100%}
  .print-area td,.print-area th{border:1px solid #999;padding:6px 8px;vertical-align:top}
  /* The Sales Kit proposal prints from here too, and it rules its own table:
     one hairline **under** each row and nothing else. The rule above sets the
     `border` shorthand, so the kit's `border-bottom` won on specificity while
     top/left/right had no competitor and drew a grid the proposal never had.
     Those three sides are taken back off; the kit keeps the bottom. */
  .print-area #proposal td,.print-area #proposal th{border-top:0;border-left:0;border-right:0}
  .print-area #proposal table{border:0}
  /* A Sales quote prints the same letter (see quoteDocHTML) and wants the same
     restraint: one hairline under each row, none of the grid the sheet's own
     `border` shorthand would draw on the three sides nobody claimed. On paper
     it is the page itself, so the card it wears in the panel comes off. */
  .print-area .kprop{border:0;border-radius:0;padding:0;margin:0;max-width:760px;font-size:12.5px}
  .print-area .kprop td,.print-area .kprop th{border-top:0;border-left:0;border-right:0}
  .print-area .kprop table,.print-area .kprop .pto td{border:0}
  .print-area .kprop th,.print-area .kprop td{padding:7px 9px;font-size:12px}
  /* PROPOSAL-1: the letter draws its own tables — the Nomor block and the
     guideline spec have no rules at all, and the offer keeps the quote's single
     hairline. The sheet's `border` shorthand would put a grid through all of
     them, so it is taken back off here as well. */
  .print-area .a4doc td,.print-area .a4doc th{border:0;padding:0}
  /* …and the Meeting Notes sheet wants its grid back, at a specificity that
     beats the `.print-area .a4doc td` rule above rather than relying on which
     of two equal selectors came last (§74). What is measured off-screen and what
     is printed must be the same box. */
  .print-area .a4doc.mtsheet .mtn th,.print-area .a4doc.mtsheet .mtn td{border:1px solid #111}
  .print-area .a4doc.mtsheet .mtn th{padding:5px 7px}
  .print-area .a4doc.mtsheet .mtn td{padding:6px 7px}
  .print-area .a4doc.mtsheet .mtinfo2 td{border:0;border-bottom:1px solid #dcdcdc;padding:5px 10px 5px 0}
  .print-area .a4doc.mtsheet .mtinfo2 tr:last-child td{border-bottom:0}
  .print-area .a4quote th,.print-area .a4quote td{border-bottom:1px solid #ddd;padding:7px 9px}
  .print-area .a4quote .pto td,.print-area .a4quote table{border:0}
  .print-area .a4page{padding:0;margin:0}
  /* PRODUCT-CAT: the product sheet draws its own rules, so the sheet's generic
     `border` shorthand is taken off it the same way it is off the letter */
  .print-area .pcdoc td,.print-area .pcdoc th{border:0;padding:0}
  .print-area .pcsheet{background:#fff;color:#111}
  .print-area .pcshtab td{border-bottom:1px solid #eee;padding:5px 0}
  .print-area .pcshtab tr.grand td{border-bottom:0;padding-top:8px}
  .print-area .pcshimg{height:8cm}
}
.print-area{display:none}

/* ---------- RESPONSIVE / PWA ---------- */
.side-scrim{position:fixed;inset:0;background:rgba(16,24,40,.35);opacity:0;pointer-events:none;transition:opacity .2s;z-index:44}
.side-scrim.on{opacity:1;pointer-events:auto}
.mobile-only{display:none}
@media(max-width:828px){
  .app{grid-template-columns:1fr}
  .side{position:fixed;top:0;left:0;height:calc(100 * var(--vh));width:286px;max-width:calc(86 * var(--vw));z-index:46;transform:translateX(-100%);
    transition:transform .22s ease;box-shadow:2px 0 26px rgba(16,24,40,.16)}
  .side.open{transform:none;opacity:1;pointer-events:auto}
  /* mobile is drawer-only: neutralise every desktop rail rule */
  .app.side-collapsed .side,
  .app.side-collapsed .side:hover{width:286px;max-width:calc(86 * var(--vw));opacity:1;box-shadow:2px 0 26px rgba(16,24,40,.16)}
  .app.side-collapsed .side .lbl,
  .app.side-collapsed .side .gh,
  .app.side-collapsed .side .brand-txt,
  .app.side-collapsed .side .side-foot,
  .app.side-collapsed .side .chev,
  .app.side-collapsed .side .badge,
  .app.side-collapsed .side .side-collapse{opacity:1;pointer-events:auto}
  .app.side-collapsed .side .grp>.gh{height:auto;padding:4px 10px}
  .app.side-collapsed .side .divgrp.open .subitems{display:block}
  .side-open-btn{display:inline-flex}
  .side-collapse{display:none}
  .topbar{padding:0 12px;gap:8px}
  .content{padding:16px 13px 84px}
  .tiles,.tiles.t3,.tiles.t5{grid-template-columns:repeat(2,1fr);gap:11px}
  .grid2,.grid3,.grid4{grid-template-columns:1fr}
  .card>.cb.flush{overflow-x:auto}
  .card>.cb.flush table{min-width:600px}
  .cal{min-width:640px}
  .card>.cb:has(.cal){overflow-x:auto}
  .user .ur{display:none}
  .ph h1{font-size:19px}
  .peek.side,.peek.center{width:calc(100 * var(--vw));max-width:calc(100 * var(--vw));height:calc(100 * var(--vh));top:0;left:0;border-radius:0;transform:translateY(100%)}
  .peek.on{transform:none}
  .peek-grip{display:none}
  .modal{inset:0;border-radius:0}
  .modal.min{inset:auto 0 0 auto;width:100%;height:44px}
  .kv{grid-template-columns:110px 1fr}
  .proprow{grid-template-columns:110px 1fr}
  .mobile-only{display:block}
  .desk-only{display:none}
  .peek-b{padding:16px 16px 26px}
}
@media(max-width:504px){
  .user .un{display:none}
  .user{padding-left:0;border-left:0}
  .tiles,.tiles.t3,.tiles.t5{grid-template-columns:repeat(2,1fr)}
  .tile .tv{font-size:21px}
  .fnl .fl{width:112px;font-size:11px}
  .fnl .fv{width:82px}
}

/* ============ MEETING LOG (MEETING-1) ============
   The page borrows Project Space's furniture — tiles, toolbar row, card grid,
   grouped table — so only what is genuinely new is written here. */

/* ---- summary tiles that carry a listing ---- */
.tile.mttile{display:flex;flex-direction:column}
.tile.mttile .tv{margin-bottom:2px}
.mtrows{display:flex;flex-direction:column;gap:3px;margin-top:6px}
.mtrow{display:flex;align-items:center;gap:7px;border:0;background:transparent;padding:2px 5px;
  border-radius:6px;font-size:11px;color:var(--ink);cursor:pointer;text-align:left}
.mtrow:hover{background:var(--soft)}
.mtrow.on{background:var(--accent-soft);color:var(--accent);font-weight:700}
.mtrow span{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mtrow b{font-weight:800}
.mtfoot{margin-top:auto;padding-top:6px;font-size:10.5px;color:var(--sub)}
.tile.mttile[role=button]{cursor:pointer}
.tile.mttile[role=button]:hover{border-color:var(--accent)}
.tile.mttile.on{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
/* the meeting categories and the status ladder each get their own dot colour */
.mty-Coordination{background:#2f6bed}.mty-Project{background:#7a4fd1}.mty-Task{background:#0d9488}
.mty-Client{background:#c77a18}.mty-Partnership{background:#64748b}
.cdot.mst-Regular{background:#64748b}.cdot.mst-Weekly{background:#2f6bed}
.cdot.mst-Performance{background:#0d9488}.cdot.mst-Important{background:#c77a18}
.cdot.mst-Urgent{background:#dc2626}
.mst-Regular{background:var(--soft);color:var(--sub)}.mst-Regular .dot{background:var(--sub)}
.mst-Weekly{background:var(--accent-soft);color:var(--accent)}.mst-Weekly .dot{background:var(--accent)}
.mst-Performance{background:var(--okb);color:var(--ok)}.mst-Performance .dot{background:var(--ok)}
.mst-Important{background:var(--warnb);color:var(--warn)}.mst-Important .dot{background:var(--warn)}
.mst-Urgent{background:var(--dangb);color:var(--dang)}.mst-Urgent .dot{background:var(--dang)}

/* ---- the mini calendar box ---- */
.mtcal{padding-bottom:10px}
.mtcal .mini{margin-top:4px}
.mtcal .md{position:relative;padding-bottom:6px}
.md .mdot{position:absolute;left:50%;bottom:2px;transform:translateX(-50%);width:4px;height:4px;
  border-radius:50%;background:var(--accent)}
.md.today .mdot{background:#fff}
.md.has{font-weight:800}
.mtcal .md.insel{background:var(--accent-soft);border-radius:6px}

/* ---- the filter bar under the toolbar ---- */
.mtfbar{display:flex;align-items:center;gap:7px;padding:0 16px 10px;flex-wrap:wrap}
.mtfchip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--accent);
  background:var(--accent-soft);color:var(--accent);border-radius:20px;padding:3px 10px;
  font-size:11px;font-weight:700;cursor:pointer}
.mtfchip i{font-style:normal;opacity:.7}
.mtfchip:hover i{opacity:1}
.mtfclear{border:0;background:transparent;color:var(--sub);font-size:11px;cursor:pointer;text-decoration:underline}

/* ---- card ---- */
.mtcard{min-width:0}
.mtcard .pjhead{display:flex;align-items:flex-start;gap:4px}
/* the "⋯" is hidden until the card is hovered, the way the project card hides
   it — it is `.pjcard:hover` that reveals it there, so this card needs its own */
.mtcard:hover .pjhead .rowmenu{opacity:1}
.mtcard .nt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}
.mtby{margin:0 0 7px;color:var(--sub)}
.mtline{display:flex;align-items:center;gap:7px;font-size:11.5px;margin-top:7px;flex-wrap:wrap}
.mtline .sep{color:var(--sub)}
.mtline.sub{color:var(--sub);font-size:11px;margin-top:5px}
.mtstar{border:0;background:transparent;color:var(--line);font-size:14px;cursor:pointer;line-height:1;padding:2px}
.mtstar:hover{color:var(--warn)}
.mtstar.on{color:var(--warn)}

/* ---- list / status table ---- */
.mttable td .tag{margin-right:4px}
.mttable .c{color:var(--sub);font-weight:500;font-size:11px}

/* ---- the minimised panels ----
   Fixed to the window, not to a page: a minimised meeting or note is still
   there wherever the reader goes next. */
.mindock{position:fixed;right:22px;bottom:0;z-index:54;display:none;align-items:flex-end;gap:8px;
  max-width:min(calc(96 * var(--vw)),900px)}
.mindock.on{display:flex}
.mindock-i{display:flex;align-items:center;gap:9px;cursor:pointer;
  background:var(--panel);border:1px solid var(--line);border-bottom:0;border-radius:10px 10px 0 0;
  padding:8px 10px 8px 12px;box-shadow:var(--shl);font-size:12px;max-width:320px}
.mindock-i:hover{border-color:var(--accent)}
.mindock-i b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mindock-i .ic{color:var(--sub);flex:0 0 auto}
.mindock-i .c{color:var(--sub);font-size:11px;white-space:nowrap;flex:0 0 auto}
.mindock-i .icobtn{flex:0 0 auto}
@media(max-width:648px){ .mindock{right:0;left:0;justify-content:center} }

/* ---- the meeting page ---- */
.ph.mtph{display:flex;align-items:center;gap:10px}
.ph.mtph h1{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ph.mtph .ph-right{display:flex;align-items:center;gap:8px}
.mtpage .tk-meta{display:flex;align-items:center;gap:8px}
/* two boxes side by side: what the PDF carries, and what this meeting links to.
   Information is the wider of the two — its values are typed, the roll-up's are
   picked. Both hold the same row: label left, value right, one height. */
.mtcols{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:16px;margin-top:16px}
/* both open, the boxes share one height; fold either and each takes its own —
   a stretched box with nothing in it is a tall empty rectangle */
.mtcols.ragged{align-items:start}
.mtbox>.ch .bigfold{flex:0 0 auto}
.mtbox>.cb.hide{display:none}
.mtbox>.ch:has(+.cb.hide){border-bottom:0}
.mtbox{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);min-width:0}
.mtbox>.ch{display:flex;align-items:baseline;gap:9px;padding:11px 14px 9px;border-bottom:1px solid var(--line2)}
/* the heading never wraps — the hint beside it is what gives way */
.mtbox>.ch h3{font-size:12.5px;font-weight:700;white-space:nowrap;flex:0 0 auto}
.mtbox>.ch .sub{font-size:10.5px;color:var(--sub);flex:1 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mtbox>.cb{padding:8px 14px 12px}
.mtbox .proprow{grid-template-columns:118px 1fr;gap:4px 10px;min-height:32px}
/* a rule above the two rows that are about the document, not the meeting */
.mtbox .proprow.sep{border-top:1px solid var(--line2);margin-top:6px;padding-top:6px}
.pv.pvrow{display:flex;align-items:center;gap:9px;min-width:0}
.pv.pvrow select{flex:0 0 auto;width:auto;min-width:96px}
.mthint{font-size:10.5px;color:var(--sub);white-space:nowrap}
.mtarch{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--sub);cursor:pointer;padding:6px 0}
.mtarch input{width:15px;height:15px;accent-color:var(--accent);flex:0 0 auto}
.mtminutes{margin-top:18px}
.mtminutes .ch{display:flex;align-items:center;padding:0 0 8px}
.mtminutes .ch h3{font-size:13px}
.mtminutes table{width:100%;border-collapse:collapse;font-size:12px}
.mtminutes th{text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.03em;color:var(--sub);
  font-weight:700;padding:6px 8px;border-bottom:1px solid var(--line)}
.mtminutes td{border:1px solid var(--line2);padding:7px 8px;vertical-align:top}
.mtminutes td[contenteditable]:focus{outline:2px solid var(--accent);outline-offset:-2px;background:var(--soft)}
.mtminutes td.rn{width:36px;text-align:center;color:var(--sub);font-weight:700}
.mtminutes td.rm{width:36px;text-align:center}
.mtminutes td.hit{background:var(--accent-soft)}
.mtminutes .addrow{margin-top:8px}
@media(max-width:990px){ .mtcols{grid-template-columns:1fr} }

/* ---- export PDF ---- */
@media print{
  .mindock{display:none !important}
  /* §74 — `.mtinfo` / `.mtmin` / `.mtfootline` retired with the old sheet; the
     Meeting Notes export draws on the proposal's a4 shell now. */
}

/* ---- Meeting Log: the Card Summary folds, and the whole card is the Open ---- */
.sumhead{display:flex;align-items:center;gap:9px;margin:0 0 10px}
.sumhead h3{font-size:13px;font-weight:700}
.sumhead .sub{font-size:11.5px;color:var(--sub)}
.tiles.hide{display:none}
.mtcard{cursor:pointer}
.mtcard:hover{border-color:var(--accent)}
/* the controls that live on the card keep their own cursor and their own click */
.mtcard .mtstar,.mtcard .rowmenu,.mtcard .pjpill,.mtcard .pjsel{cursor:pointer}
.mttable tbody tr[data-gomtg]{cursor:pointer}
.mtline .pjpill,.mtline .pjsel{flex:0 0 auto}

/* ---- Quota Config hosts the Sales Kit (V4 MERGE QUOTA) ----
   The kit brings its own header, drawer and footer nav; the workspace supplies
   navigation, so those are hidden and the page keeps only the kit's content. */
/* sales-kit.css is loaded after this file, so every override here has to
   out-specify it — `#skRoot.skhost` beats the generated `#skRoot`. */
/* the gap under the tab row needs the id too — the kit's own `#skRoot{margin:0}`
   (from its `html,body` rule) outranks a class on its own */
/* no panel behind the kit: the page background carries it, the way the Media
   Dashboard's tabs sit straight on the page */
#skRoot.skhost{background:transparent;margin-top:16px}
#skRoot.skhost .nav,#skRoot.skhost .drawer,#skRoot.skhost .footnav{display:none}
#skRoot.skhost .wrap{max-width:none;padding:0}
#skRoot.skhost section.view{padding:0}
/* the page already names itself and carries its own tabs — the kit's eyebrow,
   heading and standfirst say it a second time */
#skRoot.skhost .sechead{display:none}
/* the workspace's typeface everywhere inside the kit, including the controls
   and the headings the kit sizes itself */
#skRoot.skhost{--font:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif}
#skRoot.skhost,#skRoot.skhost button,#skRoot.skhost input,#skRoot.skhost select,
#skRoot.skhost textarea,#skRoot.skhost h1,#skRoot.skhost h2,#skRoot.skhost h3,
#skRoot.skhost h4,#skRoot.skhost .btn{font-family:var(--font)}
/* ---- §85 — the kit reads at the workspace's size ----
   The typeface was already shared (`--font` above). The **scale** was not: the kit
   was drawn as a standalone sales page and sets 15px controls, 15px card titles
   and 34px figures, against a workspace whose body is 13px, whose labels are 11.5
   and whose buttons are 12. Four tabs therefore looked like a different product
   from the two next to them.

   Sizes only — no spacing, no weights, no colours. Every rule is `#skRoot.skhost`,
   so the kit's own standalone build is untouched, and every one names the same
   figure the workspace uses for the same kind of thing. */
#skRoot.skhost{font-size:13px}
#skRoot.skhost input,#skRoot.skhost select,#skRoot.skhost textarea{font-size:12.5px}
#skRoot.skhost .field label{font-size:11.5px}
#skRoot.skhost .btn{font-size:12.5px}
#skRoot.skhost .btn.sm,#skRoot.skhost .btn.ghostlight.sm{font-size:12px}
#skRoot.skhost .chip,#skRoot.skhost .cperiod .chip{font-size:12px}
#skRoot.skhost .eyebrow{font-size:11px}
#skRoot.skhost h2{font-size:15px}
#skRoot.skhost h3,#skRoot.skhost h4{font-size:13.5px}
/* the point cards: title, plays, address, meta */
#skRoot.skhost .qtitle b,#skRoot.skhost .pitem .info b,
#skRoot.skhost .qitem .info b,#skRoot.skhost .typecard h4{font-size:13.5px}
#skRoot.skhost .qmeta .plays b{font-size:13px}
#skRoot.skhost .qmeta .plays,#skRoot.skhost .qaddr,#skRoot.skhost .qaddr summary,
#skRoot.skhost .qaddr>div,#skRoot.skhost .pitem .info small,
#skRoot.skhost .qmeta2,#skRoot.skhost .qaddr2{font-size:11.5px}
#skRoot.skhost .qprice{font-size:12px}
#skRoot.skhost .stepper input,#skRoot.skhost .stepper button{font-size:12px}
#skRoot.skhost .usagetime{font-size:12.5px}
/* the configurator's own furniture */
#skRoot.skhost .custbox-head .ch-title{font-size:13.5px}
#skRoot.skhost .custbox-head .ch-sum,#skRoot.skhost .csheet-handle .hl{font-size:12px}
#skRoot.skhost .cstats .st b{font-size:15px}
#skRoot.skhost .cstats .st span{font-size:11px}
#skRoot.skhost .cest .lbl,#skRoot.skhost .cest .cnames,
#skRoot.skhost .mest .lbl{font-size:12px}
#skRoot.skhost .cest .cres,#skRoot.skhost .mest .cres,
#skRoot.skhost .reco-card .rc-b,#skRoot.skhost .reco-lead{font-size:11.5px}
/* the estimate is still the loudest thing on the page — just not 34px loud */
#skRoot.skhost .cest .camt,#skRoot.skhost .mest .camt{font-size:26px}
#skRoot.skhost .sumbar .t b{font-size:17px}
#skRoot.skhost .sumbar .t span{font-size:11.5px}
/* the quote's totals read like the workspace's own money rows */
#skRoot.skhost .totrow{font-size:12.5px}
#skRoot.skhost .totrow.grand{font-size:15px}
#skRoot.skhost .qsub .qs{font-size:11.5px}
#skRoot.skhost .qitem .amt input{font-size:12.5px}

/* the kit's toast is its own; keep it clear of the workspace's */
#skRoot .toast{bottom:74px}
.qtabs{margin-bottom:0}

/* ============ SALES (V4 PIPELINE V1) ============
   The page borrows the furniture the personnel space and Project Space already
   own — tiles, tab row, kanban lanes, card grid, property rows — so only what is
   genuinely new is written here. */

/* ---- the page-level tab row, under the personnel's own name ---- */
/* it sits above the Card Summary and reads as a level up from the work tabs,
   so it is the wider of the two rows rather than a second row of the same size */
.tabs.pgtabs{margin:-4px 0 16px}
.tabs.pgtabs button{padding:7px 18px;font-size:12.5px}
.tabs.pgtabs button.on{background:var(--ink);color:var(--bg)}

/* ---- the four pipeline stages: one colour source for pill and dot ----
   PIPELINE-3 names the first two: Leads grey, Prospect orange. The ladder then
   reads cold → warm → committed → won, which is the order of the board. */
.pl-Leads{background:var(--soft);color:var(--sub)}.pl-Leads .dot{background:var(--sub)}
.pl-Prospect{background:var(--warnb);color:var(--warn)}.pl-Prospect .dot{background:var(--warn)}
.pl-Potential{background:var(--accent-soft);color:var(--accent)}.pl-Potential .dot{background:var(--accent)}
.pl-Closing{background:var(--okb);color:var(--ok)}.pl-Closing .dot{background:var(--ok)}
/* the document kinds an entry carries, on its board card */
.tag.dkt{font-weight:700}
.tag.dkt-proposal{background:var(--accent-soft);color:var(--accent);border-color:transparent}
.tag.dkt-quote{background:var(--warnb);color:var(--warn);border-color:transparent}
/* a document says which of the two kinds it is the same way */
.dk-proposal{background:var(--accent-soft);color:var(--accent)}.dk-proposal .dot{background:var(--accent)}
.dk-quote{background:var(--warnb);color:var(--warn)}.dk-quote .dot{background:var(--warn)}
/* §77 — the RAB reads on the Sales Document tab beside the other two kinds */
.dk-rab{background:var(--okb);color:var(--ok)}.dk-rab .dot{background:var(--ok)}

/* ---- the board ---- */
/* the lane head carries its own total, so the value of a stage reads without
   adding the cards up by eye */
/* four lanes, not seven: they share the width instead of scrolling off the edge.
   The task board keeps its fixed 270px track — it has a lane for every status
   and was always going to scroll. */
.plkb>.kbcol{flex:1 1 0;min-width:216px}
.plkb .kh{flex-wrap:wrap}
/* the count sits with the stage it counts; the lane total goes to the far right */
.plkb .kh .c{margin-left:0}
.plkb .kh .kv2{margin-left:auto;font-size:11px;font-weight:800;color:var(--sub);white-space:nowrap}
.plcard{cursor:pointer}
.plcard .plhead{display:flex;align-items:flex-start;gap:4px}
.plcard .plhead .t{flex:1;min-width:0}
/* the "⋯" only appears on the card the pointer is over, as the project card does */
.plcard .rowmenu{opacity:0;flex:0 0 auto}
.plcard:hover .rowmenu{opacity:1}
.plcard .pls{font-size:11px;color:var(--sub);margin-top:2px}
.plcard .m .late{color:var(--dang);font-weight:700}
.plcard .plt{margin-top:6px;display:flex;gap:3px;flex-wrap:wrap}
.plcard .plt .tag.star{color:var(--warn);border-color:var(--warn)}
/* a won deal reads green the way an urgent task reads red */
.plcard.won{border-color:var(--ok);background:var(--okb)}

/* ---- the Pipelist table: every cell is the control that edits it ----
   PIPELINE-2 §7: no slider. `table-layout:fixed` with percentage columns makes
   the table fit whatever it is given — the client and the product list are the
   two that give way, and every control sizes to its own cell instead of forcing
   a minimum that pushed the table wider than the page. */
.pltable{table-layout:fixed;width:100%}
.pltable td,.pltable th{padding-left:9px;padding-right:9px;overflow:hidden}
.pltable td{vertical-align:middle}
.pltable tbody tr:hover{background:var(--soft)}
.pltable .lname{cursor:pointer}
.pltable .lname b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pltable .lname .c,.pltable .c{color:var(--sub);font-size:11px;font-weight:500;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pltable td.mid{text-align:center}
/* the nine tracks, as shares of the table. The two that hold a native control —
   the percentage spinner and the date picker — are sized to what the control
   actually needs, or the browser clips the value rather than the box. */
.pltable .c-stage{width:11%}.pltable .c-val{width:12%}.pltable .c-prob{width:8%}
.pltable .c-due{width:15%}.pltable .c-src{width:12%}.pltable .c-prod{width:14%}
.pltable .c-on{width:6%}.pltable .c-menu{width:4%}
/* PIPELINE-4: the Stage cell carries its own status colour, so the ladder reads
   down the column the way it reads across the board. It is a real <select>, so
   it takes the colour pair directly rather than wrapping a pill around it —
   and it needs to out-specify `.mini-input.cell`, which clears the background. */
.mini-input.cell.stagesel{font-weight:700;border-radius:20px;padding:4px 6px 4px 9px;
  border-color:transparent}
.mini-input.cell.stagesel.pl-Leads{background:var(--soft);color:var(--sub)}
.mini-input.cell.stagesel.pl-Prospect{background:var(--warnb);color:var(--warn)}
.mini-input.cell.stagesel.pl-Potential{background:var(--accent-soft);color:var(--accent)}
.mini-input.cell.stagesel.pl-Closing{background:var(--okb);color:var(--ok)}
.mini-input.cell.stagesel:focus{border-color:var(--accent)}
/* the options themselves drop back to the page colours — a coloured background
   on a native option list is unreadable on most platforms */
.mini-input.cell.stagesel option{background:var(--panel);color:var(--ink);font-weight:600}
/* the spinner arrows cost a third of the percentage cell and are never used —
   the figure is typed */
.mini-input.cell.prob{-moz-appearance:textfield;appearance:textfield}
.mini-input.cell.prob::-webkit-outer-spin-button,
.mini-input.cell.prob::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.mini-input.cell.dt{font-size:11px;padding-left:4px;padding-right:2px}
/* the Database list and the Close ledger reuse the same table with their own tracks */
.dbtable .c-star{width:4%}.dbtable .c-contact{width:12%}.dbtable .c-ind{width:11%}
.dbtable .c-area{width:9%}.dbtable .c-prod{width:16%}.dbtable .c-stage2{width:11%}
.dbtable .c-val{width:11%}.dbtable .c-doc{width:7%}.dbtable .c-menu{width:4%}
.clstable .c-ind{width:11%}.clstable .c-area{width:9%}.clstable .c-prod{width:16%}
.clstable .c-when{width:14%}.clstable .c-val{width:14%}.clstable .c-doc{width:12%}
.clstable .c-menu{width:4%}
/* Doc Status is not a column here (PIPELINE-4) — the status lives on the
   document itself, and the list is for finding one, not for triaging by state */
.doctable .c-star{width:4%}.doctable .c-kind{width:11%}.doctable .c-client{width:23%}
.doctable .c-val{width:12%}.doctable .c-date{width:10%}
.doctable .c-lead{width:16%}.doctable .c-menu{width:4%}
/* a document reachable straight from the ledger row */
.tag.lnk{cursor:pointer;border-color:var(--line);background:var(--bg)}
.tag.lnk:hover{border-color:var(--accent);color:var(--accent)}
/* an entry taken off the board reads quieter in the list too */
.pltable tr.off td{opacity:.6}
.pltable tr.off:hover td{opacity:1}
/* Source and Product edit in place: the chips fill the cell and wrap inside it */
.pltable .relcell .subrel.inline{display:flex;flex-wrap:wrap;gap:3px;min-height:26px;
  align-items:center;padding:3px 4px;border-radius:7px;cursor:pointer}
.pltable .relcell .subrel.inline:hover{background:var(--soft);box-shadow:0 0 0 1px var(--line) inset}
.pltable .relcell .asgchip{max-width:100%}
.pltable .relcell .asgchip .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pltable .relcell .asgph{font-size:11px;color:var(--sub)}
/* the date cell keeps its native picker but never demands more than its track */
.mini-input.cell.dt{min-width:0}
.mini-input.cell{width:100%;padding:5px 7px;font-size:11.5px;background:transparent;border-color:transparent}
.mini-input.cell:hover{border-color:var(--line)}
.mini-input.cell:focus{border-color:var(--accent);background:var(--bg)}
.mini-input.cell.money,.mini-input.cell.prob{text-align:right;font-weight:700}
.mini-input.cell.late{color:var(--dang);font-weight:700}
.ckbox{width:15px;height:15px;accent-color:var(--accent)}

/* ---- the Database card ---- */
.dbcard .dbline{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:12px;flex-wrap:wrap}
.dbcard .dbline.sub,.doccard .dbline{margin-top:6px}
.dbcard .dbline .c,.doccard .nf .c{color:var(--sub);font-size:11px}
.dbcard:hover,.doccard:hover{border-color:var(--accent)}
.dbcard,.doccard{cursor:pointer}
/* an entry taken off the board still reads, but reads quieter */
.dbcard.off{opacity:.62}
.dbcard.off:hover{opacity:1}
.doccard .dbline{display:flex;align-items:center;gap:8px;font-size:12px;flex-wrap:wrap}
/* PIPELINE-2 §8: the writer closes the Database tab rather than opening it */
.dbwriter{margin:16px 0 0}
/* the count above the card grid, matching the card header the list view gets */
.sumhead.dbcount{margin:0 0 12px;align-items:baseline}
.sumhead.dbcount .sub{margin-left:auto}

/* ---- the toolbar row: search, the open tab's own filters, then + Add ----
   PIPELINE-3: **one row, never two.** Four facets as chips wrapped the bar and
   carried + Add down with them; each tab now has a single dropdown button, so
   the row holds tabs · search · filter · view · + Add at any usable width. */
.salesbar{flex-wrap:nowrap}
.salesbar .stools{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.salesbar .addwrap{margin-left:auto;flex:0 0 auto}
.salesbar #sText{flex:1 1 180px;min-width:120px;max-width:280px}
.salesbar .tabs{flex:0 0 auto}
/* the dropdown itself */
.sfmenu{top:34px;left:0;min-width:212px;max-height:340px;overflow-y:auto;padding:6px;z-index:95}
.sfmenu .mh{padding:7px 9px 3px}
.sfmenu .fopt{font-size:12px}
.fpick{display:flex;align-items:center;gap:8px;width:100%;border:0;background:transparent;
  padding:7px 9px;border-radius:7px;font-size:12.5px;text-align:left;color:var(--ink);cursor:pointer}
.fpick:hover{background:var(--soft)}
.fpick.on{font-weight:700}
.fpick .ck{margin-left:auto;color:var(--accent);font-size:11px}
/* By Card / By List — a segmented pair, not two loose chips */
.seg.viewseg{display:inline-flex;background:var(--bg);border:1px solid var(--line);
  border-radius:9px;padding:3px;gap:3px;flex:0 0 auto}
.seg.viewseg button{border:0;background:transparent;padding:5px 11px;border-radius:6px;
  font-size:11.5px;font-weight:600;color:var(--sub);white-space:nowrap;cursor:pointer}
.seg.viewseg button:hover{color:var(--ink)}
.seg.viewseg button.on{background:var(--ink);color:var(--bg)}
/* below a laptop the tab row takes its own line, and the rest stays together */
@media(max-width:972px){
  .salesbar{flex-wrap:wrap}
  .salesbar .tabs{order:-1;flex:1 0 100%}
}

/* ---- the entry panel ---- */
/* the Active switch rides in the meta line beside the stage, because the two
   are one decision: which stage, and whether it is on the board at all */
.ldsw{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--sub);cursor:pointer;white-space:nowrap}
.ldsw input{width:15px;height:15px;accent-color:var(--accent)}
/* a value the panel shows but does not own reads as text, not as a dead field */
.pv .ro{display:inline-block;padding:5px 0;font-size:12.5px}

/* ---- the quote panel ---- */
/* ---------- the quote, drawn as the letter Quota Config prints ----------
   PIPELINE-5. One block serves the panel and the print sheet, so what is
   exported is the file the client was already sent. It is a printed page, not
   a workspace surface: it keeps paper colours in either theme, and the kit's
   own palette, because the print sheet moves it outside every var() it knew. */
.kprop{--kblue:#1B4DFF;--knavy:#0A1A3F;--klime:#B2FF3C;
  background:#fff;color:var(--knavy);font-size:12px;line-height:1.5;
  border:1px solid var(--line);border-radius:12px;padding:14px 16px;margin-top:4px;overflow-x:auto}
.kprop table{width:100%;border-collapse:collapse;margin:8px 0}
.kprop th,.kprop td{padding:6px 7px;border-bottom:1px solid #ddd;text-align:left;font-size:11.5px;
  color:var(--knavy);vertical-align:top}
.kprop thead th{background:#F0F4FF;text-transform:uppercase;font-size:10px;letter-spacing:.04em;color:#33405e}
.kprop td.r,.kprop th.r{text-align:right;white-space:nowrap}
.kprop .grand{font-size:14px;font-weight:800}
/* in the panel the letter is read at a quarter of a page's width, so the item
   table is given fixed tracks — left to itself the thumbnails push the amount
   column off the edge, and a figure you have to scroll to is not a total */
.kprop:not(.print) .pitems{table-layout:fixed}
.kprop:not(.print) .pitems th:nth-child(1),.kprop:not(.print) .pitems td:nth-child(1){width:16px;padding-left:0;padding-right:0}
.kprop:not(.print) .pitems th:nth-child(3),.kprop:not(.print) .pitems td:nth-child(3){width:28px;padding-left:2px;padding-right:2px}
.kprop:not(.print) .pitems th:nth-child(4),.kprop:not(.print) .pitems td:nth-child(4){width:86px;padding-right:4px}
.kprop:not(.print) .pitems th:nth-child(5),.kprop:not(.print) .pitems td:nth-child(5){width:96px;padding-right:0}
.kprop:not(.print) .grand{font-size:12.5px}
.kprop:not(.print) .pitems td{word-break:break-word}
.kprop .pto td{border:none;padding:0 0 2px;font-size:11.5px}
.kprop .pto td.r{text-align:right}
.kprop .pthanks{margin:4px 0 8px;color:#1E8E4E;font-size:11.5px}
.kprop .pthanks i{color:var(--knavy)}
.kprop .pdesc{display:flex;gap:9px;align-items:flex-start}
.kprop .pthumb{width:58px;height:36px;object-fit:cover;border-radius:6px;flex:none;border:1px solid #dde3f0}
.kprop .pmeta{color:var(--kblue);font-size:11px}
.kprop .paddr{color:#556;font-size:11px}
.kprop .pdates{color:var(--kblue);font-size:11px}
.kprop .psubs{margin-top:5px;display:flex;flex-direction:column;gap:4px}
.kprop .psub{display:flex;align-items:flex-start;gap:7px;font-size:10.5px;color:#556}
.kprop .psub img,.kprop .psub .psubph{width:32px;height:21px;object-fit:cover;border-radius:4px;flex:none;
  border:1px solid #dde3f0;background:#123A9E}
.kprop .psub b{color:#0A1A3F}
.kprop .psave{display:inline-block;background:#EAF9F0;color:#1E8E4E;font-weight:800;font-size:10.5px;
  padding:2px 8px;border-radius:6px;margin-top:4px}
.kprop .pempty{text-align:center;color:#8892a6;padding:16px}
.kprop .pterms{font-size:9.5px;color:#8892a6;margin-top:8px;line-height:1.45}
/* the two estimate rows are the only controls on the letter */
.kprop tr.pedit td{color:#33405e}
.kprop tr.pedit label{display:inline-flex;align-items:center;gap:7px;cursor:pointer}
.kprop tr.pedit label input{width:14px;height:14px;accent-color:var(--kblue)}
.kprop tr.pedit input[type=number]{width:56px;border:1px solid #dde3f0;border-radius:6px;padding:3px 6px;
  font-size:11px;text-align:right;background:#fff;color:var(--knavy);outline:none;margin-left:8px}
.kprop tr.pedit input[type=number]:focus{border-color:var(--kblue)}
.kprop tr.pedit i{font-style:normal;opacity:.6;margin-left:8px}
/* full letter — the letterhead and the sign-off, printed only */
.kprop .phead{display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  border-bottom:3px solid var(--kblue);padding-bottom:10px;margin-bottom:8px}
.kprop .plogo{width:auto;height:auto;max-width:2cm;max-height:2cm}
.kprop .phead .ht{font-size:11px;color:#33405e;line-height:1.55}
.kprop .phead .ht b{font-size:14px;color:var(--knavy)}
.kprop .bp{font-size:15px;font-weight:800;color:var(--kblue);margin:14px 0 4px}
.kprop .bps{font-size:12.5px}
.kprop .foot{margin-top:16px;padding-top:12px;border-top:2px solid var(--kblue);font-size:11px;color:#33405e}

/* the document open right now — the row says so, and closes it when clicked */
.opentag{display:inline-block;margin-left:8px;font-size:10px;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;color:var(--accent);vertical-align:middle}
tr.active>td{background:var(--accent-soft)}
tr.active>td:first-child{box-shadow:inset 3px 0 0 var(--accent)}
.doccard.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}

/* a receipt above the button that earned it (notePop) */
.notepop{position:fixed;z-index:130;display:flex;gap:9px;align-items:flex-start;max-width:300px;
  padding:11px 13px;background:var(--panel);border:1px solid var(--line);border-radius:12px;
  box-shadow:var(--shl);opacity:0;transform:translateY(5px);transition:.16s}
.notepop.on{opacity:1;transform:none}
.notepop .nk{width:19px;height:19px;border-radius:50%;background:var(--ok);color:#fff;flex:none;
  font-size:11px;font-weight:800;display:grid;place-items:center}
.notepop .nb{font-size:12px;line-height:1.5}
.notepop .nb b{display:block}
.notepop .nb span{color:var(--sub);font-size:11px}

/* ============================================================
   PROPOSAL (V4 PROPOSAL V1A)
   The letter fills the window: a header, four sections in a 2 × 2 grid and the
   action bar under them. Each section scrolls inside its own box, so the page
   itself never scrolls — the same arrangement Event Overview uses.
   ============================================================ */
.content.proppg{display:flex;flex-direction:column;overflow:hidden;padding-bottom:16px}
.content.proppg>.ph{flex:0 0 auto}
/* PROPOSAL V1 — the same page drawn inside Quota Config's Proposal tab, so the
   tab row is a third fixed band above the letter and must not be squeezed */
.content.proppg>.qtabs{flex:0 0 auto;margin-bottom:12px}
/* §84 — two things about that tab row, on **every** Quota Config tab:

   · it keeps the Proposal tab's air under it. The RAB stopped wearing `proppg` in
     §78 and inherited a tab row with no bottom margin, so its title sat on the
     tabs; the spacing belongs to the row, not to one tab's layout.
   · it **stays put while the page scrolls**. Quota Project is a tall page and the
     tabs went off the top of it, so there was no way back to Quote without
     scrolling all the way up. Sticky rather than fixed: it holds the top of the
     scrolling area it already lives in. */
.qtabs{position:sticky;top:0;z-index:6;background:var(--bg);
  padding-top:2px;padding-bottom:2px;margin-bottom:12px}
.content.proppg>.qtabs{margin-bottom:12px}
.propwrap.kitprop{margin-top:0}
.propwrap{flex:1;min-height:0;display:flex;flex-direction:column;gap:10px}
.prophead{flex:0 0 auto}
.prophead .tk-title{margin:0}
.propgrid{flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:12px}
.propsec{min-height:0;display:flex;flex-direction:column;overflow:hidden;margin:0}
.propsec>.ch{flex:0 0 auto}
.propsec>.ch .sub{margin-left:auto;font-style:italic}
.propsec>.cb{flex:1;min-height:0;overflow:auto;padding:12px 14px}
.propsec>.cb::-webkit-scrollbar{width:9px}
.propsec>.cb::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.propsep{height:1px;background:var(--line);margin:10px 0}
.proplabel{font-size:11.5px;color:var(--sub);font-weight:600;margin:10px 0 6px}
.propfoot{flex:0 0 auto;display:flex;justify-content:flex-end;align-items:center;gap:8px}
/* the date is picked, not typed into a box — the direction draws it without one */
input.dateflat{border:1px solid transparent;background:transparent;padding:3px 4px;
  font:inherit;color:var(--ink);border-radius:7px;outline:none}
input.dateflat:hover{background:var(--soft)}
input.dateflat:focus{border-color:var(--accent);background:var(--panel)}

/* Section 2 — the template rail and the box it fills */
.ctxbody{display:flex;gap:12px}
.ctxpills{display:flex;flex-direction:column;gap:6px;flex:0 0 auto}
.ctxpill{border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:999px;
  padding:4px 12px;font-size:11.5px;cursor:pointer;white-space:nowrap;transition:.15s}
.ctxpill:hover{border-color:var(--accent)}
.ctxpill.on{background:var(--soft);border-color:var(--line);color:var(--sub);font-weight:600}
.ctxbox{flex:1;min-width:0;min-height:0;resize:none;overflow:auto;border:1px solid var(--line);
  border-radius:10px;background:var(--panel);color:var(--ink);padding:10px 12px;font:inherit;
  line-height:1.6;outline:none}
.ctxbox:focus{border-color:var(--accent)}

/* Section 3 — the notes box and the signature strip */
.infobox{width:100%;height:120px;resize:none;overflow:auto;border:1px solid var(--line);border-radius:10px;
  background:var(--panel);color:var(--ink);padding:10px 12px;font:inherit;line-height:1.6;outline:none;margin-bottom:10px}
.infobox:focus{border-color:var(--accent)}
.signwrap{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.signpick{position:relative;display:inline-block;border:1px solid var(--line);border-radius:8px;
  background:var(--panel);padding:2px;line-height:0}
.signpick img{height:34px;width:auto;max-width:110px;object-fit:contain}
.signhist{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.signthumb{position:relative;display:inline-block;border:1px solid var(--line);border-radius:7px;
  padding:2px;line-height:0;cursor:pointer;background:var(--panel)}
.signthumb.on{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
.signthumb img{height:24px;width:auto;max-width:78px;object-fit:contain}
.signadd{width:26px;height:26px;border-radius:7px;border:1px dashed var(--line);background:transparent;
  color:var(--sub);cursor:pointer;font-size:14px;line-height:1}
.signadd:hover{border-color:var(--accent);color:var(--accent)}
.thumbx{position:absolute;top:3px;right:3px;width:16px;height:16px;border-radius:50%;border:1px solid var(--line);
  background:var(--panel);color:var(--sub);font-size:11px;line-height:1;cursor:pointer;padding:0;
  display:grid;place-items:center;box-shadow:var(--sh)}
.thumbx:hover{color:var(--dang);border-color:var(--dang)}

/* Section 4 — the media kit grid; a filled tile can be dragged to reorder */
.agridwrap{overflow-x:hidden}
.agrid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;align-content:start}
.aslot{position:relative;aspect-ratio:4/3;border:1px dashed var(--line);border-radius:9px;display:grid;
  place-items:center;color:var(--sub);font-size:15px;cursor:pointer;overflow:visible;background:transparent}
.aslot:hover{border-color:var(--accent);color:var(--accent)}
.aslot.filled{border:1px solid var(--line);cursor:grab;padding:0}
.aslot.filled img{width:100%;height:100%;object-fit:cover;border-radius:8px;display:block}
.aslot.drag{opacity:.4}
.aslot.over{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}

/* ---------- the exported letter (A4, 1cm margin, [N] of [N]) ----------
   Built as real pages rather than one long flow: the count is known before the
   sheet exists, and "N of N" is not something a print counter can produce. */
.a4doc{font-family:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;color:#111}
.a4page{position:relative;display:flex;flex-direction:column;background:#fff;color:#111;
  width:19cm;min-height:27.7cm;page-break-after:always;break-after:page}
.a4page:last-child{page-break-after:auto;break-after:auto}
.a4logo{width:auto;height:1.1cm;object-fit:contain;align-self:flex-start;margin-bottom:.7cm}
.a4body{flex:1;min-height:0;font-size:10.5pt;line-height:1.55}
.a4foot{flex:0 0 auto;display:flex;justify-content:space-between;align-items:flex-end;
  font-size:7.5pt;color:#8a8f98;padding-top:.4cm}
.a4sender{font-size:10pt;line-height:1.5}
.a4sender b{font-size:10.5pt}
.a4city{text-align:right;margin:1.1cm 0 .9cm}
.a4no{border-collapse:collapse;margin-bottom:1.1cm}
.a4no td{border:0;padding:0 6px 2px 0;vertical-align:top;white-space:nowrap}
.a4no td:first-child{width:62px}
.a4to{margin-bottom:1.1cm;line-height:1.5}
.a4ctx p{margin:0 0 10px;text-align:justify}
.a4from{margin-top:1.2cm;font-weight:700}
.a4h{font-weight:700;font-size:11pt;margin:0 0 8px}
.a4h2{font-weight:700;font-size:10pt;margin:14px 0 4px}
.a4quote{border:0;border-radius:0;padding:0;margin:0 0 14px;background:transparent}
.a4info,.a4list{margin:0;padding-left:20px}
.a4info li,.a4list li{margin-bottom:3px}
.a4p{margin:10px 0 0}
.a4spec{border-collapse:collapse;width:100%}
.a4spec td{border:0;padding:1px 0;vertical-align:top;font-size:9.5pt}
.a4spec td:first-child{width:120px;white-space:nowrap}
/* the guideline sheet is fixed text that runs ~3 cm past A4 at the letter's own
   type size, and the direction asks for one page — so that page, and only that
   page, is set tighter. Nothing is dropped; the leading and the gaps carry it. */
.a4page.tight .a4body{font-size:9.4pt;line-height:1.42;display:flex;flex-direction:column}
.a4page.tight .a4h{font-size:11pt;margin-bottom:8px}
.a4page.tight .a4h2{font-size:9.6pt;margin:11px 0 4px}
.a4page.tight .a4spec td{font-size:9.2pt;padding:1px 0}
.a4page.tight .a4spec td:first-child{width:116px}
.a4page.tight .a4list{padding-left:19px}
.a4page.tight .a4list li{margin-bottom:3px}
.a4page.tight .a4p{margin-top:10px}
/* the closing block is pushed to the foot of the sheet rather than left hanging
   under the last paragraph — that empty band was the whole complaint */
.a4page.tight .a4sign{margin-top:auto;padding-top:10px}
.a4page.tight .a4sig{height:2cm}
.a4page.tight .a4sigsp{height:2cm}
.a4sign{margin-top:16px}
.a4sig{height:1.7cm;width:auto;object-fit:contain;display:block}
.a4sigsp{height:1.7cm}
.a4name{margin-top:2px;padding-left:14px}
/* two to a page, no frame once an image is in — the frame is the empty state */
.a4imgs{display:flex;flex-direction:column;gap:.8cm;height:100%}
.a4img{flex:1;min-height:0;display:flex;align-items:center;justify-content:center}
.a4img img{max-width:100%;max-height:100%;object-fit:contain}

/* ---------- the exported Meeting Notes sheet (§74) ----------
   The direction's layout on the proposal's letterhead. These rules are global
   rather than print-only on purpose: `mtMeasure` renders the sheet off-screen to
   count its pages, so what it measures has to be what the printer draws. The
   print block re-asserts the borders the a4 sheet otherwise strips. */
.mtsheet .mtnh{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  margin:0 0 8px;font-size:9pt;font-weight:800;letter-spacing:.09em;text-transform:uppercase}
.mtsheet .mtnh .nm{font-size:9pt;font-weight:600;letter-spacing:.01em;text-transform:none;
  color:#555;text-align:right}
/* the information block is ruled, not boxed: one hairline per row, a rule top
   and bottom, and no vertical lines at all */
.mtsheet .mtinfo2{width:100%;border-collapse:collapse;margin:0 0 16px;
  border-top:1px solid #111;border-bottom:1px solid #111}
.mtsheet .mtinfo2 td{border:0;border-bottom:1px solid #dcdcdc;padding:5px 10px 5px 0;
  font-size:9.5pt;line-height:1.45;vertical-align:top}
.mtsheet .mtinfo2 tr:last-child td{border-bottom:0}
.mtsheet .mtinfo2 td.k{width:13%;font-style:italic;color:#444;white-space:nowrap}
.mtsheet .mtinfo2 td.v{width:37%}
/* the minutes are a grid, the way the sheet draws them. ⚠ every inherited
   property is written out: the workspace's own `th` rule paints a grey fill,
   grey text and uppercase, which is a screen table's look, not a document's. */
.mtsheet .mtn{width:100%;border-collapse:collapse}
.mtsheet .mtn th{border:1px solid #111;padding:5px 7px;font-size:9pt;font-weight:700;
  text-align:left;vertical-align:top;background:transparent;color:#111;
  text-transform:none;letter-spacing:0}
.mtsheet .mtn td{border:1px solid #111;padding:6px 7px;font-size:9.5pt;line-height:1.45;
  vertical-align:top;color:#111;background:transparent}
/* the sheet bullets with hyphens, not discs */
.mtsheet .mtn ul{margin:0;padding-left:12px;list-style:none}
.mtsheet .mtn li{position:relative;margin:0 0 4px}
.mtsheet .mtn li::before{content:'-';position:absolute;left:-12px;top:0}
.mtsheet .mtn li:last-child{margin-bottom:0}
.mtsheet .mtby{margin-top:20px;font-size:9.5pt;line-height:1.6;color:#111}


/* ============================================================
   V5 ROLE PERMISSION V1B — sign-in extras, the Position group in the
   sidebar, the Role Permission tab, the permission panel and Profil.
   ============================================================ */

/* ---- sign-in / recovery ---- */
.login .hint2 a{color:var(--accent);text-decoration:none}
.login .hint2 a:hover{text-decoration:underline}
.rkbox{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:17px;letter-spacing:1.5px;
  font-weight:700;text-align:center;padding:14px 10px;border:1px dashed var(--line);border-radius:10px;
  background:var(--soft);margin:4px 0 12px;word-break:break-all}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;letter-spacing:.6px}

/* ---- a Position holding more than one person (pasal 9.2) ---- */
.posgrp>.item.pos{font-weight:600}
.posgrp .poscount{margin-left:auto;font-size:10px;background:var(--soft);color:var(--sub);
  border-radius:20px;padding:1px 7px;font-weight:700}
.posgrp>.item.pos .chevbtn{margin-left:6px;flex:0 0 auto;display:grid;place-items:center;width:20px;height:20px;
  border:0;background:transparent;border-radius:6px;padding:0;cursor:pointer}
.posgrp>.item.pos .chevbtn:hover{background:var(--line2)}
.posgrp .chev{flex:0 0 12px;width:12px;height:12px;stroke:var(--sub);transition:transform .15s;fill:none;stroke-width:2}
.posgrp.open .chev{transform:rotate(90deg)}
.posmem{display:none;margin:2px 0 4px 8px;padding-left:9px;border-left:1px solid var(--line)}
.posgrp.open .posmem{display:block}
.posmem .item{font-size:12px;opacity:.8}
.app.side-collapsed .side .posmem{display:none}
.app.side-collapsed .side:hover .posgrp.open .posmem{display:block}
.app.side-collapsed .side .posgrp .poscount{display:none}
.app.side-collapsed .side:hover .posgrp .poscount{display:inline}

/* ---- a division page (PRO-CAMPAIGN V1) ----
   It is not a Position, so it does not read like one: a dot marks it as the
   division's own page and the label carries the weight the Positions do not. */
.subitems .item.dpage{font-weight:600;display:flex;align-items:center;gap:7px}
.subitems .item.dpage::before{content:'';flex:0 0 5px;width:5px;height:5px;border-radius:50%;
  background:var(--accent);opacity:.75}
.subitems .item.dpage.active::before{opacity:1}

/* ============================================================
   REQUEST DOCUMENTS — SPD & LPJ (V5)
   A paper, not a spreadsheet: the grid is here to line the numbers up, not to
   pretend the screen is a sheet of A4.
   ============================================================ */
/* the paper is named on the paper: a field that reads as the page title until
   somebody puts the caret in it */
.rqtitle{flex:1;min-width:0;border:1px solid transparent;border-radius:9px;background:transparent;
  color:var(--ink);font:inherit;font-size:23px;font-weight:800;letter-spacing:-.5px;
  padding:2px 8px;margin:-2px 0;outline:none}
.rqtitle::placeholder{color:var(--sub);opacity:.55;font-weight:800}
.rqtitle:hover{border-color:var(--line2)}
.rqtitle:focus{border-color:var(--accent);background:var(--bg)}
/* the card's own "⋯", which only shows when the card is under the pointer */
.rqcard .rowmenu{margin-left:auto;opacity:0}
.rqcard:hover .rowmenu{opacity:1}
/* a turned-down paper says so, and says what can be done about it */
.rqreject{border:1px solid var(--dang);background:var(--dangb);color:var(--dang);
  border-radius:10px;padding:9px 14px;font-size:12px;margin:0 0 14px}
.rqreject b{color:var(--ink);font-weight:600}
.rqmeta{display:flex;align-items:center;gap:12px;margin:0 0 16px;flex-wrap:wrap}
.rqmeta .sub{font-size:11.5px;color:var(--sub)}
.rqmeta .sub.lock{margin-left:auto;border:1px solid var(--line);border-radius:20px;padding:2px 10px}
.rqgrid{display:grid;grid-template-columns:1fr 1fr;gap:2px 26px}
@media(max-width:810px){.rqgrid{grid-template-columns:1fr}}
.rqgrid .proprow{grid-template-columns:130px 1fr}
/* the line table */
.rqtbl{table-layout:fixed;width:100%}
.rqtbl th{font-size:10px;letter-spacing:.4px}
.rqtbl td{vertical-align:middle}
.rqtbl td .sub{font-size:10.5px;color:var(--sub)}
.rqtbl input,.rqtbl select{width:100%;padding:5px 8px;border:1px solid transparent;border-radius:7px;
  background:transparent;color:var(--ink);font:inherit;font-size:12px}
.rqtbl input:hover,.rqtbl select:hover{border-color:var(--line2)}
.rqtbl input:focus,.rqtbl select:focus{outline:none;border-color:var(--accent);background:var(--bg)}
.rqtbl input:disabled,.rqtbl select:disabled{border-color:transparent;background:transparent;color:var(--ink);opacity:1}
.rqtbl td.n input{text-align:right}
/* Qty is a small integer, and the browser's own spinner was eating the column:
   the field measured 36px inside a 64px cell and the digit was clipped to a
   sliver. The spinner buys nothing for a number somebody types once. */
.rqtbl input[type=number]{width:100%;min-width:0;text-align:right;-moz-appearance:textfield;appearance:textfield}
.rqtbl input[type=number]::-webkit-outer-spin-button,
.rqtbl input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;appearance:none;margin:0}
.rqtbl .rowmenu{opacity:0}
.rqtbl tr:hover .rowmenu{opacity:1}
/* the totals sit apart from the lines — they are the answer, not another row */
.rqsum .cb{padding:14px 18px}
.rqtot{display:flex;align-items:baseline;gap:12px;padding:5px 0;font-size:12.5px}
.rqtot span:first-child{flex:1;color:var(--sub)}
.rqtot b{font-size:15px;font-weight:800;letter-spacing:-.3px}
.rqtot.big{border-top:1px solid var(--line2);margin-top:6px;padding-top:11px}
.rqtot.big b{font-size:19px}
.rqstate{flex:0 0 auto;font-size:10.5px;font-weight:700;border-radius:20px;padding:2px 10px}
.rqstate.sisa{background:var(--okb);color:var(--ok)}
.rqstate.kurang{background:var(--dangb);color:var(--dang)}
.rqstate.pas{background:var(--soft);color:var(--sub)}
.rqsay{display:flex;gap:12px;border-top:1px solid var(--line2);margin-top:9px;padding-top:9px;font-size:11.5px}
.rqsay span{flex:0 0 auto;color:var(--sub)}
.rqsay i{color:var(--ink)}
/* V1A — Catatan and Tanda Tangan each take the full width. Side by side, the
   note was a narrow column and the three signature cells were squeezed into two
   thirds of the page; stacked, both read at the width of the document. */
.rqfoot{display:block}
.rqfoot>.card{margin-bottom:14px}
.rqnote{width:100%;min-height:104px;resize:vertical;border:0;background:transparent;color:var(--ink);
  font:inherit;font-size:12.5px;line-height:1.6;outline:none;padding:0}
.rqsigrow{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
@media(max-width:738px){.rqsigrow{grid-template-columns:1fr}}
.rqsigcell{border:1px solid var(--line2);border-radius:10px;padding:10px;display:flex;flex-direction:column;gap:7px}
.rqsigh{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--sub);min-height:24px}
.rqsigbox{height:74px;border-bottom:1px solid var(--line);display:grid;place-items:center;overflow:hidden}
.rqsigbox .ph{font-size:10.5px;color:var(--sub);opacity:.7;text-align:center;padding:0 6px}
.rqsig{max-height:70px;max-width:100%;object-fit:contain}
.rqsigfoot{font-size:11px;display:flex;flex-direction:column;gap:2px}
.rqsigfoot span{color:var(--sub);display:inline-block;width:38px}
.rqsigup{font-size:11px;color:var(--accent);cursor:pointer;text-align:center;
  border:1px dashed var(--line);border-radius:7px;padding:4px}
.rqsigup:hover{border-color:var(--accent);background:var(--accent-soft)}
.rqsend{margin-top:12px;border:1px solid var(--accent);border-radius:9px;background:var(--accent-soft)}
.rqsend span{color:var(--ink);font-weight:600}
.rqsendhint{margin-top:12px}
/* receipts */
.rqattach{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:10px}
.rqatt{position:relative;width:118px;height:118px;border:1px solid var(--line);border-radius:9px;overflow:hidden;background:var(--soft)}
.rqatt img{width:100%;height:100%;object-fit:cover}
.rqatt .rm{position:absolute;top:4px;right:4px;width:20px;height:20px;border:0;border-radius:50%;
  background:rgba(0,0,0,.55);color:#fff;cursor:pointer;font-size:12px;line-height:1;padding:0}
.rqattadd{display:inline-block;cursor:pointer}
/* the card in Notes → Document, and the queue on the Office dashboard */
.rqcard{cursor:pointer}
.rqcard:hover{border-color:var(--accent)}
/* §66 — the Proposal and Quote cards carry the same "⋯" the SPD/LPJ card does.
   They have no header row to hang it on, so it sits in the corner rather than
   pushing the title down; it appears on hover, and stays while its menu is open
   (`:focus-within` would not help — the menu is a sibling on `body`). */
.sdcard{position:relative}
.sdcard .rowmenu{position:absolute;top:7px;right:8px;opacity:0;transition:opacity .12s}
.sdcard:hover .rowmenu,.sdcard .rowmenu:focus{opacity:1}
.sdcard .nt{padding-right:22px}
.rqchead{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.rqkind{font-size:9.5px;font-weight:800;letter-spacing:.6px;border-radius:5px;padding:2px 6px;
  background:var(--accent-soft);color:var(--accent)}
.rqkind.lpj{background:var(--violetb,var(--soft));color:var(--violet)}
/* §76 — the third paper reads as its own kind at a glance, the way SPD and LPJ do */
.rqkind.rab{background:var(--warnb);color:var(--warn)}
/* the RAB's line carries nine columns, so its money fields are narrower than the
   SPD's and its two computed columns are read-only text rather than inputs */
/* §77 — the RAB's table fits its card: fixed layout, proportional columns, and
   every cell allowed to shrink (a table cell's min-width is its content unless
   something says otherwise — that is what forced the slider). */
.rqtbl.rab{table-layout:fixed;width:100%;min-width:0}
.rqtbl.rab th,.rqtbl.rab td{padding:6px 6px;font-size:11.5px;overflow:hidden}
.rqtbl.rab th{font-size:9.5px;white-space:normal;line-height:1.25}
.rqtbl.rab td input,.rqtbl.rab td select{width:100%;min-width:0;max-width:100%}
.rqtbl.rab td input[type=number]{-moz-appearance:textfield}
.rqtbl.rab td input[type=number]::-webkit-outer-spin-button,
.rqtbl.rab td input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.rqtbl.rab td.n{white-space:nowrap;text-overflow:ellipsis}
.rqtbl.rab td.rm{padding-left:0;padding-right:0}
/* §78 — the item field: a text input with the workspace's own picker beside it,
   and what the quote says about the line reading underneath */
.rqitemfield{display:flex;align-items:center;gap:2px;min-width:0}
.rqitemfield input{flex:1;min-width:0}
.rqitempick{flex:0 0 auto;width:18px;height:22px;border:0;background:transparent;
  color:var(--sub);cursor:pointer;font-size:10px;line-height:1;border-radius:5px}
.rqitempick:hover{background:var(--soft);color:var(--ink)}
/* the quote's own words wrap rather than being cut: they are the reason the line
   is on the paper at all */
.rqitemsub{font-size:10px;color:var(--sub);line-height:1.3;margin-top:2px;white-space:normal}
/* §79 — a line's breakdown: the products a Quota Project line is made of. Read as
   children of the row above, so they are indented, quieter, and their own money
   fields are the ones the parent's totals are built from. */
.rqtbl.rab tr.rqparent td{border-bottom:0}
.rqtbl.rab tr.rqsubrow td{background:var(--soft);border-top:0}
.rqtbl.rab tr.rqsubrow+tr:not(.rqsubrow) td{border-top:1px solid var(--line2)}
.rqsubname{display:flex;flex-wrap:wrap;align-items:center;gap:4px}
.rqsubname input{flex:1;min-width:0}
.rqsubtick{flex:0 0 auto;color:var(--sub);font-size:10px;opacity:.7}
.rqsubname .rqitemsub{flex:1 1 100%}
.print-area .rqsubprint td{color:#333}
/* the vocabulary rows read name over figures, so a long item never squeezes them */
.pickpop .plist button .sub{display:block;font-size:10.5px;color:var(--sub)}
.rqtbl.rab .n.late{color:var(--dang)}
.rqsum .rqstate.pas{background:var(--soft);color:var(--sub)}
/* the composer wears the proposal tab's frame, so the paper's own cards sit in
   one scrolling column inside it rather than spilling past the page */
.kitrab #rqBody{display:flex;flex-direction:column;gap:12px}
/* §77 — Catatan and Tanda Tangan stack in the composer exactly as they do on the
   full page: side by side the three signature cells had no room to breathe */
.kitrab .rqfoot{display:flex;flex-direction:column;gap:12px}
.kitrab .rqfoot>*{width:100%}
/* the page's own foot bar, under the paper */
.rqpagefoot{margin-top:14px}
.rqcard .nf b{font-size:13px}
.rqqueue tbody tr{cursor:pointer}
.rqqueue tbody tr:hover{background:var(--soft)}
.rqqueue .sub{font-size:10.5px;color:var(--sub)}
/* the two totals under the Office queue, foldable from the heading */
.rqtotrow{display:grid;grid-template-columns:1fr 1fr;gap:14px;border-top:1px solid var(--line2)}
@media(max-width:630px){.rqtotrow{grid-template-columns:1fr}}
.rqtotcell{display:flex;flex-direction:column;gap:2px}
.rqtotcell span{font-size:10px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--sub)}
.rqtotcell b{font-size:19px;font-weight:800;letter-spacing:-.4px}
.rqtotcell i{font-size:10.5px;color:var(--sub);font-style:normal}
.rqtotcell.ok b{color:var(--ok)}
.rqtotcell.ok i{opacity:.85}
/* "editing" says so plainly while the approver has the body unlocked */
.rqediting{margin-right:auto;font-size:11.5px;color:var(--accent);font-weight:600}
/* a paper of the reader's own that is still waiting, above Urgent */
.rqpend{border:1px solid var(--warnb,var(--line));border-radius:10px;overflow:hidden;margin:0 0 14px}
.rqpendrow{display:flex;align-items:center;gap:10px;width:100%;text-align:left;border:0;
  background:var(--soft);padding:9px 14px;cursor:pointer;font:inherit}
.rqpendrow+.rqpendrow{border-top:1px solid var(--line2)}
.rqpendrow:hover{background:var(--accent-soft)}
.rqpendrow .tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.rqpendrow .tx b{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rqpendrow .tx .wh{font-size:10.5px;color:var(--sub)}
.rqpendrow .amt{font-size:12.5px;font-weight:700;white-space:nowrap}
.rqpendrow .dt{font-size:11px;color:var(--sub);white-space:nowrap}
/* a foldable group heading on the Notes tab */
/* every Notes-tab section sits on one left edge — Document's. `.grouph` pads
   12px and only `.grid3 + .grouph` / `.rowbtn + .grouph` pull it back to 2, so
   which heading was flush depended on **what happened to precede it**: Document
   follows + Add Note and was always right, the rest moved 10px in and out as the
   section above them was folded, emptied or filled. A section's own indent is
   not a fact about its neighbour, so the foldable ones say it themselves. */
.grouph.nfold{display:flex;align-items:center;gap:8px;padding-left:2px;padding-right:2px}
.grouph.nfold.gap{margin-top:18px}
.grouph.nfold .bigfold{flex:0 0 auto}

/* the print sheet: same A4 shell as the proposal */
.rqprint th{font-size:9px}
.rqprint td{font-size:9.5px;vertical-align:top}
/* V1A — the No. column was as wide as a text column for a one-digit number */
.rqprint th.no,.rqprint td.no{width:26px;text-align:center;padding-right:2px}
/* …and Qty sat flush against Satuan, so "1" and "Paket" read as "1Paket" */
.rqprint th.qty,.rqprint td.qty{width:34px;text-align:right;padding-right:12px}
.rqprint th.unit,.rqprint td.unit{width:56px}
/* the information block: two columns, and Keperluan across both */
.a4info{width:100%;border-collapse:collapse;margin-bottom:8px}
.a4info td{vertical-align:top;padding:0;width:50%}
.a4kv{width:100%;border-collapse:collapse}
.a4kv td{font-size:9.5px;padding:1.5px 0;border:0}
.a4kv td:first-child{width:76px;color:#555}
.a4kv td:nth-child(2){width:8px}
.a4full{margin-top:4px;font-size:9.5px}
.a4full b{color:#555;font-weight:400;display:inline-block;width:76px}
/* the words for the amount are a footnote, not a heading */
.a4say{font-size:8.5px;font-style:italic;color:#444;margin:3px 0 0}
/* V1C — the note reads at the weight of the totals it sits under, and keeps the
   line breaks that were typed into it */
.a4note{margin-top:10px;font-size:10px;line-height:1.55}
.a4note b{display:block;font-size:10px;font-weight:700;margin-bottom:2px}
/* the writer's name is a fact of the paper, not a field */
.rqfix{display:inline-block;padding:6px 0;font-size:12.5px}
.a4tot{width:100%;margin-top:8px;border-collapse:collapse}
.a4tot td{padding:4px 6px;font-size:10px;border-top:1px solid #d7dbe0}
.a4tot td.n{text-align:right;white-space:nowrap}
.a4tot tr.grand td{font-weight:800;font-size:11px;border-top:1.5px solid #333}
.a4signs{width:100%;margin-top:14px;border-collapse:collapse}
.a4signs td{width:33.33%;vertical-align:top;padding:0 8px;text-align:center}
.a4signs .cap{font-size:8.5px;font-weight:700;text-transform:uppercase;color:#555;min-height:22px}
.a4signs .box{height:58px;border-bottom:1px solid #333;display:flex;align-items:flex-end;justify-content:center}
.a4signs .box img{max-height:56px;max-width:100%;object-fit:contain}
.a4signs .nm{font-size:9.5px;font-weight:700;margin-top:3px}
.a4signs .dt{font-size:8.5px;color:#666}
.a4att{width:100%;max-height:330px;object-fit:contain;margin-bottom:10px}

/* ---- Config → Structure (V5) ----
   One row is: what it is called by default · what it is called here · restore.
   The placeholder carries the built-in name, so an empty field is never a blank
   row — it reads as "still called this". */
.strow{display:grid;grid-template-columns:190px 1fr 30px;align-items:center;gap:10px;padding:5px 0}
.strow+.strow{border-top:1px solid var(--line2)}
.strow .stk{font-size:11.5px;color:var(--sub)}
.strow .stv input{width:100%;padding:6px 9px;border:1px solid var(--line);border-radius:8px;
  background:var(--bg);color:var(--ink);font-size:12.5px;font-family:inherit}
.strow .stv input:focus{outline:none;border-color:var(--accent)}
.strow .stv input::placeholder{color:var(--sub);opacity:.55}
/* two things answering to the same name is legal but worth seeing */
.strow .stv input.dupe{border-color:var(--warn)}
.stundo{width:26px;height:26px;border:1px solid var(--line);border-radius:7px;background:var(--bg);
  color:var(--sub);cursor:pointer;font-size:12px;line-height:1;padding:0}
.stundo:hover{border-color:var(--accent);color:var(--accent)}
/* the Teamspace block keeps the sidebar's own shape */
.stgrp{padding:12px 0 4px}
.stgrp+.stgrp{border-top:1px solid var(--line);margin-top:8px}
.stgrp>.stname{font-size:12.5px;font-weight:700;margin-bottom:4px}
.stsub{padding:8px 0 4px 18px;border-left:2px solid var(--line2);margin-left:4px}
.stsub>.stname{font-size:12px;font-weight:600;color:var(--sub);margin-bottom:2px}
.stsub.stpage>.stname{color:var(--accent)}
.stfields .strow{grid-template-columns:120px 1fr 30px}
/* STREAMDATA V1 — a Stream Data row carries one control more than the others:
   a page the company added can be taken away again. The seeded five keep the
   fourth cell empty rather than losing it, so every row stays on one grid. */
.strow.sdrow{grid-template-columns:190px 1fr 30px 30px}
.stundo.ghost{border-color:transparent;background:transparent;pointer-events:none}
.stundo.stdel:hover{border-color:var(--dang);color:var(--dang)}

/* ---- the lock card ---- */
.rplock{display:grid;place-items:center;padding:56px 12px}
.rplock-card{width:380px;max-width:calc(94 * var(--vw));border:1px solid var(--line);border-radius:14px;background:var(--panel);
  box-shadow:var(--sh);padding:28px 26px;text-align:center}
.rplock-ic{width:44px;height:44px;border-radius:12px;background:var(--soft);display:grid;place-items:center;
  margin:0 auto 14px;color:var(--sub)}
.rplock-ic svg{width:22px;height:22px}
.rplock h3{margin:0 0 6px;font-size:15px}
.rplock p{margin:0 0 18px;color:var(--sub);font-size:12.5px;line-height:1.7}
.rplock .field{text-align:left}
.rplock .btn{width:100%;justify-content:center;margin-top:4px}

/* ---- the open tab ---- */
.rpbar{display:flex;align-items:center;gap:10px;padding:9px 13px;border:1px solid var(--line);
  border-radius:10px;background:var(--soft);font-size:12px}
.rpbar .rpstate{color:var(--sub)}
.rpbar .btn{margin-left:auto}
table.rptab th.c,table.rptab td.c{text-align:center;width:76px}
tr.rpgrp td{background:var(--soft);font-size:11.5px;padding-top:9px;padding-bottom:9px}
tr.rpgrp td .sub{color:var(--sub);font-weight:400}
table.rptab tbody tr:not(.rpgrp){cursor:pointer}
.rpwho{display:flex;align-items:center;gap:9px}
.rpwho>span{display:flex;flex-direction:column;line-height:1.45;min-width:0}
.rpwho .sub{color:var(--sub);font-size:11px}
.lvlpill{border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:20px;
  padding:2px 10px;font-size:11px;font-weight:700;cursor:pointer}
.lvlpill:hover{border-color:var(--accent)}
.lvlpill.lv-superadmin{background:var(--dangb);border-color:transparent;color:var(--dang)}
.lvlpill.lv-admin{background:var(--accent-soft);border-color:transparent;color:var(--accent)}
.lvlpill.lv-manager{background:var(--warnb);border-color:transparent;color:var(--warn)}
.lvlpill.lv-viewer{background:var(--slateb);border-color:transparent;color:var(--slate)}
.tgl{width:34px;height:19px;border-radius:20px;border:1px solid var(--line);background:var(--soft);
  position:relative;cursor:pointer;padding:0;vertical-align:middle}
.tgl::after{content:"";position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;
  background:var(--sub);transition:left .14s,background .14s}
.tgl.on{background:var(--accent-soft);border-color:transparent}
.tgl.on::after{left:17px;background:var(--accent)}
.stpill{border:0;border-radius:20px;padding:2px 10px;font-size:11px;font-weight:700;cursor:pointer}
.stpill.on{background:var(--okb);color:var(--ok)}
.stpill.off{background:var(--slateb);color:var(--slate)}
.tag.warnq{background:var(--warnb);color:var(--warn);border:0;margin-left:6px}

/* ---- capability list, used by the panel and the level template ---- */
.capgrp{margin-bottom:16px}
.capgh{font-size:10.5px;font-weight:700;color:var(--sub);text-transform:uppercase;letter-spacing:.4px;
  padding:0 0 6px;border-bottom:1px solid var(--line2);margin-bottom:4px}
.caprow{display:flex;align-items:center;gap:10px;padding:5px 0;font-size:12.5px}
.caprow:hover{background:var(--soft)}
.capl{flex:1;min-width:0}
.capv{flex:0 0 auto}
.capv select{min-width:132px}
.capwrap{margin-top:6px}
.rphead{display:flex;align-items:center;gap:11px;padding-bottom:14px;border-bottom:1px solid var(--line);margin-bottom:14px}
.rphead .sub{color:var(--sub);font-size:11.5px}
.excwrap{margin:8px 0}
.excrow{display:flex;align-items:center;gap:8px;font-size:12px;padding:5px 0;border-bottom:1px solid var(--line2)}
.excrow i{color:var(--sub);font-style:normal}
.excrow .icobtn{margin-left:auto}
.audrow{display:flex;align-items:center;gap:10px;font-size:11.5px;padding:5px 0;border-bottom:1px solid var(--line2)}
.audrow .audk{font-weight:700;min-width:118px}
.audrow .audb{flex:1;min-width:0;color:var(--sub);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.audrow .sub{color:var(--sub)}

/* ---- the credential card, shown once ---- */
.credbox{border:1px solid var(--line);border-radius:10px;background:var(--soft);padding:12px 14px}
.credbox>div{display:flex;align-items:baseline;gap:12px;padding:5px 0;font-size:13px}
.credbox>div+div{border-top:1px solid var(--line2)}
.credbox span{flex:0 0 128px;font-size:10.5px;font-weight:700;color:var(--sub);text-transform:uppercase}

/* ---- Profil ---- */
.pfhead{display:flex;align-items:center;gap:14px;margin-bottom:16px}
.pfav{width:56px;height:56px;border-radius:50%;background:var(--soft);display:grid;place-items:center;
  font-weight:700;font-size:17px;color:var(--sub);overflow:hidden;flex:0 0 56px}
.pfav img{width:100%;height:100%;object-fit:cover}
.pfhead .btn+.btn{margin-left:6px}

/* ---- T6 · who wrote this (pasal 10.2) ---- */
.bychip{flex:0 0 18px;width:18px;height:18px;border-radius:50%;background:var(--soft);color:var(--sub);
  display:grid;place-items:center;font-size:8.5px;font-weight:700;overflow:hidden;margin-right:2px;
  border:1px solid var(--line2)}
.bychip img{width:100%;height:100%;object-fit:cover}
.byline{display:flex;align-items:center;gap:8px;padding-left:7px}
.byline>span{display:flex;flex-direction:column;line-height:1.4;font-size:12.5px}
.byline i{font-style:normal;color:var(--sub);font-size:11px}

/* ---- the eye on a password field ----
   Sits inside the box, on the right, and never covers the text: the input keeps
   its own padding so a long password scrolls under the label, not under the eye. */
.pwwrap{position:relative;display:block}
.pwwrap>input{padding-right:36px !important}
.pweye{position:absolute;top:50%;right:5px;transform:translateY(-50%);width:26px;height:26px;
  display:grid;place-items:center;border:0;background:transparent;border-radius:6px;padding:0;
  cursor:pointer;color:var(--sub)}
.pweye:hover{background:var(--soft);color:var(--ink)}
.pweye.on{color:var(--accent)}
.pweye svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}

/* ---- device-notification indicator ----
   Green when the browser has granted it, red when it has not. It says the state
   without the reader having to open anything to find out. */
.pdot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:8px;
  flex:0 0 8px;vertical-align:middle}
.pdot.on{background:var(--ok);box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 18%,transparent)}
.pdot.off{background:var(--dang);box-shadow:0 0 0 3px color-mix(in srgb,var(--dang) 18%,transparent)}
/* the menu row and the Profil button both lay the dot out beside their label */
#userMenu button[data-u="push"]{display:flex;align-items:center}
#pfPush{display:inline-flex;align-items:center}

/* ============================================================
   STREAM DATA — the design space (V5 · STREAMDATA V1)
   A page is a stack of section cards; a section card is the project page's
   card with writing where the task table sits. The shared rules live on
   `.pjsec` already — only what is different is written here.
   ============================================================ */
/* the whole header is the way into the full page, so it says so under the
   pointer. The name and the two operations sit above it and take their own
   clicks — `.secname` keeps the text cursor it already had. */
.sdsec>.ch.sdhead{cursor:pointer}
.sdsec>.ch.sdhead:hover{background:var(--soft)}
.sdsec>.ch.sdhead .secname,.sdsec>.ch.sdhead .secops{cursor:auto}
/* the stamp follows the name the way the project card's "0/0 done" follows its
   bar — `.secops` already carries the `margin-left:auto` that pushes the two
   operations to the edge, and a second one here would strand it mid-header */
.sdsec .sdstamp{font-size:11px;white-space:nowrap}
/* V1A — the card is the reading surface: Tags, then the writing as it reads.
   The editor and its toolbar moved to the full page, so nothing here is typed. */
.sdsec>.cb.sdcb{padding-top:12px}
/* Tags sit above the writing, on the card and on the full page alike */
.sdtags{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:10px}
.sdtags.page{margin:-6px 0 14px}
.sdtags:empty{display:none}
.tag.add{background:transparent;border-style:dashed;color:var(--sub);cursor:pointer;
  font-family:inherit;line-height:inherit}
.tag.add:hover{border-style:solid;border-color:var(--accent);color:var(--accent)}
/* what a reader without `data.write` sees: the same text, nothing to type into */
.sdread{font-size:13px;line-height:1.75}
.sdread img{max-width:100%;height:auto}
/* one section given the window — where the writing property lives */
.sdfull .editor.sdbody{min-height:calc(calc(100 * var(--vh)) - 340px)}
.sdfull .sdread{min-height:120px}
.sdtitle{font-size:22px}

/* ---- PARTIAL TASK §7 — a section that is a file ---- */
/* the card: a live thumbnail beside the file's own name and size */
.sdfile{display:flex;gap:14px;align-items:stretch}
.sdthumb{position:relative;flex:0 0 200px;height:132px;overflow:hidden;border:1px solid var(--line2);
  border-radius:10px;background:var(--bg);display:flex;align-items:center;justify-content:center}
.sdthumbph{font-size:26px;opacity:.55}
/* ⚠ `pointer-events:none` is not decoration: without it the frame swallows the
   click that is meant to open the card, and the thumbnail reads as a dead spot */
.sdthumbfr{position:absolute;top:0;left:0;width:900px;height:594px;border:0;background:#fff;
  transform:scale(.2222);transform-origin:0 0;pointer-events:none}
.sdthumb.gone{color:var(--sub);font-size:11.5px;text-align:center;padding:8px}
.sdthumb.gone .sdthumbph{font-size:11.5px}
.sdfmeta{display:flex;flex-direction:column;gap:6px;align-items:flex-start;justify-content:center;min-width:0}
.sdfmeta .fname{font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}

/* the full page: the bar that says what it is, then the file at full size */
.sdvbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.sdvmodes,.sdvpage{display:flex;align-items:center;gap:6px;margin-left:auto}
.sdvpage{margin-left:0}
.sdvpage b{font-size:12.5px;min-width:18px;text-align:center}
.sdvnote{margin-left:auto}
.sdview{height:calc(calc(100 * var(--vh)) - 330px);min-height:340px;border:1px solid var(--line2);
  border-radius:10px;overflow:hidden;background:var(--bg);display:flex}
.sdviewfr{flex:1 1 auto;width:100%;height:100%;border:0;display:block;background:#fff}
.sdvfoot{display:block;margin-top:8px;font-size:11.5px}
#sdFull{margin-left:8px;flex:0 0 auto}
.sdvnote+#sdFull{margin-left:12px}
/* presenting: the card takes the screen and the frame takes the card. ⚠ the page
   is drawn at `zoom`, so a fullscreen element still lives under it — `100vh`
   would come out at the zoom's share of the screen. `--vh`/`--vw` are the
   viewport divided by the zoom, which is what makes this land exactly. */
.card.sdfull:fullscreen{width:calc(100 * var(--vw));height:calc(100 * var(--vh));
  margin:0;border:0;border-radius:0;background:var(--panel);display:flex;flex-direction:column;overflow:hidden}
.card.sdfull:fullscreen>.cb{flex:1 1 auto;display:flex;flex-direction:column;min-height:0;padding:10px 14px 12px}
.card.sdfull:fullscreen .sdview{flex:1 1 auto;height:auto;min-height:0}
.card.sdfull:fullscreen .sdvfoot{display:none}
@media (max-width:828px){
  .sdfile{flex-direction:column}
  .sdthumb{flex:0 0 auto;width:100%;height:150px}
  .sdthumbfr{transform:scale(.35)}
}

/* ---- Config → Structure: every block folds (V1A) ---- */
.stcard>.ch{gap:9px}
.stcard.closed>.cb{display:none}
.stcard>.ch .bigfold{flex:0 0 auto;font-size:11px}
/* the built-in pages somebody removed, and the way back */
.stgone{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px;
  font-size:11.5px;color:var(--sub)}

/* ============================================================
   BOARD OFFICE — the space above the streams (V5 · BOARD OFFICE V1)
   ============================================================ */
/* "Hanya ada Board office sebagai dashboard (tanpa dropdown, langsung open)":
   the row has no chevron, so it must not keep the space one would sit in, and
   the group is always open — there is nothing to fold it with. */
.boardgrp>.dh{padding-right:12px}
.boardgrp>.subitems{display:block}
/* "Beri pembatas Line" — the divider between the Positions and the pages */
.navrule{height:1px;margin:8px 14px 8px 30px;background:var(--line);opacity:.9}
.side-collapsed .navrule{margin:8px 10px}

/* ---- the cross-space ticks on a Role Permission row ---- */
.rptab td.rpspaces{white-space:normal;min-width:132px;padding-top:6px;padding-bottom:6px}
.rptab td.rpspaces .spbox{display:flex;margin:0 0 3px}
.spbox{display:inline-flex;align-items:center;gap:4px;margin:1px 4px 1px 0;padding:2px 7px 2px 4px;
  border:1px solid var(--line);border-radius:999px;font-size:10.5px;color:var(--sub);
  cursor:pointer;user-select:none;background:var(--bg)}
.spbox input{width:12px;height:12px;margin:0;cursor:pointer;accent-color:var(--accent)}
.spbox.on{border-color:var(--accent);color:var(--accent);background:var(--accent-soft)}
.spbox.fixed{cursor:default;opacity:.72}
.spbox.fixed input{cursor:default}
.spbox:not(.fixed):hover{border-color:var(--accent)}
/* the switcher row for a space that is declared but not built yet */
.wssub .wsnone{color:var(--sub);font-size:11.5px;opacity:.8}

/* ---- Board Office · Document ---- */
.bdoctbl tbody tr{cursor:pointer}
.bdoctbl tbody tr:hover{background:var(--soft)}
.tabs .tabn{margin-left:6px;font-size:10px;opacity:.65;font-weight:600}
/* the status column carries a full pill — "Menunggu Persetujuan" is a long word */
.bdoctbl td:nth-child(4){overflow:visible;white-space:nowrap}
/* a space this reader does not hold: drawn, named, and shut */
.brandmenu .wsrow.locked{opacity:.55;cursor:not-allowed}
.brandmenu .wsrow.locked:hover{background:transparent}

/* ---- the multi-select people picker (ADVISOR V1) ---- */
.peoplepick{min-width:280px}
.peoplepick .plist{max-height:260px}
.peoplepick .plist button{display:flex;align-items:center;gap:8px;width:100%;text-align:left}
.peoplepick .plist button .nm{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.peoplepick .plist button .c{color:var(--sub);font-size:10.5px;margin-left:auto;white-space:nowrap}
.peoplepick .plist button .ck{color:var(--accent);margin-left:6px;flex:0 0 auto}
.peoplepick .plist button.on{background:var(--accent-soft)}
.pkfoot{display:flex;align-items:center;gap:8px;padding:8px 9px 4px;border-top:1px solid var(--line2);margin-top:4px}
.pkfoot .pkn{font-size:11px;color:var(--sub)}
.pkfoot .btn{margin-left:auto}
/* `.pickpop button:hover` outranks `.btn.primary` -- one class and a pseudo
   beat two classes -- so hovering the picker's own Save / Add To Document
   button swapped its dark fill for `--soft` while the label stayed `--bg`:
   white on near-white, readable only until the pointer arrived. A real button
   in the foot keeps its fill on hover and dims instead. A plain `.btn` there
   needs nothing: `--soft` under `--ink` is the hover it would have had. */
.pickpop .pkfoot .btn.primary:hover{background:var(--ink);opacity:.9}

/* ---------- CONFIG → ARCHIVE (PARTIAL TASK §9) ---------- */
.archbar{display:flex;align-items:center;gap:10px;padding:0 0 12px;
  border-bottom:1px solid var(--line2);margin-bottom:12px}
.archbar .btn.danger{color:var(--dang);border-color:var(--line)}
.archbar .btn.danger:hover{border-color:var(--dang);background:var(--soft)}
.archsp{margin-bottom:18px}
.archsp>.grouph{padding-left:2px}
.archgrp{margin:0 0 10px}
.archgrp>.grouph{padding-left:2px;font-size:9.5px;opacity:.8}
.archrow{display:flex;align-items:center;gap:10px;padding:7px 8px;border-radius:8px;
  border-bottom:1px solid var(--line2);cursor:pointer}
.archrow:hover{background:var(--soft)}
.archrow input[type=checkbox]{width:14px;height:14px;accent-color:var(--accent);flex:0 0 14px}
.archrow .ax{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.3}
.archrow .ax b{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.archrow .ax i{font-style:normal;font-size:10.5px;color:var(--sub);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.archrow .ad{font-size:10.5px;color:var(--sub);flex:0 0 auto}
.archrow .btn{flex:0 0 auto}

/* ---------- MEMO (PARTIAL TASK §3) ---------- */
/* the popover: small, centred, draggable — *"tidak terlalu besar, seperti
   section di Proposal"*. Its own thing rather than `#modal`, which is inset:24px
   and fills the screen. */
/* ⚠ **145, not 180.** `.pickpop` sits at 160 on purpose — the comment above it
   says a picker "opened from it is never trapped behind the box" — so anything
   that opens one has to stay below it. At 180 the recipient picker rendered
   *behind* this window: all the reader saw was the strip of it sticking out past
   the bottom edge. 145 puts the memo with `.calpop` (140), the other floating
   card, and under every picker it can open. The ladder: peek 50 · modal 55 ·
   calpop 140 · memowin 145 · pickpop 160. */
.memowin{position:fixed;z-index:145;width:min(520px,calc(calc(100 * var(--vw)) - 24px));
  max-height:calc(calc(100 * var(--vh)) - 24px);display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shl)}
.memowin .mwh{display:flex;align-items:center;gap:8px;padding:9px 10px;
  border-bottom:1px solid var(--line2);cursor:grab;touch-action:none}
.memowin .mwh:active{cursor:grabbing}
.memowin .mwg{color:var(--sub);font-size:11px;flex:0 0 auto}
.memowin .mwh .ttl{flex:1;min-width:0;font-weight:700;font-size:13px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.memowin .mwb{flex:1;min-height:0;overflow:auto;padding:12px 14px}
.memowin .mwf{flex:0 0 auto;display:flex;align-items:center;gap:8px;
  padding:9px 12px;border-top:1px solid var(--line2)}
.memowin .mwf .sub{flex:1;min-width:0;font-size:11px}
.memowin .mrow{display:flex;gap:10px;align-items:flex-start;padding:5px 0}
.memowin .mrow .mk{flex:0 0 84px;font-size:11.5px;color:var(--sub);padding-top:5px}
.memowin .mrow .mv{flex:1;min-width:0}
.memowin .mrow .mv.ro{padding-top:5px;font-size:12.5px}
.memowin .mrow input{width:100%}
.memowin .pjsel.pic{display:flex;flex-wrap:wrap;gap:4px;align-items:center;width:100%;
  min-height:30px;text-align:left}
.memowin .mbody{margin-top:8px;border:1px solid var(--line);border-radius:9px;overflow:hidden}
.memowin .memoed{min-height:120px;max-height:calc(38 * var(--vh));overflow:auto;padding:10px 12px}
.memowin .mread{white-space:pre-wrap;margin-top:10px;padding-top:10px;border-top:1px solid var(--line2);
  font-size:12.5px;line-height:1.65}
.memowin .mok{display:flex;align-items:center;gap:7px;margin-left:auto;
  font-size:12.5px;font-weight:600;cursor:pointer}
.memowin .mok input{width:15px;height:15px;accent-color:var(--accent)}
/* the Home band. It is only ever in the DOM when there is something in it. */
.memoband{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));
  gap:12px;margin-bottom:14px}
.memocard{padding:12px 13px;cursor:pointer;display:flex;flex-direction:column;gap:5px}
.memocard:hover{border-color:var(--accent)}
.memocard .mc-h{display:flex;align-items:center;gap:8px}
.memocard .mc-k{font-size:9.5px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;
  color:var(--accent);background:var(--accent-soft);padding:2px 7px;border-radius:5px}
.memocard .mc-d{margin-left:auto;font-size:10.5px;color:var(--sub)}
.memocard .mc-t{font-size:13px;font-weight:700}
.memocard .mc-b{font-size:11.5px;color:var(--sub);line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.memocard .mc-f{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--sub);margin-top:2px}

/* §3b — the memo foot: sent time, Read at beneath it, the tick on the right */
.memowin .mwf{align-items:flex-start}
.memowin .mfl{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.memowin .mrdl{font-size:11px}
.memowin .mrd{display:block;font-size:11px;color:var(--sub)}
.memowin .mrd b{font-weight:600;color:var(--ink)}
.memowin .mrdd{font-size:11px;color:var(--sub)}
.memowin .mrdd>summary{cursor:pointer;list-style:none;color:var(--accent);font-weight:600}
.memowin .mrdd>summary::-webkit-details-marker{display:none}
.memowin .mrdd>summary::before{content:'▸';display:inline-block;margin-right:4px;transition:transform .12s}
.memowin .mrdd[open]>summary::before{transform:rotate(90deg)}
.memowin .mrdb{display:block;padding:4px 0 0 12px}
.memowin .mok{align-self:center}

/* ---------- SPEAKER / ANNOUNCEMENT (PARTIAL TASK §4) ---------- */
.memowin .spcpick,.memowin .durpick{display:flex;flex-wrap:wrap;gap:5px}
.memowin .chip{padding:4px 10px;border:1px solid var(--line);border-radius:999px;
  background:var(--bg);font-size:11.5px;font-weight:600;color:var(--sub);cursor:pointer}
.memowin .chip.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
.memowin .chip.locked{opacity:.5;cursor:not-allowed}
/* §86 — and the two read surfaces keep the breaks in what is **already** stored:
   every announcement and memo written before `editorHTML` learned to convert them
   carries bare newlines, and `pre-wrap` is what makes those readable again. */
.memowin .spread{font-size:12.5px;line-height:1.65;white-space:pre-wrap}
.memowin .spmeta{display:flex;align-items:center;gap:7px;margin-top:12px;padding-top:10px;
  border-top:1px solid var(--line2);font-size:11.5px}
.memowin .spmeta .sub{margin-left:auto;font-size:11px}
/* the Home band, under the memos. Drawn only when there is something in it. */
.speakband{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));
  gap:12px;margin-bottom:14px}
.speakcard{padding:12px 13px;cursor:pointer;display:flex;flex-direction:column;gap:5px;
  border-left:3px solid var(--warn)}
.speakcard:hover{border-color:var(--warn)}
.speakcard .sp-h{display:flex;align-items:center;gap:8px}
.speakcard .sp-k{font-size:9.5px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;
  color:var(--warn);background:var(--warnb);padding:2px 7px;border-radius:5px}
.speakcard .sp-left{margin-left:auto;font-size:10.5px;color:var(--sub)}
.speakcard .sp-t{font-size:13px;font-weight:700}
.speakcard .sp-b{font-size:11.5px;color:var(--sub);line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.speakcard .sp-f{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--sub);margin-top:2px}
.speakcard .sp-f .sub{margin-left:auto}

/* §4a — the card whose window is open wears the same mark a note card wears.
   `.ncard.active` already covers the ones in Notes; the Home band cards are
   `.card.memocard` / `.card.speakcard`, so they need saying explicitly. */
.memocard.active,.speakcard.active{background:var(--soft);
  box-shadow:inset 0 0 0 1px var(--line)}
.memocard.active{border-color:var(--accent)}
.speakcard.active{border-color:var(--warn)}

/* §82 — a quote discounted past what its points cost says so */
#skRoot .skwarn{color:var(--dang)}

/* ---------- SYNC (B2) ----------
   A dot beside the clock, and deliberately almost invisible when all is well:
   it is there to be noticed when it is *not* green, not to be looked at. */
.syncdot{width:7px;height:7px;border-radius:50%;background:var(--ok);opacity:.5;
  flex:0 0 auto;margin-left:-4px;transition:background .2s,opacity .2s}
.syncdot.busy{background:var(--warn);opacity:1}
.syncdot.off{background:var(--dang);opacity:1}

/* ---------- CONFIG → DATABASE (B0 — export & import) ---------- */
/* `.pill` carries no ground of its own — every use pairs it with a state class
   that brings one. These counters have no state, so they get their own. */
.dbpill{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;
  padding:3px 10px;border-radius:20px;background:var(--soft);color:var(--sub);white-space:nowrap}
.dbpill b{color:var(--ink);font-weight:700}
.dbchk{display:flex;align-items:center;gap:8px;margin-top:16px;font-size:12.5px;cursor:pointer}
.dbchk input{cursor:pointer}
/* the chosen backup, described before it is allowed to overwrite anything */
.dbfile{margin-top:14px;padding:14px;border:1px solid var(--line);border-radius:10px;background:var(--soft)}
.dbfn{font-weight:700;font-size:13px;word-break:break-all}
.dbfm{font-size:11.5px;color:var(--sub);margin:2px 0 10px}
