/* ===================================================================
   Shell chrome: fixed left department nav + the offset it imposes on
   each department page. SINGLE SOURCE OF TRUTH — build.cjs copies this
   to dist/shell.css and links it from every department page.

   Scoping rule: every selector here is prefixed .tmf-nav / .tmf-crumb
   or targets body[data-dept] / :root custom properties. Department pages
   were written independently and their CSS is unnamespaced, so the shell
   must never introduce a bare element or generic class selector.

   Light theme (2026-07-28). Was a dark navy rail; now a white panel that
   reads as a sibling of the pages' white cards on their #f5f7fb ground.
   =================================================================== */

:root {
  /* Wider than the old 186px because a row is now icon + label + a
     right-hand state chip inside a padded pill. Widest row is
     "Client Services" + SOON: 10 rail + 10 pill + 17 icon + 10 gap +
     ~97 label + 8 + ~30 chip + 10 pill + 10 rail ~= 202px. 232 leaves
     slack without taking more from the department pages than the new row
     needs. Single knob — it also drives the body offset below. */
  --tmf-nav-w: 232px;

  /* Air between the nav's right edge and where page content starts.
     Content used to sit flush: padding-left was exactly the nav width. */
  --tmf-gutter: 24px;

  /* Top of the content column — the breadcrumb's offset from the viewport.
     Matches what the Sales page used to set on its own body. */
  --tmf-gutter-top: 16px;

  /* The content-area ground. Same value the department pages use for their own
     --bg, so cards keep reading as white-on-grey. */
  --tmf-page-bg: #f5f7fb;

  --tmf-navy: #101B5B;       /* brand navy — the active pill */
  --tmf-nav-bg: #ffffff;
  --tmf-nav-edge: #e3e8f0;   /* == the sales page's --border */
  --tmf-nav-ink: #364152;
  --tmf-nav-muted: #64748b;  /* == the sales page's --muted */
  --tmf-nav-hover: #f1f4f9;  /* between the pages' --bg and white */
  --tmf-nav-ok: #1a7f37;     /* == the sales page's --green */

  /* ---- Canonical department palette (2026-07-30) ----------------------
     The department pages were each ported from an independent artifact and
     each brought its own copy of this palette, which had already drifted:
     `--teal` meant #5EEAD4 on Sales and #72AEE6 on Hiring, and Hiring carried
     a parallel alias set (--blue/--orange/--purple) for colors Sales already
     named --navy/--amber/--link. Five tokens (--gold, --gold-text, --mint and
     Sales' --teal) had zero usages anywhere.

     Declared here so there is one source. shell.css is linked AFTER each
     page's own <style>, so these win on source order at equal specificity —
     which is only safe because the values are byte-identical to what the
     pages already declared. A page can still override deliberately with a
     higher-specificity selector.

     Custom properties on :root only. Per the scoping rule at the top of this
     file, the shell must never introduce a bare element or class selector. */
  --navy:   #101B5B;
  --green:  #1a7f37;
  --red:    #CF1229;
  --amber:  #b7791f;
  --sky:    #72AEE6;
  --link:   #056BBF;
  --bg:     #f5f7fb;
  --card:   #ffffff;
  --border: #e3e8f0;
  --text:   #212121;
  --muted:  #64748b;
}

/* The page frame. The shell owns it so every department page sits in the same
   box — a ported page shouldn't need to know the shell's measurements, and
   before this each one brought its own (Sales had a body background and 16px of
   top padding; Recruiting had neither, so its breadcrumb hugged the viewport
   edge on a white ground while its content sat on grey).
   Padding on body (not a margin or transform) so a page's own fixed/sticky
   headers still work. `body[data-dept]` is (0,1,1), so it beats a page's own
   bare `body` rule regardless of source order. */
body[data-dept] {
  box-sizing: border-box;          /* pages that set html,body{height:100%} would
                                      otherwise overflow by the padding below */
  /* Zero the UA's default 8px body margin. Every ported page happens to kill it with its own
     `* { margin:0 }` reset, so this was invisible until src/home/ — which has no reset — put
     its content at 264px instead of the house 256px. The shell owns the frame, so it owns
     this too; it is a no-op for pages that already reset. */
  margin: 0;
  padding-left: calc(var(--tmf-nav-w) + var(--tmf-gutter));
  padding-right: var(--tmf-gutter);
  padding-top: var(--tmf-gutter-top);
  background: var(--tmf-page-bg);
}

/* A canvas must never be able to pin its container wider than the page (2026-08-12).
   Chart.js writes an inline pixel width onto the canvas, and for a replaced element that
   width IS its min-content contribution — so after a window resize from desktop to phone
   width the grid COLLAPSED correctly to one track and then could not shrink that track
   below the stale canvas width. Measured on /support: container 343px, track 537px, page
   553px wide inside a 375px viewport, and it never recovered.

   Why this and not a JS fix: `tmfRebuildChart` already clears the inline width, but
   Chart.js's own ResizeObserver rewrites it from the container before layout can settle —
   verified, clearing every canvas by hand did nothing. So the shrink loses a race it can
   never win. `max-width` removes the pin outright: it is a no-op in the steady state
   (the inline width already equals the container) and only binds during the stale window,
   which lets the track collapse, after which Chart.js re-measures and redraws correctly.
   Fixes the overflow on /support, /retention and /marketing/paid. */
body[data-dept] canvas { max-width: 100%; }

/* Baseline typeface, and the ONE deliberate bare-element exception to the scoping
   rule above. Same class of gap as the body margin: nothing in the shell set a font,
   so a page that declares none renders in the UA's Times — invisible until src/home/
   arrived, because every ported page either sets `body { font-family }` itself or
   scopes everything under an #app wrapper that does.

   On `html`, NOT on `body[data-dept]`, and that distinction is the whole point:
   seven pages declare `body { font-family: "Open Sans", Arial, sans-serif }` at
   (0,0,1), and a body[data-dept] rule at (0,1,1) would silently override all seven
   and restyle the entire dashboard. Inheritance loses to any own declaration, so
   this reaches only what nothing else claims. */
html { font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }

.tmf-nav {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--tmf-nav-w);
  background: var(--tmf-nav-bg);
  color: var(--tmf-nav-ink);
  display: flex;
  flex-direction: column;
  z-index: 9000;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* Right edge as an INSET shadow, not a border: it cannot change the
     computed width, so the body offset above stays exact whether or not
     the host page resets box-sizing. */
  box-shadow: inset -1px 0 0 var(--tmf-nav-edge);
}

/* Don't depend on the host page's box model. sales/index.html happens to
   ship `* { box-sizing:border-box; margin:0; padding:0 }`; the next
   department page may not. Scoped to nav descendants only. */
.tmf-nav,
.tmf-nav *,
.tmf-nav__scrim { box-sizing: border-box; }

/* ---- brand: "TMF/Reporting", no mark ----
   Sized as a logo, not as a nav label: it is the only piece of identity in the
   chrome, so it gets its own scale. 27px measures the wordmark at ~174px inside
   the 204px of usable rail (232 - 2x14 padding) — filling most of the width with
   a deliberate ~30px of breathing room rather than running to the edge. Grow it
   further only alongside --tmf-nav-w; white-space is nowrap, so an oversized
   wordmark overflows rather than wraps. */
/* An <a> to "/" since 2026-07-30 — the wordmark is the way home. Text-decoration and
   colour are reset explicitly because it is a link now and would otherwise pick up the
   page's own anchor styling, which differs per department. */
.tmf-nav__brand {
  flex: 0 0 auto;
  display: flex;
  text-decoration: none;
  align-items: center;
  height: 70px;
  padding: 0 14px;
  border-bottom: 1px solid var(--tmf-nav-edge);
  font-size: 27px;
  line-height: 1;
  letter-spacing: -.028em;
  white-space: nowrap;
}
.tmf-nav__brand-name { font-weight: 800; color: var(--tmf-navy); }
/* margin, not a literal space — see the note on the markup in nav.html. */
.tmf-nav__brand-sub  { font-weight: 500; color: var(--tmf-nav-muted); margin-left: .26em; }
.tmf-nav__brand:hover .tmf-nav__brand-name,
.tmf-nav__brand:hover .tmf-nav__brand-sub { color: var(--tmf-navy); }
.tmf-nav__brand:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: -2px; }

/* =====================================================================
   COLLAPSED RAIL (2026-08-12, Elliot: "I want to be able to collapse the sidebar nav")
   =====================================================================
   Collapses to an ICON RAIL rather than hiding: the icons are already there, so navigation
   stays one click away instead of two. 232px -> 58px gives the content back ~174px, which is
   most of a table column.

   ⚠️ THE WHOLE THING HINGES ON ONE DECLARATION. Both the rail's width and the page's
   padding-left already read var(--tmf-nav-w), so redefining that custom property on <body>
   moves the rail AND the content together — there is no second measurement to keep in sync,
   which is exactly how the 256px content edge drifted in the past.

   The collapse button and this state are DESKTOP-ONLY; the @media block at the bottom of this
   file resets the width and hides the button below 900px, where the rail is off-canvas and the
   hamburger owns it. */
body.tmf-nav-collapsed { --tmf-nav-w: 58px; }

/* Transitions are opt-in via .tmf-nav-tx, added one frame after load. Without that gate a
   visitor who left the rail collapsed would watch it animate open-to-closed on every single
   page load, because the class is applied while the document is still parsing. */
body.tmf-nav-tx .tmf-nav { transition: width .16s ease; }
body.tmf-nav-tx { transition: padding-left .16s ease; }

/* Lives in the FOOTER, right-aligned opposite the freshness dot (moved out of the brand row
   2026-08-12 at Elliot's request; the version stamp that used to hold this slot is gone). */
.tmf-nav__collapse {
  flex: 0 0 auto;
  margin-left: auto;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--tmf-nav-muted);
  cursor: pointer;
}
/* Boxed chevron (Elliot picked the icon 2026-08-12). stroke-width is 1.5 rather than the
   rail icons' 1.9 because the outer rect reads heavy at this size next to 10.5px text. */
.tmf-nav__collapse svg { width: 18px; height: 18px; fill: none; stroke: currentColor;
                         stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.tmf-nav__collapse:hover { background: var(--tmf-nav-hover); color: var(--tmf-navy); }
.tmf-nav__collapse:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: 1px; }

/* ---- what the collapsed rail hides ---- */
body.tmf-nav-collapsed .tmf-nav__brand-sub,
body.tmf-nav-collapsed .tmf-nav__label,
body.tmf-nav-collapsed .tmf-nav__searchlabel,
body.tmf-nav-collapsed .tmf-nav__kbd,
body.tmf-nav-collapsed .tmf-nav__sectionlabel { display: none; }

/* Brand shrinks to "TMF" and centres. */
body.tmf-nav-collapsed .tmf-nav__brand { padding: 0; justify-content: center; font-size: 19px; }

/* The chevron flips to point outward. Flipping the whole SVG is safe because the box is
   symmetric about the viewBox centre — only the chevron inside it moves. */
body.tmf-nav-collapsed .tmf-nav__collapse svg { transform: scaleX(-1); }

/* Items become centred icons. gap:0 matters — the label is display:none but a flex gap is
   applied between remaining items only, so without this the icon sits off-centre. */
body.tmf-nav-collapsed .tmf-nav__list a { justify-content: center; gap: 0; padding: 9px 0; }
body.tmf-nav-collapsed .tmf-nav__search { padding: 10px 8px 0; }
body.tmf-nav-collapsed .tmf-nav__searchbox { justify-content: center; padding: 7px 0; }
/* The footer stacks: 58px will not hold the dot, a gap and a 26px button side by side without
   crowding both against the edges. `margin-left` is reset because `auto` in a column direction
   would centre nothing and shove the button right. */
body.tmf-nav-collapsed .tmf-nav__foot {
  flex-direction: column;
  gap: 9px;
  justify-content: center;
  padding: 10px 0 12px;
}
body.tmf-nav-collapsed .tmf-nav__collapse { margin-left: 0; }
/* The freshness stamp keeps its DOT and loses its words — "Data through 2026-08-11" cannot fit
   58px and was clipping to "Data thro…". font-size:0 works because the dot is a ::before with an
   explicit 6px box, so it does not shrink with the text; gap:0 stops the now-empty text node
   holding the dot 3px off centre. The full stamp is still on the element's title. */
body.tmf-nav-collapsed .tmf-nav__status { font-size: 0; gap: 0; }

/* ---- mobile top bar (markup emitted by nav.html) ----
   Desktop hides it entirely: the rail's own wordmark is right there. It only exists
   below 900px, where the rail is off-canvas — see the @media block near the bottom. */
.tmf-topbar { display: none; }

/* ---- quick search ----
   Sits between the wordmark and the rail because it is a filter OF the rail:
   putting it below the list, or in the footer, would separate the control from
   the thing it controls. It is `flex: 0 0 auto` for the same reason the brand and
   footer are — only .tmf-nav__list may absorb the leftover height, or the rail
   stops scrolling independently and long menus push the footer off screen. */
.tmf-nav__search {
  flex: 0 0 auto;
  padding: 10px 10px 0;
}
/* A <label>, so the whole field — icon, padding and the "/" hint — is a click
   target for the input, not just the 100-odd pixels of the input itself. */
.tmf-nav__searchbox {
  display: flex;
  align-items: center;
  gap: 7px;
  /* A <button> is shrink-to-fit, unlike the <label> this used to be — without the
     width it collapses to its text and stops reading as a field. */
  width: 100%;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 8px;
  background: var(--tmf-nav-hover);
  cursor: text;
}
/* Inset field → white on focus: the box reads as "somewhere to type" only once
   it is live, which is also what tells you the "/" shortcut landed. */
.tmf-nav__searchbox:focus-within {
  background: var(--tmf-nav-bg);
  border-color: var(--tmf-navy);
  box-shadow: 0 0 0 2px rgba(16, 27, 91, .10);
}
.tmf-nav__searchico {
  flex: 0 0 auto;
  width: 13px;
  height: 13px;
  fill: none;
  stroke: var(--tmf-nav-muted);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Every property a host page's `input` rule might have set is restated. Seven of
   the eleven pages style their own controls and this element is inside their
   document, so inheriting a page's input chrome would make the nav look different
   per department. */
.tmf-nav__search input {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.2;
  color: var(--tmf-nav-ink);
}
.tmf-nav__search input::placeholder { color: var(--tmf-nav-muted); opacity: 1; }
/* The hint is how you get here, so it is noise once you have arrived. Hidden
   rather than removed: taking it out of flow would shift the input mid-keystroke. */
.tmf-nav__kbd {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 4px;
  background: var(--tmf-nav-bg);
  font-family: inherit;
  font-size: 10px;
  line-height: 1;
  color: var(--tmf-nav-muted);
}
.tmf-nav__searchbox:focus-within .tmf-nav__kbd { visibility: hidden; }
/* The rail button is an affordance, not a field — it opens .tmf-pal. Styled to read
   as an input anyway, because that is what tells you it is somewhere to search. */
.tmf-nav__searchlabel {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
  font-size: 12.5px;
  color: var(--tmf-nav-muted);
}
.tmf-nav__searchbox:hover { background: var(--tmf-nav-bg); border-color: #cdd6e4; }
.tmf-nav__searchbox:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: 1px; }

/* ---- the search palette (a second <dialog>, see nav.html) ---- */
.tmf-pal {
  width: min(560px, calc(100vw - 32px));
  max-height: min(70vh, 560px);
  padding: 0;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 14px;
  background: var(--tmf-nav-bg);
  color: var(--tmf-nav-ink);
  box-shadow: 0 24px 64px rgba(16, 27, 91, .22);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* ⚠️ Restated because a page's global `* { margin:0 }` reset kills a dialog's
     centring and pins it to the viewport's top-left. src/sales/index.html has one.
     Same trap already documented on .tmf-info — the shell must assume nothing about
     a page's reset. margin-top biases it upward: a palette belongs under your eyes,
     not in the vertical centre. */
  margin: auto;
  margin-top: 12vh;
  display: none;
  flex-direction: column;
  overflow: hidden;
}
.tmf-pal[open] { display: flex; }
.tmf-pal::backdrop { background: rgba(16, 27, 91, .28); }
.tmf-pal, .tmf-pal * { box-sizing: border-box; }

.tmf-pal__head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 14px;
  border-bottom: 1px solid var(--tmf-nav-edge);
}
.tmf-pal__ico {
  flex: 0 0 auto;
  width: 16px; height: 16px;
  fill: none; stroke: var(--tmf-nav-muted); stroke-width: 2; stroke-linecap: round;
}
/* Every property restated — this input lives inside eleven documents that style
   their own controls, and inheriting one page's chrome would make the palette look
   different per department. */
.tmf-pal__head input {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0; padding: 0; border: 0; outline: none; background: transparent;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.3;
  color: var(--tmf-nav-ink);
}
.tmf-pal__head input::placeholder { color: var(--tmf-nav-muted); opacity: 1; }
.tmf-pal__esc {
  flex: 0 0 auto;
  padding: 2px 6px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 5px;
  background: var(--tmf-page-bg);
  font-family: inherit;
  font-size: 10px;
  color: var(--tmf-nav-muted);
}

.tmf-pal__list {
  flex: 1 1 auto;
  list-style: none;
  margin: 0;
  padding: 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.tmf-pal__list li { margin: 0; }
.tmf-pal__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 0;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
/* ONE cursor style driven by the class, not by :hover — the keyboard and the mouse
   must agree on which row Enter will open. A :hover rule would light a second row. */
.tmf-pal__item.is-cursor { background: var(--tmf-nav-hover); }
.tmf-pal__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.tmf-pal__label {
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.25;
  color: var(--tmf-nav-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tmf-pal__crumb {
  font-size: 11.5px;
  line-height: 1.25;
  color: var(--tmf-nav-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tmf-pal__kind {
  flex: 0 0 auto;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: var(--tmf-page-bg);
  color: var(--tmf-nav-muted);
}
.tmf-pal__kind--page { background: rgba(16, 27, 91, .08); color: var(--tmf-navy); }

.tmf-pal__empty {
  margin: 0;
  padding: 18px 16px 22px;
  font-size: 13px;
  color: var(--tmf-nav-muted);
}
.tmf-pal__empty[hidden] { display: none; }

.tmf-pal__foot {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 9px 14px;
  border-top: 1px solid var(--tmf-nav-edge);
  background: var(--tmf-page-bg);
  font-size: 11px;
  color: var(--tmf-nav-muted);
}
.tmf-pal__foot kbd {
  display: inline-block;
  min-width: 16px;
  margin-right: 3px;
  padding: 1px 4px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 4px;
  background: var(--tmf-nav-bg);
  font-family: inherit;
  font-size: 10px;
  text-align: center;
}
.tmf-pal__count { margin-left: auto; font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .tmf-pal { margin-top: 8vh; max-height: 78vh; }
  /* The hint row is desktop affordance; a phone has no arrow keys and the space is
     better spent on results. */
  .tmf-pal__foot { display: none; }
}

/* ---- rail ---- */
.tmf-nav__list {
  list-style: none;
  margin: 0;
  padding: 6px 10px 14px;       /* horizontal padding insets the pills */
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.tmf-nav__list li { margin: 0; }

/* ---- sections ---- */
.tmf-nav__sectionlabel {
  display: block;
  padding: 18px 10px 6px;       /* generous above, tight below */
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .085em;
  text-transform: uppercase;
  color: var(--tmf-nav-muted);
}
/* The first section still sits tighter than the 18px between sections — a full gap
   under the wordmark reads as a missing item — but 6px had it crowding the brand.
   14px separates it from the wordmark without opening a hole. */
.tmf-nav__section:first-child .tmf-nav__sectionlabel { padding-top: 14px; }
/* A rule between sections (2026-08-12, Elliot). On the SECOND section onward, so the
   first one is not separated from the wordmark — that edge already has its own border.
   The label's 18px of top padding sits below the line, which is what keeps the heading
   attached to the items it names rather than floating between two groups.

   The padding-bottom is the other half of that: without it the line sat hard against the
   last item of the section ABOVE, so the rule read as belonging to that item rather than
   separating the two groups (Elliot, same day). 12px above the line against 18px below it
   is deliberate and not a mistake — the label needs the larger gap because it is the thing
   being separated, and an even split makes the heading look adrift between two sections. */
.tmf-nav__section { padding-bottom: 12px; }
.tmf-nav__section + .tmf-nav__section { border-top: 1px solid var(--tmf-nav-edge); }
/* The last section has no rule under it, so its padding would only push the freshness
   footer down. */
.tmf-nav__section:last-child { padding-bottom: 0; }
.tmf-nav__section ul {
  list-style: none;
  margin: 0;
  padding: 0;                   /* flat — no child indent */
}
.tmf-nav__section ul li + li { margin-top: 2px; }

/* ---- items: pill rows ---- */
.tmf-nav__list a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;            /* ~= 37px tall */
  border-radius: 8px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--tmf-nav-ink);
  text-decoration: none;
}
.tmf-nav__ico {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  /* Every icon's shared presentation lives here, not repeated six times
     in the markup — nav.html is inlined into every department page. */
  fill: none;
  stroke: currentColor;         /* so the active pill's icon turns white */
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.tmf-nav__list a:hover { background: var(--tmf-nav-hover); }
.tmf-nav__list a:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: 1px; }

/* Must stay AFTER :hover — same specificity (0,2,1), source order decides,
   and an active item should not lighten on hover. */
.tmf-nav__list a.is-active {
  background: var(--tmf-navy);
  color: #fff;
  font-weight: 600;
}

/* Sections still living in Claude. Visible on purpose — the nav doubles as
   the migration scoreboard — but inert, so nobody lands on a 404. The
   opacity is on the anchor so it dims the inline icon and the chip too. */
.tmf-nav__list a.is-pending {
  opacity: .48;                 /* .38 read as almost-gone on white */
  cursor: not-allowed;
}
.tmf-nav__list a.is-pending:hover { background: transparent; }
.tmf-nav__list a.is-pending::after {
  content: "soon";
  margin-left: auto;            /* was float:right — the anchor is flex now */
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  border-radius: 4px;
  padding: 1px 4px;
  line-height: 1.3;
}

/* ---- footer: freshness dot + collapse toggle ----
   The version stamp was deleted 2026-08-12 (Elliot: "I dont need to see v1.0") and the
   collapse button took its place; the vertical padding is trimmed from 11/13 so the taller
   button does not grow the footer past the ~38px it has always been. */
.tmf-nav__foot {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 7px;
  border-top: 1px solid var(--tmf-nav-edge);
  font-size: 10.5px;
  line-height: 1.3;
  white-space: nowrap;
}
.tmf-nav__status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  color: var(--tmf-nav-muted);
}
.tmf-nav__status::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--tmf-nav-ok);
}
/* No stamp yet (the page publishes one after its first query resolves) →
   no dot either, or the nav would claim a freshness it doesn't have. */
.tmf-nav__status:empty::before { display: none; }

/* ==================== SHARED DATE-RANGE CONTROL ====================
   The pill row + custom-range popover behind window.tmfDateRange (nav.html).
   Adopted by /support 2026-08-11; every other page still ships its own `.seg`
   until it is migrated, so nothing here may lean on a page's own styles.

   ⚠️ THE PILL ROW MUST NOT EXCEED 34px TALL. Pages put it in a `.rangebar`, whose
   `min-height:34px` is what holds every page header at the house 53.81px; a taller
   control makes the header grow and the page jump between tabs. Measured here at
   32px (26px pill + 3px padding each side). Do not add vertical padding without
   re-measuring the header on every tab of the adopting page. */
/* ⚠️ SPECIFICITY: every pill/popover rule below is written as `.tmf-dr .tmf-dr__pill`
   rather than `.tmf-dr__pill`, and the extra class is load-bearing. The pages were each
   ported from a standalone artifact and their CSS is unnamespaced — /sales carries
   `.rangebar button { background: var(--navy); color:#fff }` at (0,1,1), which outranks a
   bare `.tmf-dr__pill` at (0,1,0) and painted EVERY pill as if it were the active one.
   (0,2,0) beats it. The shell tells pages never to introduce bare selectors; the
   converse is that shell components must survive the ones pages already have. */
.tmf-dr {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 9px;
  background: var(--tmf-page-bg);
  /* Wrap as a WHOLE GROUP, never fragmenting mid-row: a seg that breaks between its
     own buttons reads as broken rather than as a wrapped control. */
  flex: 0 0 auto;
  flex-wrap: wrap;
  max-width: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.tmf-dr .tmf-dr__pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  margin: 0;
  padding: 0 11px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  color: var(--tmf-nav-muted);
  white-space: nowrap;
  cursor: pointer;
}
/* ⚠️ HOVER PINS BOTH COLOUR AND BACKGROUND, and the background half is why. Setting
   only `color` left the background to whatever the page happened to declare: /sales has
   `.rangebar button:hover { background:#0a1242 }`, so hovering any pill there painted it
   dark navy while this rule set the text navy too — invisible. Reported 2026-08-12 on
   Quality's cohort control.

   Matching /support, the reference: an inactive pill does NOT gain a fill on hover, it
   just darkens its text. The active pill keeps its navy fill and white text — stated
   explicitly rather than left to `:not(.is-active)`, so no page rule can repaint it. */
.tmf-dr .tmf-dr__pill:hover:not(:disabled):not(.is-active) {
  background: transparent;
  color: var(--tmf-navy);
}
.tmf-dr .tmf-dr__pill.is-active:hover {
  background: var(--tmf-navy);
  color: #fff;
}
.tmf-dr .tmf-dr__pill:disabled:hover { background: transparent; }
/* Navy, not the reference's black — the reference is someone else's brand. */
.tmf-dr .tmf-dr__pill.is-active {
  background: var(--tmf-navy);
  border-color: var(--tmf-navy);
  color: #fff;
}
.tmf-dr .tmf-dr__pill:disabled { opacity: .4; cursor: not-allowed; }
.tmf-dr .tmf-dr__pill:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: 1px; }
.tmf-dr .tmf-dr__pill--custom { padding-left: 9px; }
.tmf-dr .tmf-dr__pill--custom svg {
  width: 13px; height: 13px;
  fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.tmf-dr__customlabel { font-variant-numeric: tabular-nums; }

/* ---- the popover ----
   Parented to <body> and position:fixed, so no page's overflow can clip it and no
   transformed ancestor can capture it. z-index sits below the nav rail (9000) and
   below the mobile scrim (8900): this belongs to the content area, and an open
   drawer should cover it. */
.tmf-dr__pop {
  position: fixed;
  z-index: 8600;
  display: none;
  flex-direction: column;
  width: max-content;
  max-width: calc(100vw - 16px);
  /* Bounded, with the BODY scrolling rather than the popover growing past the
     viewport: stacked on a phone the two calendars plus the preset rail run to
     ~720px, which does not fit under a header in an 812px window. The footer must
     stay reachable — an Apply button you cannot scroll to is a dead end. */
  max-height: calc(100vh - 16px);
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 14px;
  background: var(--tmf-nav-bg);
  box-shadow: 0 20px 56px rgba(16, 27, 91, .20);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--tmf-nav-ink);
}
.tmf-dr__pop.is-open { display: flex; }
.tmf-dr__pop, .tmf-dr__pop * { box-sizing: border-box; }
.tmf-dr__popbody {
  display: flex;
  gap: 0;
  padding: 12px;
  min-height: 0;          /* or the flex child refuses to shrink and overflow wins */
  overflow-y: auto;
  overscroll-behavior: contain;
}

.tmf-dr__presets {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 168px;
  padding-right: 12px;
  margin-right: 12px;
  border-right: 1px solid var(--tmf-nav-edge);
}
.tmf-dr__pop .tmf-dr__preset {
  margin: 0;
  padding: 7px 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.2;
  text-align: left;
  color: var(--tmf-nav-ink);
  white-space: nowrap;
  cursor: pointer;
}
.tmf-dr__pop .tmf-dr__preset:hover:not(:disabled):not(.is-active) { background: var(--tmf-nav-hover); }
.tmf-dr__pop .tmf-dr__preset.is-active { background: var(--tmf-navy); color: #fff; font-weight: 600; }
.tmf-dr__pop .tmf-dr__preset:disabled { opacity: .4; cursor: not-allowed; }

.tmf-dr__cal { display: flex; flex-direction: column; gap: 10px; }
.tmf-dr__calhead { display: flex; gap: 8px; }
.tmf-dr__pop .tmf-dr__sel {
  flex: 1 1 auto;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 8px;
  background: var(--tmf-nav-bg);
  font-family: inherit;
  font-size: 12.5px;
  color: var(--tmf-nav-ink);
}
.tmf-dr__months { display: flex; gap: 18px; }
.tmf-dr__mname {
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  color: var(--tmf-nav-ink);
}
.tmf-dr__grid { display: grid; grid-template-columns: repeat(7, 30px); gap: 1px; }
.tmf-dr__dow {
  height: 24px;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600;
  color: var(--tmf-nav-muted);
}
.tmf-dr__pad { height: 30px; }
.tmf-dr__pop .tmf-dr__day {
  height: 30px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1;
  color: var(--tmf-nav-ink);
  cursor: pointer;
}
.tmf-dr__pop .tmf-dr__day:hover:not(:disabled) { background: var(--tmf-nav-hover); }
/* A day the data cannot answer is DISABLED, not merely unselected — on Support that
   is today and every future day, because rc_call_daily is a nightly mirror and a
   window ending today is structurally empty. */
.tmf-dr__pop .tmf-dr__day:disabled { color: #c3cbd8; cursor: not-allowed; }
.tmf-dr__pop .tmf-dr__day.is-in { background: var(--tmf-nav-hover); border-radius: 0; }
.tmf-dr__pop .tmf-dr__day.is-end { background: var(--tmf-navy); color: #fff; font-weight: 600; }
/* Square off the inner edges so the two endpoints read as caps on one bar. */
.tmf-dr__day.is-start { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.tmf-dr__day.is-finish { border-top-left-radius: 0; border-bottom-left-radius: 0; }

.tmf-dr__stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 5px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 9px;
}
.tmf-dr__pop .tmf-dr__step {
  width: 26px; height: 26px;
  margin: 0; padding: 0;
  border: 0; border-radius: 7px;
  background: transparent;
  font-family: inherit; font-size: 15px; line-height: 1;
  color: var(--tmf-nav-ink);
  cursor: pointer;
}
.tmf-dr__pop .tmf-dr__step:hover { background: var(--tmf-nav-hover); }
.tmf-dr__steplabel { font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }

.tmf-dr__popfoot {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-top: 1px solid var(--tmf-nav-edge);
  background: var(--tmf-page-bg);
  border-radius: 0 0 13px 13px;
}
.tmf-dr__pop .tmf-dr__btn {
  height: 32px;
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 8px;
  background: var(--tmf-nav-bg);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--tmf-nav-ink);
  cursor: pointer;
}
.tmf-dr__pop .tmf-dr__btn:hover { background: var(--tmf-nav-hover); }
.tmf-dr__pop .tmf-dr__btn--go { background: var(--tmf-navy); border-color: var(--tmf-navy); color: #fff; }
.tmf-dr__pop .tmf-dr__btn--go:hover { background: #0b1442; }
/* Apply stays dead until both ends are picked — half a range is not a range. */
.tmf-dr__pop .tmf-dr__btn--go:disabled { opacity: .45; cursor: not-allowed; background: var(--tmf-navy); }

@media (max-width: 720px) {
  /* Two months side by side is ~430px of calendar plus a 180px preset rail; neither
     fits a phone. Stack the months and put the presets above them as a wrapped row. */
  .tmf-dr__popbody { flex-direction: column; padding: 10px; }
  .tmf-dr__presets {
    flex-direction: row;
    flex-wrap: wrap;
    width: auto;
    margin: 0 0 10px;
    padding: 0 0 10px;
    border-right: 0;
    border-bottom: 1px solid var(--tmf-nav-edge);
  }
  .tmf-dr__months { flex-direction: column; gap: 12px; }
  .tmf-dr__grid { grid-template-columns: repeat(7, 1fr); }
  .tmf-dr__pop { width: calc(100vw - 16px); }
}

/* ⚠️ The header caption squeeze, fixed once for every page that adopts the control.
   Pages label their controls "PERIOD" / "RANGE" / "TEAM" in a `.rangebar .ctl > label`.
   Those captions cost 50-70px each, and between the 900px drawer breakpoint and about
   1080px that is the difference between a one-row header and a two- or three-row one —
   /support went 54px -> 78.5px, /reviews 54px -> 120.5px once its date pills arrived.
   The pills are self-describing and the controls carry real aria-labels, so the caption
   is the affordable loss.

   Scoped under body[data-dept] to honour this file's rule that nothing here may claim a
   bare element selector, and so it only reaches pages inside the shell frame. Note the
   squeeze is ABOVE the mobile breakpoint: below 900px the rail goes off-canvas and the
   width comes back, so keying this to 900px would miss it entirely. */
/* ⚠️ The caption to the LEFT of a date control is GONE FROM THE MARKUP (2026-08-12), not
   hidden by a rule here. Pages spelled it three different ways — "DATE RANGE" on Sales,
   "RANGE" on Reviews, "PERIOD" on Support — which read as three different controls. The
   pills say what they are and each control carries a real aria-label, so nothing is lost.

   It was briefly a `:has(+ .tmf-dr)` rule in this file, and that is the part worth
   remembering: an ADJACENT `:has()` rule in this same stylesheet was silently dropped by
   the CSS parser — it never entered the CSSOM while feature detection reported support —
   so a visual requirement resting on `:has()` is a requirement that can vanish without
   any error anywhere. 15 labels deleted, verified in-browser one at a time rather than by
   pattern-matching the source: the sixteenth match, `<label for="viewScopeSel">`, names a
   real <select> and is still on screen. Captions that name a DIFFERENT filter — Team,
   Form — are not self-describing and stay. */

/* A view that genuinely cannot answer another window gets a SCOPE LINE, not a control.
   One style for it here (2026-08-12) because it was being expressed three ways: a plain
   span on /book-of-business, and — worse — a <select> with a SINGLE option on /sales'
   Show Rate / Conversion / Projections and on /retention's Client Retention. Those two
   rendered a dropdown ARROW next to text nobody can change, which is a control that lies
   about being one; Elliot read them as broken formatting, correctly. Static text, muted,
   no border, no affordance. */
body[data-dept] .tmf-scope {
  font-size: 12.5px;
  color: var(--tmf-nav-muted);
  font-weight: 600;
  white-space: nowrap;
}

/* ---- trailing filters sit against the right edge ----------------------------
   House rule (Elliot, 2026-08-11): when a header carries a filter BESIDES the date
   control — a Team select, a coverage toggle — that filter is right-aligned. The date
   control owns the left, everything else answers "and narrowed to what?" from the far
   side, so the eye has two fixed places to look instead of a ragged middle.

   ⚠️ This only works if the status text does NOT grow. `flex: 1 1 0` was given to
   `#status` to stop it wrapping the header onto a second row, and that fixed the wrap
   but made it absorb every pixel of free space — which is what pushed the Team select
   in from the right edge on /reviews. Flex-grow resolves BEFORE auto margins get
   anything, so a growing status starves `margin-left:auto` completely. Pages pair this
   class with `flex: 0 1 auto` + a `max-width` on their status element: a bounded
   pre-shrink size still cannot force a wrap in the normal states, and an empty status
   collapses to nothing so the trailing filter lands flush right. */
.tmf-endfilter { margin-left: auto; }
/* ⚠️ An auto margin can only push to the edge of its OWN parent. The pages wrap each
   control group in a `.ctl` that is `flex: 0 0 auto`, so on /marketing/paid the Form
   filter sat at the right edge of a 618px `.ctl` inside an 883px bar — visibly adrift,
   and exactly what "still not right aligned" looked like. The containing group has to
   span the row before its child's auto margin means anything.

   Put `tmf-endfilter-row` on the CONTAINER and `tmf-endfilter` on the filter inside it.
   (This was briefly written as `.ctl:has(.tmf-endfilter)` so pages needed only one
   class — the rule was silently dropped by the CSS parser while an adjacent `:has(+ …)`
   rule in the same file parsed fine. Not worth the mystery for a class name.) */
body[data-dept] .rangebar .tmf-endfilter-row { flex: 1 1 auto; }

/* ---- breadcrumb (content-area chrome, emitted by nav.html) ---- */
.tmf-crumb {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-bottom: 10px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .085em;
  text-transform: uppercase;
  color: var(--tmf-nav-muted);
}
/* The department segment is the page's only <h1>. This beats a page's bare
   `h1` rule on specificity: (0,1,1) > (0,0,1). */
.tmf-crumb h1 {
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  font-family: inherit;
  color: inherit;
  margin: 0;
}
.tmf-crumb__sep { opacity: .55; }
.tmf-crumb__view { color: var(--tmf-nav-ink); }
.tmf-crumb__sep[hidden], .tmf-crumb__view[hidden] { display: none; }

/* ---- shared "?" explainer popup (markup emitted by nav.html) ----
   Replaced the old inline .infopop reveal, which expanded in place and pushed
   the card's own content down — you lost sight of the number you were asking
   about. Every department page shares this one dialog.

   No padding on the dialog itself: the click handler treats a hit on the
   element (rather than a child) as a backdrop click, which only works if the
   element has no inner clickable margin of its own. */
.tmf-info {
  /* margin:auto is what centres a modal <dialog> inside its fixed inset box.
     It is the UA default — but src/sales/index.html ships a global
     `* { margin:0; padding:0 }` reset that wipes it, which pinned the popup to
     the top-left corner of the viewport. Restated here, deliberately, because
     the shell cannot assume anything about a department page's reset. */
  margin: auto;
  padding: 0;
  border: 1px solid var(--tmf-nav-edge);
  border-radius: 12px;
  width: min(560px, calc(100vw - 32px));
  /* Column flex + min-height:0 on the body is what makes the body scroll and
     the header stay put. An explicit max-height calc on the body instead of
     this fought the UA's own max-height on modal dialogs and clipped content. */
  max-height: min(78vh, 640px);
  display: flex;
  flex-direction: column;
  overflow: hidden;                /* the body scrolls, not the dialog */
  background: var(--tmf-nav-bg);
  color: var(--tmf-nav-ink);
  box-shadow: 0 12px 40px rgba(16, 27, 91, .22);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
/* The UA gives a modal dialog `display:block` when open and `display:none`
   otherwise; re-assert the flex layout only for the open state. */
.tmf-info:not([open]) { display: none; }
.tmf-info, .tmf-info * { box-sizing: border-box; }
.tmf-info::backdrop { background: rgba(16, 27, 91, .34); }

.tmf-info__head {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 13px 16px 11px;
  border-bottom: 1px solid var(--tmf-nav-edge);
}
/* Not the page's <h1> — the breadcrumb keeps that. Sized as a card title. */
.tmf-info__title {
  flex: 1 1 auto;
  margin: 0;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--tmf-navy);
}
.tmf-info__close {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  margin: -2px -4px 0 0;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--tmf-nav-muted);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
}
.tmf-info__close:hover { background: var(--tmf-nav-hover); color: var(--tmf-navy); }
.tmf-info__close:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: 1px; }

/* The content is lifted verbatim out of a page's .infopop, so it arrives as
   loose text with <b>, <code> and <br>. Slightly larger than the 11.5px it
   used to render at inline: this is now a focused reading surface, not a
   marginal note competing with a chart. */
.tmf-info__body {
  flex: 1 1 auto;
  min-height: 0;                   /* without this a flex item refuses to shrink
                                      below its content and nothing scrolls */
  padding: 13px 16px 16px;
  overflow-y: auto;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--tmf-nav-muted);
  overscroll-behavior: contain;
}
.tmf-info__body b, .tmf-info__body strong { color: var(--tmf-nav-ink); }
.tmf-info__body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .92em;
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--tmf-nav-hover);
  color: var(--tmf-nav-ink);
}
.tmf-info__body em { font-style: italic; }
.tmf-info__body p { margin: 0 0 8px; }
.tmf-info__body p:last-child { margin-bottom: 0; }

@media (max-width: 560px) {
  .tmf-info { width: calc(100vw - 20px); max-height: 84vh; }
}

/* ---- mobile drawer ---- */
.tmf-nav__toggle { display: none; }
.tmf-nav__scrim { display: none; }

@media (max-width: 900px) {
  :root { --tmf-gutter: 16px; }

  /* ⚠️ COLLAPSE IS INERT BELOW 900px. Here the rail is off-canvas and the hamburger owns it,
     so a collapsed width would only shrink the DRAWER — and a visitor who collapsed on desktop
     would find a 58px drawer on their phone. Reset the width and hide the button; the stored
     preference survives untouched for when they are back on a wide screen. */
  body.tmf-nav-collapsed { --tmf-nav-w: 232px; }
  .tmf-nav__collapse { display: none; }

  body[data-dept] {
    /* No nav to clear, but keep a gutter — this used to be 0, which put
       content flush against the viewport edge. padding-right inherits
       the gutter from the base rule. */
    padding-left: var(--tmf-gutter);
    /* ⚠️ The BAR HEIGHT PLUS THE NORMAL TOP GUTTER. This was a bare 46px — exactly the
       bar's height — so the breadcrumb began at the pixel the bar ended and read as
       glued to it, while desktop enjoys 16px of air from --tmf-gutter-top. Reported
       2026-08-12. Derived rather than hardcoded so the two cannot drift apart. */
    padding-top: calc(46px + var(--tmf-gutter-top));
  }

  /* The always-visible way home. Fills the 46px band body[data-dept] already reserves
     above, which until now held nothing but the floating hamburger — so this adds a bar
     without moving a single pixel of page content.
     z-index sits BELOW the scrim (8900) on purpose: opening the drawer should dim the bar
     along with the page. The toggle stays above everything at 9100, as it is also the
     close affordance. */
  .tmf-topbar {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 46px;
    z-index: 8800;
    background: var(--tmf-nav-bg);
    box-shadow: inset 0 -1px 0 var(--tmf-nav-edge);
  }
  /* Centred on the VIEWPORT, not on the space left of the toggle — the toggle is
     position:fixed and out of flow, so the flex centring already ignores it. Padding
     keeps the wordmark off the button if the two ever meet on a very narrow screen. */
  .tmf-topbar__brand {
    display: flex;
    align-items: center;
    /* Clear the toggle on both sides so the centred wordmark cannot collide with it:
       gutter + button width + breathing room. Symmetric, so it stays centred. */
    padding: 0 calc(var(--tmf-gutter) + 38px + 10px);
    font-size: 18px;
    line-height: 1;
    letter-spacing: -.028em;
    white-space: nowrap;
    text-decoration: none;
  }
  .tmf-topbar__brand:focus-visible { outline: 2px solid var(--tmf-navy); outline-offset: -2px; }

  .tmf-nav {
    transform: translateX(-100%);
    transition: transform .18s ease-out;
    /* box-shadow is not additive — restate the right edge alongside the
       drawer lift. */
    box-shadow: inset -1px 0 0 var(--tmf-nav-edge), 0 0 24px rgba(16, 27, 91, .18);
  }
  body.tmf-nav-open .tmf-nav { transform: translateX(0); }

  /* The floating toggle sits over the drawer's brand band when open, which
     leaves only ~160px for the wordmark — not enough for it at 23px, and
     white-space:nowrap would overflow rather than wrap. Step it down. */
  .tmf-nav__brand { padding-left: 58px; font-size: 19px; }

  .tmf-nav__toggle {
    position: fixed;
    /* Centred in the 46px bar — (46 - 34) / 2 — instead of the old top:10px, which left
       10px above and 2px below and read as sitting high. Left edge matches the content
       gutter so it lines up with the breadcrumb and cards beneath it, rather than being
       6px further out. */
    top: calc((46px - 34px) / 2);
    left: var(--tmf-gutter);
    z-index: 9100;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 38px;
    height: 34px;
    padding: 0 8px;
    border: 1px solid var(--tmf-nav-edge);
    border-radius: 7px;
    background: #fff;
    cursor: pointer;
  }
  .tmf-nav__toggle span {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: var(--tmf-navy);
  }

  /* No physical keyboard to press it on, and the field is already one tap away
     inside an open drawer. */
  .tmf-nav__kbd { display: none; }

  .tmf-nav__scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 8900;
    background: rgba(16, 27, 91, .32);
  }
  .tmf-nav__scrim[hidden] { display: none; }
}

@media print {
  .tmf-nav, .tmf-nav__toggle, .tmf-nav__scrim { display: none !important; }
  body[data-dept] { padding-left: 0; padding-right: 0; padding-top: 0; }
}

/* ==================== SHARED LOADING-STATE LANGUAGE ====================
   Moved here 2026-07-30 alongside tmfKpiSkeleton()/tmfPaintKpiSkeletons() in
   nav.html. These rules were duplicated in eight page <style> blocks and — more
   to the point — were MISSING from the three pages that never adopted skeletons
   at all (/people hand-rolled its placeholders, /recruiting and /ready-to-sell
   had none), so the shared helper had nothing to style there. Owning them here
   means a page gets correct loading states by declaring data-sk and nothing else.

   A page that still declares these locally overrides with identical rules and is
   therefore harmless, but the local copy should go: the point is one definition. */

/* The shimmer bar. Inline by default (skeleton table cells use it that way). */
.skbar {
  display: inline-block;
  width: 60%;
  height: 12px;
  border-radius: 3px;
  background: #e7ebf2;
  animation: skpulse 1.1s ease-in-out infinite;
}
@keyframes skpulse { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }

/* A skeleton KPI card is a REAL .kpi card whose rows each hold an &nbsp;, so the
   row keeps its natural line box and the card comes out the exact height it will
   be with data in it (measured: 129px for a 4-row Company card). The bar is
   absolutely positioned inside the row so it cannot affect that height. */
.kpi-sk > div { position: relative; }
.kpi-sk .skbar {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  background: #e7ebf2;
  border-radius: 4px;
  animation: skpulse 1.1s ease-in-out infinite;
}
.kpi-sk .label  .skbar { width: 62%; height: 9px; }
.kpi-sk .value  .skbar { width: 46%; height: 22px; }
.kpi-sk .cmp    .skbar { width: 54%; height: 9px; }
.kpi-sk .detail .skbar { width: 80%; height: 8px; }

/* A card holding a chart or table must reserve its final size while loading —
   rendering nothing and then snapping to full height reads as broken. */
.skeleton {
  color: var(--muted);
  font-size: 14px;
  padding: 30px 0;
  text-align: center;
  min-height: 180px;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Genuinely single-line spots opt out. */
.drill .skeleton, .skeleton.sk-inline { min-height: 0; display: block; padding: 8px 0; }

@media (prefers-reduced-motion: reduce) {
  .skbar, .kpi-sk .skbar { animation: none; }
}
