/* ============================================================
   INDUSTRIES — ASSOCIATIONS (/industries/associations/)
   ============================================================
   Page overrides only. The layout comes from the shared association
   LP kit imported below; read that file's header before editing it,
   because /lp/asae/ and /lp/ndap/ load the same rules.

   Body class: .lp-assoc.page-industries-associations
   Everything here is prefixed .page-industries-associations so it
   cannot reach the other two pages.

   Three changes to the kit:
     1. The hero fills the viewport height and runs a five-slide
        cross-fade behind the copy, with its own readability scrim.
     2. The meet-us people go one per row, portrait left and the
        name, role and bio right, and the section grid rebalances so
        the text column has room to read.
     3. The carousel's NASSCO panel carries an extra standout line.
   ============================================================ */

@import url("/css/lp-asae.css");

/* ============================================================
   HERO — slideshow instead of the kit's single photo
   ============================================================
   The kit's hero paints one photo on .asae-hero__bg plus two scrims
   over it. Here the imagery comes from the five stacked <picture>
   slides below, so this element keeps the scrims and drops the photo.
   ============================================================ */

/* .asae-hero__bg carries the gradients only — the slideshow behind it supplies
   the imagery, so its own background must stay transparent or it would cover
   the slides (it follows them in the DOM). */
.page-industries-associations .asae-hero__bg {
    background-image: none;
    background-color: transparent;
}

/* Readability scrim. The kit's 95deg version is replaced, not disabled: the
   banner photography is far too bright for white text bare — the H1 measures
   1.05:1 against the worst of the four slides where WCAG wants 3:1.

   Two shapes, because the hero is `100svh` and so takes the viewport's own
   proportions. A horizontal ramp suits the 16:9 landscape crop, where the
   copy occupies the left two thirds and the subjects sit right of centre. It
   is the wrong shape entirely on the 9:16 portrait crop, where the headline
   spans 94% of the width — hence the near-flat wash under
   `(orientation: portrait)` below.

   Numbers are measured, not modelled: the text layer is hidden, the page
   screenshotted per slide with the cross-fade disabled, and the 99th
   percentile luminance taken inside each text element's own box. Landscape
   worst case of the four slides — H1 3.89:1 (needs 3:1 as large text),
   subtitle 10.79:1, note 13.0:1 (both need 4.5:1).

   The landscape ramp has to reach 80% because the H1 runs to 65% of the
   width and the brightest glass on slides 2-4 sits right behind its last
   word. Measured alternatives that clear earlier all fail: 76% reaches only
   2.97:1, 72% 2.38:1, and the 58% this page shipped before the real art
   landed 1.05:1. The right 20% stays untouched, which is where every crop
   puts its subjects. */
.page-industries-associations .asae-hero__bg::before {
    background: linear-gradient(to right,
        rgba(26, 26, 36, 0.90) 0%,
        rgba(26, 26, 36, 0.80) 36%,
        rgba(26, 26, 36, 0.66) 56%,
        rgba(26, 26, 36, 0.36) 70%,
        rgba(26, 26, 36, 0) 80%);
}

/* Portrait crop: the copy spans nearly the full width, so there is no clear
   side to fade toward. A near-flat wash, eased off at top and bottom so it
   meets the nav and the section below without a seam. Worst case of the four
   slides — H1 4.28:1, subtitle 7.63:1. */
@media (orientation: portrait) {
    .page-industries-associations .asae-hero__bg::before {
        background: linear-gradient(180deg,
            rgba(26, 26, 36, 0.44) 0%,
            rgba(26, 26, 36, 0.58) 18%,
            rgba(26, 26, 36, 0.58) 72%,
            rgba(26, 26, 36, 0.44) 100%);
    }
}

/* ============================================================
   HERO SLIDESHOW
   ============================================================
   Five <picture> slides stacked and cross-faded on opacity. The ink base sits
   under them so there is no flash of nothing before slide 1 decodes.
   ============================================================ */

.page-industries-associations .assoc-hero-slides {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    background: var(--asae-ink);
}

.page-industries-associations .assoc-hero-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 1.2s ease-in-out;
}

.page-industries-associations .assoc-hero-slide.is-on {
    opacity: 1;
}

/* Same framing the kit's background-position gave: fill the box, bias the
   crop above the midline. */
/* The banner art is supplied pre-cropped to the two target aspect ratios, so
   centre is the correct framing — the per-slide object-position that used to
   live here existed only to rescue auto-cropped stand-ins. `cover` still
   trims when a viewport's ratio differs from the crop's (sides at 1440x900,
   top/bottom on an ultrawide), which centre handles evenly. */
.page-industries-associations .assoc-hero-slide img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* The JS stops advancing under this preference; kill the fade too so a
   mid-transition state can't be left half-way. */
@media (prefers-reduced-motion: reduce) {
    .page-industries-associations .assoc-hero-slide {
        transition: none;
    }
}

/* Full-height banner. `min-height` (not `height`) so a short viewport or a
   long headline grows the hero instead of clipping it, and the kit's own
   padding still keeps the text clear of the fixed nav.

   svh, not dvh: dvh tracks the mobile URL bar, so the hero would resize —
   and the content re-centre — on the first scroll. svh is the small
   viewport, so the hero fits the worst case and never moves. The vh line
   above it is the fallback for browsers without the 2022 units; it slightly
   overshoots on mobile, which min-height absorbs. */
.page-industries-associations .asae-hero {
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    align-items: center;
}

/* .asae-hero__inner is the centred max-width column; as a flex child it needs
   the width back that `align-items: center` would otherwise leave it without. */
.page-industries-associations .asae-hero__inner {
    width: 100%;
}

/* ============================================================
   MEET US — one person per row
   ============================================================ */

/* The kit subtracts the whole 128px gutter from the people column so
   its two portraits narrow rather than the form. With the bio moved
   beside the portrait that column needs the width back, so the gutter
   is split evenly between the two columns instead.

   Bounded to the range where the kit is still two columns. At 0,2,0 an
   unscoped rule here would outrank the kit's `grid-template-columns: 1fr`
   in its own max-width: 1199px block and hold the two columns all the way
   down, which crushes the people column to ~150px on a phone. */
@media (min-width: 1200px) {
    /* Half the kit's 128px gutter comes off the people column instead of all
       of it, which leaves the form the wider share — the bios are short
       enough to read at that measure and the form has six stacked fields to
       fit. (An earlier revision gave the people column the remainder after a
       fixed-width form, which read better per line but starved the form; the
       call was to favour the form.)

       Text column: ~52 characters at 1440, ~37 at 1200 — around five lines
       for the longest of the three bios. */
    .page-industries-associations .asae-meet__inner {
        grid-template-columns: minmax(0, calc(50% - var(--space-3xl))) minmax(0, 1fr);
    }
}

/* Rows, not columns: three people stack. */
.page-industries-associations .asae-meet__row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-lg);
}

/* Portrait left, name + role + bio right. The left track is the portrait's
   own 112px and nothing more — with the name moved into the text column
   there is no text under the photo to widen it for. */
.page-industries-associations .asae-person {
    display: grid;
    grid-template-columns: 112px minmax(0, 1fr);
    gap: var(--space-lg);
    align-items: start;
}

/* The kit gives the portrait a bottom margin for its stacked card. Nothing
   sits under it here, so it would only push the card taller than the photo. */
.page-industries-associations .asae-person__id img {
    margin-bottom: 0;
    display: block;
}

/* The name leads the text column, so it loses the h6's default top offset
   and lines up with the top of the portrait beside it. */
.page-industries-associations .asae-person__text h3 {
    margin-top: 0;
}

.page-industries-associations .asae-person__bio {
    margin: 0;
    line-height: var(--leading-relaxed);
    color: var(--color-text-secondary);
}

/* Below the meet section's stacked breakpoint the people column runs
   full width, so the two-column card holds. It only breaks down when
   the card itself gets too narrow for a 168px left track. */
@media (max-width: 767px) {
    .page-industries-associations .asae-person {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-md);
    }

    /* The two columns hold on a phone — 112px of portrait plus a 16px gap
       still leaves the text column the greater share — so only the gap
       tightens. Below 479 the photo comes down with it (next block). */
    .page-industries-associations .asae-person {
        gap: var(--space-md);
    }
}

@media (max-width: 479px) {
    /* Two columns cannot survive here. At 320 the card is 272px wide; once
       its padding, the portrait and the gap come out, the bio is left with
       120px — about fifteen characters a line. So the portrait goes back on
       its own row above the text, which is the one place on the page the
       name does not sit beside the photo, and the card's padding comes in a
       step to buy the copy back another 16px. Text column: ~28 characters
       at 320, ~37 at 390. */
    .page-industries-associations .asae-person {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-md);
        padding: var(--space-lg);
    }

    .page-industries-associations .asae-person__id img {
        width: 88px;
        height: 88px;
    }
}

/* ============================================================
   CASE STUDY CAROUSEL — the NASSCO board paragraph
   ============================================================
   The kit already stacks panels in one grid cell, so the band grows
   to fit the taller NASSCO panel rather than clipping it. Two things
   the extra paragraph does need:
   ============================================================ */

/* Bold at the body colour's 85% white reads as heavier grey rather than
   emphasis, so the standout takes full white. */
.page-industries-associations .csc-panel__body--standout {
    color: #fff;
}

/* The standout belongs to the paragraph above it, so the two sit closer
   than two independent paragraphs would. */
.page-industries-associations .csc-panel__body:has(+ .csc-panel__body--standout) {
    margin-bottom: var(--space-sm);
}

/* The lab staggers the panel's entrance for children 2–5 only, which was
   every child that needed one. The extra paragraph pushes the stats row and
   the button to 6 and 7, where they would both fire at 0ms and arrive ahead
   of the testimonial above them. Continue the 70ms series. */
.page-industries-associations .csc-panel.is-active > *:nth-child(6) { animation-delay: 350ms; }
.page-industries-associations .csc-panel.is-active > *:nth-child(7) { animation-delay: 420ms; }

/* ============================================================
   FOUR-WAYS RAIL — animated example score card
   ============================================================
   The card steps through four states as the rail scrolls, driven by
   /js/industries-associations.js off the rail's `sfr:activate` event. Only the
   transitions and the per-row "Start here" visibility live here; the values
   themselves are set inline by that script.

   Scoped to this page because the score card, its rows and the library grid
   below all come from the shared kit, which /lp/asae/ also loads.
   ============================================================ */

/* Every row ships a "Start here" tag; only the weakest row's is shown, so the
   marker moves by class toggle instead of a DOM move. The kit's `is-gap` rules
   already handle its placement — this only controls which one renders. */
.page-industries-associations .asae-score-card--rail .asae-score-card__row em {
    display: none;
}

.page-industries-associations .asae-score-card--rail .asae-score-card__row.is-gap em {
    display: block;
}

/* `is-gap` changes the row's grid tracks, so the two rows swapping the marker
   reflow. Transitioning the bar and the ring keeps the eye on the values
   rather than on that reflow. 0.5s matches the number tick's longest run. */
.page-industries-associations .asae-score-card__bar i {
    transition: width 0.5s var(--easing-smooth);
}

.page-industries-associations .asae-score-card__fill {
    transition: stroke-dashoffset 0.5s var(--easing-smooth);
}

@media (prefers-reduced-motion: reduce) {
    .page-industries-associations .asae-score-card__bar i,
    .page-industries-associations .asae-score-card__fill {
        transition: none;
    }
}

/* ============================================================
   CASE-STUDY CAROUSEL — stat columns sized to their labels
   ============================================================
   The kit gives the three stats equal thirds of the panel, which wrapped
   "to recover the investment" onto a second line. The panel has spare width to
   the right of them, so the columns take only what their labels need and the
   slack collects at the end of the row. Below 560 the kit's equal thirds come
   back and labels wrap again, which is fine on a phone.
   ============================================================ */
@media (min-width: 561px) {
    .page-industries-associations .csc-panel__stats {
        grid-template-columns: repeat(3, max-content);
        column-gap: var(--space-2xl);
    }
}

/* ============================================================
   RESOURCE LIBRARY — gutter matched to the meet-us section
   ============================================================
   The kit gives the library a 64px gutter and the meet-us grid 128px; this
   brings the library up to match.

   Two constraints make the obvious one-liner wrong. `column-gap`, not the
   `gap` shorthand: at =<1199 the kit stacks the library into one column and
   drops to a 48px gap, and a shorthand here outranks that media query on
   specificity, so it would wedge 128px of dead space between the heading and
   the article list on every phone. And the whole rule is bounded to =>1200
   for the same reason — above that breakpoint is the only place a column
   gutter exists to widen.
   ============================================================ */
@media (min-width: 1200px) {
    .page-industries-associations .asae-library {
        column-gap: calc(var(--space-3xl) * 2);
    }
}

/* The kit hard-codes the ring at 46% (`stroke-dashoffset: 176.4`) to match the
   score /lp/asae/ shows. This page's first state is 33, so the no-JS render
   needs its own default or the ring and the number disagree.
   C = 2*pi*52 = 326.73; 326.73 * (1 - 0.33) = 218.9. */
.page-industries-associations .asae-score-card__fill {
    stroke-dashoffset: 218.9;
}

/* Band pill colours. The kit paints it one orange whatever it says, which was
   fine while every state read "Developing" — the four states now span Getting
   Started to Strong, so the pill has to carry the difference. Values match the
   four bands in the quiz's own emailed report (education-score.js) so the
   example card and the real result agree. */
/* The rail card sits inside .asae-ch, which is background: var(--color-bg) —
   WHITE. .asae-score-card has no background of its own, so these pills are
   painted over white, not over a dark card. Text must therefore be dark and
   saturated over a pale tint, which is exactly what the kit's own .asae-ch
   override does for the single-orange default. Scoped under .asae-ch here so
   it outranks that rule (equal specificity, later in the cascade) rather
   than fighting it. Do not paste dark-card values in: contrast measured from
   the rendered pixels, not from a computed-style model. */
.page-industries-associations .asae-ch .asae-score-card__band--leading {
    color: #065f46;
    background: rgba(16, 185, 129, 0.18);
}

.page-industries-associations .asae-ch .asae-score-card__band--strong {
    color: #05585e;
    background: rgba(0, 161, 172, 0.2);
}

.page-industries-associations .asae-ch .asae-score-card__band--developing {
    color: #8a4e02;
    background: rgba(249, 147, 13, 0.2);
}

.page-industries-associations .asae-ch .asae-score-card__band--getting-started {
    color: #991b1b;
    background: rgba(220, 38, 38, 0.14);
}
