/* =========================================================================
   NSBIZ shell — the deliberate differences from the Northstar UI kit.
   NSBIZ-REWORK-1, 2026-11-12.

   LOADED AFTER public/vendor/northstar-ui/<hubcommit>/northstar-ui.css AND
   NEVER INSTEAD OF IT. Everything here either adds a part the kit does not
   have, or overrides a kit rule for a reason written beside it. If you find
   yourself re-declaring a colour, a radius or a size, stop: read the token.

   🔴 NOTHING HERE MAY BE A FIX THAT BELONGS UPSTREAM. The kit is a copy
   (`SOURCE.md` beside it) and `bin/check-ui-kit-drift.php` proves it is
   unedited. A bug in the kit is fixed in the hub and re-copied, or every
   other app on this box keeps the bug. This file is for what NSBIZ is, not
   for what the kit got wrong.
   ========================================================================= */

/*
  🔴 `#FFFFFF` IS DELIBERATE WHERE IT APPEARS BELOW, AND IS NOT A MISSED TOKEN.
  NSBIZ-REWORK-2's colour sweep put every other literal in this repo onto a
  kit token; these eight stayed. White here is TEXT AND BORDER SITTING ON THE
  BRAND BAR, which is a contrast partner rather than a surface — and the kit
  writes it exactly this way itself (`.nsbtn.nsprimary { color: #FFFFFF }`),
  because it is the one colour the hub's per-app brand-colour refusal exists
  to protect. `var(--surface)` would be a claim that it follows the page
  background, which is the opposite of what it must do.
*/

/* ------------------------------------------------------- emoji fallback */
/*
  🔴 ADDING THE EMOJI FAMILIES BACK ONTO THE STACK, BECAUSE INTER HAS A
  VISIBLE `.notdef`.

  The kit's `body` declares `'InterVariable', Inter, system-ui, …` and Inter
  carries no emoji glyphs. NSBIZ's page bodies do use emoji — the channels
  card on the tenant home draws ✅ / ⚠️ / ⭕ per channel, the composer has a
  camera and a calendar — and with the old `system-ui` stack a missing glyph
  came out blank, while with Inter first it comes out as a box.

  Per-glyph fallback means a machine with an emoji font (every Mac, Windows,
  Android and iOS device) renders them correctly either way; this only shows
  on a machine with none, which is what this server is — `fc-list` reports
  zero emoji fonts, which is why the REWORK-1 screenshots show boxes. Naming
  the three system emoji families explicitly costs nothing and makes the
  stack say what it means instead of relying on the UA's last-resort font.

  It is NOT a kit fix: the hub's screens contain no emoji at all, so the kit
  is right for the hub. This is the deliberate NSBIZ difference this file is
  for. (Converting those emoji to `ui.icon()` is Phase 2's job and the real
  answer.)
*/
body {
  font-family: 'InterVariable', Inter, system-ui, -apple-system, 'Segoe UI',
               'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif;
}

/* ------------------------------------------------- the mobile nav drawer */
/*
  🔴 THE ONE REAL DISAGREEMENT WITH THE KIT, AND IT IS A COUNT.

  Under 900px the kit turns the sidebar into a horizontal strip that scrolls
  sideways, and hides the group labels because "they read as dead items in a
  horizontal strip". That is right for the hub: thirteen items, one flat list,
  no sub-navigation.

  NSBIZ's tenant sidebar has nineteen items across five groups, because the
  gear dropdown's twelve settings pages moved into it — that is most of what
  adopting a sidebar buys. Nineteen items in a horizontal strip is a ~1,500px
  sideways worm in which the twelfth item is unreachable without knowing it is
  there, and dropping the group labels makes "Keywords" (a settings page) sit
  beside "Posts" (a section) with nothing to tell them apart.

  So below 900px NSBIZ collapses the whole sidebar behind a button instead,
  and the list stays VERTICAL and KEEPS ITS GROUPS. The button is in the
  header, left of the brand, and it is the only control the kit does not have.

  An expanding panel rather than an overlay drawer: it needs no scroll lock,
  no focus trap and no backdrop, it cannot strand a user behind an invisible
  overlay if the JavaScript half fails, and a full-page screenshot of it is
  the truth rather than a composite.
*/
.nsbnavtoggle {
  display: none;              /* desktop: the sidebar is always there */
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid rgba(255, 255, 255, .4);
  border-radius: var(--radius);
  background: transparent;
  color: #FFFFFF;
  cursor: pointer;
  padding: 0;
}
.nsbnavtoggle:hover { background: rgba(255, 255, 255, .12); }
.nsbnavtoggle[aria-expanded="true"] {
  background: #FFFFFF;
  color: var(--brand);
  border-color: #FFFFFF;
}

@media (max-width: 900px) {
  .nsbnavtoggle { display: inline-flex; width: 44px; height: 44px; }

  /* Closed by default. `.nsbnavopen` goes on .nsshell, not on the aside, so
     one class drives the button's state and the panel's together and they
     cannot disagree. */
  .nsside { display: none; }
  .nsbnavopen .nsside {
    display: flex;
    /* Back to the kit's DESKTOP shape: a full-width block under the header,
       not the horizontal strip the kit's own media query builds. */
    flex: 1 1 100%;
    max-width: none;
    min-width: 0;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .nsbnavopen .nssidenav {
    flex-direction: column;
    overflow-x: visible;
    max-width: 100%;
    min-width: 0;
  }
  .nsbnavopen .nssidenav a { flex: 0 0 auto; }
  /* The groups come back: this is a vertical list again, so they are doing
     the job they were written for. */
  .nsbnavopen .nsnavgroup { display: block; }

  /* The brand's 204px basis is a desktop column width; on a phone it fights
     the search box for the one row there is. */
  .nsheaderbrand { flex: 0 0 auto; }
}

@media (max-width: 600px) {
  /*
    The wordmark goes, the star stays. The kit already sends the search box
    to its own row under 900px (`order: 10`), which leaves the menu button,
    the mark, the wordmark, the surface tag and the avatar competing for one
    358px line — and at 390px the avatar loses by about three pixels and
    wraps onto a row of its own, making the header three rows deep before
    any content.

    Measured rather than guessed: toggle 44 + brand ~170 + tag ~60 + avatar
    28, plus four 20px gaps. Dropping the 140px wordmark is the one cut that
    costs nothing — the mark and the TENANT/ADMIN/PARTNER tag beside it
    already say which product and which surface this is.
  */
  .nsheaderbrandname { display: none; }
}

/* ------------------------------------------------------- header, NSBIZ's */
/*
  The surface tag — TENANT / ADMIN / PARTNER. It is not a status and must
  never be coloured like one, which is exactly what `ui.apptag` is for; this
  is the same shape on a blue ground, where the kit's grey tint would vanish.
*/
.nsbsurfacetag {
  flex: 0 0 auto;
  background: rgba(255, 255, 255, .16);
  border: 1px solid rgba(255, 255, 255, .34);
  color: #FFFFFF;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 2px 7px;
  border-radius: var(--radiuspill);
  white-space: nowrap;
}

/* The signed-in name beside the brand. Truncates rather than wrapping: a
   tenant called "Lakes Area Seamless Gutters of Northern Minnesota" must not
   push the search box onto a second row. */
.nsbheaderwho {
  flex: 0 1 auto;
  min-width: 0;
  font-size: var(--fontsizesm);
  font-weight: 500;
  color: #FFFFFF;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nsbheaderwho .nsbrole { opacity: .75; font-weight: 400; }

@media (max-width: 900px) {
  /* On a phone the name is the first thing to go — the sidebar drawer names
     the account, and the row has to hold a menu button, a brand and a search
     box before it holds a label. */
  .nsbheaderwho { display: none; }
}

/* --------------------------------------------------------- flash + footer */
.nsbshellfoot {
  border-top: 1px solid var(--line);
  padding: 12px var(--gutter);
  color: var(--muted);
  font-size: var(--fontsizexs);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--gap);
  flex-wrap: wrap;
  background: var(--surface);
}
.nsbshellfoot a { color: var(--brand); }

/*
  The impersonation / servicing banner. Chrome, so it is here rather than in
  the compatibility layer — it does not shrink away with the page bodies.

  🔴 IT KEEPS ITS `.imp-banner` CLASS NAMES. Three Playwright assertions and
  one POST form target them, and renaming chrome a spec selects on is how a
  rework breaks a test for a reason that has nothing to do with the test.
  The look is the kit's; the hooks are the ones that already existed.
*/
.imp-banner {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: var(--bad);
  color: #FFFFFF;
  padding: 8px var(--gutter);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--gapsm);
  flex-wrap: wrap;
  font-size: var(--fontsizesm);
}
.imp-banner__icon { margin-right: 4px; }
.imp-banner__msg { flex: 1 1 auto; min-width: 0; }
.imp-banner__who { margin-left: 6px; opacity: .9; font-style: italic; }
.imp-banner form { margin: 0; }
.imp-banner button {
  background: #FFFFFF;
  color: var(--bad);
  border: 0;
  border-radius: var(--radius);
  padding: 4px 12px;
  min-height: var(--controlheight);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.imp-banner button:hover { background: var(--dangerline); }

/* ------------------------------------------------ the account menu panel */
/*
  The kit's `.nsmenupanel` is a `[popover]` positioned from JavaScript. NSBIZ
  uses it as-is; the only addition is that a logout form inside the panel has
  to look like the links beside it, since the kit's panel styles anchors.
*/
.nsmenupanel form { margin: 0; }
.nsmenupanel form button {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  font: inherit;
  cursor: pointer;
}
