/* ===================================================================
   /about — the team photograph behind the opening copy
   -------------------------------------------------------------------
   The copy sits ON the photograph. That is the whole design, and it
   forces one decision that everything else follows from: dark type
   cannot share space with a visible photograph. Whatever is behind
   dark text has to be washed almost white, which is what an earlier
   version did — and it left the eight people on the left invisible.

   So the tones are inverted instead. A dark scrim goes over the WHOLE
   frame and the type turns light. All fourteen of them stay visible,
   including the ones directly behind the wording.

   Contrast, measured against the photograph rather than assumed: the
   frame contains genuinely white pixels (the exhibition curtain — max
   255, 99th percentile 244), so the scrim has to beat white, not the
   average. At .68 alpha on the copy side the brightest possible pixel
   lands on #525252, which gives:

       headline    #ffffff   on #525252   7.8:1
       body        #e8eaee   on #525252   6.5:1
       eyebrow     #fce7f3   on #525252   6.6:1

   and at the .63 the scrim has reached by the end of the longest line,
   still 6.5 / 5.4 / 5.5:1. All clear of the 4.5:1 AA bar.

   Do not lighten the scrim below about .60 to make the photograph
   prettier. The white curtain is the binding constraint and it is in
   the upper right, exactly where the headline runs.

   .about-intro-inner carries a solid --ink background of its own. That
   is not decoration: it means a failed or slow image still leaves light
   type on a dark panel rather than light type on white.
   =================================================================== */

.about-intro {
    position: relative;
    padding-block: clamp(20px, 2.6vw, 44px) clamp(24px, 3vw, 48px);
}

.about-intro-inner {
    position: relative;
    background: var(--ink);
    border-radius: var(--r-lg);
    /* Breathing room so the type is not flush to the panel's edge. The
       horizontal inset is the container's own --gutter padding. */
    padding-block: clamp(36px, 4.5vw, 64px);
}

/* No overflow:hidden here — below 992px the band is positioned outside
   this box and would be clipped away. The media clips itself instead. */
.about-intro-media {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    border-radius: var(--r-lg);
    pointer-events: none;
}

/* Natural aspect, NOT object-fit:cover. This is the important one.

   Cover makes the image fill the panel, and the panel's height is set by
   however tall the copy wraps. Below ~1400px that panel is taller than
   the photograph is proportionally, so cover switched to trimming WIDTH
   — and width is where the people are. At 1024px it was cutting five of
   them off the ends.

   Letting the image keep its own aspect at full width means it can never
   be trimmed horizontally: all fourteen are in frame at every size. When
   the panel is taller than the picture, --ink shows above and below it,
   which is what .about-intro-inner's background is for. When the panel
   is shorter, the overflow is clipped off the top and bottom — a height
   trim, which costs nothing but ceiling and carpet.

   -55% rather than -50% biases that height trim towards the group (heads
   at 36% of the frame, feet at 88%) instead of centring it on the
   architecture. */
.about-intro-media img {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-55%);
    width: 100%;
    height: auto;
    /* Softens the picture's own top and bottom edges into the dark panel
       so the band does not end on a hard line. */
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 7%, #000 93%, transparent 100%);
            mask-image: linear-gradient(180deg, transparent 0, #000 7%, #000 93%, transparent 100%);
}

/* The scrim. Slightly heavier on the copy side, easing off across the
   right where nothing is written, so the group reads a touch brighter
   there without the type ever dropping below AA. */
.about-intro-media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        rgba(8, 8, 8, .68)   0%,
        rgba(8, 8, 8, .66)  35%,
        rgba(8, 8, 8, .63)  55%,
        rgba(8, 8, 8, .58) 100%);
}

.about-intro-copy {
    position: relative;
    z-index: 1;
}

/* ---- Type, inverted for the dark panel ------------------------------ */

.about-intro .eyebrow   { color: var(--brand-tint-2); }   /* ::before dash is currentColor */
.about-intro .h-display { color: #fff; }
.about-intro .prose     { color: #e8eaee; }
.about-intro .prose strong { color: #fff; }

.about-intro .link-arrow { color: var(--brand-tint-2); }
.about-intro .link-arrow:hover { color: #fff; }

/* --brand on a dark panel is 2.7:1; the focus ring has to be light. */
.about-intro .link-arrow:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 3px;
    border-radius: 3px;
}

@media (max-width: 991.98px) {
    /* The copy goes full width, and a tall narrow panel would crop the
       line-up to three or four people. So the photograph leaves the
       copy: the panel stays dark (--ink on .about-intro-inner) with the
       light type on it, and the picture becomes a free-standing band
       below, at full strength with no scrim and all fourteen in shot.

       NOTE the anchor. .about-intro-media is a child of .container,
       whose box ends at the last line of copy — NOT at the section's
       padded edge. The band is pushed below with top:100% and the
       section reserves room for it in padding-bottom. Pinning it with
       bottom:0 instead lands it on top of the closing paragraphs. */
    .about-intro { padding-bottom: calc(clamp(170px, 56vw, 300px) + 44px); }

    .about-intro-media {
        top: 100%;
        bottom: auto;
        margin-top: 16px;
        height: clamp(170px, 56vw, 300px);
    }

    /* The band must stay WIDER than the source's 1.51:1 or cover starts
       trimming width and eats the people at both ends. Hence the 170px
       floor: on a 320px phone a 200px band is 1.44:1 and clips the
       group; 179px is 1.61:1 and holds all fourteen. */
    .about-intro-media::after { content: none; }

    /* Here the band has a fixed height, so cover is right again — and the
       band is kept WIDER than the source's 1.51:1 so cover trims height,
       never width. Hence the 170px floor: on a 320px phone a 200px band
       is 1.44:1 and clips the group; 179px is 1.61:1 and holds all
       fourteen. The mask and the absolute placement above are undone. */
    .about-intro-media img {
        position: static;
        transform: none;
        height: 100%;
        object-fit: cover;
        object-position: 50% 55%;
        -webkit-mask-image: none;
                mask-image: none;
    }
}

@media print {
    .about-intro-media { display: none; }
    .about-intro-inner { background: none; padding-block: 0; }
    .about-intro { padding-bottom: 0; }
    .about-intro .h-display,
    .about-intro .prose,
    .about-intro .prose strong { color: #000; }
    .about-intro .eyebrow,
    .about-intro .link-arrow { color: #000; }
}

/* ===================================================================
   ENTRANCE — the opening copy rising over the photograph on load
   -------------------------------------------------------------------
   Pure CSS keyframes, deliberately. The site-wide AOS pattern hides
   [data-aos] in CSS and reveals it in JS, which on this panel would put
   the whole introduction one failed request away from being invisible.
   A keyframe needs nothing but the stylesheet that declares it, so the
   worst case here is text that is simply already in place.

   The image animates SCALE ONLY, never opacity. It is the one element
   that may still be downloading when the animation fires, and a photo
   arriving after an opacity fade has finished would pop in. Arriving
   after a scale settle, it is already at scale 1 and nothing is seen.

   Two durations, not one: the type travels 14px and reads best brisk,
   while the photograph is a large surface where the same speed looks
   hurried. Easing matches awards.css so the two pages move alike.
   =================================================================== */

.about-intro {
    --ai-ease:       cubic-bezier(.22, 1, .36, 1);
    --ai-rise-dur:   620ms;
    --ai-settle-dur: 1600ms;
}

@keyframes ai-rise {
    from { opacity: 0; transform: translate3d(0, 14px, 0); }
    to   { opacity: 1; transform: none; }
}

/* Keeps the -55% bias from the base rule; a bare scale() would drop it
   and jerk the group out of frame for the length of the animation. */
@keyframes ai-settle {
    from { transform: translateY(-55%) scale(1.055); }
    to   { transform: translateY(-55%) scale(1); }
}

/* Below 992px the image is static and untransformed, so it needs the
   flat variant — see the media query. */
@keyframes ai-settle-flat {
    from { transform: scale(1.055); }
    to   { transform: none; }
}

.about-intro-media img {
    animation: ai-settle var(--ai-settle-dur) var(--ai-ease) both;
}

.about-intro-copy .eyebrow    { animation: ai-rise var(--ai-rise-dur) var(--ai-ease) 120ms both; }
.about-intro-copy .h-display  { animation: ai-rise var(--ai-rise-dur) var(--ai-ease) 210ms both; }
.about-intro-copy .prose      { animation: ai-rise var(--ai-rise-dur) var(--ai-ease) 310ms both; }
.about-intro-copy .link-arrow { animation: ai-rise var(--ai-rise-dur) var(--ai-ease) 410ms both; }

@media (max-width: 991.98px) {
    .about-intro-media img { animation-name: ai-settle-flat; }
}

/* site.css already collapses animation-duration globally under reduce;
   this is explicit so the intent survives any future edit to that rule. */
@media (prefers-reduced-motion: reduce) {
    .about-intro-media img,
    .about-intro-copy .eyebrow,
    .about-intro-copy .h-display,
    .about-intro-copy .prose,
    .about-intro-copy .link-arrow {
        animation: none !important;
        opacity: 1 !important;
    }
}
