/* Match Engine v1 UI (2026-08-19) -- Property Owner's Matches tab. See
   templates/dashboard-tabs/tab-matches.php. Card accent colors reuse the existing global
   --match-role-contractor (orange) / --match-role-capital-provider (green) tokens (see
   class-npca-design-tokens.php) via a per-card --card-color custom property, rather than
   hardcoding hex values here -- same "one set of role colors" rule the role badge/portal nav
   already follow (dashboard.css). Property Owner's own blue (--match-role-property-owner) is not
   used on this tab: every card here represents a Contractor or Capital Provider, never the
   Property Owner viewing the page. */

.npca-v2-match-pane h2 {
    margin: 0;
    font-size: 1.25em;
}

/* Header row: title and Project selector share one line instead of stacking into three separate
   blocks (title / label / select), which is where most of the old dead space came from. */
.npca-v2-match-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
/* ================================================================================================
   MATCH WORKSPACE GEOMETRY
   ------------------------------------------------------------------------------------------------
   This page renders inside a Bricks Builder site running Automatic.css, and that matters for how
   these rules are written. Automatic.css applies global spacing through zero-specificity selectors
   -- `:where(section:not(section section)) { padding-block: var(--section-padding-block) }` resolves
   to roughly 90-96px, and `:where(p, h1..h6, ul, ol, li)` sets typographic margins -- which land on
   any element the plugin does not explicitly control. Bricks' own frontend stylesheet loads AFTER
   the plugin's and its reset is unlayered.

   The consequence: anything left to inherit its box gets framework spacing, which is what made this
   page read as disconnected widgets separated by dead air. So every element in the Match control
   area declares its own margin, display and width. Zero-specificity `:where()` rules lose to any
   real declaration, so one explicit line per property is enough -- no !important needed anywhere.

   Do not "clean up" these explicit margin: 0 declarations. They are load-bearing.
   ================================================================================================ */

/* Screen-reader-only text. Counts in this workspace mean two different things -- unread activity vs
   Match candidates -- and that distinction is carried here rather than in visible clutter. */
.npca-v2-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ------------------------------------------------------------------ Project selector
   Left-aligned in the toolbar now, not centred under a title: it is a control, and controls line up
   with the other controls. */
.npca-v2-match-project-select {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    margin: 0;
    min-width: 0;
}

.npca-v2-match-project-select__control {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-width: 0;
    margin: 0;
}

.npca-v2-match-project-select select {
    /* min-width: 0 is required, not stylistic: a <select> takes its intrinsic width from its longest
       <option>, and a flex item will not shrink below that, which overflowed the card at 375px. */
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    max-width: 100%;
    margin: 0;
    padding: 9px 12px;
    border: 2px solid var(--match-border, #E2E8EE);
    border-radius: calc(var(--radius-card, 14px) / 2);
    background: #fff;
    color: var(--match-ink, #272F3D);
    font-family: inherit;
    font-size: 0.98rem;
    font-weight: 600;
    text-overflow: ellipsis;
}

.npca-v2-match-project-select select:focus-visible {
    outline: 2px solid var(--brand-primary, #2E7D32);
    outline-offset: 1px;
}

/* Unread-activity badge. Same visual language as the left-navigation badge on purpose -- they count
   the same thing, one per Project and one in aggregate. */
.npca-v2-match-project-select__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    min-width: 22px;
    height: 22px;
    padding: 0 7px;
    border-radius: 999px;
    background: var(--brand-primary, #2E7D32);
    color: #fff;
    font-size: 0.76rem;
    font-weight: 800;
    line-height: 1;
}

/* ------------------------------------------------------------------ the control toolbar
   Two rows inside one panel. Row 1 answers "what am I looking at": which Project, and which audience
   within it -- the Project takes the slack, the audience selector keeps its natural width. Row 2
   narrows that selection by relationship state. The internal record-source filter, when an authorised
   reviewer sees it, is the panel's last row: least important, and the only row a participant never
   gets.

   Row geometry is declared here rather than left to the elements' own margins, for the same reason as
   everything else in this stylesheet -- see the note at the top of the file. */
.npca-v2-match-controls__row {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    margin: 0;
    flex-wrap: wrap;
}

.npca-v2-match-controls__row--primary > .npca-v2-match-project-select {
    /* Takes the remaining width so a long Project name gets the room, but may shrink: min-width: 0 is
       what stops a <select> refusing to go below its longest option's intrinsic width. */
    flex: 1 1 320px;
    min-width: 0;
}

.npca-v2-match-controls__row--primary > .npca-v2-match-toggle {
    flex: 0 0 auto;
}

/* ------------------------------------------------------------------ the control panel */
.npca-v2-match-controls {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0 0 14px;
    padding: 12px 14px;
    border: 1px solid var(--match-border, #E2E8EE);
    border-radius: calc(var(--radius-card, 14px) / 1.4);
    background: color-mix(in srgb, var(--match-ink, #272F3D) 3%, #fff);
}

/* ------------------------------------------------------------------ audience selector */
.npca-v2-match-toggle {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
    padding: 0;
    border: 0;
}

/* A segmented audience selector, not two call-to-action buttons. Deliberately reads as a filter:
   the inactive side is a quiet outline, and only the active side takes its role colour. */
.npca-v2-match-toggle__btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    padding: 7px 14px;
    border: 1.5px solid var(--match-border, #E2E8EE);
    border-radius: 999px;
    background: #fff;
    color: var(--match-ink, #272F3D);
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.2;
    cursor: pointer;
    opacity: 0.72;
    /* 38px tall including border -- comfortably above the 24px minimum for a pointer target and
       large enough to hit on a phone. */
    min-height: 38px;
}

.npca-v2-match-toggle__btn:hover { opacity: 1; }

.npca-v2-match-toggle__btn:focus-visible {
    outline: 2px solid var(--match-ink, #272F3D);
    outline-offset: 2px;
}

.npca-v2-match-toggle__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: rgba(39, 47, 61, 0.10);
    font-size: 0.78rem;
    font-weight: 800;
    line-height: 1;
}

/* Role colour language, unchanged: Contractors orange, Capital Providers green. Selected state is
   the filled one, so which audience is active is obvious at a glance rather than a subtle underline. */
.npca-v2-match-toggle__btn--contractor.is-active {
    opacity: 1;
    border-color: var(--match-role-contractor, #F86902);
    background: var(--match-role-contractor, #F86902);
    color: #fff;
}

.npca-v2-match-toggle__btn--capital.is-active {
    opacity: 1;
    border-color: var(--match-role-capital-provider, #036836);
    background: var(--match-role-capital-provider, #036836);
    color: #fff;
}

.npca-v2-match-toggle__btn.is-active .npca-v2-match-toggle__count {
    background: rgba(255, 255, 255, 0.26);
    color: #fff;
}

/* ------------------------------------------------------------------ relationship-state filters */
.npca-v2-match-subnav {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin: 0;
    padding: 0;
}

.npca-v2-match-subnav__btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 5px 11px;
    border: 1px solid var(--match-border, #E2E8EE);
    border-radius: 999px;
    background: #fff;
    color: var(--match-ink, #272F3D);
    font-family: inherit;
    font-size: 0.84rem;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    opacity: 0.72;
    min-height: 30px;
}

.npca-v2-match-subnav__btn:hover { opacity: 1; }

.npca-v2-match-subnav__btn:focus-visible {
    outline: 2px solid var(--match-ink, #272F3D);
    outline-offset: 2px;
}

.npca-v2-match-subnav__btn.is-active {
    opacity: 1;
    background: var(--match-ink, #272F3D);
    border-color: var(--match-ink, #272F3D);
    color: #fff;
}

.npca-v2-match-subnav__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: rgba(39, 47, 61, 0.10);
    font-size: 0.76rem;
    font-weight: 700;
    line-height: 1;
}

.npca-v2-match-subnav__btn.is-active .npca-v2-match-subnav__count {
    background: rgba(255, 255, 255, 0.28);
}

/* ================================================================== geometry ownership

   The MATCH WORKSPACE GEOMETRY note at the top of this file already establishes the principle:
   under Automatic.css, anything this plugin leaves unclaimed gets framework spacing. That note
   cites the framework's `padding-block` and typographic-margin rules and applies the principle to
   the control toolbar. It missed two rules, and those two are what produced the reported
   "excessive vertical whitespace" in expanded Match cards:

       section:where(:not(.bricks-shape-divider)) {
           display: flex; flex-direction: column; align-items: center; gap: var(--container-gap);
       }
       section > div:where(:not(.bricks-shape-divider)) {
           display: flex; flex-direction: column; align-items: flex-start; gap: var(--content-gap);
       }

   Not padding and not margins -- `display` and `gap`. Measured live at 1280px on a real Matched
   card, before this block existed:

       .npca-v2-match-contact   flex column, gap 65.4px   (--container-gap)
       .npca-v2-match-pane      flex column, gap 65.4px
       .npca-v2-match-track     flex column, gap 29.5px   (--content-gap)

   The contact block's own margins computed EXACTLY as authored -- and were visually irrelevant,
   because flex `gap` is added between items on top of their margins rather than collapsing with
   them. The arithmetic is exact: 65.4 + 8 = 73px measured, 65.4 + 10 = 75px and 76px measured. The
   block stood 433px where the same markup in block flow stands 207px. The component's spacing
   values were never the problem, which is why tightening them alone would not have fixed this.

   `align-items` was the same rule's other half, and this file already carried a workaround for it:
   `.npca-v2-match-track > .npca-v2-match-card { width: 100% }` below exists because
   `align-items: flex-start` was shrink-wrapping cards. That treated the symptom; restoring block
   flow removes the cause. The width rule is kept -- correct on its own terms, and costs nothing.

   No `!important`, consistent with the note above: a single class is (0,1,0) and beats (0,0,1)
   outright, and this plugin's stylesheets print after automatic.css anyway, so even a tie falls our
   way. Scoped NPCA component classes only -- no element selectors, no global reset.

   SCOPE, deliberately not widened: `.npca-v2-status-card` (platform-shell.css) declares no
   `display` either, so every other NPCA pane -- onboarding, Projects, Documents, Settings, the
   project form -- is being handed the same 65.4px gap. Real finding, recorded for a separate
   decision, NOT fixed here. Re-flowing every pane on the platform is not a presentation tweak. */
.npca-v2-match-pane,
.npca-v2-match-contact,
.npca-v2-match-track {
    display: block;
    gap: 0;
}

/* The `display: block` above is an AUTHOR rule, which beats the browser's own
   [hidden] { display: none } UA default by cascade ORIGIN regardless of specificity. Without this
   override, the audience toggle setting `.npca-v2-match-track[hidden]` (assets/js/match-dashboard.js)
   had NO visual effect -- both the Contractor and Capital Provider tracks stayed displayed at once,
   so switching audiences appeared to do nothing. Exactly the bug, and exactly the fix, already
   applied to `.npca-v2-portal-nav__children[hidden]` in dashboard.css. A class+attribute (0,2,0)
   beats the plain class (0,1,0) above, so no !important is needed. */
.npca-v2-match-track[hidden] {
    display: none;
}

/* ------------------------------------------------------------------ results

   `.npca-v2-match-track { margin: 0 }` was removed 2026-08-24. It dated from when the framework was
   injecting a 65.4px gap around this element and a hard zero was the only way to get the Match list
   to sit sensibly under its sub-navigation. The isolation work removed that gap at the source, so the
   zero survived as a compensation for a problem that no longer exists -- and it was overriding
   `.npca-v2-status-card > * + *`, which is why the sub-navigation tabs sat FLUSH against the first
   Match card at 0px on both the Contractor and Capital Provider dashboards.

   Deleting it lets the pane's own flow rule supply the spacing. Nothing here re-admits framework
   spacing: the track still declares `display: block; gap: 0` above, so the framework still cannot
   restructure it. */

/* Names the audience that owns this result region, so an empty-state sentence about Contractors can
   never read as belonging to Capital Provider cards. */
.npca-v2-match-track__heading {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 8px;
    padding: 0 0 6px;
    border-bottom: 1px solid var(--match-border, #E2E8EE);
    font-size: 0.95rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--card-color, var(--match-ink, #272F3D));
}

.npca-v2-match-track--contractor .npca-v2-match-track__heading { --card-color: var(--match-role-contractor, #F86902); }
.npca-v2-match-track--capital .npca-v2-match-track__heading { --card-color: var(--match-role-capital-provider, #036836); }

.npca-v2-match-track__heading-count {
    margin-left: auto;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--match-ink, #272F3D);
    opacity: 0.6;
}

.npca-v2-match-empty {
    margin: 0;
    padding: 14px 16px;
    border: 1px dashed var(--match-border, #E2E8EE);
    border-radius: calc(var(--radius-card, 14px) / 2);
    background: color-mix(in srgb, var(--match-ink, #272F3D) 2%, #fff);
    font-size: 0.92rem;
}

/* Cards take the full result width. There is no narrow central column: on desktop this workspace has
   1000px+ to work with and a Match card carries a name, badges and several reasons. */
.npca-v2-match-track > .npca-v2-match-card {
    width: 100%;
    max-width: 100%;
}


/* Result cards -- elongated, full-width, one visual language shared by both tracks; only the
   accent color (--card-color, set per modifier below) and the fact list inside .npca-v2-match-
   card__detail differ between a Contractor card and a Capital Provider card. */
.npca-v2-match-card--contractor {
    --card-color: var(--match-role-contractor, #F86902);
}

.npca-v2-match-card--capital {
    --card-color: var(--match-role-capital-provider, #036836);
}

.npca-v2-match-card {
    background: #fff;
    border: 2px solid var(--match-border, #E2E8EE);
    border-left: 6px solid var(--card-color, var(--brand-primary, #2E7D32));
    border-radius: var(--radius-card, 14px);
    margin-bottom: 10px;
}

/* Best Match: a soft tint + slightly stronger accent border, not a heavier/louder treatment that
   would make partial-coverage cards read as "bad" by contrast -- per explicit product direction
   that a Match not being "Best" should not look like a rejection. */
.npca-v2-match-card--best {
    border-left-width: 8px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--card-color) 6%, #fff) 0%, #fff 220px);
}

.npca-v2-match-card__summary {
    display: block;
    position: relative;
    width: 100%;
    padding: 12px 40px 12px 18px;
    background: none;
    border: none;
    text-align: left;
    cursor: pointer;
    font-family: var(--font-body, inherit);
}

.npca-v2-match-card__summary-main {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.npca-v2-match-card__name {
    font-family: var(--font-heading, system-ui, sans-serif);
    font-weight: 700;
    font-size: 1.1em;
    color: var(--match-ink, #272F3D);
}

.npca-v2-match-card__badge {
    display: inline-block;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: 0.78em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.npca-v2-match-card__badge--best {
    background: var(--card-color);
    color: #fff;
}

.npca-v2-match-card__reasons {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.npca-v2-match-card__reasons li {
    position: relative;
    padding-left: 16px;
    font-size: 0.92em;
    color: var(--match-ink, #272F3D);
    opacity: 0.85;
}

.npca-v2-match-card__reasons li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--card-color);
}

/* Plain CSS-triangle chevron -- same border-trick pattern as .npca-v2-portal-nav__toggle span
   (dashboard.css), not a font/emoji glyph, so it renders identically everywhere. Lives on the
   summary button itself, so `[aria-expanded="true"]` (set by match-dashboard.js on click) is
   enough to flip it with no extra JS-managed class. */
.npca-v2-match-card__chevron {
    display: block;
    position: absolute;
    top: 17px;
    right: 20px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 7px 5px 0 5px;
    border-color: var(--card-color) transparent transparent transparent;
    transition: transform 0.15s ease;
}

.npca-v2-match-card__summary[aria-expanded="true"] .npca-v2-match-card__chevron {
    transform: rotate(180deg);
}

/* The chevron's 150ms rotate is kept -- it is a transform on a 0x0 triangle, so it composites and
   cannot thrash layout, and it is the only thing telling the user the click registered.
   Reduced-motion still gets an opt-out, and it matters more since the accordion landed: a single
   click now rotates TWO chevrons, the one opening and the one collapsing on the user's behalf. The
   rotation itself is kept under reduced motion, only made instant -- removing it would leave the
   collapsed card's chevron pointing the wrong way, which is worse than a little movement. Matches
   the existing @media (prefers-reduced-motion: reduce) block in dashboard.css. */
@media (prefers-reduced-motion: reduce) {
    .npca-v2-match-card__chevron { transition: none; }
}

/* Detail panel -- deliberately no `display` rule on the [hidden] state here; the plain
   attribute-driven UA default (display: none) is left alone rather than fighting it with an
   author rule, per the lesson recorded in dashboard.css about author `display` rules beating
   [hidden] -- this element simply never gets an author `display` declaration at all. */
/* One shorthand, not a shorthand followed by a longhand. The previous form -- `padding: 0 18px 16px`
   then `padding-top: 12px` -- worked here but set the trap that the narrow-screen override below fell
   into: any later `padding` shorthand silently resets the top back to 0. */
.npca-v2-match-card__detail {
    padding: 12px 18px 16px;
    border-top: 1px solid var(--match-border, #E2E8EE);
}

.npca-v2-match-card__intro {
    margin: 0 0 12px;
    font-style: italic;
    color: var(--match-ink, #272F3D);
    opacity: 0.85;
}

.npca-v2-match-card__reasons--full li {
    opacity: 1;
    font-size: 0.95em;
}

.npca-v2-match-card__facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 8px 20px;
    margin: 10px 0;
}

.npca-v2-match-card__facts dt {
    font-size: 0.8em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--match-ink, #272F3D);
    opacity: 0.6;
}

.npca-v2-match-card__facts dd {
    margin: 2px 0 0;
}

.npca-v2-match-card__interest {
    margin-top: 6px;
}

.npca-v2-match-card__interest:hover {
    background: color-mix(in srgb, var(--card-color) 10%, transparent);
}

/* NOTE: colour for this button and its .is-active state is declared ONCE, further down with the
   other card action styling. It used to be declared here as well, with the two states INVERTED --
   inactive filled here, inactive outlined there. The later block won, so these were dead
   declarations that still looked authoritative. Do not re-add colour here. */

@media (max-width: 720px) {

    .npca-v2-match-card__summary {
        padding: 14px 16px;
    }

    /* Was `padding: 0 16px 16px`, which reset the base rule's 12px top padding to zero -- measured
       on a 375px viewport, the expanded detail had no top padding at all and its first row sat
       directly against the border-top. Only the horizontal value needs to change on a narrow
       screen. */
    .npca-v2-match-card__detail {
        padding: 12px 16px 16px;
    }

    .npca-v2-match-card__facts {
        grid-template-columns: 1fr;
    }
}

/* =============================================================================================
   Match v1.1 additions: Saved / Interested / Matched sub-navigation, relationship actions,
   Matched state, and the disclosure confirmation modal.
   ============================================================================================= */

/* Matched is the strongest state on the board -- a full role-coloured left edge and a tinted
   ground, so it reads as "this one is live" without shouting at the others. */
.npca-v2-match-card--matched {
    border-left-width: 8px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--card-color) 10%, #fff) 0%, #fff 280px);
}

.npca-v2-match-card__badge--matched {
    background: var(--card-color);
    color: #fff;
}

/* Inbound interest: informational, not celebratory -- the user still has a decision to make. */
.npca-v2-match-card__badge--inbound {
    background: rgba(39, 47, 61, 0.08);
    color: var(--match-ink, #272F3D);
    text-transform: none;
    letter-spacing: 0;
}

/* Private Saved marker. Intentionally small and unobtrusive: saving is inert and must not read as
   an action that told anyone anything. */
.npca-v2-match-card__pin {
    color: var(--card-color);
    font-size: 1.05em;
    line-height: 1;
}

.npca-v2-match-card__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

.npca-v2-button--quiet {
    background: transparent;
    color: var(--match-ink, #272F3D);
    border: 1px solid var(--match-border, #E2E8EE);
}

.npca-v2-button--quiet:hover {
    border-color: var(--card-color, var(--match-ink, #272F3D));
    color: var(--card-color, var(--match-ink, #272F3D));
}

.npca-v2-match-card__save.is-active {
    border-color: var(--card-color);
    color: var(--card-color);
    font-weight: 700;
}

.npca-v2-match-card__interest {
    background: var(--card-color);
    border: 2px solid var(--card-color);
    color: #fff;
}

.npca-v2-match-card__interest.is-active {
    background: transparent;
    color: var(--card-color);
}

.npca-v2-match-card__interest[disabled],
.npca-v2-match-card__save[disabled] { opacity: 0.55; cursor: default; }

.npca-v2-match-card__matched-note {
    margin: 10px 0 0;
    padding: 8px 12px;
    border-radius: calc(var(--radius-card, 14px) / 2);
    background: color-mix(in srgb, var(--card-color) 8%, transparent);
    font-size: 0.92em;
}

/* The standing reminder of what Saving vs Interest actually do. Small, always present, never a
   surprise at the moment of clicking. */
.npca-v2-match-card__privacy-note {
    margin: 8px 0 0;
    font-size: 0.82em;
    color: var(--match-ink, #272F3D);
    opacity: 0.6;
}

.npca-v2-match-card__error { margin-top: 8px; }

/* MATCH CONTACT. The first thing inside an expanded Matched card, above the description, the match
   reasons and every capability fact -- once two parties are Matched, "how do I reach them" is the
   question the card exists to answer. Given the card's own accent so it reads as the payoff of
   matching, but built from type and spacing rather than a button, because it is information to use,
   not an action to take. Rendered only on a current Match, and only ever by
   templates/components/match-contact-block.php, so both directions look identical. */
/* Spacing ladder, deliberate rather than uniform -- a small step under the section label, a
   moderate one between the person and how to reach them, and a moderate one before the footer, so
   the block reads as three related things and not five unrelated ones. Removing the injected 65.4px
   gap (see "geometry ownership" above) is what did the heavy lifting; these values are the
   intended design, now actually reachable. */
.npca-v2-match-contact {
    margin: 0 0 12px;
    padding: 10px 12px;
    border: 1px solid color-mix(in srgb, var(--card-color) 35%, transparent);
    border-radius: calc(var(--radius-card, 14px) / 2);
    background: color-mix(in srgb, var(--card-color) 7%, transparent);
}

.npca-v2-match-contact__heading {
    margin: 0 0 5px;
    font-size: 0.74em;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--card-color);
}

.npca-v2-match-contact__person {
    margin: 0 0 9px;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 10px;
}

.npca-v2-match-contact__name {
    font-size: 1.06em;
    font-weight: 700;
    color: var(--match-ink, #272F3D);
}

.npca-v2-match-contact__role {
    font-size: 0.88em;
    color: var(--match-ink, #272F3D);
    opacity: 0.7;
}

.npca-v2-match-contact__channels {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 8px 20px;
}

/* Two columns once there is room; the address, being multi-line, is allowed to run full width so a
   long street line never squeezes the email into an ellipsis. */
@media (min-width: 620px) {
    .npca-v2-match-contact__channels {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .npca-v2-match-contact__channel--address {
        grid-column: 1 / -1;
    }
}

.npca-v2-match-contact__label {
    display: block;
    font-size: 0.72em;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--match-ink, #272F3D);
    opacity: 0.55;
}

.npca-v2-match-contact__value {
    display: block;
    font-size: 0.95em;
    color: var(--match-ink, #272F3D);
    /* An email address is one long unbreakable token on a narrow screen. */
    overflow-wrap: anywhere;
}

a.npca-v2-match-contact__value {
    color: var(--card-color);
    text-decoration: underline;
    text-underline-offset: 2px;
}

a.npca-v2-match-contact__value:hover,
a.npca-v2-match-contact__value:focus-visible {
    text-decoration-thickness: 2px;
}

/* Deliberately plain. This says who shared the details and that the platform is not in the middle;
   it must never read as confirmation that a message was sent. */
.npca-v2-match-contact__note {
    margin: 9px 0 0;
    font-size: 0.8em;
    color: var(--match-ink, #272F3D);
    opacity: 0.65;
}

/* Contact tracking. Sits between the matched note and the action buttons: it is the thing to do
   once a Match exists, but it is a report rather than a decision, so it is visually quieter than
   the Interest button and never styled as a call to action. */
.npca-v2-match-card__contact {
    margin: 12px 0 0;
    padding: 12px;
    border: 1px solid var(--match-border, #E2E8EE);
    border-radius: calc(var(--radius-card, 14px) / 2);
    background: color-mix(in srgb, var(--card-color) 4%, transparent);
}

.npca-v2-match-card__contact-question {
    display: block;
    margin: 0 0 6px;
    font-size: 0.92em;
    font-weight: 600;
    color: var(--match-ink, #272F3D);
}

.npca-v2-match-card__contact-select {
    width: 100%;
    max-width: 320px;
    padding: 8px 10px;
    font: inherit;
    font-size: 0.94em;
    color: var(--match-ink, #272F3D);
    background: #fff;
    border: 1px solid var(--match-border, #E2E8EE);
    border-radius: calc(var(--radius-card, 14px) / 3);
}

.npca-v2-match-card__contact-select:focus-visible {
    outline: 2px solid var(--card-color);
    outline-offset: 1px;
}

.npca-v2-match-card__contact-select[disabled] { opacity: 0.55; cursor: default; }

/* Momentary acknowledgement that the server accepted the report. */
.npca-v2-match-card__contact-select.is-saved {
    border-color: var(--card-color);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--card-color) 25%, transparent);
}

/* What the OTHER side reported. Always attributed, never stated as established fact, because the
   platform does not observe communications -- see migration 055. */
.npca-v2-match-card__contact-echo {
    margin: 8px 0 0;
    font-size: 0.86em;
    font-style: italic;
    color: var(--match-ink, #272F3D);
    opacity: 0.75;
}

.npca-v2-match-card__contact-note {
    margin: 8px 0 0;
    font-size: 0.82em;
    color: var(--match-ink, #272F3D);
    opacity: 0.6;
}

.npca-v2-match-card__contact-error { margin: 8px 0 0; }

/* Disclosure confirmation modal. This is a consent surface, so it is deliberately plain and
   explicit: it names the counterparty and lists exactly what will be shared. */
.npca-v2-match-modal {
    position: fixed;
    inset: 0;
    z-index: 10000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(39, 47, 61, 0.55);
}

.npca-v2-match-modal__box {
    width: min(100%, 480px);
    max-height: 85vh;
    overflow-y: auto;
    background: #fff;
    border-radius: var(--radius-card, 14px);
    padding: 22px 24px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.22);
}

.npca-v2-match-modal__title {
    margin: 0 0 10px;
    font-family: var(--font-heading, system-ui, sans-serif);
    font-size: 1.15em;
    color: var(--match-ink, #272F3D);
}

.npca-v2-match-modal__box p { margin: 0 0 10px; }

.npca-v2-match-modal__list {
    margin: 0 0 12px;
    padding-left: 20px;
}

.npca-v2-match-modal__list li { margin-bottom: 4px; }

.npca-v2-match-modal__actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin-top: 16px;
}

@media (max-width: 720px) {
    .npca-v2-match-card__actions { flex-direction: column; align-items: stretch; }
    .npca-v2-match-card__actions .npca-v2-button { width: 100%; text-align: center; }
    .npca-v2-match-modal__actions { flex-direction: column-reverse; }
    .npca-v2-match-modal__actions .npca-v2-button { width: 100%; text-align: center; }
}

/* --------------------------------------------------------------------------------------------
   Internal QA test-data affordances (migration 052 record_classification).
   Rendered only for participants holding test-data visibility. Intentionally quiet: the internal
   marketplace should be obvious at a glance without making the interface look like a debug tool.
   -------------------------------------------------------------------------------------------- */
/* CURRENT ALGORITHMIC FIT, not relationship status (Tranche 4).
   Deliberately the quietest badge on the card: outlined, sentence case, no accent colour and no
   uppercase. It sits next to "Matched" or "Interested in your Project" and must never out-shout
   them, because the relationship is the important fact and this is only a note about the Match
   Engine's current view. Anything red, filled, or warning-shaped would read as "your Match has a
   problem", which is exactly the false impression the wording was chosen to avoid.
   `max-width` + wrapping: the label is a short sentence rather than a word, and on a narrow card it
   must wrap instead of forcing the summary row to overflow. */
.npca-v2-match-card__badge--scope {
    background: transparent;
    color: var(--match-ink, #272F3D);
    border: 1px solid var(--match-border, #E2E8EE);
    opacity: 0.75;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
    font-size: 0.74em;
    white-space: normal;
    max-width: 100%;
}

.npca-v2-match-card__badge--testdata {
    background: #6B7280;
    color: #fff;
    letter-spacing: 0.5px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
}

.npca-v2-match-testfilter {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin: 0 0 10px 0;
    padding: 6px 10px;
    border: 1px dashed #9CA3AF;
    border-radius: 6px;
    background: #F9FAFB;
}

.npca-v2-match-testfilter__label {
    font-size: 12px;
    font-weight: 700;
    color: #6B7280;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-right: 2px;
}

.npca-v2-match-testfilter__btn {
    border: 1px solid #D1D5DB;
    background: #fff;
    color: #374151;
    border-radius: 999px;
    padding: 3px 12px;
    font-size: 12px;
    line-height: 1.6;
    cursor: pointer;
}

.npca-v2-match-testfilter__btn:hover { border-color: #9CA3AF; }

.npca-v2-match-testfilter__btn.is-active {
    background: #163D67;
    border-color: #163D67;
    color: #fff;
    font-weight: 600;
}

/* --------------------------------------------------------------------------------------------
   Match header: centred title with the Project selector beneath it, and a selector wide enough for
   real Project names such as "QA-PROJ-002 Boone Contractor-Only HVAC Replacement".
   -------------------------------------------------------------------------------------------- */
.npca-v2-match-header--centered {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
}
/* ================================================================================================
   MATCH WORKSPACE -- RESPONSIVE
   Appended last so these overrides win over the base rules above regardless of source order.
   ================================================================================================ */

/* Tablet / mid-width: the audience selector and state filters keep their own rows and wrap within
   them. Nothing is allowed to shrink below a comfortable hit target. */
@media (max-width: 900px) {
    .npca-v2-match-project-select__control {
        max-width: 100%;
    }
}

@media (max-width: 720px) {
    /* Full available width, and no horizontal scroll: the selector is the widest thing in the hero
       and a <select> will happily push past its container without min-width: 0 above. */
    .npca-v2-match-project-select__control {
        width: 100%;
        max-width: 100%;
    }

    .npca-v2-match-controls {
        gap: 8px;
        padding: 10px;
    }

    /* Two audience buttons share the row evenly rather than wrapping to two lines -- at 375px the
       labels "Contractors" and "Capital Providers" both still fit at this size. */
    .npca-v2-match-toggle__btn {
        flex: 1 1 0;
        justify-content: center;
        padding: 8px 8px;
        font-size: 0.82rem;
        min-height: 40px;
    }

    .npca-v2-match-toggle__count {
        min-width: 18px;
        height: 18px;
        padding: 0 5px;
        font-size: 0.72rem;
    }

    /* The state filters stay a wrapping pill row. Five of them cannot fit on one line at 375px, and
       forcing them to would either shrink the text below readable size or create the horizontal
       scroll this pass is explicitly required not to introduce. */
    .npca-v2-match-subnav {
        gap: 4px;
    }

    .npca-v2-match-subnav__btn {
        padding: 5px 9px;
        font-size: 0.78rem;
        min-height: 32px;
    }

    .npca-v2-match-track__heading {
        flex-wrap: wrap;
        font-size: 0.88rem;
    }

    .npca-v2-match-track__heading-count {
        margin-left: 0;
        flex-basis: 100%;
    }

    .npca-v2-match-empty {
        padding: 12px 13px;
        font-size: 0.88rem;
    }
}

/* ================================================================================================
   COMPLETED SETUP TRACKER
   A Property Owner who finished onboarding should not carry a full-width progress bar forever, but
   the detail stays one click away rather than being deleted -- an incomplete user still needs the
   guidance, and a complete user occasionally wants to confirm what was checked.
   ================================================================================================ */
.npca-v2-readiness-stepper--complete {
    margin: 0 0 14px;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--npca-v2-role-color, #2E7D32) 30%, transparent);
    border-radius: calc(var(--radius-card, 14px) / 1.6);
    background: color-mix(in srgb, var(--npca-v2-role-color, #2E7D32) 6%, #fff);
}

.npca-v2-readiness-stepper--complete > summary {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0;
    padding: 9px 13px;
    list-style: none;
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--match-ink, #272F3D);
}

/* Safari renders a disclosure triangle through a pseudo-element the standard rule misses. */
.npca-v2-readiness-stepper--complete > summary::-webkit-details-marker { display: none; }

.npca-v2-readiness-stepper--complete > summary:focus-visible {
    outline: 2px solid var(--npca-v2-role-color, #2E7D32);
    outline-offset: 2px;
}

.npca-v2-readiness-stepper__tick {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 999px;
    background: var(--npca-v2-role-color, #2E7D32);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 900;
    line-height: 1;
}

.npca-v2-readiness-stepper__hint {
    margin-left: auto;
    font-size: 0.78rem;
    font-weight: 600;
    opacity: 0.6;
}

.npca-v2-readiness-stepper--complete .npca-v2-readiness-stepper__track {
    padding: 0 13px 13px;
}

@media (max-width: 720px) {
    .npca-v2-readiness-stepper--complete > summary {
        padding: 9px 11px;
        font-size: 0.86rem;
    }
    /* At phone width the hint would push the row to two lines for no benefit. */
    .npca-v2-readiness-stepper__hint { display: none; }
}

/* Single-Project case: no <select> to render, so the Project is a label-and-value pair occupying the
   same toolbar slot, at the same height, so the row does not change shape between a participant with
   one Project and a participant with nine. */
.npca-v2-match-project-select__label {
    display: block;
    margin: 0;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    line-height: 1.2;
    color: var(--match-ink, #272F3D);
    opacity: 0.55;
}

.npca-v2-match-project-select__value {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    min-height: 40px;
    font-size: 1.02rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--match-ink, #272F3D);
}

@media (max-width: 720px) {
    /* Project above audience on a phone: two full-width rows read better than two half-width
       controls, and the audience buttons already share their row evenly. */
    .npca-v2-match-controls__row {
        gap: 8px;
    }

    .npca-v2-match-controls__row--primary > .npca-v2-match-project-select,
    .npca-v2-match-controls__row--primary > .npca-v2-match-toggle {
        flex: 1 1 100%;
    }

    .npca-v2-match-project-select__value {
        min-height: 0;
        font-size: 0.98rem;
    }
}

/* ------------------------------------------------------------------ deep-link focus
 * A card arrived at from a notification link (?focus=org:<id> / ?focus=project:<uuid>). It is a
 * quiet, persistent outline rather than a flash: the participant may take a moment to look at the
 * screen after following a link, and an animation they missed tells them nothing. Deliberately NOT
 * a background change -- the card already uses background to carry relationship state. */
.npca-v2-match-card--focused {
    outline: 2px solid var(--brand-secondary, #76BC21);
    outline-offset: 2px;
}
