/* ============================================================
   JoFiPA — Job Fit And Productivity Analysis
   Corporate Design System — Navy Blue, Black And Gold
   Light, Dark And System Themes · Glassmorphism
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
:root{
  --navy:#0b1f4b; --navy-2:#12306e; --navy-3:#1c4394;
  --gold:#D6A62A; --gold-2:#E3BF4E; --gold-soft:rgba(214,166,42,.15);
  --black:#081C4B;
  --bg:#081C4B;
  --surface:#10285F;
  --surface-strong:#0C224F;
  --surface-border:rgba(255,255,255,.08);
  --text:#FFFFFF;
  --text-muted:#BFC7DA;
  --radius:12px;
  --font:'Poppins',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  --ok:#1a7f4e; --ok-soft:rgba(26,127,78,.14);
  --warn:#a66a00; --warn-soft:rgba(166,106,0,.14);
  --bad:#b3261e; --bad-soft:rgba(179,38,30,.12);
  --ease:cubic-bezier(.22,.8,.3,1);
  /* --card was referenced across the app but never defined, which made the
     appbar, notification panel, chat panes and tab chips render with a
     TRANSPARENT background (client fix, Jul 2026). It now always resolves
     to the solid card colour of the active theme. */
  --card-solid:#ffffff;
  --card:var(--card-solid);
}
html[data-theme="light"]{
  --bg:#eef1f6; --bg-glow-1:rgba(11,31,75,.10); --bg-glow-2:rgba(201,162,39,.12);
  --glass:rgba(255,255,255,.72); --glass-strong:rgba(255,255,255,.9);
  --ink:#10131c; --ink-2:#3d4557; --ink-3:#8a92a6;
  --line:rgba(11,31,75,.14); --line-gold:rgba(201,162,39,.4);
  --shadow:0 8px 28px rgba(11,31,75,.10);
  --side-grad:linear-gradient(180deg,#0b1f4b 0%,#0c2456 55%,#0b0d12 100%);
  --input-bg:rgba(255,255,255,.85);
  --hover:rgba(11,31,75,.05);
  --card-solid:#ffffff;
}
html[data-theme="dark"]{
  --bg:#0a0d16; --bg-glow-1:rgba(28,67,148,.25); --bg-glow-2:rgba(201,162,39,.10);
  --glass:rgba(18,26,46,.62); --glass-strong:rgba(18,26,46,.88);
  --ink:#eef1f8; --ink-2:#b6bfd2; --ink-3:#6e7891;
  --line:rgba(227,191,78,.14); --line-gold:rgba(201,162,39,.35);
  --shadow:0 10px 34px rgba(0,0,0,.45);
  --side-grad:linear-gradient(180deg,#0b1f4b 0%,#0a1533 55%,#05060a 100%);
  --input-bg:rgba(10,14,26,.6);
  --hover:rgba(227,191,78,.07);
  --card-solid:#141a2c;
}
*{box-sizing:border-box;margin:0;padding:0}
html{font-size:15.5px}
body{
  font-family:var(--font);color:var(--ink);line-height:1.6;min-height:100vh;
  background:var(--bg);
  background-image:radial-gradient(560px 380px at 12% -4%,var(--bg-glow-1),transparent 65%),
                   radial-gradient(620px 420px at 96% 8%,var(--bg-glow-2),transparent 60%),
                   radial-gradient(500px 400px at 55% 110%,var(--bg-glow-1),transparent 65%);
  background-attachment:fixed;
  transition:background .35s var(--ease),color .35s var(--ease);
}
a{color:var(--navy-3);text-decoration:none}
html[data-theme="dark"] a{color:var(--gold-2)}

@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes popIn{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}

/* ---------- Layout ---------- */
/* ============================================================
   v39 item 4 — THE MENU STOPPED DECIDING HOW TALL THE PAGE IS.

     "Re-arrange and neatly align the Settings page, Dashboard, and
      other pages with the side-bar to make scrolling and navigation
      on modules across devices user-friendly."

   MEASURED, not guessed. On a 1440x900 laptop, signed in as a
   Director:

     personnel.html      content 900,  PAGE 1400 — 500px of nothing
     communications.html content 900,  PAGE 1446 — 546px of nothing
     index.html          content 3194, PAGE 3194
     the sidebar itself  1353px, with fifteen of its sixteen groups
                         COLLAPSED

   The cause is one line of flexbox. .app is a flex row; the sidebar
   is a flex item 1353px tall; a flex row is as tall as its tallest
   item; .main is stretched to match. So on every page whose content
   is shorter than the menu — which is most of them — you scroll five
   hundred pixels of empty page to reach nothing, and the scrollbar
   says there is more when there is not. On Communications it is
   worse than cosmetic: that page sizes its own message list from the
   window (v35's --chatTop / --chatGap), and a page that is 546px
   taller than the window puts the composer below the fold.

   THE THREE THINGS THIS HAD TO DO AT ONCE
     1. stop the menu setting the page height (this)
     2. not clip the menu, which is what v34 did
     3. not turn the menu into a squeezed little scrolling panel with
        its own gold scrollbar, which is what v35 did and what the
        client asked to have reversed in v36

   Sixteen collapsed group headers are 768px before the logo, the
   search box and Sign Out are counted, so on a 900px laptop the menu
   CANNOT fit however it is arranged. Something has to scroll. The
   question v35 got wrong was WHICH PART:

     v35 scrolled .sidebar__body — search box and all — inside a box
     that a hand-applied max-height:calc(100vh - 200px) had already
     made 200px shorter than it needed to be. That is the "collapsed
     menu" the client reported.

     v39 scrolls ONLY .sidebar-nav, in the full height left over after
     the logo and Sign Out, with nothing shrinking (flex-shrink:0 on
     everything that is not the list). The logo stays put, SIGN OUT IS
     ALWAYS REACHABLE — in v34 and v36 you had to scroll the whole
     page past the menu to find it — and the page is exactly as tall
     as the page.

   And the scrollbar is DELIBERATELY VISIBLE, with a fade at the foot
   of the list. That is the v37 lesson written into CSS: the org chart
   had scrolled since v32 without ever saying so, because the platform
   draws overlay scrollbars, and it was reported as broken. A menu
   that scrolls invisibly is a menu with items nobody knows are there.

   Anybody who preferred it the old way has body.menu-flows, from one
   switch in Settings → Appearance. That also closes the question the
   v36 notes left open.
   ============================================================ */
/* ============================================================
   v40 item 2 — THE SIDEBAR IS AS TALL AS THE PAGE, NOT AS TALL AS
   THE WINDOW.

   The v39 Dressing document asks for the opposite of what v39 did,
   and each is right about a different thing:

     v39 was asked to stop the MENU deciding the page height. It did
     that by clamping the column to exactly one viewport
     (height:100dvh) with the nav scrolling inside it. The page became
     exactly as tall as the page — and on a 3,194px dashboard the dark
     column stopped 2,100px short of the bottom, because a viewport is
     all it ever was.

     v40 asks for the other half: "the sidebar height must dynamically
     follow the full height of the current page/content container... if
     a page such as Settings extends 1400px vertically, the sidebar
     must also extend to approximately the same document height", and
     equally "if another page is shorter, the sidebar must not
     artificially create unnecessary page height".

   BOTH AT ONCE, AND IT IS THREE DECLARATIONS:

     .app             align-items:stretch  — a flex row stretches its
                      items to the row's height, and the row's height
                      is now always set by .main
     .sidebar         no height of its own; its CONTENT is one sticky
                      panel, so what it contributes to the row is a
                      viewport and never the 1,353px of menu
     .sidebar__sticky position:sticky; height:100dvh — the panel
                      travels down as the document scrolls

   So the column is painted from the top of the layout to the bottom
   of the current page's content, whatever that is; a short page gains
   no extra height, because the sidebar never asks for more than a
   viewport; and a long page does not push Sign Out three screens
   down, because the panel inside is sticky rather than laid out along
   the whole column.

   NOTHING IS MEASURED IN JAVASCRIPT. No resize handler, no
   ResizeObserver, no height calculation — the two pages this had to
   work on differ by a factor of two and neither is named anywhere in
   this file.

   Not position:fixed, which takes the column out of the flow and
   leaves it following nothing. Not height:100vh, which is the rule
   being replaced. And no new inner scrollbar: .sidebar-nav's is the
   one v39 added deliberately, and it is the existing design.

   body.menu-flows still works and still means what it meant.
   ============================================================ */
.app{display:flex;min-height:100vh;min-height:100dvh;overflow-x:hidden;background:var(--bg);font-family:var(--font);
  /* v40: STRETCH, not flex-start. This is the line that carries the
     dark column to the foot of a long page. v39 needed flex-start to
     stop the menu stretching .main; that is now prevented where it
     belongs — by the sidebar not being tall in the first place. */
  align-items:stretch}
/* v36 — THE MENU IS NOT A SCROLLING BOX INSIDE THE MENU.
   (Client request, Sep 2026: "uncollapse the side bar to as it was in
   v34.")

   v35 clamped the sidebar to exactly one viewport — height:100dvh,
   max-height:100dvh, overflow:hidden — so that .sidebar__body's
   long-standing `overflow-y:auto` would finally have a ceiling to work
   against and the 136px of stray PAGE scroll would go away. It did go
   away. What arrived in its place is worse to use: the navigation
   became a short scrolling panel with its own gold scrollbar, the
   groups were squeezed, and on a tall menu the bottom of the list was
   reachable only by scrolling inside a box most people do not notice
   is scrollable. A second, hand-applied `max-height:calc(100vh-200px)`
   on the body made it shorter still, which is how the client came to
   report the menu as collapsed.

   So the ceiling is given up and the pixels are paid instead. The
   sidebar is at LEAST a viewport tall — so on every ordinary screen
   the dark column still reaches the bottom and there is no stray
   scroll — and it GROWS past that when the menu is genuinely taller
   than the window, exactly as it did in v34. Nothing is clipped,
   nothing is squeezed, and no inner scrollbar appears.

   `align-self:flex-start` is what makes growth safe with sticky: it
   stops the flex row stretching the sidebar to the row's height, so
   sticky has somewhere to travel and the foot of a long menu can
   actually be scrolled to — which was true in NEITHER v34 (where
   overflow:hidden clipped it) nor v35 (where the inner box hid it). */
/* v39: the column is EXACTLY one viewport and does not scroll itself
   — .sidebar-nav below is the only thing that does. height rather
   than min-height is the whole difference: min-height let it grow to
   1353px and take the page with it.

   v40: THE COLUMN IS THE PAGE'S HEIGHT AND THE PANEL INSIDE IT IS ONE
   VIEWPORT. The element keeps no height, no max-height and no sticky
   of its own — .sidebar__sticky below has all three — so the flex row
   stretches it to whatever .main turns out to be, and its own content
   never makes the row taller than a screen. align-self:stretch is
   named rather than left to inherit, because .app's align-items is
   the sort of line a later release edits without looking down here. */
.sidebar{width:280px;min-width:280px;flex-shrink:0;align-self:stretch;background:var(--black);color:var(--text);padding:0;display:block;border-right:1px solid rgba(214,166,42,.18);box-shadow:4px 0 30px rgba(0,0,0,.24)}
/* The panel: one viewport, sticky, and the only thing inside the
   column. Everything the sidebar used to be — the flex column, the
   padding, the gap, the overflow rule — moved here, unchanged, so
   that the parts below (header, body, nav, footer) keep working
   against exactly the box they were written for. */
.sidebar__sticky{position:sticky;top:0;height:100vh;height:100dvh;max-height:100dvh;
  display:flex;flex-direction:column;gap:10px;padding:20px 14px 0;overflow:hidden;will-change:transform}
/* The opt-out: the v34/v36 menu, which grows past the window and
   takes the page's scrollbar with it. One switch in Settings.
   v40 — applied to the panel now, since that is where the height is. */
body.menu-flows .sidebar__sticky{position:static;height:auto;max-height:none;min-height:100dvh;overflow:visible}
body.menu-flows .sidebar-nav{overflow:visible;-webkit-mask-image:none;mask-image:none}
.sidebar__header{position:relative;padding:18px 0 12px;border-bottom:1px solid rgba(255,255,255,.08);}
.sidebar__brand{display:block;width:100%;text-align:center;padding:0;margin:0;}
.sidebar__brand-logo{width:180px;max-width:100%;height:auto;border-radius:16px;object-fit:cover;background:var(--surface);display:inline-block;margin:0 auto;}
.sidebar__brand-title,.sidebar__brand-subtitle{display:none !important;}
/* v36: no inner scroller. The menu shows in full and the page carries
   it, which is what "uncollapsed" means here. The scrollbar styling
   below is kept for the one place that still scrolls internally —
   the off-canvas drawer under 1024px, where the sidebar IS a fixed
   panel and has no page to grow into. */
/* v39: the body no longer scrolls — the LIST inside it does. v35
   scrolled this element, search box and all, which is how the search
   box came to disappear off the top of a menu somebody was scrolling. */
.sidebar__body{overflow:visible;display:flex;flex:1 1 auto;flex-direction:column;min-height:0;padding-right:8px;margin-top:12px}
.sidebar__search{padding:0 6px 12px;flex:0 0 auto}
/* v39 — THE ONLY THING THAT SCROLLS is .sidebar-nav, and its rule is
   the one further down this file beside the other .sidebar-nav
   properties — NOT here. Splitting a selector across two places in
   one stylesheet is how v37 lost an hour to organization.html
   re-declaring .oc-scroll after the linked sheet and silently
   winning. Search for "v39 item 4" again below.
   Not an overlay scrollbar: a visible one, always, because the whole
   point is that the person can see the list continues. */
.sidebar-nav::-webkit-scrollbar{width:8px}
.sidebar-nav::-webkit-scrollbar-track{background:rgba(255,255,255,.04);border-radius:99px}
.sidebar-nav::-webkit-scrollbar-thumb{background:rgba(214,166,42,.55);border-radius:99px;
  border:2px solid transparent;background-clip:content-box}
.sidebar-nav::-webkit-scrollbar-thumb:hover{background:rgba(214,166,42,.8);background-clip:content-box}
/* Nothing but the list gives way. This is what stopped the groups
   being squeezed, which is what v36 was asked to undo. */
.sidebar__header,.sidebar__footer{flex:0 0 auto}
.sidebar-group{flex:0 0 auto}
.sidebar-search__input{width:100%;padding:11px 14px;border-radius:12px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.06);color:var(--text);font-size:0.95rem;transition:border-color .2s ease,box-shadow .2s ease}
.sidebar-search__input:focus{outline:none;border-color:rgba(214,166,42,.45);box-shadow:0 0 0 4px rgba(214,166,42,.08);background:rgba(255,255,255,.1)}
.sidebar__body::-webkit-scrollbar{width:8px}
.sidebar__body::-webkit-scrollbar-track{background:transparent}
.sidebar__body::-webkit-scrollbar-thumb{background:rgba(214,166,42,.35);border-radius:99px;border:2px solid transparent;background-clip:content-box}
.sidebar-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.55);backdrop-filter:blur(5px);opacity:0;pointer-events:none;transition:opacity .25s ease;z-index:24}
body.sidebar-open .sidebar-backdrop{display:block;opacity:1;pointer-events:auto}
.sidebar-close{display:none;position:absolute;top:14px;right:14px;width:44px;height:44px;border:none;border-radius:12px;background:rgba(255,255,255,.08);color:var(--text);font-size:1.05rem;cursor:pointer;align-items:center;justify-content:center;display:grid}
/* v39 item 4 — THE ONLY THING IN THE MENU THAT SCROLLS.
   min-height:0 is what makes overflow work at all inside a flex
   column: without it a flex item refuses to be shorter than its
   content and the overflow-y rule does precisely nothing.
   The mask is the fade that says there IS more below — the v37 lesson
   written into CSS, because this platform draws overlay scrollbars
   and a list that scrolls silently is a list whose bottom items
   nobody ever finds. */
.sidebar-nav{display:flex;flex-direction:column;gap:12px;
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding-right:4px;
  scrollbar-width:thin;scrollbar-color:rgba(214,166,42,.55) transparent;
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 26px),transparent 100%);
          mask-image:linear-gradient(to bottom,#000 calc(100% - 26px),transparent 100%)}
.sidebar-group{display:flex;flex-direction:column;border-radius:15px;overflow:hidden;background:var(--surface);border:1px solid rgba(255,255,255,.08)}
.sidebar-group__button{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:46px;padding:0 16px;font-size:14px;font-weight:600;color:var(--text);background:transparent;border:none;cursor:pointer;transition:background .2s ease,color .2s ease}
.sidebar-group__button:hover,.sidebar-group__button:focus-visible{background:rgba(214,166,42,.12);outline:2px solid rgba(214,166,42,.45);outline-offset:2px}
.sidebar-group__button[aria-expanded="true"]{background:rgba(214,166,42,.16)}
.sidebar-group__title{letter-spacing:.02em}
.sidebar-group__chevron{font-size:.92rem;color:var(--gold);transition:transform .24s ease}
.sidebar-group.is-open .sidebar-group__chevron{transform:rotate(180deg)}
.sidebar-group__panel{max-height:0;overflow:hidden;transition:max-height .24s ease,opacity .24s ease;opacity:0}
.sidebar-group.is-open .sidebar-group__panel{opacity:1}
.sidebar-link{display:flex;align-items:center;gap:12px;width:100%;padding:12px 16px;font-size:14px;font-weight:500;color:var(--text-muted);background:transparent;text-decoration:none;border-radius:12px;transition:background .2s ease,color .2s ease,transform .2s ease}
.sidebar-link:hover,.sidebar-link:focus-visible{background:rgba(214,166,42,.15);color:var(--text);outline:2px solid rgba(214,166,42,.38);outline-offset:2px;transform:translateX(1px)}
.sidebar-link.active{background:rgba(214,166,42,.22);color:var(--text);font-weight:600;box-shadow:inset 4px 0 0 0 var(--gold)}
.sidebar-link__icon{width:20px;height:20px;display:grid;place-items:center;color:var(--gold);flex-shrink:0}
.sidebar-link__svg{width:18px;height:18px;display:block}
.sidebar-link__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidebar__footer{border-top:1px solid rgba(255,255,255,.1);padding:14px 0 18px;display:flex;flex-direction:column;gap:8px;margin-top:auto}
.sidebar-action{display:flex;align-items:center;gap:12px;width:100%;padding:12px 16px;background:var(--surface);color:var(--text);border:1px solid rgba(255,255,255,.08);border-radius:12px;text-decoration:none;font-size:14px;font-weight:600;transition:background .2s ease,border-color .2s ease}
.sidebar-action:hover,.sidebar-action:focus-visible{background:rgba(214,166,42,.15);border-color:rgba(214,166,42,.25);outline:2px solid rgba(214,166,42,.38);outline-offset:2px}
.sidebar-action--logout{background:rgba(255,255,255,.04);color:var(--text)}
@media(max-width:1200px){
  .sidebar{width:280px;min-width:280px}
}
@media(max-width:992px){
  .sidebar{position:fixed;left:0;top:0;bottom:0;width:min(85vw,300px);max-width:300px;transform:translateX(-100%);transition:transform .25s ease-in-out;z-index:1030;border-right:1px solid rgba(255,255,255,.12);box-shadow:16px 0 30px rgba(0,0,0,.35);visibility:hidden;}
  body.sidebar-open .sidebar{transform:translateX(0);visibility:visible;}
  body.sidebar-open{overflow:hidden;}
  /* v36: here the sidebar is a FIXED drawer pinned top:0/bottom:0. It
     has no page to grow into, so this is the one place the menu keeps
     its own scroller — without it a tall menu runs off the bottom of
     the screen with no way to reach the end of it. */
  .sidebar{overflow:hidden;min-height:0}
  /* v40 — the drawer IS the viewport here, so the panel stops being
     sticky and simply fills it. Leaving it sticky inside a fixed
     drawer is harmless on most browsers and produces a panel that
     will not reach its own footer on a few, which is the sort of
     difference nobody finds until somebody reports the menu as
     broken on one telephone. */
  .sidebar__sticky{position:static;height:100%;max-height:none;padding:20px 14px 0}
  .sidebar__body{overflow-y:auto;padding-right:10px;}
  .sidebar-close{display:grid}
  .btn.sidebar-toggle,.sidebar-toggle{display:flex !important;position:fixed;top:16px;left:16px;z-index:9999;width:48px;height:48px;border-radius:12px;background:#10285F;color:#FFFFFF;font-size:24px;align-items:center;justify-content:center;cursor:pointer;border:none;box-shadow:0 12px 32px rgba(0,0,0,.28);}
  .sidebar-toggle:focus{outline:2px solid rgba(214,166,42,.65);outline-offset:2px;}
  /* v39 — align-items:stretch AGAIN, and this is not belt and braces.
     Below 992px .app turns into a COLUMN, so its cross axis is
     HORIZONTAL. The align-items:flex-start put on .app for the
     desktop layout — where it stops the menu stretching the page —
     therefore means "shrink to fit" SIDEWAYS down here, and a page
     containing a wide register shrink-fits to the register: .main
     measured 1303px inside a 390px telephone, with the account menu
     and half the dashboard pushed off the right-hand edge, where
     .app{overflow-x:hidden} swallowed them without so much as a
     scrollbar to say they were there. Found by screenshotting a
     telephone, never by reading the rule. */
  .app{flex-direction:column;align-items:stretch}
  .main{padding:18px 16px 30px;min-width:0;max-width:100%}
  .sidebar-group__button{font-size:13px;padding:12px 14px}
  .sidebar-link{font-size:13px;padding:11px 14px}
  .sidebar-action{font-size:13px;padding:11px 14px}
}
@media(min-width:992px){
  .sidebar-toggle{display:none !important;}
}
@media(min-width:768px) and (max-width:991px){
  .sidebar{width:280px;}
}
@media(max-width:767px){
  .sidebar{width:min(85vw,300px);}
}
@media(max-width:480px){
  .main{padding:14px 12px 24px}
}
@media(max-width:680px){
  .sidebar{width:86vw}
  .sidebar__brand-title{font-size:.98rem}
}
@media(max-width:520px){
  .main{padding:14px 12px 24px}
}

.main{flex:1;min-width:0;padding:26px 36px 64px;animation:fadeIn .4s var(--ease)}
/* ---------- Global header bar (Jul 2026) ---------- */
.appbar{position:sticky;top:8px;z-index:60;display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;
  margin:0 0 18px;padding:8px 14px;background:var(--card);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 6px 18px rgba(0,0,0,.08);backdrop-filter:blur(8px)}
.appbar-left{display:flex;align-items:center;gap:10px;min-width:0;flex:1 1 auto}
/* v36 — WHAT THE PRODUCT IS, on the title bar (client request, Sep 2026).
   Two lines in the space one line used: the organization, and under it
   what JoFiPA does. Stacked rather than side by side, because that way
   the two read as one heading and the organization keeps the emphasis —
   the description is context, not a competing title. When the bar runs
   out of room it is the SECOND line that goes, never the tenant's own
   name, and the full text stays on the title attribute either way. */
.appbar-title{display:flex;flex-direction:column;gap:1px;min-width:0;flex:0 1 auto}
.appbar-org{font-weight:800;font-size:.95rem;color:var(--navy);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;min-width:0;line-height:1.25}
.appbar-what{font-size:.7rem;font-weight:600;letter-spacing:.02em;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;min-width:0;line-height:1.2}
[data-theme=dark] .appbar-org{color:var(--ink)}
.appbar-right{display:flex;align-items:center;gap:9px;flex-wrap:wrap;justify-content:flex-end}
.userdd{position:relative;display:inline-block}
.userdd-btn{display:flex;align-items:center;gap:8px;border:1px solid var(--line);background:var(--input-bg);
  border-radius:99px;padding:4px 12px 4px 4px;cursor:pointer;font-family:inherit;color:var(--ink);transition:box-shadow .2s}
.userdd-btn:hover{box-shadow:0 0 0 3px var(--gold-soft)}
.userdd-av{width:30px;height:30px;border-radius:99px;background:linear-gradient(135deg,var(--navy),var(--navy-2));
  color:#e8ddb0;display:grid;place-items:center;font-weight:800;font-size:.72rem;flex:none}
.userdd-name{display:flex;flex-direction:column;align-items:flex-start;line-height:1.15;max-width:150px}
.userdd-name b{font-size:.8rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.userdd-name small{font-size:.62rem;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.userdd-caret{font-size:.7rem;color:var(--ink-2)}
.userdd-menu{display:none;position:absolute;right:0;top:112%;min-width:210px;background:var(--card-solid);border:1px solid var(--line);
  border-radius:12px;box-shadow:0 14px 34px rgba(0,0,0,.28);padding:6px;z-index:90;
  max-width:calc(100vw - 24px);max-height:min(70vh,420px);overflow:auto;color:var(--ink)}
.userdd-menu.open{display:block}
/* dropdown panels must be fully OPAQUE — content behind them must never
   show through (client request, Jul 2026) */
#notifPanel,.userdd-menu,#notifPrefs{background:var(--card-solid)!important;backdrop-filter:none!important}
/* the notification panel must never spill off a small screen */
#notifPanel{max-width:calc(100vw - 24px);color:var(--ink)}
/* avatar images (profile pictures) */
.userdd-av{overflow:hidden}
.userdd-av img,.avat img{width:100%;height:100%;object-fit:cover;border-radius:99px;display:block}
/* appbar auto-hide: slides away scrolling DOWN, reappears the moment the
   user scrolls UP — no need to travel back to the top */
.appbar{transition:transform .25s ease,opacity .2s ease}
.appbar.appbar-hide{transform:translateY(calc(-100% - 14px));opacity:0;pointer-events:none}
/* the mobile hamburger lives INSIDE the appbar flow so it can never cover
   the organization name */
.appbar .sidebar-toggle{position:static!important;top:auto!important;left:auto!important;width:40px!important;height:40px!important;
  font-size:19px!important;border-radius:10px!important;box-shadow:0 3px 10px rgba(0,0,0,.18)!important;flex:none}
.userdd-menu a{display:block;padding:9px 12px;border-radius:8px;font-size:.84rem;color:var(--ink);text-decoration:none}
.userdd-menu a:hover{background:var(--gold-soft)}
.userdd-menu .userdd-out{border-top:1px solid var(--line);margin-top:4px;color:var(--bad)}
@media(max-width:640px){
  .appbar{padding:6px 10px}
  .userdd-name{display:none}
  /* the organization name shares the row with the hamburger; it truncates
     with an ellipsis instead of being covered (client fix, Jul 2026) */
  .appbar-org{font-size:.84rem}
  /* No room for two lines beside the hamburger and the bell. The
     organization stays; what the product is goes to the title. */
  .appbar-what{display:none}
}

.topbar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:24px;flex-wrap:wrap;position:relative;}
.topbar > div:first-child{flex:1 1 0%;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;}
.topbar h1{font-size:1.5rem;font-weight:700;letter-spacing:-.3px;margin:0;}
.topbar h1::after{content:"";display:block;width:56px;height:3px;margin-top:7px;border-radius:3px;background:linear-gradient(90deg,var(--gold),transparent)}
.topbar .sub{color:var(--ink-2);font-size:.9rem;line-height:1.55;margin-top:8px;max-width:100%;display:block;white-space:normal;overflow:visible;text-overflow:unset;}
.topbar .actions{display:flex;gap:9px;flex-wrap:wrap;align-items:center;flex:0 0 auto;justify-content:flex-end;}

/* Theme switcher + session chip */
.tswitch{display:inline-flex;border:1px solid var(--line);border-radius:99px;overflow:hidden;background:var(--glass);backdrop-filter:blur(10px)}
.tswitch button{border:none;background:transparent;color:var(--ink-2);padding:6px 12px;font-size:.78rem;cursor:pointer;font-family:inherit;transition:all .2s}
.tswitch button.on{background:linear-gradient(135deg,var(--navy),var(--navy-3));color:#fff}
.who{font-size:.78rem;color:var(--ink-2);background:var(--glass);border:1px solid var(--line);border-radius:99px;padding:6px 14px;backdrop-filter:blur(10px)}
.who b{color:var(--gold)}

/* ---------- Glass Cards ---------- */
.card{background:var(--glass);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border:1px solid var(--line);border-top:1px solid var(--line-gold);border-radius:var(--radius);box-shadow:var(--shadow);padding:22px 24px;margin-bottom:20px;animation:rise .45s var(--ease) both}
.card:nth-child(2){animation-delay:.05s}.card:nth-child(3){animation-delay:.1s}.card:nth-child(4){animation-delay:.15s}
.card h2{font-size:1.02rem;font-weight:700;margin-bottom:4px}
.card .hint{color:var(--ink-3);font-size:.82rem;margin-bottom:14px}
.grid{display:grid;gap:16px}
.g2{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.g4{grid-template-columns:repeat(auto-fit,minmax(185px,1fr))}

.kpi{background:var(--glass);backdrop-filter:blur(16px);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:17px 19px;display:flex;flex-direction:column;gap:2px;transition:transform .25s var(--ease),box-shadow .25s;animation:rise .45s var(--ease) both}
.kpi:hover{transform:translateY(-3px)}
.kpi .lab{font-size:.72rem;text-transform:uppercase;letter-spacing:.9px;color:var(--ink-3);font-weight:700}
.kpi .val{font-size:1.7rem;font-weight:800;letter-spacing:-.5px}
.kpi .det{font-size:.78rem;color:var(--ink-2)}
.kpi.b-navy{border-top:3px solid var(--navy-3)} .kpi.b-gold{border-top:3px solid var(--gold)}
.kpi.b-ok{border-top:3px solid var(--ok)} .kpi.b-bad{border-top:3px solid var(--bad)}
.kpi.b-warn{border-top:3px solid var(--warn)} .kpi.b-ink{border-top:3px solid var(--ink-3)}

/* ---------- Buttons ---------- */
.btn{display:inline-flex;align-items:center;gap:7px;border:1px solid transparent;border-radius:10px;padding:9px 17px;font-size:.88rem;font-weight:600;cursor:pointer;font-family:inherit;transition:all .2s var(--ease);white-space:nowrap}
.btn:active{transform:scale(.97)}
.btn-p{background:linear-gradient(135deg,var(--navy) 0%,var(--navy-3) 100%);color:#fff;box-shadow:0 4px 14px rgba(11,31,75,.3)}
.btn-p:hover{box-shadow:0 6px 20px rgba(11,31,75,.42);transform:translateY(-1px)}
.btn-g{background:linear-gradient(135deg,var(--gold) 0%,var(--gold-2) 100%);color:var(--navy);box-shadow:0 4px 14px rgba(201,162,39,.35);font-weight:700}
.btn-g:hover{box-shadow:0 6px 20px rgba(201,162,39,.5);transform:translateY(-1px)}
.btn-s{background:var(--glass-strong);color:var(--ink);border-color:var(--line)}
.btn-s:hover{border-color:var(--line-gold);background:var(--hover)}
.btn-ok{background:var(--ok);color:#fff}
.btn-d{background:var(--bad-soft);color:var(--bad);border-color:rgba(179,38,30,.3)}
.btn-sm{padding:4px 11px;font-size:.78rem;border-radius:8px}
.btn:disabled{opacity:.5;cursor:not-allowed}

/* ---------- Forms ---------- */
label.f{display:block;font-size:.8rem;font-weight:600;color:var(--ink-2);margin:12px 0 4px}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]),
input[type=text],input[type=number],input[type=email],input[type=password],input[type=date],input[type=time],
input[type=search],select,textarea{
  width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:9px;font-family:inherit;font-size:.9rem;
  background:var(--input-bg);color:var(--ink);transition:border .2s,box-shadow .2s;backdrop-filter:blur(6px)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-soft)}
input::placeholder,textarea::placeholder{color:var(--ink-3);opacity:.8}
textarea{resize:vertical;min-height:76px}
.frow{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}

/* ---------- Tables ---------- */
.tbl-wrap{overflow-x:auto;border-radius:10px}
table.tbl{width:100%;border-collapse:collapse;font-size:.87rem}
.tbl th{text-align:left;padding:10px 12px;background:linear-gradient(135deg,var(--navy),var(--navy-2));color:#e8ddb0;font-size:.7rem;text-transform:uppercase;letter-spacing:.8px;white-space:nowrap}
.tbl th:first-child{border-radius:9px 0 0 0}.tbl th:last-child{border-radius:0 9px 0 0}
.tbl td{padding:11px 12px;border-bottom:1px solid var(--line);vertical-align:middle}
.tbl tr{transition:background .15s}
.tbl tr:hover td{background:var(--hover)}
.tbl .num{text-align:right;font-variant-numeric:tabular-nums}

/* ---------- Badges, Bars ---------- */
.badge{display:inline-block;padding:3px 11px;border-radius:999px;font-size:.72rem;font-weight:700;letter-spacing:.3px}
.bg-ok{background:var(--ok-soft);color:var(--ok)} .bg-warn{background:var(--warn-soft);color:var(--warn)}
.bg-bad{background:var(--bad-soft);color:var(--bad)}
.bg-navy{background:rgba(28,67,148,.15);color:var(--navy-3)}
html[data-theme="dark"] .bg-navy{color:#9db8ee}
.bg-gold{background:var(--gold-soft);color:var(--gold)}
.bg-mut{background:var(--hover);color:var(--ink-2)}

.bar{height:8px;background:var(--hover);border-radius:99px;overflow:hidden;min-width:70px;border:1px solid var(--line)}
.bar>i{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--navy-3),var(--gold));transition:width .6s var(--ease)}
.bar>i.ok{background:var(--ok)} .bar>i.warn{background:var(--warn)} .bar>i.bad{background:var(--bad)}
.score-cell{display:flex;align-items:center;gap:9px}
.score-cell b{min-width:38px;text-align:right;font-variant-numeric:tabular-nums}

.empty{text-align:center;color:var(--ink-3);padding:38px 12px;font-size:.9rem}
.empty .big{font-size:2.1rem;margin-bottom:6px}
.chips{display:flex;flex-wrap:wrap;gap:6px}
.chip{background:var(--hover);border:1px solid var(--line);border-radius:999px;padding:2px 12px;font-size:.76rem;color:var(--ink-2)}
.divider{border:none;border-top:1px solid var(--line);margin:16px 0}
.muted{color:var(--ink-3);font-size:.82rem}
.right{text-align:right}
.flex{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.spacer{flex:1}

/* Likert */
.likert{display:flex;gap:5px}
.likert label{flex:1;text-align:center;border:1px solid var(--line);border-radius:8px;padding:7px 2px;font-size:.78rem;cursor:pointer;background:var(--input-bg);color:var(--ink-2);transition:all .18s var(--ease)}
.likert label:hover{border-color:var(--gold)}
.likert input{display:none}
.likert label:has(input:checked){background:var(--gold-soft);border-color:var(--gold);color:var(--ink);font-weight:700;transform:scale(1.05)}

/* Rating dots */
.rate{display:inline-flex;gap:5px}
.rate button{width:31px;height:31px;border-radius:50%;border:1.5px solid var(--line);background:var(--input-bg);cursor:pointer;font-size:.8rem;font-weight:700;color:var(--ink-3);transition:all .18s var(--ease)}
.rate button:hover{border-color:var(--gold)}
.rate button.on{background:linear-gradient(135deg,var(--navy),var(--navy-3));border-color:var(--gold);color:#fff;transform:scale(1.1)}

/* Dropzone */
.drop{border:2.5px dashed var(--line-gold);border-radius:var(--radius);padding:40px 20px;text-align:center;color:var(--ink-2);background:var(--gold-soft);cursor:pointer;transition:all .25s var(--ease)}
.drop:hover,.drop.over{border-color:var(--gold);background:var(--gold-soft);transform:scale(1.005);box-shadow:0 0 0 5px var(--gold-soft)}
.drop .big{font-size:2.3rem;margin-bottom:8px;color:var(--gold)}

/* Modal */
.modal-bg{position:fixed;inset:0;background:rgba(5,8,18,.6);backdrop-filter:blur(5px);display:none;align-items:flex-start;justify-content:center;padding:40px 16px;z-index:60;overflow-y:auto}
.modal-bg.open{display:flex}
.modal{background:var(--glass-strong);backdrop-filter:blur(24px);border:1px solid var(--line-gold);border-radius:16px;max-width:740px;width:100%;padding:26px 28px;box-shadow:0 24px 70px rgba(0,0,0,.4);animation:popIn .3s var(--ease)}
.modal h3{font-size:1.1rem;margin-bottom:14px}
.modal .m-foot{display:flex;justify-content:flex-end;gap:9px;margin-top:20px}

/* Toast — v39 item 5: THE LOWER RIGHT-HAND CORNER.

   "Display notifications on the lower right-side corner of the
    device's screen"

   There were two notification corners and they were not the same
   corner. .cm-toast (a new chat message) was already bottom-right;
   #toast — which is what every "Saved", every failure and every
   confirmation in the product uses — was centred on the bottom edge,
   where on a phone it sat squarely over the thumb and on a desktop it
   was nowhere near the other one. They are one family now, in one
   place, and they stack rather than overlap (stackCorner() in app.js
   measures the cards, because they are different heights).

   16px from the right and the bottom on a phone as well: a card
   pinned to the very corner of a handset is a card half under the
   home indicator. */
#toast{position:fixed;bottom:16px;right:16px;left:auto;transform:translateY(16px);
  max-width:min(420px,calc(100vw - 32px));background:var(--navy);border:1px solid var(--gold);
  color:#fff;padding:11px 20px;border-radius:11px;font-size:.88rem;opacity:0;pointer-events:none;
  transition:opacity .3s var(--ease),transform .3s var(--ease);z-index:99;
  box-shadow:0 10px 30px rgba(0,0,0,.35)}
#toast.show{opacity:1;transform:translateY(0)}
/* Above whatever notification cards are already stacked there, so a
   "Saved" confirmation never lands on top of an unread message. */
body:has(.cm-toast) #toast{bottom:96px}

/* Pipeline */
.pipe{display:flex;gap:0;flex-wrap:wrap}
.pipe .st{flex:1;min-width:110px;text-align:center;padding:11px 6px;background:var(--hover);border:1px solid var(--line);font-size:.78rem;color:var(--ink-2);transition:all .2s}
.pipe .st:first-child{border-radius:10px 0 0 10px}
.pipe .st:last-child{border-radius:0 10px 10px 0}
.pipe .st b{display:block;font-size:1.3rem;color:var(--ink)}
.pipe .st.hot{background:var(--gold-soft);border-color:var(--line-gold)}
.pipe .st.hot b{color:var(--gold)}

/* SWOT */
.swot{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.swot .q{border-radius:11px;padding:15px 17px;border:1px solid var(--line);background:var(--glass)}
.swot .q h4{font-size:.8rem;text-transform:uppercase;letter-spacing:.9px;margin-bottom:8px}
.swot .q.s h4{color:var(--ok)} .swot .q.w h4{color:var(--bad)}
.swot .q.o h4{color:var(--navy-3)} .swot .q.t h4{color:var(--warn)}
html[data-theme="dark"] .swot .q.o h4{color:#9db8ee}
.swot .q.s{border-left:3px solid var(--ok)} .swot .q.w{border-left:3px solid var(--bad)}
.swot .q.o{border-left:3px solid var(--navy-3)} .swot .q.t{border-left:3px solid var(--warn)}
.swot ul{padding-left:18px;font-size:.85rem}

/* Animal cards */
.animal-grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.animal{border:1px solid var(--line);border-radius:13px;padding:16px 12px;text-align:center;background:var(--glass);transition:all .25s var(--ease);position:relative;overflow:hidden}
.animal:hover{transform:translateY(-4px);border-color:var(--line-gold)}
.animal.dom{border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-soft);background:var(--gold-soft)}
.animal .emo{font-size:2.3rem;display:block;margin-bottom:4px}
.animal .nm{font-weight:700;font-size:.92rem}
.animal .ttl{font-size:.72rem;color:var(--gold);font-weight:700;letter-spacing:.4px}
.animal .pc{font-size:1.25rem;font-weight:800;margin-top:6px}
.animal .crown{position:absolute;top:8px;right:10px;font-size:1rem}

/* Login */
.login-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:30px 16px}
.login-card{max-width:920px;width:100%;display:grid;grid-template-columns:1fr 1fr;border-radius:20px;overflow:hidden;box-shadow:0 30px 80px rgba(0,0,0,.35);animation:popIn .5s var(--ease)}
.login-brand{background:var(--side-grad);color:#fff;padding:46px 40px;display:flex;flex-direction:column;justify-content:center;gap:14px;position:relative}
.login-brand::after{content:"";position:absolute;inset:0;background:radial-gradient(340px 260px at 90% 0%,rgba(201,162,39,.25),transparent 70%)}
.login-brand *{position:relative;z-index:1}
.login-panel{background:var(--glass-strong);backdrop-filter:blur(24px);padding:42px 40px}
.ltabs{display:flex;gap:8px;margin-bottom:22px}
.ltabs button{flex:1;padding:10px;border-radius:10px;border:1px solid var(--line);background:transparent;color:var(--ink-2);font-family:inherit;font-weight:600;font-size:.88rem;cursor:pointer;transition:all .2s}
.ltabs button.on{background:linear-gradient(135deg,var(--navy),var(--navy-3));color:#fff;border-color:var(--gold)}
.pwd-wrap{position:relative}
.pwd-wrap .eye{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;font-size:1rem;color:var(--ink-3)}

@media print{
  .sidebar,.topbar .actions,.no-print,#toast{display:none!important}
  .main{padding:0}
  body{background:#fff!important}
  .card{box-shadow:none;break-inside:avoid;background:#fff}
}
@media(max-width:980px){
  .login-card{grid-template-columns:1fr}
  .login-brand{padding:32px}
}
@media(max-width:900px){
  .topbar{flex-direction:column}
  .topbar .actions{width:100%;justify-content:flex-start}
  .main{padding:18px 16px 30px}
}
@media(max-width:560px){
  .main{padding:14px 12px 24px}
}
@media(prefers-reduced-motion:reduce){
  *,.card,.kpi{animation:none!important;transition:none!important}
}

/* ---- table search + pagination (v6.0) ---- */
.tbl-controls{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:10px 0 6px}
.tbl-controls .tbl-q{flex:0 1 250px;min-width:150px;padding:7px 10px;border:1px solid var(--line);border-radius:8px;font-size:.82rem}
.tbl-controls .tbl-info{font-size:.72rem;color:var(--ink-2)}
.tbl-controls .tbl-pager{display:inline-flex;gap:6px;align-items:center;margin-left:auto;flex-wrap:wrap}
.tbl-controls .tbl-page{font-size:.74rem;min-width:80px;text-align:center;color:var(--ink-2)}
.tbl-controls .tbl-size{width:auto;padding:6px 8px;font-size:.76rem}
.tbl-controls button:disabled{opacity:.4;cursor:default}
@media print{.tbl-controls{display:none!important}}

/* ---------- v27: network banner and demo strip ---------- */
#netBanner{display:none;position:sticky;top:0;z-index:100;background:#8a1c1c;color:#fff;font-weight:700;font-size:.85rem;text-align:center;padding:6px 12px;letter-spacing:.2px}
.demo-strip{background:#f4d58d;color:#3b2a00;font-weight:700;font-size:.8rem;text-align:center;padding:5px 12px;border-radius:8px;margin:0 0 8px}
.rt-dot{display:inline-block;width:8px;height:8px;border-radius:99px;background:#9aa4b2;margin-left:6px;vertical-align:middle}
.rt-dot.live{background:#1f9d55;box-shadow:0 0 0 3px rgba(31,157,85,.18)}
/* meetings */
.mtg-card{border:1px solid var(--line);border-radius:12px;padding:12px 14px;margin-bottom:10px;background:var(--card-solid)}
.mtg-card.live{border-color:#1f9d55}
.mtg-when{font-weight:800;color:var(--navy)}
.mtg-kind{font-size:.72rem;font-weight:700;padding:2px 8px;border-radius:99px;background:var(--line);margin-left:6px}
.mtg-room{width:100%;min-height:70vh;border:1px solid var(--line);border-radius:12px;background:#000}
.mtg-actions textarea{width:100%;min-height:120px}
.mtg-act{display:grid;grid-template-columns:1fr 200px 140px 40px;gap:6px;margin-bottom:6px}
@media(max-width:720px){.mtg-act{grid-template-columns:1fr}}

/* ============================================================
   v31 — NEW MESSAGE ALERTS

   The bar in the corner deliberately looks like the one people
   already recognise from their mail: a line of text, and two words to
   act on. No icon, no card, no animation to sit through. It sits above
   everything except a modal, and never covers the compose box on the
   Communications page, because that is the one screen where it would
   be in the way.
   ============================================================ */
.cm-toast{position:fixed;right:16px;bottom:16px;z-index:70;max-width:min(460px,calc(100vw - 32px));
  display:flex;align-items:center;gap:14px;padding:11px 16px;border-radius:10px;
  background:#fdf6cf;border:1px solid #e8d98a;color:#3c3407;
  box-shadow:0 10px 30px rgba(0,0,0,.20);font-size:.82rem;line-height:1.35;
  /* v39: stackCorner() sets `bottom` per card, so the transition is
     named rather than `all` — `all` animates the restack of every
     other card each time one arrives or leaves, which reads as the
     whole corner sliding about. */
  transition:bottom .18s var(--ease)}
/* v39 — an ALERT in the same corner as a message. Given the navy of
   the product rather than the chat card's paper-yellow, so that the
   two are one family and still tell each other apart at a glance. */
.cm-toast--alert{background:#0e2657;border-color:rgba(214,166,42,.45);color:#e7ecf7;align-items:flex-start}
.cm-toast--alert.urgent{background:#41100c;border-color:#7a2a22;color:#ffd9d3}
.cm-toast--alert .cm-toast__act{color:#e3bf4e}
.cm-toast__ico{display:inline-block;margin-right:8px;opacity:.85}
[data-theme=dark] .cm-toast--alert{background:#0e2657;border-color:rgba(214,166,42,.45);color:#e7ecf7}
.cm-toast.urgent{background:#fdecea;border-color:#f0b4ad;color:#5c1610}
.cm-toast__txt{min-width:0}
.cm-toast__peek{display:block;opacity:.72;font-size:.75rem;margin-top:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cm-toast__act{color:#1d4ed8;font-weight:600;text-decoration:none;white-space:nowrap}
.cm-toast.urgent .cm-toast__act{color:#9a2318}
.cm-toast__act:hover{text-decoration:underline}
[data-theme=dark] .cm-toast{background:#3a3410;border-color:#6b5f1d;color:#f7eebd}
[data-theme=dark] .cm-toast.urgent{background:#41100c;border-color:#7a2a22;color:#ffd9d3}
[data-theme=dark] .cm-toast__act{color:#9dc0ff}
@media(max-width:600px){.cm-toast{left:12px;right:12px;bottom:12px;max-width:none}}

/* The count on the Communications item in the sidebar. Small, and on
   every page — the whole complaint was that you had to be looking at
   the chat to know there was anything in it. */
.cm-navcount{margin-left:auto;background:var(--bad);color:#fff;border-radius:99px;
  min-width:18px;height:18px;padding:0 5px;font-size:.62rem;font-weight:800;
  display:inline-grid;place-items:center;flex:none}

/* "Since you were last here", once per sign-in. */
.cm-digest{position:fixed;right:16px;top:70px;z-index:69;width:min(340px,calc(100vw - 32px));
  background:var(--card-solid);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 38px rgba(0,0,0,.22);overflow:hidden;font-size:.8rem}
.cm-digest__hd{display:flex;justify-content:space-between;align-items:center;
  padding:9px 12px;border-bottom:1px solid var(--line);background:var(--navy);color:#fff}
.cm-digest__hd b{font-size:.82rem}
.cm-digest__x{background:none;border:0;color:#fff;cursor:pointer;font-size:.9rem;line-height:1}
.cm-digest__bd{max-height:60vh;overflow:auto}
.cm-digest__row{padding:8px 12px;border-bottom:1px solid var(--line)}
.cm-digest__conv{display:flex;align-items:center;gap:8px;padding:8px 12px;
  border-bottom:1px solid var(--line);text-decoration:none;color:inherit}
.cm-digest__conv:hover{background:var(--hover)}
.cm-digest__who{font-weight:700;white-space:nowrap}
.cm-digest__peek{flex:1;min-width:0;opacity:.7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cm-digest__n{background:var(--bad);color:#fff;border-radius:99px;min-width:18px;height:18px;
  padding:0 5px;font-size:.62rem;font-weight:800;display:inline-grid;place-items:center;flex:none}
@media(max-width:600px){.cm-digest{left:12px;right:12px;top:60px;width:auto}}

/* ============================================================
   v31 — the sub-module page format, shared by every module

   The Document Repository set the pattern the rest of the system is
   now held to: the sub-module names itself, says in one line what it
   is for, and puts its four numbers where they can be read before
   anything is scrolled. Monitoring & Evaluation and Governance &
   Sustainability had the sidebar and the tables but not this, so the
   two heaviest modules in the product were the two that told you
   least about where you were.
   ============================================================ */
.subhead{margin:2px 0 14px}
.subhead .card{margin-bottom:0}
.sub-kpis{margin-bottom:14px}

/* ============================================================
   v32 — THE COMPACT SUB-MODULE BAR (subBar() in app.js)
   Secondary by design: small type, light outline, one row that wraps,
   the current sub-module the only filled chip. Below 700px the row
   becomes a single "Jump to" menu. Shared by Governance and M&E.
   ============================================================ */
.sub-strip{margin:4px 0 12px;display:block}
.sub-crumb{font-size:.74rem;color:var(--ink-3);margin-bottom:6px;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.sub-crumb a{color:var(--ink-2);text-decoration:none;font-weight:600}
.sub-crumb a:hover{color:var(--gold);text-decoration:underline}
.sub-crumb b{color:var(--ink);font-weight:700}
.sub-crumb .sub-sep{opacity:.6}
.sub-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.sub-chips{display:flex;gap:5px;flex-wrap:wrap;align-items:center}
.sub-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:99px;
  border:1px solid var(--line);background:transparent;color:var(--ink-2);font-size:.74rem;font-weight:600;
  line-height:1.5;text-decoration:none;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}
.sub-chip:hover{border-color:var(--line-gold);color:var(--ink);background:var(--hover)}
.sub-chip.on{background:var(--navy);border-color:var(--navy);color:#fff}
html[data-theme="dark"] .sub-chip.on{background:var(--gold);border-color:var(--gold);color:var(--navy)}
.sub-chip .sub-n{font-size:.64rem;font-weight:800;background:var(--gold-soft);color:var(--ink);border-radius:99px;padding:0 6px}
.sub-chip.on .sub-n{background:rgba(255,255,255,.22);color:inherit}
.sub-grp{font-size:.62rem;font-weight:800;letter-spacing:.8px;text-transform:uppercase;color:var(--ink-3);margin:0 2px 0 6px}
.sub-lead{display:inline-flex;align-items:center}
.sub-lead select,.sub-area{font-size:.74rem;font-weight:700;padding:3px 26px 3px 10px;border-radius:99px;
  border:1px solid var(--line-gold);background-color:var(--gold-soft);color:var(--ink);min-width:0;max-width:260px;height:auto}
.sub-jump{display:none;align-items:center;gap:6px;font-size:.74rem;font-weight:700;color:var(--ink-2);flex:1 1 220px}
.sub-jump select{flex:1;font-size:.82rem;padding:5px 8px;min-width:0}
@media(max-width:700px){
  .sub-chips{display:none}
  .sub-jump{display:flex}
}
@media print{.sub-strip{display:none!important}}
/* A second-level switch INSIDE a sub-module (the Sustainability
   Scorecard's own views) is a segmented control, so it can never be
   mistaken for the sub-module row above it. */
.seg{display:inline-flex;border:1px solid var(--line);border-radius:10px;overflow:hidden;margin:0 0 12px;flex-wrap:wrap;background:var(--card)}
.seg button{border:0;background:transparent;padding:6px 13px;font:inherit;font-size:.8rem;font-weight:600;color:var(--ink-2);cursor:pointer;border-right:1px solid var(--line)}
.seg button:last-child{border-right:0}
.seg button.on{background:var(--gold-soft);color:var(--ink);box-shadow:inset 0 -2px 0 var(--gold)}
.seg button:hover{background:var(--hover)}
/* The one-line "choose the programme area for this screen" prompt that
   replaces the full-screen picker everywhere except Overview. */
.area-prompt{display:flex;gap:10px;align-items:center;flex-wrap:wrap;border:1px dashed var(--line-gold);
  background:var(--gold-soft);border-radius:12px;padding:10px 14px;margin-bottom:14px;font-size:.86rem}
.area-prompt select{max-width:280px}

/* ============================================================
   v33 — PRIORITY, AND THE DELIVERY LEDGER

   Two pieces of chat furniture. Both are deliberately quiet: a chat
   window that shouts about its own plumbing is harder to read, and the
   plumbing is only interesting when something has gone wrong.
   ============================================================ */

/* The priority picker in the composer. Narrow, and it gets out of the
   way on a phone — where the textarea and Send matter more than a
   control most messages do not need. */
.prisel select{font-size:.72rem;padding:4px 6px;max-width:190px;border-radius:8px;
  border:1px solid var(--line);background:var(--card-solid);color:inherit}
@media(max-width:700px){
  .prisel select{max-width:112px}
  /* Keep the long option text readable once it is open, even though the
     closed control is narrow. */
  .prisel select option{font-size:.8rem}
}

/* The flag on a message. An Important message is marked; an Urgent one
   is marked and the bubble carries a red edge, because somebody
   scrolling a busy group has to be able to find it without reading. */
.pri{display:inline-block;font-size:.6rem;font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;padding:1px 6px;border-radius:99px;margin-bottom:3px}
.pri-i{background:#fdf6cf;border:1px solid #e8d98a;color:#5c4d07}
.pri-u{background:#fdecea;border:1px solid #f0b4ad;color:#7a1b12}
.m.urgent{border-left:3px solid var(--bad)}
[data-theme=dark] .pri-i{background:#3a3410;border-color:#6b5f1d;color:#f7eebd}
[data-theme=dark] .pri-u{background:#41100c;border-color:#7a2a22;color:#ffd9d3}

/* The ledger. A modal rather than a popover: it carries two or three
   tables and is read, not glanced at. */
.cm-ledger{position:fixed;inset:0;z-index:95;background:rgba(10,15,30,.45);
  display:flex;align-items:center;justify-content:center;padding:16px}
.cm-ledger__card{background:var(--card-solid);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 18px 50px rgba(0,0,0,.3);width:min(760px,100%);max-height:86vh;
  display:flex;flex-direction:column;text-align:left}
.cm-ledger__hd{display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:11px 14px;border-bottom:1px solid var(--line)}
.cm-ledger__bd{padding:12px 14px;overflow:auto}
/* Tables inside it scroll sideways rather than widening the dialog. */
.cm-ledger__bd table{width:100%;min-width:420px}
.cm-ledger__bd{overflow-x:auto}

/* ============================================================
   v34 — "YOU ARE IN A MEETING"

   A slim bar, bottom-left, so it cannot sit on top of the new-message
   toast (bottom-right) — two things shouting from the same corner is
   how people learn to ignore both.
   ============================================================ */
.mtg-bar{position:fixed;left:16px;bottom:16px;z-index:72;
  display:flex;align-items:center;gap:10px;padding:8px 14px;border-radius:99px;
  background:#12613a;color:#eafaf1;box-shadow:0 10px 28px rgba(0,0,0,.26);
  font-size:.78rem;max-width:min(460px,calc(100vw - 32px))}
.mtg-bar__dot{width:9px;height:9px;border-radius:99px;background:#7ef2b0;flex:none;
  animation:mtgPulse 2s ease-in-out infinite}
@keyframes mtgPulse{0%,100%{opacity:1}50%{opacity:.35}}
.mtg-bar__txt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mtg-bar__left{opacity:.8}
.mtg-bar__act{color:#eafaf1;font-weight:700;text-decoration:underline;white-space:nowrap}
@media(max-width:600px){
  .mtg-bar{left:12px;right:12px;bottom:12px;max-width:none;justify-content:space-between}
}

/* ============================================================
   v37 — "YOUR COMMAND IS BEING WORKED ON"  (client item 8)

   A progress bar on the page's top edge and a spinner inside the button
   that was pressed. Driven entirely by jofipaBusy() in app.js, which
   counts requests in flight — so nothing here has to know which page it
   is on.

   The bar is deliberately an indeterminate sweep rather than a
   percentage: JoFiPA does not know how far through a request it is, and
   a progress bar that invents a number is a worse lie than no number.
   prefers-reduced-motion gets a static bar instead of the sweep.
   ============================================================ */
.jf-busy{position:fixed;left:0;right:0;top:0;height:3px;z-index:99;pointer-events:none;
  opacity:0;transition:opacity .18s ease;background:rgba(214,166,42,.16)}
.jf-busy.on{opacity:1}
.jf-busy i{display:block;height:100%;width:38%;border-radius:0 3px 3px 0;
  background:linear-gradient(90deg,rgba(214,166,42,0),var(--gold,#D6A62A),rgba(214,166,42,0));
  animation:jfBusySweep 1.05s ease-in-out infinite}
@keyframes jfBusySweep{0%{transform:translateX(-100%)}100%{transform:translateX(320%)}}
.jf-spin{display:inline-block;width:.82em;height:.82em;margin-right:.5em;vertical-align:-1px;
  border:2px solid currentColor;border-right-color:transparent;border-radius:99px;
  animation:jfSpin .7s linear infinite;opacity:.85}
@keyframes jfSpin{to{transform:rotate(360deg)}}
/* A button the busy layer has taken over keeps its size, so the row it
   sits in does not jump when "Save" becomes "Saving…". */
button[disabled] .jf-spin{opacity:.9}
@media (prefers-reduced-motion: reduce){
  .jf-busy i{animation:none;width:100%}
  .jf-spin{animation-duration:2.4s}
}

/* ============================================================
   v37 — THE ORGANIZATION CHART'S SLIDE BAR  (client item 2)

     "Enable slide-bar on the organization chart"

   The chart has always scrolled — .oc-scroll is overflow:auto — but on
   macOS and on every modern browser with overlay scrollbars, the bar
   only appears WHILE you are already scrolling. So a chart wider than
   the screen looked like a chart that had been cut off, and there was
   nothing on screen to suggest otherwise.

   So the bar is made permanent and given a size you can actually grab,
   the chart says out loud that it can be dragged, and a zoom control
   lets a wide organization be seen whole. Nothing here changes the
   chart's layout; drawChartLines() divides by the zoom factor so the
   connectors stay on the boxes.
   ============================================================ */
.oc-scroll{overflow-x:scroll;overflow-y:auto;scrollbar-width:auto;scrollbar-gutter:stable;
  scrollbar-color:var(--gold,#D6A62A) rgba(127,127,127,.16);cursor:grab}
.oc-scroll.drag{cursor:grabbing;user-select:none}
.oc-scroll::-webkit-scrollbar{height:14px;width:14px;-webkit-appearance:none}
.oc-scroll::-webkit-scrollbar-track{background:rgba(127,127,127,.16);border-radius:99px}
.oc-scroll::-webkit-scrollbar-thumb{background:var(--gold,#D6A62A);border-radius:99px;
  border:3px solid transparent;background-clip:content-box;min-width:44px}
.oc-scroll::-webkit-scrollbar-thumb:hover{background:var(--gold-2,#E3BF4E);background-clip:content-box}
.oc-zoomwrap{transform-origin:0 0}
/* When zoomed, the wrapper is given the SCALED size and hides the
   overflow. A transform does not change layout, so without this the
   full-width chart still overflows the scroller and Fit width leaves a
   scrollbar for space nothing occupies — which is exactly what it was
   supposed to remove. Nothing is clipped: the content inside has been
   scaled to fit the box the same instant the box was sized. */
.oc-zoomwrap[data-z]{overflow:hidden}
.oc-tools{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:8px 0 2px}
.oc-tools .btn{min-width:34px}
.oc-tools .oc-pct{font-size:.76rem;color:var(--ink-2);min-width:46px;text-align:center}
.oc-hint{font-size:.74rem;color:var(--ink-3,var(--ink-2));margin-left:4px}
@media print{ .oc-tools{display:none} .oc-zoomwrap{transform:none!important} }

/* ============================================================
   v39 item 4 — THE SETTINGS PANES

   .set-pane is a wrapper around cards that already existed; it never
   sets display on a card itself. The boot code reveals the
   developer-only cards with an inline style, and an inline style
   beats a class — so a pane that also had an opinion about a card
   would silently re-hide it for the System Developer. The pane hides
   ITSELF and nothing else.

   .set-grid is what makes the panes short on a wide screen and
   readable on a narrow one: two columns where there is room for two,
   one where there is not, and align-items:start so a short card does
   not stretch to the height of the register beside it — which is how
   a settings page ends up with an acre of empty navy next to a form
   four fields long.
   ============================================================ */
.set-pane{display:none}
.set-pane.on{display:block;animation:fadeIn .25s var(--ease)}
.set-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(440px,1fr));
  gap:18px;align-items:start}
@media (max-width:980px){ .set-grid{grid-template-columns:1fr} }
/* A register inside a pane keeps its own scroll rather than making the
   page four thousand pixels long. */
.set-grid .tbl-wrap{max-height:min(58vh,560px);overflow:auto}

/* v39 item 4 — the top bar stays ONE row on a telephone.
   Measured: on a 390px screen the theme control, the bell and the
   account chip wrapped onto a second line, so every page began 60px
   further down than it needed to. The symbol carries the meaning
   under 620px; the word is still in title= and aria-label. */
.tswitch__ico{display:none}
@media (max-width:620px){
  .tswitch__lbl{display:none}
  .tswitch__ico{display:inline}
  .tswitch button{padding:7px 12px;font-size:.95rem;line-height:1}
  /* THE BAR STILL WRAPS. Its own header comment in app.js promises
     "wraps instead of overflowing", and the first cut of this rule
     forced nowrap — which made .appbar 1279px wide inside a 390px
     screen on personnel.html, with the account menu pushed clean off
     the side where .app{overflow-x:hidden} swallowed it without a
     scrollbar to say so. Wrapping is the safe behaviour. The job is
     to make the contents small enough that it does not have to. */
  .appbar{gap:8px}
  .appbar-left{min-width:0;flex:1 1 0;overflow:hidden}
  .appbar-right{flex:0 0 auto;flex-wrap:nowrap;gap:6px}
  .appbar-what{display:none}
  .userdd-name{display:none}      /* the avatar already says who it is */
  .userdd-caret{margin-left:2px}
}

/* v39 items 4 & 5 — the sign-in digest joins the corner on a phone.
   .cm-digest is fixed at top:70px, which on a 390px screen lands
   squarely on the page's own heading: the Dashboard's title was
   underneath it. It is a notification, and as of v39 notifications
   live in the lower right, so on a narrow screen it goes there with
   the rest of them rather than over the page. */
@media (max-width:620px){
  .cm-digest{top:auto;bottom:16px;right:16px;left:16px;width:auto;max-height:52vh}
  .cm-digest__bd{max-height:40vh}
}

/* ============================================================
   v39 item 6 — THE TERMS GATEWAY

   Covers everything, at a size somebody can actually read. The type
   is 1rem and the measure is capped at 68 characters, because the
   request was "easy to read and understand" and eleven-point text
   across a 1400px card is neither.
   ============================================================ */
.terms-gate{position:fixed;inset:0;z-index:2000;display:grid;place-items:center;
  padding:16px;background:rgba(6,14,33,.72);backdrop-filter:blur(6px)}
body.terms-gated{overflow:hidden}
.terms-gate__card{width:min(760px,100%);max-height:min(92vh,900px);display:flex;flex-direction:column;
  background:var(--card,#fff);color:var(--ink,#0b1f4b);border:1px solid var(--line);
  border-radius:16px;box-shadow:0 30px 80px rgba(0,0,0,.45);overflow:hidden}
.terms-gate__hd{padding:18px 24px 12px;border-bottom:1px solid var(--line);flex:0 0 auto}
.terms-gate__hd h2{margin:0;font-size:1.22rem}
.terms-gate__ver{font-size:.74rem;color:var(--ink-2);font-weight:600}
.terms-gate__changed{margin:0;padding:12px 24px;background:rgba(201,162,39,.14);
  border-bottom:1px solid var(--line);font-size:.86rem;line-height:1.5;flex:0 0 auto}
.terms-gate__changed div{margin-top:4px;white-space:pre-wrap}
/* min-height:0 again — without it the scroller refuses to be shorter
   than its content and the whole card grows past the screen, taking
   the two buttons with it. */
.terms-gate__scroll{flex:1 1 auto;min-height:0;overflow-y:auto;padding:18px 24px;
  font-size:1rem;line-height:1.62}
.terms-gate__plain{max-width:68ch}
.terms-gate__plain p{margin:0 0 14px}
/* The first line of each paragraph in the summary is its heading —
   written in capitals on purpose, so it needs no markup to be found. */
.terms-gate__full{margin-top:10px;border-top:1px solid var(--line);padding-top:12px}
.terms-gate__full summary{cursor:pointer;font-weight:700;font-size:.9rem;color:var(--navy-3)}
[data-theme=dark] .terms-gate__full summary{color:var(--gold-2)}
.terms-gate__legal{white-space:pre-wrap;font-size:.86rem;line-height:1.6;margin-top:10px;
  max-width:74ch;color:var(--ink-2)}
.terms-gate__foot{flex:0 0 auto;padding:14px 24px 18px;border-top:1px solid var(--line);
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;justify-content:space-between}
.terms-gate__hint{font-size:.78rem;color:var(--ink-2);flex:1 1 200px}
.terms-gate__btns{display:flex;gap:10px;flex:0 0 auto}
.terms-gate__btns .btn[disabled]{opacity:.45;cursor:not-allowed}
@media (max-width:620px){
  .terms-gate{padding:0}
  .terms-gate__card{max-height:100dvh;height:100dvh;border-radius:0;width:100%}
  .terms-gate__btns{width:100%}
  .terms-gate__btns .btn{flex:1}
}

/* v39 item 2 — the duplicates panel */
.dup-pair{border:1px solid var(--line);border-radius:12px;padding:12px 14px;margin:10px 0;background:var(--glass)}
.dup-why{font-size:.82rem;margin-bottom:8px}
.dup-grid{display:grid;grid-template-columns:1fr auto 1fr;gap:12px;align-items:center}
.dup-side{border:1px solid var(--line);border-radius:10px;padding:10px 12px;min-width:0}
.dup-side--keep{border-color:rgba(76,207,142,.55);background:rgba(76,207,142,.07)}
.dup-mid{font-size:1.2rem;color:var(--gold);text-align:center}
.dup-hist{font-size:.74rem;margin-top:6px;opacity:.8}
.dup-act{margin-top:10px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
@media (max-width:700px){
  .dup-grid{grid-template-columns:1fr}
  .dup-mid{transform:rotate(90deg)}
}

/* ============================================================
   v39 Phase 4 — reply, forward, search results and the outbox
   ============================================================ */
.p4-quote{border-left:3px solid var(--gold);padding:4px 0 4px 9px;margin:0 0 6px;
  font-size:.78rem;opacity:.85;cursor:pointer;min-width:0}
.p4-quote__txt{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:44ch}
.p4-quote--gone{font-style:italic;opacity:.6;cursor:default;border-left-color:var(--line)}
/* the bar above the composer while a reply is being written */
.p4-quote--bar{display:flex;align-items:center;gap:10px;justify-content:space-between;
  background:var(--glass);border:1px solid var(--line);border-left:3px solid var(--gold);
  border-radius:8px;padding:7px 10px;margin:0 0 8px;cursor:default}
.p4-quote--bar .x{background:none;border:0;color:var(--ink-2);cursor:pointer;font-size:1rem;line-height:1}
.p4-fwd{font-size:.74rem;opacity:.72;margin-bottom:4px}
/* a message still waiting for a connection: theirs, on screen, and
   plainly not yet sent */
.m.p4-pending{opacity:.62;border:1px dashed var(--line)}
.p4-outbox{margin:0 0 8px;padding:8px 12px;border-radius:8px;font-size:.78rem;
  background:rgba(224,106,59,.12);border:1px solid rgba(224,106,59,.35)}
/* a message arrived at from a search result */
.p4-found{animation:p4Flash 2.4s ease}
@keyframes p4Flash{0%,70%{background:rgba(214,166,42,.28)}100%{background:transparent}}
/* the search results themselves */
.p4-hit{display:block;padding:9px 11px;border:1px solid var(--line);border-radius:9px;
  margin-bottom:7px;text-decoration:none;color:inherit;background:var(--glass)}
.p4-hit:hover{border-color:rgba(214,166,42,.5)}
.p4-hit__top{font-size:.78rem}
.p4-hit__txt{font-size:.84rem;margin-top:3px;line-height:1.45}
/* v39 — the card an anchor pointed at, so arriving by link lands
   somewhere visible rather than merely on the right pane. */
.set-found{outline:2px solid var(--gold);outline-offset:3px;animation:p4Flash 2.4s ease}

/* ============================================================
   v40 — THE NOTIFICATION PANEL, to the supplied design.

   A row is a face, who did what, the relative time at the top right
   and the exact moment underneath it. Unread rows are TINTED rather
   than emboldened: half of these rows have no bold part to make, and
   a list where only some rows can show their state shows it for none.

   Built entirely from this stylesheet's own variables — the card, the
   line, the navy and the two ink greys — so it follows the theme
   switch and the dark mode like everything else. Nothing here is a
   new colour.
   ============================================================ */
.nt-panel{position:absolute;right:0;top:115%;width:370px;max-width:92vw;max-height:520px;overflow:auto;
  background:var(--card-solid);border:1px solid var(--line);border-radius:14px;
  box-shadow:0 18px 44px rgba(0,0,0,.20);z-index:90;text-align:left}
.nt-head{display:flex;justify-content:space-between;align-items:center;gap:10px;
  padding:13px 16px 11px;border-bottom:1px solid var(--line);position:sticky;top:0;
  background:var(--card-solid);z-index:2}
.nt-head b{font-size:.95rem}
.nt-mark{font-size:.78rem;color:var(--navy-3);text-decoration:none;font-weight:600;white-space:nowrap}
.nt-mark:hover{text-decoration:underline}
.nt-list{display:block}
.nt-row{display:flex;gap:11px;align-items:flex-start;padding:11px 14px 10px;border-bottom:1px solid var(--line);position:relative}
.nt-row--new{background:rgba(28,67,148,.055)}
.nt-row--alert{box-shadow:inset 3px 0 0 0 var(--bad)}
.nt-row:hover{background:rgba(120,120,120,.06)}
.nt-face{width:36px;height:36px;border-radius:99px;flex:none;object-fit:cover;
  display:grid;place-items:center;font-size:.76rem;font-weight:800;
  background:var(--navy);color:#fff;overflow:hidden}
.nt-face--ini[data-t="urgent"],.nt-face--ini[data-t="warning"]{background:var(--bad)}
.nt-face--ini[data-t="approval"],.nt-face--ini[data-t="success"]{background:#1f7a46}
.nt-body{flex:1;min-width:0}
.nt-top{display:flex;gap:8px;align-items:flex-start;justify-content:space-between}
.nt-who{font-size:.83rem;line-height:1.42;min-width:0;cursor:pointer}
.nt-what{color:var(--ink-2)}
.nt-ago{font-size:.7rem;color:var(--ink-3);white-space:nowrap;flex:none;padding-top:1px}
.nt-when{display:flex;align-items:center;gap:5px;font-size:.7rem;color:var(--ink-3);margin-top:5px}
.nt-clock{font-size:.72rem;opacity:.75}
.nt-acts{margin-top:6px;display:flex;gap:5px;flex-wrap:wrap}
.nt-acts .btn{font-size:.68rem;padding:2px 9px}
.nt-x{border:none;background:none;color:var(--ink-3);font-size:.74rem;cursor:pointer;
  padding:2px 4px;border-radius:6px;flex:none;opacity:0;transition:opacity .15s ease}
.nt-row:hover .nt-x,.nt-x:focus-visible{opacity:1}
.nt-x:hover{background:rgba(120,120,120,.14);color:var(--ink)}
.nt-empty{padding:26px 16px;text-align:center;font-size:.82rem;color:var(--ink-2)}
.nt-foot{padding:11px 14px;border-top:1px solid var(--line);text-align:center;
  position:sticky;bottom:0;background:var(--card-solid)}
.nt-foot>a{font-size:.8rem;color:var(--navy-3);font-weight:600;text-decoration:none}
.nt-foot>a:hover{text-decoration:underline}
.nt-foot__opts{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:7px}
.nt-foot__opts a{font-size:.68rem;color:var(--ink-3);text-decoration:none}
.nt-foot__opts a:hover{color:var(--ink);text-decoration:underline}
@media(max-width:520px){
  /* On a telephone the bell is at the right-hand edge and a 370px
     panel hung off it runs past the screen. Anchored to the viewport
     instead, with the same card. */
  .nt-panel{position:fixed;left:8px;right:8px;top:64px;width:auto;max-width:none;max-height:72vh}
}
