/* ===== WEB04 Phase 03b — public partner directory (`/partners`,
   `/partners/<slug>`). 2026-08-30. =====

   🔴 WHY THIS IS A SECOND FILE AND NOT A `site.css` BAND. Spec §6 and §23
   describe `site.css` as the append-only home for each section's rules;
   §22's ratified D1 amendment overrides that for this band. `WEB-72` charges
   the HOMEPAGE for `site.css` byte-for-byte and had 87 B of headroom — the
   tightest that envelope has ever been — so a directory band there would
   have spent a homepage budget on CSS no homepage visitor uses. `SiteLayout`
   links this file only when a page passes `directoryCSS: true`. `site.css`
   finishes WEB04 Phase 03b BYTE-IDENTICAL, and that is a decision, not an
   omission.

   🔴 NO MOTION LIVES HERE — no keyframe blocks, no animation declarations,
   no zero-opacity or `.reveal`-style hiding rule. (Their literal spellings
   are deliberately absent from this comment: a phase gate greps this file
   for them and must find zero, and a gate that counts its own prose proves
   nothing.) `WEB-61` (the no-JS safety guard) walks
   `site.css` and ONLY `site.css`: it proves every rule that hides content is
   scoped under the JS-stamped `html.js-reveal` marker, so a no-script
   visitor is never left staring at an invisible page. A second stylesheet is
   precisely the route by which a hiding rule could ship past that guard —
   silently, greenly. If a later phase wants motion on these pages, the
   correct move is to WIDEN `WEB-61` to sweep every served stylesheet, not to
   add the rule and hope.

   This file ADDS; it never re-declares. `glass-card`, `eyebrow`,
   `section-sub`, `lift-hover` and `visually-hidden` are defined in
   `site.css`, which `SiteLayout` still links unconditionally on these pages
   and links FIRST, so equal-specificity rules here win where they overlap.

   ⚠️ `class="partners"` is ALREADY TAKEN — `site.css` styles it for the
   homepage pricing paragraph. Every class below is prefixed
   `partner-directory-` or `partner-detail-`, matching the 03a page files.

   🔴 WEB10 (2026-09-12) ADDED THE `<details>` FILTER DISCLOSURE, AND ADDED NO
   HIDING RULE TO DO IT. The collapsed state is the browser's own, not a CSS
   declaration, which is exactly why the decision is safe under the guard
   described above — there is nothing here for a widened `WEB-61` to find. Open
   and closed differ by a SHAPE, not by a colour. If a later phase wants to
   suppress that marker, `summary { list-style: … }` styles a MARKER and is
   admissible; a rule that hides the panel is not, at any specificity. The
   disclosure triangle below is re-drawn as generated content because the
   summary is a flex container (which suppresses the browser's own `::marker`),
   and it CHANGES GLYPH on open so the state is never carried by colour.

   Responsive overrides live inside this file's own banner (the WEB02
   convention), at the bottom. */

/* ---------- /partners — hero ---------- */

.partner-directory-hero {
    padding: 3.5rem 0 2rem;
    text-align: center;
}

.partner-directory-hero h1 {
    margin: 0 0 0.8rem;
    font-size: 2.4rem;
    line-height: 1.15;
}

.partner-directory-hero .section-sub {
    max-width: 42rem;
    margin: 0 auto;
}

/* ---------- /partners — the filter form ----------

   `.field` and `.btn-primary` exist in `site.css` only SCOPED under
   `.auth-form` / the portal forms, so the directory's form would otherwise
   render as unstyled browser defaults. These rules are scoped under
   `.partner-directory-filters` for the same reason: a bare global
   `.btn-primary` here would reach into surfaces this file has no business
   restyling. */

.partner-directory-filters {
    padding: 1.4rem 1.5rem;
    margin-bottom: 2.2rem;
    /* 🔴 THE OPEN PANEL OVERLAYS THE RESULTS, so the card must PAINT above
       them. `.glass-card`'s `backdrop-filter` already makes this card a
       stacking context, and the results grid is a LATER sibling — without an
       explicit z-index the overflowing panel would render UNDERNEATH the
       first row of partner cards. It does not clip: no ancestor of the panel
       sets `overflow: hidden`. */
    position: relative;
    z-index: 5;
}

/* WEB10: ONE search field spanning the card, then a four-across row of
   collapsed disclosures. The old five-field place row is gone — its region,
   town and postcode legs are token scopes in the search box now. */
.partner-directory-search {
    margin-bottom: 1.1rem;
}

.partner-directory-filter-hint {
    margin: 0.4rem 0 0;
    color: var(--text-muted);
    font-size: 0.85rem;
    line-height: 1.45;
}

.partner-directory-filter-groups {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 0.8rem;
    align-items: start;
}

.partner-directory-filters .field {
    margin: 0;
    min-width: 0;
}

.partner-directory-filters label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text);
}

.partner-directory-filters input[type="text"] {
    width: 100%;
    padding: 0.6rem 0.75rem;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text);
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.4;
}

/* Visible focus for pointer users too — both pseudo-classes styled, the
   `site.css` auth-form precedent. */
.partner-directory-filters input:focus,
.partner-directory-filters input:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 1px;
    border-color: var(--accent);
}

/* WEB10 — one collapsed filter group. The four groups replace a `<select>`
   and three `<fieldset>`s; the accessible grouping moved to the panel's
   `role="group"` + `aria-labelledby`, so there is no legend to style here and
   no duplicated group name to hide. */
.filter-dropdown {
    position: relative;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: 8px;
}

/* An OPEN group paints above its three siblings — otherwise a panel dropping
   past the next group in the grid row would slide behind it. */
.filter-dropdown[open] {
    z-index: 2;
}

.filter-dropdown summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    color: var(--text);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}

/* 🔴 THE OPEN/CLOSED STATE CARRIES A SHAPE, NOT A COLOUR. `display: flex`
   above suppresses the browser's own `::marker` on a `<summary>`, so the
   marker is re-drawn here explicitly and CHANGES GLYPH on open — colour is
   never the sole signal (the standing accessibility rule), and a visitor who
   cannot perceive the panel's presence still sees which way the group points.
   The disclosure STATE itself is announced natively by `<details>`; this is
   decoration on top of that, which is why it is safe to mark it
   `aria-hidden`-equivalent by being generated content a screen reader ignores.
   Adding a marker is not hiding content — the rule this file's header states
   forbids the latter only. */
.filter-dropdown summary::before {
    content: "▸";
    color: var(--text-muted);
    font-size: 0.8rem;
}

.filter-dropdown[open] > summary::before {
    content: "▾";
}

/* 🔴 The summary is now a PRIMARY keyboard target — it is how the group is
   opened at all — so it carries the same visible focus ring the chip options
   and the text inputs do. Both pseudo-classes, the `site.css` auth-form
   precedent. */
.filter-dropdown summary:focus,
.filter-dropdown summary:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 1px;
    border-radius: 8px;
}

/* The applied-selection count. Server-rendered, so it reflects what was
   APPLIED, never unsubmitted ticks (WEB10 owner ruling D2). */
.filter-count {
    margin-left: auto;
    padding: 0.1rem 0.5rem;
    background: var(--bg);
    border: 1px solid var(--accent);
    border-radius: 999px;
    color: var(--accent-bright);
    font-size: 0.78rem;
    font-weight: 600;
}

/* 🔴 THE PANEL OVERLAYS, IT DOES NOT PUSH. Taking it out of flow is what
   keeps opening a group from re-flowing the card and shoving the results
   down the page — the collapse this whole change exists for.

   ⚠️ This is NOT a content-hiding rule and must not be mistaken for one.
   `position: absolute` RENDERS the panel; the closed state is still supplied
   natively by `<details>`, never by this sheet. The header's standing rule
   (no `display:none` / `opacity:0` / `visibility:hidden` in a sheet `WEB-61`
   cannot see) is intact — a reader with scripting off still opens the group
   and reads every option. */
.filter-dropdown-panel {
    position: absolute;
    top: calc(100% + 0.35rem);
    /* 🔴 PINNED TO ITS OWN GROUP'S EDGES — never `width: max-content`. Two
       groups can be open at once (the applied-selection rule opens every
       group that carries one), and a panel free to grow past its summary
       slides OVER its neighbour's: measured overlapping on 4 of 6 pairs
       with all four open. Spanning exactly the group it belongs to makes
       that structurally impossible, keeps each panel visually anchored to
       the summary that owns it, and costs only label wrapping — which the
       flat chip rows did anyway. It also removes any need to anchor the
       rightmost group leftward: nothing can reach the viewport edge. */
    left: 0;
    right: 0;
    z-index: 1;
    max-height: 21rem;
    overflow-y: auto;
    padding: 0.35rem 0.75rem 0.6rem;
    background: var(--bg-raised);
    /* A full border and a shadow now that it floats free of the summary —
       the `border-top` separator it used to carry only read as a divider
       while the two shared one box. */
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 12px 28px rgb(0 0 0 / 55%);
}


/* A checkbox + its label as one pill. The native checkbox is KEPT and
   visible, never replaced by a styled span — it is the real control, it is
   keyboard-reachable, and it is what a screen reader announces. */
.chip-option {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0.5rem 0.5rem 0;
    padding: 0.35rem 0.7rem;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: 999px;
}

.chip-option label {
    margin: 0;
    font-size: 0.9rem;
    font-weight: 500;
}

/* 🔴 INSIDE THE PANEL AN OPTION IS A ROW, NOT A PILL — and the reason is
   geometric, not stylistic. A 999px radius resolves to HALF the element's
   height, so the moment a label wraps to two lines (and "Wholesale &
   distribution" does, in a ~13rem column) the curve cuts inward across the
   text, and the scroll cap slices the last visible option through the middle
   of that curve. A rectangle has neither problem: the label wraps inside
   straight sides, every option is the same width, and the scroll edge cuts a
   clean line. The pill survives where it still reads as one — the partner
   cards' chip rows, which are short, single-line and never scrolled.

   The native checkbox is still KEPT and visible (the standing rule above);
   only the box around it changed shape. */
.filter-dropdown-panel .chip-option {
    display: flex;
    width: 100%;
    margin: 0.1rem 0;
    padding: 0.45rem 0.55rem;
    background: transparent;
    border-color: transparent;
    border-radius: 6px;
}

.filter-dropdown-panel .chip-option:hover {
    background: var(--bg);
}

/* The checkbox never shrinks to make room for a wrapping label. */
.filter-dropdown-panel .chip-option input[type="checkbox"] {
    flex: none;
}

/* The label fills the row, so the whole row is the hit target rather than
   just the words — a real affordance, not a hover effect, and it costs
   nothing because the `for=` binding already does the work. */
.filter-dropdown-panel .chip-option label {
    flex: 1;
    line-height: 1.35;
    cursor: pointer;
}

.chip-option:focus-within {
    outline: 2px solid var(--accent-bright);
    outline-offset: 1px;
    border-color: var(--accent);
}

.partner-directory-filter-actions {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-top: 1.4rem;
}

.partner-directory-filters .btn-primary {
    padding: 0.6rem 1.4rem;
    background: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 8px;
    color: var(--bg);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
}

.partner-directory-filters .btn-primary:hover {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    color: var(--bg);
}

.partner-directory-filters .btn-primary:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 2px;
}

.partner-directory-clear {
    color: var(--text-muted);
    font-size: 0.95rem;
}

/* ---------- /partners — the count line and the card grid ---------- */

.partner-directory-count {
    margin: 0 0 1.2rem;
    color: var(--text-muted);
    font-size: 0.95rem;
}

.partner-directory-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
    gap: 1.25rem;
}

/* The whole card is one anchor (the interaction-triad rule — a card that
   looks openable IS the control), so the text colour has to be reset off the
   UA link default and restored on the inner elements. */
.partner-directory-card {
    display: block;
    padding: 1.3rem;
    color: var(--text);
    text-decoration: none;
}

.partner-directory-card:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 3px;
}

.partner-directory-card-head {
    display: flex;
    align-items: flex-start;
    gap: 0.9rem;
}

.partner-directory-card-logo img,
.partner-directory-lettermark {
    display: block;
    width: 3rem;
    height: 3rem;
    border-radius: 10px;
    object-fit: contain;
}

/* The lettermark is `aria-hidden` in the markup and sits BESIDE the real
   name — it is decoration with a fallback glyph, never the accessible name. */
.partner-directory-lettermark {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    color: var(--accent-bright);
    font-size: 1.35rem;
    font-weight: 700;
}

.partner-directory-card-title h2 {
    margin: 0;
    font-size: 1.15rem;
    line-height: 1.25;
}

.partner-directory-card-tagline {
    margin: 0.3rem 0 0;
    color: var(--accent-bright);
    font-size: 0.92rem;
}

.partner-directory-card-location,
.partner-directory-card-summary {
    color: var(--text-muted);
    font-size: 0.92rem;
}

.partner-directory-card-location {
    margin: 0.25rem 0 0;
}

.partner-directory-card-summary {
    margin: 0.9rem 0 0;
    line-height: 1.5;
}

/* ---------- chips (shared by both pages) ---------- */

.partner-directory-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.9rem 0 0;
    padding: 0;
    list-style: none;
}

/* WCAG 1.4.1 — the chip's meaning is carried by its TEXT. The two variant
   tints below are decoration on top of a label that already says which kind
   it is; colour is never the only signal. */
.partner-directory-chip {
    padding: 0.2rem 0.6rem;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-muted);
    font-size: 0.82rem;
}

.partner-directory-chip-service {
    border-color: var(--accent);
    color: var(--accent-bright);
}

.partner-directory-chip-language {
    color: var(--text);
}

/* ---------- /partners — the empty state ---------- */

.partner-directory-empty {
    padding: 2rem 1.6rem;
    text-align: center;
}

.partner-directory-empty h2 {
    margin: 0 0 0.6rem;
    font-size: 1.2rem;
}

.partner-directory-empty p {
    margin: 0 auto 0.8rem;
    max-width: 34rem;
    color: var(--text-muted);
}

/* ---------- /partners/<slug> — identity band ---------- */

.partner-detail-identity {
    padding: 1.8rem;
    margin: 2.5rem 0 2rem;
}

.partner-detail-identity-head {
    display: flex;
    align-items: flex-start;
    gap: 1.2rem;
}

.partner-detail-logo img,
.partner-detail-logo .partner-directory-lettermark {
    width: 4.5rem;
    height: 4.5rem;
}

.partner-detail-identity-title h1 {
    margin: 0;
    font-size: 2rem;
    line-height: 1.15;
}

.partner-detail-identity-title .section-sub {
    margin: 0.5rem 0 0;
}

.partner-detail-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.4rem;
    margin: 1.4rem 0 0;
    padding: 0;
    list-style: none;
    color: var(--text-muted);
    font-size: 0.92rem;
}

.partner-detail-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    margin-top: 1.4rem;
}

.partner-detail-action {
    padding: 0.55rem 1.1rem;
    background: var(--bg-raised);
    border: 1px solid var(--accent);
    border-radius: 8px;
    color: var(--accent-bright);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
}

.partner-detail-action:hover {
    background: var(--accent);
    color: var(--bg);
}

.partner-detail-action:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 2px;
}

/* ---------- /partners/<slug> — body sections ---------- */

.partner-detail-about,
.partner-detail-offices,
.partner-detail-coverage,
.partner-detail-gallery {
    margin-bottom: 2.4rem;
}

.partner-detail-about h2,
.partner-detail-offices h2,
.partner-detail-coverage h2,
.partner-detail-gallery h2 {
    margin: 0 0 0.9rem;
    font-size: 1.3rem;
}

/* The description is prose — it keeps a reading measure even though the page
   is `main.wide` (68 rem), or the lines run far past comfortable length. */
.partner-detail-about p {
    max-width: 46rem;
    margin: 0 0 1rem;
    line-height: 1.65;
}

.partner-detail-office-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: 1rem;
}

.partner-detail-office {
    padding: 1.1rem 1.2rem;
}

.partner-detail-office h3 {
    margin: 0 0 0.4rem;
    font-size: 1rem;
}

.partner-detail-office address {
    color: var(--text-muted);
    font-size: 0.92rem;
    font-style: normal;
    line-height: 1.5;
}

.partner-detail-office address p {
    margin: 0;
}

/* The badge pairs its tint with the words "Main office" — colour is never
   the sole signal (WCAG 1.4.1). */
.partner-detail-office-badge {
    display: inline-block;
    margin: 0 0 0.5rem;
    padding: 0.15rem 0.55rem;
    background: var(--bg-raised);
    border: 1px solid var(--tone-ok);
    border-radius: 999px;
    color: var(--text);
    font-size: 0.78rem;
    font-weight: 600;
}

.partner-detail-chip-group {
    margin-bottom: 1.1rem;
}

.partner-detail-chip-group h3 {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
}

.partner-detail-gallery-strip {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
    gap: 0.9rem;
}

.partner-detail-gallery-strip img {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--border);
    border-radius: 12px;
}

.partner-detail-back {
    margin: 2.5rem 0 3rem;
}

/* ---------- responsive overrides (WEB02 convention: inside this file's own
     banner, never in a shared media-query block) ---------- */

@media (max-width: 640px) {
    .partner-directory-hero {
        padding: 2.5rem 0 1.5rem;
    }

    .partner-directory-hero h1 {
        font-size: 1.9rem;
    }

    .partner-directory-filters {
        padding: 1.1rem;
    }

    /* One disclosure per row: four collapsed summaries stack to four short
       rows, which is the whole point of the WEB10 collapse on a phone. */
    .partner-directory-filter-groups {
        grid-template-columns: 1fr;
    }

    /* Still an overlay — a phone is where pushing the results down the page
       hurts most — just shorter, since one group spans the full card width
       and its options stack. */
    .filter-dropdown-panel {
        max-height: 40vh;
    }

    .partner-directory-filter-actions {
        flex-direction: column;
        align-items: stretch;
        gap: 0.7rem;
    }

    .partner-directory-filters .btn-primary {
        width: 100%;
    }

    .partner-directory-clear {
        text-align: center;
    }

    .partner-detail-identity {
        padding: 1.3rem;
    }

    .partner-detail-identity-head {
        flex-direction: column;
        gap: 0.9rem;
    }

    .partner-detail-identity-title h1 {
        font-size: 1.6rem;
    }
}
