/* ==========================================================================
   MEMBER JOURNEY — the working relationship with BBN
   --------------------------------------------------------------------------
   DISCIPLINED RICHNESS. The structures below are deliberately varied — an
   attention strip reads differently from a compact row, which reads differently
   from a timeline entry — because a screen built from one repeated card teaches
   a member nothing about what kind of thing they are looking at.
   No KPI tiles, no scores, no streaks, no decorative charts.

   Everything is drawn from tokens.css. Ordinary radius is --bbn-radius (6px).

   NOTHING HERE DECIDES ACCESS. Every list is what a server projection returned.
   There is no `display:none` for a record the member may not see, because such
   a record never reaches the browser.
   ========================================================================== */
.bbnmj{ font-family:var(--bbn-font); color:var(--bbn-text); margin:20px 0; }
.bbnmj *{ box-sizing:border-box }

/* ---- workspace sub-navigation -------------------------------------------
   A horizontal rail rather than a grid of cards: these are places, not
   choices, and a member returning for the third time wants the same target in
   the same spot. Scrolls horizontally on phones instead of wrapping into a
   block that pushes content off-screen.

   IA v4 narrowed what this rail contains. It used to list all eight journey
   modules, which made it a second global navigation sitting inside a page the
   portal rail had already navigated to. It now lists only the current
   section's siblings, and renders nothing for a section of one — so on most
   screens it reads as that section's tabs.

   .bbnmj__count was removed with the same change: the needs-attention badge
   belongs on Dashboard in the portal rail (nav.js), where it is visible from
   every page rather than only from inside the workspace. */
.bbnmj__rail{
  display:flex; gap:4px; overflow-x:auto; padding:0 0 2px;
  border-bottom:1px solid var(--bbn-border); margin-bottom:18px;
  scrollbar-width:thin;
}
.bbnmj__rail::-webkit-scrollbar{ height:4px }
.bbnmj__rail a{
  flex:none; padding:9px 14px; font-size:var(--bbn-size-support);
  font-weight:var(--bbn-weight-strong); color:var(--bbn-text-secondary);
  text-decoration:none; border-bottom:2px solid transparent; white-space:nowrap;
}
.bbnmj__rail a:hover{ color:var(--bbn-link-hover) }
.bbnmj__rail a[aria-current="page"]{
  color:var(--bbn-brand); border-bottom-color:var(--bbn-brand);
}

/* ---- section scaffolding ---- */
.bbnmj__section{ margin-bottom:26px }
.bbnmj__h2{
  font-size:var(--bbn-size-section); font-weight:var(--bbn-weight-section);
  margin:0 0 3px; line-height:var(--bbn-leading-tight);
}
.bbnmj__lede{
  margin:0 0 14px; color:var(--bbn-text-secondary);
  font-size:var(--bbn-size-support); line-height:var(--bbn-leading-body);
}
.bbnmj__label{
  font-size:var(--bbn-size-label); font-weight:var(--bbn-weight-strong);
  letter-spacing:.08em; text-transform:uppercase; color:var(--bbn-text-muted);
  margin:0 0 8px;
}

/* ---- ATTENTION STRIP ------------------------------------------------------
   Deliberately not a card. An action is a line of work, so it reads as a line:
   a coloured edge, a claim, a sentence, a control. Stacking five cards here
   would make five equal-weight objects out of a ranked list. */
.bbnmj__strip{
  display:flex; gap:12px; align-items:flex-start;
  border:1px solid var(--bbn-border); border-left:3px solid var(--bbn-accent-ink);
  border-radius:var(--bbn-radius); background:var(--bbn-surface);
  padding:12px 14px; margin-bottom:8px;
}
.bbnmj__strip--urgent{ border-left-color:var(--bbn-error); background:var(--bbn-error-surface) }
.bbnmj__strip--soon{ border-left-color:var(--bbn-warning) }
.bbnmj__strip-body{ flex:1 1 auto; min-width:0 }
.bbnmj__strip-title{
  font-size:var(--bbn-size-body); font-weight:var(--bbn-weight-strong); margin:0 0 2px;
}
.bbnmj__strip-detail{
  margin:0; font-size:var(--bbn-size-meta); color:var(--bbn-text-secondary);
  line-height:var(--bbn-leading-body);
}
.bbnmj__strip-due{
  display:block; margin-top:4px; font-size:var(--bbn-size-meta); color:var(--bbn-text-muted);
}

/* ---- COMPACT ROW ---------------------------------------------------------
   For lists where scanning matters more than detail: support requests,
   placements, introductions. A row, not a card, so ten of them stay readable. */
.bbnmj__rows{ border:1px solid var(--bbn-border); border-radius:var(--bbn-radius); overflow:hidden }
.bbnmj__row{
  display:flex; gap:14px; align-items:center; padding:13px 14px;
  background:var(--bbn-surface); border-top:1px solid var(--bbn-border);
  text-decoration:none; color:inherit; width:100%; text-align:left;
  font:inherit; border-left:0; border-right:0; border-bottom:0; cursor:pointer;
}
.bbnmj__rows > .bbnmj__row:first-child{ border-top:0 }
.bbnmj__row:hover{ background:var(--bbn-hover-tint) }
.bbnmj__row-main{ flex:1 1 auto; min-width:0 }
.bbnmj__row-main{ display:block }
/* display:block matters: these are <span>s inside a <button>, because a button
   may not contain block-level elements, and an inline title would run straight
   into the meta line on one row. */
.bbnmj__row-title{
  display:block; font-size:var(--bbn-size-body); font-weight:var(--bbn-weight-strong);
  margin:0 0 2px; overflow-wrap:anywhere;
}
.bbnmj__row-meta{
  display:block; margin:0; font-size:var(--bbn-size-meta); color:var(--bbn-text-muted);
  overflow-wrap:anywhere; line-height:var(--bbn-leading-body);
}
.bbnmj__row-side{ flex:none; text-align:right; font-size:var(--bbn-size-meta); color:var(--bbn-text-muted) }

/* ---- DOCUMENTS ------------------------------------------------------------
   A library row carries more than a list row: an action pair, a privacy line,
   and on an outstanding requirement a reuse control. At 360px those cannot sit
   on one line, so the row wraps rather than being squeezed — wrapping is the
   only honest option when the content genuinely does not fit. */
.bbnmj__row--stack{ flex-wrap:wrap; row-gap:10px }
.bbnmj__row-act{
  display:flex; flex-wrap:wrap; gap:8px; align-items:center;
  flex:1 1 100%; justify-content:flex-end;
}
.bbnmj__row-act .bbnmj__select{ width:auto; min-width:0; flex:1 1 220px; max-width:100% }
@media (max-width:560px){
  .bbnmj__row-act{ justify-content:flex-start }
  .bbnmj__row-act .bbnmj__select{ flex:1 1 100% }
}
/* Category heading inside the library. Quieter than .bbnmj__label, which marks
   a whole section — these subdivide one. */
.bbnmj__sublabel{
  margin:16px 0 6px; font-size:var(--bbn-size-meta); font-weight:var(--bbn-weight-strong);
  color:var(--bbn-text-secondary);
}
.bbnmj__rows + .bbnmj__sublabel{ margin-top:20px }
/* Privacy, stated on every row WITH its consequence. "Only me" on its own is a
   setting people choose by accident and then wonder why BBN never received it. */
.bbnmj__priv{ margin-top:4px; font-style:italic }
/* A disabled action must still be legible — greying it into the background
   turns "not yet" into "broken". */
.bbnmj__btn[disabled]{ opacity:.55; cursor:not-allowed }
/* .bbnmj__note carries margin:0 because it usually sits inside a field. As the
   page-level storage banner it needs to breathe, or the section label below
   reads as part of it. */
[data-storage-state]{ margin-bottom:18px }

/* ---- STATUS CHIP. Never colour alone: the word carries the meaning. ---- */
.bbnmj__chip{
  display:inline-block; padding:2px 9px; border-radius:var(--bbn-radius-pill);
  font-size:var(--bbn-size-badge); font-weight:var(--bbn-weight-strong);
  border:1px solid var(--bbn-border-strong); color:var(--bbn-text-secondary);
  background:var(--bbn-surface-tint); white-space:nowrap;
}
.bbnmj__chip--go{ background:var(--bbn-success-surface); border-color:var(--bbn-success-border); color:var(--bbn-success) }
.bbnmj__chip--wait{ background:var(--bbn-warning-surface); border-color:var(--bbn-warning-border); color:var(--bbn-warning) }
.bbnmj__chip--stop{ background:var(--bbn-error-surface); border-color:var(--bbn-error-border); color:var(--bbn-error) }
.bbnmj__chip--info{ background:var(--bbn-info-surface); border-color:var(--bbn-info-border); color:var(--bbn-info) }

/* ---- TIMELINE. State over time, which a table cannot show. ---- */
.bbnmj__timeline{ list-style:none; margin:0; padding:0 }
.bbnmj__tl{ position:relative; padding:0 0 16px 22px }
.bbnmj__tl::before{
  content:""; position:absolute; left:4px; top:5px; width:9px; height:9px;
  border-radius:50%; background:var(--bbn-brand);
}
.bbnmj__tl:not(:last-child)::after{
  content:""; position:absolute; left:8px; top:18px; bottom:0; width:1px; background:var(--bbn-border);
}
.bbnmj__tl-when{ display:block; font-size:var(--bbn-size-meta); color:var(--bbn-text-muted) }
.bbnmj__tl-what{ margin:1px 0 0; font-size:var(--bbn-size-support) }

/* ---- EDITORIAL DETAIL. Label/value pairs for placement logistics. ---- */
.bbnmj__dl{ margin:0; display:grid; grid-template-columns:minmax(120px,auto) 1fr; gap:6px 16px }
.bbnmj__dl dt{ font-size:var(--bbn-size-meta); color:var(--bbn-text-muted) }
.bbnmj__dl dd{ margin:0; font-size:var(--bbn-size-support); overflow-wrap:anywhere }

.bbnmj__panel{
  border:1px solid var(--bbn-border); border-radius:var(--bbn-radius);
  background:var(--bbn-surface); padding:16px; margin-bottom:14px;
}
.bbnmj__panel--sunken{ background:var(--bbn-surface-sunken) }

/* ---- controls ---- */
.bbnmj__actions{ display:flex; flex-wrap:wrap; gap:8px; margin-top:12px }
.bbnmj__btn{
  font:inherit; font-size:var(--bbn-size-support); font-weight:var(--bbn-weight-strong);
  border-radius:var(--bbn-radius); padding:9px 15px; cursor:pointer;
  background:var(--bbn-brand); color:var(--bbn-text-on-brand); border:1px solid var(--bbn-brand);
  text-decoration:none; display:inline-block;
}
.bbnmj__btn:hover{ background:var(--bbn-brand-deep); border-color:var(--bbn-brand-deep) }
.bbnmj__btn--quiet{ background:transparent; color:var(--bbn-link); border-color:var(--bbn-border-strong) }
.bbnmj__btn--quiet:hover{ background:var(--bbn-hover-tint); color:var(--bbn-link-hover) }
.bbnmj__btn[disabled]{ cursor:default; opacity:var(--bbn-disabled-opacity);
  background:var(--bbn-disabled-surface); color:var(--bbn-disabled-text); border-color:var(--bbn-border) }
.bbnmj__btn:focus-visible, .bbnmj__row:focus-visible, .bbnmj__rail a:focus-visible{
  outline:3px solid var(--bbn-focus-inner); box-shadow:0 0 0 5px var(--bbn-focus-ring);
}
.bbnmj__field{ display:block; margin-bottom:12px }
.bbnmj__field > span{ display:block; font-size:var(--bbn-size-meta); color:var(--bbn-text-muted); margin-bottom:4px }
.bbnmj__input, .bbnmj__select, .bbnmj__textarea{
  width:100%; font:inherit; font-size:var(--bbn-size-support); padding:9px 10px;
  border:1px solid var(--bbn-border-strong); border-radius:var(--bbn-radius);
  background:var(--bbn-surface); color:var(--bbn-text);
}
.bbnmj__textarea{ min-height:96px; resize:vertical }

/* ---- PROGRAM APPLICATION FORM ----------------------------------------------
   Program Builder writes the questions, so nothing here may assume a length, a
   type or a count. */

/* A question label is a SENTENCE, not a section heading. .bbnmj__label is
   uppercase with wide tracking, which is right for "ON FILE" and unreadable for
   "Describe how your business would use this programme". Scoped override rather
   than a second class, so the markup stays one vocabulary. */
.bbnmj__field > .bbnmj__label{
  text-transform:none; letter-spacing:0; font-size:var(--bbn-size-support);
  font-weight:var(--bbn-weight-strong); color:var(--bbn-text); margin:0 0 4px;
}
/* LOAD-BEARING. A conditional question is hidden with the `hidden` attribute,
   whose UA default is display:none — and .bbnmj__field sets display:block,
   which BEATS it. Without this rule every show_when question renders all the
   time and the condition silently does nothing. */
.bbnmj__field[hidden]{ display:none }

.bbnmj__req{
  margin-left:6px; font-size:var(--bbn-size-label); font-weight:var(--bbn-weight-strong);
  letter-spacing:.06em; text-transform:uppercase; color:var(--bbn-text-muted);
}
.bbnmj__help{
  margin:0 0 6px; font-size:var(--bbn-size-meta); color:var(--bbn-text-secondary);
  line-height:var(--bbn-leading-body);
}
/* What the Portal cannot do yet, said in the place it would have been done. */
.bbnmj__note{
  margin:0; padding:10px 12px; font-size:var(--bbn-size-meta);
  color:var(--bbn-text-secondary); line-height:var(--bbn-leading-body);
  background:var(--bbn-surface-sunken); border-radius:var(--bbn-radius);
}
/* A submitted answer, read back. Not an input: it is not editable, and drawing
   it as a greyed-out field invites a member to try. */
.bbnmj__answer{
  margin:0; font-size:var(--bbn-size-support); color:var(--bbn-text);
  overflow-wrap:anywhere; line-height:var(--bbn-leading-body);
}
/* BOTH of these override .bbnmj__field > span, which is the muted meta styling
   meant for a hint line, not for a control.
   Found in a screenshot, not by an assertion: a boolean question rendered as a
   checkbox with "Yes" jammed against it and sitting a few pixels low, because
   display:block beat .bbnmj__check's display:flex and took the gap with it. The
   markup was correct; only the cascade was wrong, which is exactly the class of
   defect a passing test suite says nothing about. */
.bbnmj__field > .bbnmj__checks{
  display:flex; flex-direction:column; gap:6px; font-size:var(--bbn-size-support);
  color:var(--bbn-text); margin-bottom:0;
}
.bbnmj__field > .bbnmj__check{
  display:flex; align-items:flex-start; gap:8px; font-size:var(--bbn-size-support);
  color:var(--bbn-text); margin-bottom:0;
}
.bbnmj__check{ display:flex; align-items:flex-start; gap:8px; font-size:var(--bbn-size-support) }
/* 16px is the minimum that stays comfortably tappable at 360px without the
   label having to be the whole hit area. */
.bbnmj__check input{ width:16px; height:16px; margin:2px 0 0; flex:none }
.bbnmj__check label{ line-height:var(--bbn-leading-body); overflow-wrap:anywhere }
.bbnmj__status{ margin:0 0 12px; display:flex; align-items:center; gap:8px; flex-wrap:wrap }
/* The form needs air between it and whatever preceded it — the status chip, the
   closing date, or BBN's request. Without it the first question's label sits on
   the line above and reads as part of it. */
.bbnmj__section > .bbnmj__field:first-child{ margin-top:18px }

/* ---- the three states that must never be confused with one another ---- */
.bbnmj__skel{ height:64px; border-radius:var(--bbn-radius); background:var(--bbn-surface-sunken); margin-bottom:8px }
.bbnmj__empty{
  border:1px dashed var(--bbn-border-strong); border-radius:var(--bbn-radius);
  background:var(--bbn-surface-tint); padding:20px; text-align:center;
  font-size:var(--bbn-size-support); color:var(--bbn-text-secondary);
}
.bbnmj__error{
  border:1px solid var(--bbn-error-border); background:var(--bbn-error-surface);
  color:var(--bbn-error); border-radius:var(--bbn-radius); padding:14px;
  font-size:var(--bbn-size-support); line-height:var(--bbn-leading-body);
}
/* An upstream system being unreachable is NOT the same as having no records,
   and it must never be drawn as an empty state. */
.bbnmj__degraded{
  border:1px solid var(--bbn-info-border); background:var(--bbn-info-surface);
  color:var(--bbn-info); border-radius:var(--bbn-radius); padding:11px 13px;
  font-size:var(--bbn-size-meta); margin-bottom:12px;
}
.bbnmj__msg{ margin:10px 0 0; font-size:var(--bbn-size-meta); min-height:1em }
.bbnmj__msg--err{ color:var(--bbn-error) }
.bbnmj__msg--ok{ color:var(--bbn-success) }

.bbnmj__sr{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ---- mobile. These are phone tools; dense rows stack rather than scroll. ---- */
@media (max-width:620px){
  .bbnmj__row{ flex-direction:column; align-items:stretch; gap:6px }
  .bbnmj__row-side{ text-align:left }
  .bbnmj__dl{ grid-template-columns:1fr; gap:2px 0 }
  .bbnmj__dl dd{ margin-bottom:10px }
  .bbnmj__strip{ flex-direction:column; gap:10px }

  /* BUTTON HIERARCHY SURVIVES THE PHONE.
   *
   * This used to stack EVERY button full width. That was right when a screen had one call to
   * action and wrong the moment a screen had five: a dashboard with "All opportunities", "Open
   * saved", "Open messages", "See BBN updates" and "Resource library" became five identical
   * full-width blocks, every one shouting equally, which is the same as none of them leading.
   *
   * The primary action still spans — it is the one thing to do, and it should be unmissable and
   * thumb-sized. Quiet actions are secondary by definition, so they sit inline and wrap, which
   * is also how they read on desktop. Hierarchy is a property of the design, not of the width. */
  .bbnmj__actions{ flex-direction:row; flex-wrap:wrap; align-items:stretch }
  .bbnmj__btn{ width:auto; text-align:center }
  .bbnmj__actions > .bbnmj__btn:not(.bbnmj__btn--quiet){ flex:1 1 100% }

  /* 44px is the touch target, not the type size. The buttons are 14px text with 9px padding,
   * which lands around 36px — comfortable with a mouse and a miss with a thumb. */
  .bbnmj__btn{ min-height:44px; display:inline-flex; align-items:center; justify-content:center }
}

@media (prefers-reduced-motion:reduce){
  .bbnmj *{ animation:none !important; transition:none !important }
}

/* ---- ACCOUNT: the person's own editable facts -------------------------------
   Added for Phase B Wave 1, when Account became editable. Only three classes are
   new; the name field, the buttons and the checkbox rows reuse .bbnmj__field,
   .bbnmj__btn and .bbnmj__check, because Account should not look like a
   different product from the rest of the portal. */

/* The save line under a control. DELIBERATELY NOT .bbnmj__status, which is an
   existing flex chip-row with a 12px bottom margin — reusing that name here
   would lay an inline confirmation out as a chip strip. */
.bbnmj__save{
  margin:6px 0 0; min-height:1.2em;
  font-size:var(--bbn-size-meta); color:var(--bbn-text-muted);
}

/* The sign-in address: a VALUE, not an input. It reads as a field so the screen
   stays visually regular, but it must never look typeable — a member who tries
   to edit it and cannot has been misled by the styling. */
.bbnmj__readonly{
  margin:0; padding:9px 10px;
  border:1px solid var(--bbn-border); border-radius:var(--bbn-radius);
  background:var(--bbn-surface-sunken); color:var(--bbn-text-secondary);
  font-size:var(--bbn-size-support); overflow-wrap:anywhere;
}

/* One preference: control, explanation, and its own save line. The rule below
   separates them from each other so three independent settings do not read as
   one group with one outcome. */
.bbnmj__notify{ padding:12px 0; border-top:1px solid var(--bbn-border) }
.bbnmj__notify:first-of-type{ border-top:0; padding-top:4px }
/* display:block IS LOAD-BEARING. .bbnmj__help declares no display and is used on a <p>
   everywhere else, but here it is a <span> — so without this it is an inline box and the 24px
   indent offsets only the FIRST line. The second line of a wrapped explanation returned to the
   container edge and sat under the checkbox, reading as a new sentence at a different level.
   Caught at 360px, where these strings wrap. */
.bbnmj__notify .bbnmj__help{ display:block; margin:4px 0 0 24px }
.bbnmj__notify .bbnmj__save{ display:block; margin-left:24px }

/* A closing aside that points somewhere else needs air above it, or it reads as
   part of the control it follows. */
.bbnmj__help--sep{
  margin-top:14px; padding-top:12px; border-top:1px solid var(--bbn-border);
}

/* ============================================================================
   WAVE 3 — reading width and editorial hierarchy
   ----------------------------------------------------------------------------
   The Wave 2 closeout noted the Programs screen reading "very wide and sparse"
   at 1280px. The cause is structural, not decorative: a member screen that
   stretches edge to edge turns a short paragraph into a single thin line and
   makes four ordinary sections look like a dashboard of empty cards.

   `--bbn-reading` is a measure, not a breakpoint. It caps the column at a
   comfortable line length and centres it, so desktop gains hierarchy rather
   than width. Mobile is untouched — the cap is never smaller than the viewport.
   ============================================================================ */
.bbnmj__reading{ max-width:var(--bbn-reading, 60rem); margin-inline:auto }

/* The one section carrying the richest content earns visual weight, so the eye
   has somewhere to land. This is emphasis by contrast: if every panel were a
   lead panel, none would be. */
.bbnmj__panel--lead{
  border-color:var(--bbn-brand);
  border-left-width:3px;
  background:var(--bbn-surface);
}
.bbnmj__panel--lead .bbnmj__count{ font-size:var(--bbn-size-section) }

/* Section headings are real <h3>s now rather than styled paragraphs, so the
   label styling has to apply to both while the document outline stays correct. */
h3.bbnmj__label{ margin:0 0 8px }

/* ============================================================================
   DASHBOARD — ONE OPENING, AND THE RETIREMENT OF THE OLD ONE
   ----------------------------------------------------------------------------
   The page used to open three times: a monthly-theme hero, a "Your BBN"
   heading and a greeting, with the business named in three separate blocks.
   One opening now carries all of it — an eyebrow, a greeting, the business
   once, and a sentence saying what the screen is for.
   ============================================================================ */
.bbnmj__dashhead{ margin:0 0 22px }

/* The theme is an EYEBROW, never a hero. It changes monthly and it is context,
   not the headline: the member's own name is the headline. Sized and coloured
   to sit above the greeting rather than compete with it. */
.bbnmj__eyebrow{
  margin:0 0 6px;
  font-size:11px; font-weight:600; letter-spacing:.09em; text-transform:uppercase;
  color:var(--bbn-brand);
}
.bbnmj__eyebrow-theme{ color:var(--bbn-accent-ink) }

/* The business is named ONCE, here, and no section below repeats it. */
.bbnmj__dashbiz{
  margin:2px 0 0;
  font-size:var(--bbn-size-card-title); font-weight:var(--bbn-weight-strong);
  color:var(--bbn-text-secondary);
}
.bbnmj__dashhead .bbnmj__lede{ margin-top:6px }

/* "All caught up" is good news, so it reads as a calm statement rather than as
   an empty container. Deliberately NOT .bbnmj__empty: a dashed 520px box for a
   positive answer looks like something failed to load. */
.bbnmj__allclear{
  margin:0; padding:12px 14px;
  background:var(--bbn-success-surface);
  border-left:3px solid var(--bbn-success);
  border-radius:var(--bbn-radius-sm, 4px);
  color:var(--bbn-text); font-size:var(--bbn-size-body);
}

/* A sub-label groups rows INSIDE one panel, so "Worth checking" stays a single
   answer instead of fragmenting into four more bordered cards. This is the
   editorial-hierarchy move: typography and spacing before another container. */
.bbnmj__label-sub{
  margin:14px 0 6px;
  font-size:var(--bbn-size-label); font-weight:var(--bbn-weight-strong);
  letter-spacing:.04em; text-transform:uppercase;
  color:var(--bbn-text-muted);
}
.bbnmj__label-sub:first-child{ margin-top:0 }

/* A row that is not a destination. The signed-out screen lists what members use
   the Portal for; those are descriptions, not links, and giving them hover and
   pointer affordances would promise navigation that does not exist. */
.bbnmj__row--static{ cursor:default; background:none }
.bbnmj__row--static:hover{ background:none }

/* ============================================================================
   LEGACY DASHBOARD RETIREMENT
   ----------------------------------------------------------------------------
   Everything below is keyed off html[data-bbn-dashboard="composed"], which
   member-journey.js sets ONLY after its composition has actually mounted. If
   the script fails or never loads, nothing here matches and the old dashboard
   is untouched — the retirement can never leave a member with a blank page.

   These blocks are retired because the composition now answers the same
   questions from better sources, not because they are ugly:

     .db2-head     a second greeting and a theme chip, above our own header
     .db2-side     the 0/3 completion ring (which read a private businesses row
                   as a public ShopBBN listing), quick actions pointing at
                   /my-account/ for notification settings that moved to Account,
                   a SourceBBN card the Network parent owns, and a "THIS MONTH"
                   updates list the composition now carries
     .db2-main's own children  the duplicate funding hero and list
   ============================================================================ */
html[data-bbn-dashboard="composed"] #bbn-db2 .db2-head,
html[data-bbn-dashboard="composed"] #bbn-db2 .db2-side{ display:none !important }

/* One column, and no card chrome around the workspace. .db2-main is itself a
   .db2-card, so without this the entire member workspace renders inside a white
   bordered box — a container around a container around every panel. */
html[data-bbn-dashboard="composed"] #bbn-db2 .db2-grid{ display:block }
html[data-bbn-dashboard="composed"] #bbn-db2 .db2-main{
  background:none; border:0; border-radius:0; padding:0;
}

/* Hide the legacy children of .db2-main while keeping the two JS-owned sections.
   Written as a :not() list rather than by naming each legacy node, so a widget
   edit that adds another stale block does not silently reappear. */
html[data-bbn-dashboard="composed"] #bbn-db2 .db2-main
  > :not(#bbn-member-journey):not(#bbn-my-bbn){ display:none !important }

/* The Holiday module keeps its place BELOW the composed dashboard rather than
   competing with Needs attention. Layout only — its behaviour is untouched. */
html[data-bbn-dashboard="composed"] #bbn-my-bbn{
  display:block; margin-top:28px;
  max-width:var(--bbn-reading, 60rem); margin-inline:auto;
}

/* ----------------------------------------------------------------------------
   RETIRED ELEMENTOR BLOCKS ON /portal/ (page 2277)
   ----------------------------------------------------------------------------
   Each of these is retired because the composition above now answers the same
   question from a source that cannot go stale. They are hidden rather than
   deleted from _elementor_data because editing that JSON is the riskiest write
   on this site — and because a stylesheet rule is revertible in one line.

     de37acf + 712478e   "Theme of the Month" heading and its info box. The box
                         hardcoded "Back to Business is BBN's focus for August"
                         and was still saying so in September, on the same page
                         whose header read the live app_config value "Business
                         Growth + Expansion". Two themes, one screen. The theme
                         is now an eyebrow read from app_config and nowhere else.
     1123f5b + 22a6440   "This Month at BBN" and its news carousel — the block
                         whose slides hardcoded a Food Truck Fridays date that
                         had passed, and which home-app.js was rewriting at
                         runtime three times over because the carousel clones
                         its slides. "Latest from BBN" replaces it with the real
                         feed and a label that makes no currency claim.
     24262ef             NNO Promo Tools, for an event on 4 August.
     407137f             "Featured Funding Opportunities" and its listing grid —
                         the same catalog the composition reads from
                         /wp-json/bbn/v1/funding-open, rendered twice on one page.
     2d0f66a + 145066b   Spacers that exist only to separate the blocks above.

   The scrubbers in home-app.js that rewrote the stale text inside these blocks
   are removed with them: a scrubber for a widget that is no longer on the
   product surface is code that can only ever be wrong.
   ---------------------------------------------------------------------------- */
html[data-bbn-dashboard="composed"] .elementor-element-2d0f66a,
html[data-bbn-dashboard="composed"] .elementor-element-145066b,
html[data-bbn-dashboard="composed"] .elementor-element-de37acf,
html[data-bbn-dashboard="composed"] .elementor-element-712478e,
html[data-bbn-dashboard="composed"] .elementor-element-1123f5b,
html[data-bbn-dashboard="composed"] .elementor-element-22a6440,
html[data-bbn-dashboard="composed"] .elementor-element-24262ef,
html[data-bbn-dashboard="composed"] .elementor-element-407137f{ display:none !important }

/* ============================================================================
   VISUAL SYSTEM PASS — A CONTAINER IS NEVER DRAWN TWICE
   ----------------------------------------------------------------------------
   The portal had drifted into a stack of bordered white cards: a panel with a
   border, containing a rows list with its own border, containing rows with
   their own dividers. Three edges to say one thing. At 1280px a screen of them
   reads as a dashboard of empty containers rather than as a workspace.

   The rule is structural, not decorative: whichever element is already acting
   as the container draws the edge, and nothing inside it draws another. A rows
   list ON THE CANVAS is a container and keeps its border; the same list INSIDE
   a panel is content and loses it. This is one rule rather than a per-screen
   override, so it applies to every module at once — which is the point of a
   system pass.
   ============================================================================ */
.bbnmj__panel > .bbnmj__rows{
  border:0; border-radius:0;
}
/* The rows still need separating from whatever text sits above them in the
   panel, so the first row keeps a top hairline it would otherwise drop. */
.bbnmj__panel > .bbnmj__rows > .bbnmj__row:first-child{
  border-top:1px solid var(--bbn-border);
}
/* Rows inside a panel share its surface, so the fill is redundant — and
   removing it lets the hover tint read against the panel instead of against a
   second white layer. */
.bbnmj__panel > .bbnmj__rows > .bbnmj__row{ background:none }
.bbnmj__panel > .bbnmj__rows > .bbnmj__row:hover{ background:var(--bbn-hover-tint) }

/* A rows list is negative space at the panel edge, so it may sit flush: the
   panel's own padding would otherwise indent every row away from the label
   that introduces it. */
.bbnmj__panel > .bbnmj__rows{ margin-left:-16px; margin-right:-16px }
.bbnmj__panel > .bbnmj__rows > .bbnmj__row{ padding-left:16px; padding-right:16px }

/* VERTICAL RHYTHM. A label introduces the thing below it and must sit closer
   to it than to the section above, or the page reads as an unsorted list of
   equal blocks. One scale, applied everywhere. */
.bbnmj__section{ margin-bottom:var(--bbn-rhythm-section, 30px) }
.bbnmj__section > .bbnmj__label{ margin-bottom:10px }
.bbnmj__section > .bbnmj__panel:last-child,
.bbnmj__section > .bbnmj__rows:last-child{ margin-bottom:0 }

@media (max-width: 600px){
  /* Tighter on mobile: the same rhythm at 360px wastes a third of the screen
     on gaps between four short sections. */
  .bbnmj__section{ margin-bottom:22px }
}

/* A short statement that is the whole answer — "2 unread messages" — reads as
   body copy, not as a metric. It needs no container and no number styling. */
.bbnmj__stat{ margin:0; font-size:var(--bbn-size-body) }

/* The one panel on the dashboard that genuinely groups several different kinds
   of thing under one question. Everything else is a label and its rows. */
.bbnmj__panel--grouped{ padding-top:14px }
.bbnmj__panel--grouped > .bbnmj__label-sub:first-child{ margin-top:0 }

/* ----------------------------------------------------------------------------
   THE READING MEASURE IS A PROPERTY OF THE WORKSPACE, NOT OF EACH SCREEN
   ----------------------------------------------------------------------------
   Wave 3 introduced .bbnmj__reading and three screens opted into it. Nine did
   not, so Programs, Support, Documents, Account, Membership, Placements,
   Appointments and Introductions still ran edge to edge at 1280px — which is
   the "too wide and sparse" finding from the Wave 2 closeout, unfixed on eight
   more screens than it was first reported on.

   Applying it per view means twelve places to remember and twelve places to
   forget. Applied at the workspace root it is true of every screen, including
   ones not written yet, and the three views that emit .bbnmj__reading keep
   working — a max-width inside an equal max-width changes nothing.

   The rail stays full width on purpose: it is navigation across the workspace,
   not part of the reading column.
   ---------------------------------------------------------------------------- */
.bbnmj > [data-view]{ max-width:var(--bbn-reading, 60rem); margin-inline:auto }

/* ============================================================================
   BBN VISUAL DEPTH v1 — 2026-09-19
   ----------------------------------------------------------------------------
   PRESENTATION ONLY. No route, no section order, no copy and no data changed.
   The audit that preceded this found the architecture sound and the surface
   flat: on Support, "Needed from you", "ThriveLink" and "Your requests" were
   three white boxes behind three identical hairlines, so nothing on screen said
   which one needed the member and which one was a service they were connected
   to. On Dashboard, six sections shared one appearance.

   THE DESKTOP FINDING, MEASURED RATHER THAN ASSUMED. At 1100px the workspace
   column is 960px (--bbn-reading), leaving a 70px gutter each side — so the
   "empty desktop" is NOT horizontal margin, and widening the column would only
   have made the line length worse. The emptiness is vertical: short rows in
   tall containers with no hierarchy between them. Everything below treats that,
   and the reading measure is left alone.

   GREEN BECOMES STRUCTURAL. It was doing one job, filling buttons. It now also
   marks section labels, the page header, the active tab and connected services
   — which is what makes the product look owned by BBN rather than assembled
   from defaults. It is not used as a card fill or a heading colour.

   All three surfaces come from tokens.css and every ratio there was computed.
   ============================================================================ */

/* ---- THE PAGE HEADER ------------------------------------------------------
   Screens began abruptly: an 18px heading the same size as the section labels
   beneath it, then straight into content. The first heading in a view is the
   page title and now reads as one, with a short brand rule to anchor it.
   Styled from position rather than a new class, so every screen gains it at
   once and no view template had to be edited. */
.bbnmj > [data-view] > .bbnmj__h2:first-child,
.bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child{
  font-size:var(--bbn-size-page-title);
  font-weight:var(--bbn-weight-title);
  letter-spacing:-.01em;
  padding-bottom:10px;
  margin-bottom:0;
  position:relative;
}
/* The rule is short and brand-coloured: a full-width divider would cut the page
   in half, and this only has to say "the page starts here". */
.bbnmj > [data-view] > .bbnmj__h2:first-child::after,
.bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child::after{
  content:""; position:absolute; left:0; bottom:0;
  width:38px; height:3px; border-radius:2px;
  background:var(--bbn-brand);
}
.bbnmj > [data-view] > .bbnmj__h2:first-child + .bbnmj__lede,
.bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child + .bbnmj__lede{
  margin-top:12px; font-size:var(--bbn-size-page-intro); max-width:60ch;
}

/* ---- SECTION LABELS CARRY THE BRAND ---------------------------------------
   A 12.5px uppercase muted label was the only thing separating one section from
   the next, and at a glance a column of them reads as one undifferentiated
   list. A small green tick in front turns each into a visible waypoint. Applied
   to the label class itself, so Dashboard, Support, Documents and every screen
   written later inherit it. */
.bbnmj__section > .bbnmj__label,
.bbnmj__section > h3.bbnmj__label{
  display:flex; align-items:center; gap:8px;
  color:var(--bbn-text-secondary);
}
.bbnmj__section > .bbnmj__label::before,
.bbnmj__section > h3.bbnmj__label::before{
  content:""; flex:none; width:3px; height:12px; border-radius:2px;
  background:var(--bbn-brand);
}
/* Sub-labels group rows INSIDE a panel and must stay quieter than the section
   label that contains them, so they take no tick. */
.bbnmj__label-sub::before{ content:none }

/* ---- LEVEL A — ATTENTION --------------------------------------------------
   What the member has to do. A warm surface and a read-strength gold edge, not
   a red one: needing an action is not an error, and the Outstanding badge is
   already carrying the urgency. --bbn-accent-ink measures 4.86:1 here; the
   decorative gold would have measured 2.16:1 and is not used. */
[data-level="attention"] > .bbnmj__rows,
.bbnmj__rows--attention{
  background:var(--bbn-surface-action);
  border-color:var(--bbn-accent-ink);
  border-left-width:3px;
}
[data-level="attention"] > .bbnmj__rows > .bbnmj__row,
.bbnmj__rows--attention > .bbnmj__row{
  background:none; border-top-color:rgba(138,100,22,.22);
}
[data-level="attention"] > .bbnmj__rows > .bbnmj__row .bbnmj__row-title,
.bbnmj__rows--attention > .bbnmj__row .bbnmj__row-title{
  font-weight:var(--bbn-weight-title);
}
[data-level="attention"] > .bbnmj__label::before{ background:var(--bbn-accent-ink) }

/* ---- CONNECTED SERVICE ----------------------------------------------------
   A service the member is part of, not another request. Light green surface and
   a brand edge, using the [data-thrivelink] hook the door already emits — no
   markup change was needed here at all. Compact on purpose: the brief for the
   door was a card, never a banner. */
[data-thrivelink] > .bbnmj__rows{
  background:var(--bbn-surface-connected);
  border-color:var(--bbn-brand);
  border-left-width:3px;
}
[data-thrivelink] > .bbnmj__rows > .bbnmj__row{
  background:none; border-top-color:rgba(10,90,69,.18);
}
[data-thrivelink] > .bbnmj__label{ color:var(--bbn-brand) }
/* The card is already carrying the connected state, so its control stays quiet
   rather than competing with the page's primary action. */
[data-thrivelink] .bbnmj__btn--quiet{
  background:var(--bbn-surface); border-color:var(--bbn-brand); color:var(--bbn-brand);
}
[data-thrivelink] .bbnmj__btn--quiet:hover{
  background:var(--bbn-brand); color:var(--bbn-text-on-brand);
}

/* ---- LEVEL C — QUIET / EDITORIAL ------------------------------------------
   News and history are for reading, not for acting on, and they were drawn in
   the same bordered white container as a support request. Dropping the fill and
   the outer frame leaves hairline-separated entries that read as a list of
   articles — which is what they are. */
[data-level="editorial"] > .bbnmj__rows{
  background:none; border:0; border-radius:0;
  border-top:1px solid var(--bbn-border);
}
[data-level="editorial"] > .bbnmj__rows > .bbnmj__row{
  background:none; padding-left:0; padding-right:0;
}
[data-level="editorial"] > .bbnmj__rows > .bbnmj__row:hover{
  background:none; color:var(--bbn-link-hover);
}
[data-level="editorial"] > .bbnmj__rows > .bbnmj__row:hover .bbnmj__row-title{
  text-decoration:underline;
}

/* ---- LEVEL B — STANDARD ---------------------------------------------------
   Unchanged white surface, with one addition: a rows list on the canvas gets a
   very slight warm lift so a stack of them stops reading as one white field. */
.bbnmj__rows{ background:var(--bbn-surface) }
.bbnmj__panel{ box-shadow:var(--bbn-shadow-sm) }
.bbnmj__rows:not([class*="--"]){ box-shadow:var(--bbn-shadow-sm) }

/* ---- BUTTON HIERARCHY -----------------------------------------------------
   The product had two button treatments and used the bordered one for
   everything secondary, so a dashboard showed four equally-weighted outlined
   buttons and no obvious lead. Primary is unchanged and stays the filled brand.
   Quiet now sits on the subtle surface with a hairline instead of the strong
   border, which is a real step down in weight while remaining unmistakably a
   button and keeping its full hit area. Secondary is the outlined brand, for
   the rare case where a second action genuinely ranks with the first. */
.bbnmj__btn--quiet{
  background:var(--bbn-surface-subtle);
  border-color:var(--bbn-border);
  color:var(--bbn-link);
}
.bbnmj__btn--quiet:hover{
  background:var(--bbn-hover-tint); border-color:var(--bbn-border-strong);
  color:var(--bbn-link-hover);
}
.bbnmj__btn--secondary{
  background:var(--bbn-surface); border-color:var(--bbn-brand); color:var(--bbn-brand);
}
.bbnmj__btn--secondary:hover{
  background:var(--bbn-brand); border-color:var(--bbn-brand); color:var(--bbn-text-on-brand);
}

/* ---- TABS -----------------------------------------------------------------
   The active tab was a 2px underline and a colour change. It now also carries
   the brand surface, so the current place is legible at a glance rather than by
   comparison. Not a pill: the rail is a set of places, and pills would make it
   look like a filter. */
.bbnmj__rail a{ border-radius:var(--bbn-radius) var(--bbn-radius) 0 0 }
.bbnmj__rail a[aria-current="page"]{
  background:var(--bbn-surface-connected);
  border-bottom-width:3px;
}

/* ---- BADGES ---------------------------------------------------------------
   Kept small and kept wordy — the word carries the meaning, the tint only
   groups. One addition: a connected state, which had no chip at all. */
.bbnmj__chip--connected{
  background:var(--bbn-surface-connected);
  border-color:var(--bbn-brand);
  color:var(--bbn-brand);
}

/* ---- RHYTHM ---------------------------------------------------------------
   With the sections now visually distinct they need slightly less separation to
   read as separate, and the page gets shorter — which is the honest fix for a
   screen that felt sparse. */
.bbnmj__section{ margin-bottom:var(--bbn-rhythm-section, 26px) }

/* ---- MOBILE IS PROTECTED --------------------------------------------------
   Mobile was already the stronger of the two and none of the above is allowed
   to make it heavier. The edges stay 3px, the surfaces are flat tints that cost
   nothing, and the one thing that would have added weight — a shadow on every
   rows list — is removed below 620px, where cards sit edge to edge and an
   elevation reads as grime rather than lift. */
@media (max-width:620px){
  .bbnmj__rows:not([class*="--"]), .bbnmj__panel{ box-shadow:none }
  .bbnmj > [data-view] > .bbnmj__h2:first-child,
  .bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child{ padding-bottom:9px }
  [data-level="editorial"] > .bbnmj__rows > .bbnmj__row{ padding-left:0; padding-right:0 }
}

/* ---- THE DASHBOARD HEADER IS A PAGE HEADER TOO -----------------------------
   The first-child rule above cannot reach it: the greeting is an <h2> nested
   inside .bbnmj__dashhead, under an eyebrow, so structurally it is not the
   first child of the view. It was therefore the one screen that kept an 18px
   title — on the highest-traffic page in the product. Given the same treatment
   explicitly rather than by loosening the selector above, which would have
   caught every nested heading in the workspace. */
.bbnmj__dashhead .bbnmj__h2{
  font-size:var(--bbn-size-page-title);
  font-weight:var(--bbn-weight-title);
  letter-spacing:-.01em;
  margin-bottom:0;
}
/* The rule sits under the business name rather than the greeting, because here
   the two lines are one unit: the member and the business they are signed in
   for. Splitting them with a rule would read as two headings. */
.bbnmj__dashhead .bbnmj__dashbiz{
  padding-bottom:10px; margin-bottom:0; position:relative;
}
.bbnmj__dashhead .bbnmj__dashbiz::after{
  content:""; position:absolute; left:0; bottom:0;
  width:38px; height:3px; border-radius:2px; background:var(--bbn-brand);
}
/* No business yet: the greeting carries the rule instead, so the header is
   never left without its anchor. */
.bbnmj__dashhead .bbnmj__h2:not(:has(+ .bbnmj__dashbiz)){
  padding-bottom:10px; position:relative;
}
.bbnmj__dashhead .bbnmj__h2:not(:has(+ .bbnmj__dashbiz))::after{
  content:""; position:absolute; left:0; bottom:0;
  width:38px; height:3px; border-radius:2px; background:var(--bbn-brand);
}
.bbnmj__dashhead .bbnmj__lede{ margin-top:12px; font-size:var(--bbn-size-page-intro) }

/* ============================================================================
   BBN BRAND FRAMING v1.1 — 2026-09-20
   ----------------------------------------------------------------------------
   Visual Depth v1 fixed the hierarchy and is untouched here. The remaining
   complaint was narrower and fair: the green was ACCURATE but tiny — ticks,
   button fills and small rules — so the viewport still read cream-white-tan and
   the brand was something you could find rather than something you felt.

   This adds brand presence in ONE place, the page header, and nothing else is
   saturated. Cards, rows, badges and metadata are all left exactly as v1 shipped
   them.

   THREE TREATMENTS WERE BUILT AND PHOTOGRAPHED BEFORE ONE WAS CHOSEN:
     A  light green wash + brand left bar        <- chosen
     B  white surface + inset brand rule         rejected: the inset rule drew
                                                 under EACH element, putting a
                                                 green line through the middle of
                                                 the header
     C  no surface, 5px brand bar only           rejected: anchors the header but
                                                 adds almost no presence, which is
                                                 the thing being asked for
   A uses --bbn-surface-connected, which already exists and already measures
   12.42:1 for body text and 7.49:1 for brand text. No new colour was invented.

   NO WRAPPER ELEMENT. 31 views emit their own <h2>, so wrapping each one would
   have been 31 edits for a presentation change. The band is drawn on the heading
   and its lede TOGETHER — same surface, same left bar, matched negative margins
   — and two adjacent elements sharing a fill read as one block with no seam.
   ============================================================================ */

/* THE HEADER AND A CONNECTED SERVICE SHARE A FILL, AND THAT WAS CHECKED, NOT ASSUMED.
   On Support both the page header and the ThriveLink card are --bbn-surface-connected, which
   risks diluting the "green fill means a service you are connected to" rule v1 established. The
   alternative — header on --bbn-surface-subtle with a heavier bar and a brand bottom rule — was
   built and photographed side by side. It does preserve the distinction, and it also lands back
   at the presence of the rejected Option C, which is the thing this pass exists to fix.
   So the wash stays, and the two are separated by structure instead: the header is full-bleed
   with a BRAND-DEEP bar and no other edge; the connected card is inset with a full brand border,
   its own green label and a control. Different shape, different weight, different place.
   If that trade is wrong, the alternative is a one-line surface swap on the three selectors
   below. */

/* The heading half of the band. The v1 short rule is retired here: the left bar
   now does that job, and keeping both gave the header two competing marks.

   BOTH HEADER SHAPES, NOT ONE. Seven views wrap their content in .bbnmj__reading
   (Opportunities, Network, Knowledge, the public dashboard and the dashboard's
   fallback branches), so their <h2> is a grandchild of [data-view], not a child.
   The v1 page-title rule already carried both selectors; the first cut of this
   block carried only the direct-child one, and Opportunities and Network came
   out of the after-pass pixel-identical to before. Every selector in this block
   is paired for that reason. */
.bbnmj > [data-view] > .bbnmj__h2:first-child,
.bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child{
  background:var(--bbn-surface-connected);
  border-left:4px solid var(--bbn-brand-deep);
  border-radius:0 var(--bbn-radius) 0 0;
  padding:16px 20px 10px;
  margin:0 -20px;
}
.bbnmj > [data-view] > .bbnmj__h2:first-child::after,
.bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child::after{ display:none }

/* The lede half. THE MEASURE IS KEPT WITHOUT CAPPING THE BAND: max-width would
   stop the fill at the end of the text and leave a visible step where the
   heading's band continues past it — which is exactly what the Option A trial
   showed at 1100px. Padding reserves the same space instead, so the text still
   wraps at a comfortable measure while the surface runs the full column. */
.bbnmj > [data-view] > .bbnmj__h2:first-child + .bbnmj__lede,
.bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child + .bbnmj__lede{
  background:var(--bbn-surface-connected);
  border-left:4px solid var(--bbn-brand-deep);
  border-radius:0 0 var(--bbn-radius) 0;
  max-width:none;
  padding:0 20px 16px;
  padding-right:max(20px, calc(100% - 62ch));
  margin:0 -20px 20px;
}

/* The Dashboard header is already one element, so it takes the band directly. */
.bbnmj__dashhead{
  background:var(--bbn-surface-connected);
  border-left:4px solid var(--bbn-brand-deep);
  border-radius:0 var(--bbn-radius) var(--bbn-radius) 0;
  padding:16px 20px;
  margin:0 -20px 22px;
}
/* Its v1 rule is retired for the same reason as the heading's. */
.bbnmj__dashhead .bbnmj__dashbiz{ padding-bottom:0 }
.bbnmj__dashhead .bbnmj__dashbiz::after,
.bbnmj__dashhead .bbnmj__h2:not(:has(+ .bbnmj__dashbiz))::after{ display:none }
.bbnmj__dashhead .bbnmj__h2:not(:has(+ .bbnmj__dashbiz)){ padding-bottom:0 }
.bbnmj__dashhead .bbnmj__lede{ margin-top:8px }
/* The eyebrow sits on the wash now, where the brand teal is the wrong weight
   against a green ground — the deeper step separates it from the surface. */
.bbnmj__dashhead .bbnmj__eyebrow{ color:var(--bbn-brand-deep) }

/* ---- WORTH CHECKING: three subgroups, one table ---------------------------
   The panel reads as one long white list because FUNDING, VISIBILITY and OPEN TO
   YOUR BUSINESS are separated by a label and nothing else. They are not made into
   cards — that would be the floating-card grid the brief rules out, and it would
   cost the scanability that makes this panel work. A rule, a small brand marker
   and a little more air is enough to say "a new group starts here". */
/* THE SEPARATION COSTS NO HEIGHT. .bbnmj__label-sub already carried margin:14px 0 6px, so the
   first attempt at this — margin-top:20 plus padding-top:14 — added 20px per group and pushed
   the Dashboard 58px taller on mobile, five times the budget. The rule is drawn INSIDE the space
   that already existed instead: 4px margin plus 10px padding is the same 14px, and the hairline
   sits in the middle of it. Measured, not assumed. */
.bbnmj__panel--grouped > .bbnmj__label-sub{
  display:flex; align-items:center; gap:7px;
  margin-top:4px; padding-top:10px;
  border-top:1px solid var(--bbn-border);
  color:var(--bbn-text-secondary);
}
.bbnmj__panel--grouped > .bbnmj__label-sub::before{
  content:""; flex:none; width:3px; height:10px; border-radius:2px;
  background:var(--bbn-brand); opacity:.55;
}
/* The first group opens the panel, so it needs neither the rule nor the air. */
.bbnmj__panel--grouped > .bbnmj__label-sub:first-child{
  margin-top:0; padding-top:0; border-top:0;
}

/* ---- MOBILE: framing from surface and edge, not from height ---------------
   The band costs vertical space, and on a phone that is the one thing it may not
   take. Tighter padding, a tighter bottom margin, and the retired v1 rule
   padding coming back off keep the net change inside the 12px budget — measured,
   not estimated: see the delta table in the PR. */
@media (max-width:620px){
  .bbnmj > [data-view] > .bbnmj__h2:first-child,
  .bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child{
    padding:11px 14px 8px; margin:0 -14px;
  }
  .bbnmj > [data-view] > .bbnmj__h2:first-child + .bbnmj__lede,
  .bbnmj > [data-view] > .bbnmj__reading > .bbnmj__h2:first-child + .bbnmj__lede{
    padding:0 14px 11px; margin:0 -14px 14px;
  }
  /* The Dashboard header is the one that carries an eyebrow, a greeting, the business and a
     lede, so it is the one the band costs most. Trimmed until the measured delta came inside
     budget rather than until it looked about right. */
  .bbnmj__dashhead{ padding:8px 14px; margin:0 -14px 12px }
  .bbnmj__dashhead .bbnmj__lede{ margin-top:6px }
}
