/* CardGroup and Card
   Presentation driven by the settings resolved in _CardGroup_Base.cshtml and
   _Card_Base.cshtml. Each setting maps to a class on the group or the card. */

.cardgroup {
    margin-bottom: 2.5rem;
}

/* Header ------------------------------------------------------------------ */
.cardgroup__header {
    margin-bottom: 1.5rem;
}

.cardgroup--align-center .cardgroup__header,
.cardgroup--align-center .cardgroup__actions {
    text-align: center;
    justify-content: center;
}

/* The kicker above the section title. Small, spaced and upper case, which is
   how this line reads as a label rather than as the first line of the title. */
.cardgroup__eyebrow {
    margin-bottom: 0.5rem;
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.85;
}

.cardgroup__title {
    margin-bottom: 0.75rem;
    font-weight: 700;
    /* Scales with the viewport. The heading level setting changes the tag, not
       the size, so a group under a page title still looks like a section. */
    font-size: clamp(1.75rem, 3vw, 2.75rem);
}

.cardgroup__intro {
    max-width: 60ch;
    opacity: 0.9;
}

.cardgroup--align-center .cardgroup__intro {
    margin-inline: auto;
}

.cardgroup__intro > :last-child {
    margin-bottom: 0;
}

/* Layout ------------------------------------------------------------------
   Grid rather than flex: every cell takes an equal share whatever is in it,
   which is what makes a row of cards line up without measuring anything. */
.cardgroup__row {
    display: grid;
    grid-template-columns: repeat(var(--cardgroup-cols, 3), minmax(0, 1fr));
    gap: var(--cardgroup-gap, 1.5rem);
}

/* One across is what a feed uses to show a post at a time. Without this the
   row falls back to the three the variable defaults to, and a single card
   takes a third of the width. */
.cardgroup--cols-1 { --cardgroup-cols: 1; }
.cardgroup--cols-2 { --cardgroup-cols: 2; }
.cardgroup--cols-3 { --cardgroup-cols: 3; }
.cardgroup--cols-4 { --cardgroup-cols: 4; }

.cardgroup--gap-tight { --cardgroup-gap: 0.75rem; }
.cardgroup--gap-normal { --cardgroup-gap: 1.5rem; }
.cardgroup--gap-loose { --cardgroup-gap: 2.5rem; }

/* Four across is too many below a large screen, and any number is too many on
   a phone. Stepping down rather than letting the columns shrink keeps the
   words in a card readable. */
@media (max-width: 991.98px) {
    .cardgroup--cols-3 { --cardgroup-cols: 2; }
    .cardgroup--cols-4 { --cardgroup-cols: 2; }
    .cardgroup--cols-1 { --cardgroup-cols: 1; }
}

@media (max-width: 575.98px) {
    .cardgroup__row { --cardgroup-cols: 1; }
}

/* The cell exists for the layout and for the editor's controls. Stretching it
   is what lets a card fill the row's height. */
.cardgroup__cell {
    position: relative;
    display: flex;
}

.cardgroup--equal .card-item {
    width: 100%;
}

.cardgroup__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 1.5rem;
}

/* Carousel ---------------------------------------------------------------
   The shared rules are in carousel.css. Only what a row of cards needs on top
   of them is here. */

/* Dots sit under the cards rather than over them, because a card's own words
   run to the foot of it and there is nothing to overlay. */
.cardgroup .carousel-indicators.cardgroup__dots {
    position: static;
    margin: 1.25rem 0 0;
}

.cardgroup .carousel-indicators.cardgroup__dots [data-bs-target] {
    background-color: currentColor;
}

/* Bootstrap's controls sit over the slide, which here means over a card. Move
   them outside the cards so they do not cover the words. */
.cardgroup .carousel-control-prev,
.cardgroup .carousel-control-next {
    width: 2.5rem;
    filter: invert(0.5) grayscale(1);
}

.cardgroup .carousel-control-prev { left: -2.75rem; }
.cardgroup .carousel-control-next { right: -2.75rem; }

@media (max-width: 1199.98px) {
    .cardgroup .carousel-control-prev,
    .cardgroup .carousel-control-next {
        display: none;
    }
}

/* Arrows above the cards, which is where the live stories band puts them: a
   pair of squares at the top of the carousel, just right of the middle. They
   sit inside the section rather than outside it, so unlike the ones at the
   edges there is always room for them and they stay on at every width. */
.cardgroup--arrows-above .carousel-control-prev,
.cardgroup--arrows-above .carousel-control-next {
    display: flex;
    top: 0;
    bottom: auto;
    width: 2.5rem;
    height: 2.5rem;
}

/* Bootstrap writes the indicators before the slides, and the rule above makes
   them static, so they land in the flow above the cards rather than under
   them. That is survivable when the arrows are out at the sides, but here it
   puts a row of dashes in the same strip as the arrows. The pair already says
   there is more to see, so the dots come off with this placement. */
.cardgroup--arrows-above .cardgroup__dots {
    display: none;
}

/* The two offsets the original uses, measured from the middle of the band.
   Both are left offsets: the pair reads left to right like the words do. */
@media (min-width: 768px) {
    .cardgroup--arrows-above .carousel-control-prev {
        left: calc(50% + 35px);
        right: auto;
    }

    .cardgroup--arrows-above .carousel-control-next {
        left: calc(50% + 85px);
        right: auto;
    }
}

/* Narrower than that, the middle is where the words are, so the pair goes to
   the edges instead - again following the original. */
@media (max-width: 767.98px) {
    /* Stacked, the middle of the band is where the picture is, so the pair
       needs a strip of its own above the cards to sit in - which is the one
       case the original pads for too. */
    .cardgroup--arrows-above .carousel {
        padding-top: 3.5rem;
    }

    .cardgroup--arrows-above .carousel-control-prev {
        left: 0;
        right: auto;
    }

    .cardgroup--arrows-above .carousel-control-next {
        left: auto;
        right: 0;
    }
}

/* A solid square behind each chevron. Bootstrap's own icons are already white
   SVGs, so the grey filter that the plain arrows need has to come off here or
   the chevron greys out against the black. */
.cardgroup--arrowfill-solid .carousel-control-prev,
.cardgroup--arrowfill-solid .carousel-control-next {
    filter: none;
    opacity: 1;
    background-color: #000;
    transition: background-color 0.2s ease-in;
}

.cardgroup--arrowfill-solid .carousel-control-prev:hover,
.cardgroup--arrowfill-solid .carousel-control-next:hover,
.cardgroup--arrowfill-solid .carousel-control-prev:focus,
.cardgroup--arrowfill-solid .carousel-control-next:focus {
    opacity: 1;
    background-color: var(--bs-primary);
}

/* Bootstrap sizes its icon for a control that spans the whole slide. In a
   40px square it needs to come down to something a chevron's size. */
.cardgroup--arrowfill-solid .carousel-control-prev-icon,
.cardgroup--arrowfill-solid .carousel-control-next-icon {
    width: 1rem;
    height: 1rem;
}

/* A carousel item is a block, and a row inside one has to be told to fill it
   so equal height still works slide to slide. */
.cardgroup .carousel-item > .cardgroup__row {
    height: 100%;
}

/* Card -------------------------------------------------------------------- */
.card-item {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background-color: var(--bs-tertiary-bg, #f8f9fa);
    color: var(--bs-body-color);
}

.card-item--edges-rounded { border-radius: var(--bs-border-radius-xl, 0.5rem); }
.card-item--edges-square { border-radius: 0; }

.card-item--align-center { text-align: center; }

.card-item__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    padding: 1.25rem;
}

.card-item__eyebrow {
    margin-bottom: 0.35rem;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.85;
}

.card-item__title {
    margin-bottom: 0.5rem;
    font-size: 1.25rem;
    font-weight: 600;
}

.card-item__text {
    opacity: 0.92;
}

.card-item__text > :last-child {
    margin-bottom: 0;
}

/* Buttons sit at the foot of the card whatever the words above them do, so a
   row of cards has its calls to action on one line. */
.card-item__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: auto;
    padding-top: 1rem;
}

.card-item--align-center .card-item__actions {
    justify-content: center;
}

/* Stacked: picture above the words --------------------------------------- */
.card-item__media {
    overflow: hidden;
}

.card-item__media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card-item--ratio-16x9 .card-item__media img { aspect-ratio: 16 / 9; }
.card-item--ratio-4x3 .card-item__media img { aspect-ratio: 4 / 3; }
.card-item--ratio-1x1 .card-item__media img { aspect-ratio: 1 / 1; }

/* Overlay: words over the picture ----------------------------------------
   The picture and its scrim are their own layer so the scrim can darken the
   picture without touching the text on top of it. */
.card-item--overlaycard {
    min-height: 320px;
    background-color: #222;
}

.card-item__backdrop {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image: var(--card-image);
    background-repeat: no-repeat;
    background-size: cover;
}

.card-item--focal-center .card-item__backdrop { background-position: center center; }
.card-item--focal-top .card-item__backdrop { background-position: center top; }
.card-item--focal-bottom .card-item__backdrop { background-position: center bottom; }

/* Overlay strength, as a variable so the two shapes below can share it. */
.card-item--overlay-none { --card-scrim: 0; }
.card-item--overlay-light { --card-scrim: 0.25; }
.card-item--overlay-medium { --card-scrim: 0.45; }
.card-item--overlay-dark { --card-scrim: 0.65; }

.card-item__backdrop::after {
    content: "";
    position: absolute;
    inset: 0;
    background-color: rgba(0, 0, 0, var(--card-scrim, 0));
}

/* Heaviest where the words sit and clear at the top, so more of the picture
   shows through than an even scrim allows. */
.card-item--scrim-gradient .card-item__backdrop::after {
    background-color: transparent;
    background-image: linear-gradient(to top,
        rgba(0, 0, 0, var(--card-scrim, 0)) 0%,
        rgba(0, 0, 0, calc(var(--card-scrim, 0) * 0.55)) 45%,
        rgba(0, 0, 0, 0) 100%);
}

.card-item--overlaycard .card-item__body {
    position: relative;
    z-index: 1;
    /* The words sit at the foot of the picture, which is where the scrim is
       heaviest and where this pattern reads from. */
    justify-content: flex-end;
    padding: 2rem 1.25rem 1.25rem;
}

.card-item--text-light { color: #fff; }
.card-item--text-dark { color: var(--bs-body-color); }

/* Editing ----------------------------------------------------------------
   The control bar sits over the card, top right, the same corner it uses for
   a page's own items. */
.cardgroup__cell--editing {
    outline: 1px dashed rgba(128, 128, 128, 0.4);
    outline-offset: 2px;
}

.cardgroup__cell--editing .content-preview-control {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    z-index: 5;
    display: flex;
    gap: 0.25rem;
    padding: 0.25rem;
    border-radius: var(--bs-border-radius, 0.375rem);
    background-color: rgba(255, 255, 255, 0.9);
}

.cardgroup__add {
    margin-top: 1rem;
}

/* Styles ------------------------------------------------------------------
   The look, as opposed to the shape. Every rule below changes only how a card
   or a group is painted, never what the renderer emits, which is what keeps
   these a setting rather than a template. */

/* Card: outlined. No fill, so a row of these reads as a list rather than as
   blocks, which suits text heavy cards. */
.card-item--style-outlined {
    background-color: transparent;
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.35));
}

/* Card: lifted. The shadow does the separating, so the fill can go. */
.card-item--style-elevated {
    background-color: var(--bs-body-bg, #fff);
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.18);
}

/* Card: highlighted title. A solid block behind the words, the treatment that
   makes a heading read as a label on top of a photograph.

   fit-content rather than display:inline, because the title is a flex item of
   the card body and flex blockifies an inline child, so the box would run the
   full width and the effect would be lost. */
.card-item--style-highlight .card-item__title,
.card-item--style-darkHighlight .card-item__title,
.card-item--style-panelHighlight .card-item__title {
    width: fit-content;
    padding: 0.1em 0.4em;
    background-color: var(--bs-primary, #0d6efd);
    color: #fff;
}

/* Centred text wants the block centred with it. */
.card-item--style-highlight.card-item--align-center .card-item__title,
.card-item--style-darkHighlight.card-item--align-center .card-item__title,
.card-item--style-panelHighlight.card-item--align-center .card-item__title {
    margin-inline: auto;
}

/* Card: dark panel. The words on a dark ground rather than the light grey one,
   which is what makes a split card read as a panel beside a photograph instead
   of a caption under it.

   Two values rather than one, because the look this is for - the legacy site's
   project rows - is a dark panel *and* a highlighted title, and style is a
   single choice. A dark panel on its own is just as reasonable a thing to
   want, so both are offered.

   An overlay card is unaffected: its backdrop is positioned over the card, so
   the background underneath never shows. */
.card-item--style-dark,
.card-item--style-darkHighlight {
    background-color: rgba(var(--bs-dark-rgb, 33, 37, 41), 1);
    color: rgba(255, 255, 255, 0.85);
}

/* The heading and its kicker at full strength, the body a shade back - the
   same relationship the light panel already has, read the other way up. */
.card-item--style-dark .card-item__eyebrow,
.card-item--style-darkHighlight .card-item__eyebrow,
.card-item--style-dark .card-item__title,
.card-item--style-darkHighlight .card-item__title {
    color: #fff;
}

/* Card: a panel over the picture ------------------------------------------
   The legacy site's project rows: the photograph fills the card and the words
   sit in a translucent black panel over one half of it, so the picture still
   shows through behind them rather than being covered.

   A style rather than a template, because the overlay card already emits the
   picture as a layer behind the body - all that changes is what the body is
   painted and sized as.

   The panel brings its own darkening, so the card's Overlay setting should be
   None or the picture is dimmed twice. */
.card-item--overlaycard.card-item--style-panel .card-item__body,
.card-item--overlaycard.card-item--style-panelHighlight .card-item__body {
    width: 50%;
    /* Against the end edge, which is the right in a left-to-right page. */
    margin-inline-start: auto;
    /* The overlay card foots its words to the bottom, where a scrim is
       heaviest. A panel is its own ground, so they start at the top. */
    justify-content: flex-start;
    padding: 1.75rem;
    background-color: rgba(0, 0, 0, 0.7);
}

/* Solid, for when the picture behind the words is a distraction rather than
   the point. The panel still sits over a full-width picture, so the half of
   the card beside it shows the photograph uncropped by any panel. */
.card-item--overlaycard.card-item--panelfill-solid .card-item__body {
    background-color: rgba(var(--bs-dark-rgb, 33, 37, 41), 1);
}

/* Half a card is too little to read in on a phone, which is where the live
   site drops the same panel to the full width. */
@media (max-width: 575.98px) {
    .card-item--overlaycard.card-item--style-panel .card-item__body,
    .card-item--overlaycard.card-item--style-panelHighlight .card-item__body {
        width: 100%;
    }
}

/* The card takes the picture's shape -------------------------------------
   An overlay card is otherwise only as tall as its words need, which crops a
   full-width photograph to a letterbox. Given the picture's own shape it is
   as tall as the photograph wants to be - and a panel over half of a wide
   card needs that height to have anywhere to put the words.

   The minimum stays as a floor for a card whose words overflow the shape.
   Icon is left out on purpose: a picture that is the whole card has no small
   version to show. */
.card-item--overlaycard.card-item--ratio-16x9 { aspect-ratio: 16 / 9; }
.card-item--overlaycard.card-item--ratio-4x3 { aspect-ratio: 4 / 3; }
.card-item--overlaycard.card-item--ratio-1x1 { aspect-ratio: 1 / 1; }

/* The panel is always a dark ground whatever the picture behind it, so it
   carries its own text colours rather than leaving them to the textColor
   setting. On any other template there is no picture to sit over, so these
   read as a plain dark panel instead of breaking. */
.card-item--style-panel,
.card-item--style-panelHighlight {
    color: rgba(255, 255, 255, 0.85);
}

.card-item--style-panel .card-item__eyebrow,
.card-item--style-panelHighlight .card-item__eyebrow,
.card-item--style-panel .card-item__title,
.card-item--style-panelHighlight .card-item__title {
    color: #fff;
}

/* Away from an overlay card there is no picture, so the panel colours would
   be light text on the light grey ground. The dark ground comes with them. */
.card-item--style-panel:not(.card-item--overlaycard),
.card-item--style-panelHighlight:not(.card-item--overlaycard) {
    background-color: rgba(var(--bs-dark-rgb, 33, 37, 41), 1);
}

/* The renderer only swaps its button classes for a card whose words sit on a
   photograph, so a dark panel has to paint the quiet two itself. The main
   button is already primary and reads as it is. */
.card-item--style-dark .card-item__cta.btn-outline-secondary,
.card-item--style-darkHighlight .card-item__cta.btn-outline-secondary,
.card-item--style-panel .card-item__cta.btn-outline-secondary,
.card-item--style-panelHighlight .card-item__cta.btn-outline-secondary {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.5);
}

.card-item--style-dark .card-item__cta.btn-outline-secondary:hover,
.card-item--style-darkHighlight .card-item__cta.btn-outline-secondary:hover,
.card-item--style-panel .card-item__cta.btn-outline-secondary:hover,
.card-item--style-panelHighlight .card-item__cta.btn-outline-secondary:hover,
.card-item--style-dark .card-item__cta.btn-outline-secondary:focus,
.card-item--style-darkHighlight .card-item__cta.btn-outline-secondary:focus,
.card-item--style-panel .card-item__cta.btn-outline-secondary:focus,
.card-item--style-panelHighlight .card-item__cta.btn-outline-secondary:focus {
    color: rgba(var(--bs-dark-rgb, 33, 37, 41), 1);
    background-color: #fff;
    border-color: #fff;
}

.card-item--style-dark .card-item__cta.btn-link,
.card-item--style-darkHighlight .card-item__cta.btn-link,
.card-item--style-panel .card-item__cta.btn-link,
.card-item--style-panelHighlight .card-item__cta.btn-link {
    color: #fff;
}

/* Group: a rule under the heading, which separates a section from the one
   above it without adding a background. */
.cardgroup--style-ruled .cardgroup__header {
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.35));
}

/* Group: eyebrow beside a highlighted title, on one line. This is the section
   heading treatment the reference site uses, and it is built from the eyebrow
   and title fields that already exist rather than from any new markup.

   The header stays a block so its two children can go inline and flow onto one
   line. Wrapping them in a flex row instead would blockify them and split the
   line again. */
.cardgroup--style-banner .cardgroup__eyebrow,
.cardgroup--style-banner .cardgroup__title {
    display: inline;
    margin: 0;
    font-size: clamp(1.75rem, 3vw, 2.75rem);
    font-weight: 700;
    letter-spacing: normal;
    line-height: 1.45;
    text-transform: uppercase;
}

.cardgroup--style-banner .cardgroup__eyebrow {
    opacity: 1;
}

/* A space between the two, which the markup does not provide because they are
   separate elements. */
.cardgroup--style-banner .cardgroup__eyebrow::after {
    content: " ";
    white-space: pre;
}

/* Cloned so a title that wraps keeps the block on every line rather than one
   box stretched behind all of them. */
.cardgroup--style-banner .cardgroup__title {
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
    padding: 0.05em 0.35em;
    background-color: var(--bs-primary, #0d6efd);
    color: #fff;
}

.cardgroup--style-banner .cardgroup__intro {
    margin-top: 1.25rem;
}

/* Split: picture beside the words ----------------------------------------
   Added for the category feed, which offers it as a layout. The Card
   component's own SplitCard template will use the same classes. */
.card-item--split {
    flex-direction: row;
    align-items: stretch;
}

.card-item--split .card-item__media {
    flex: 1 1 50%;
    min-width: 0;
}

/* The picture fills its half rather than holding the ratio: the two columns
   have to end level, and the words decide how tall that is. */
.card-item--split .card-item__media img {
    height: 100%;
    aspect-ratio: auto;
}

.card-item--split .card-item__body {
    flex: 1 1 50%;
    align-self: center;
    min-width: 0;
}

/* Which side the picture sits on. The markup always writes the picture
   first, so left is the natural order and right is the reversal. */
.card-item--split.card-item--imageside-right {
    flex-direction: row-reverse;
}

/* Side by side needs room. Below md the two stack, picture first. */
@media (max-width: 767.98px) {
    .card-item--split,
    .card-item--split.card-item--imageside-right {
        flex-direction: column;
    }

    .card-item--split .card-item__media img {
        height: auto;
    }

    .card-item--split.card-item--ratio-16x9 .card-item__media img { aspect-ratio: 16 / 9; }
    .card-item--split.card-item--ratio-4x3 .card-item__media img { aspect-ratio: 4 / 3; }
    .card-item--split.card-item--ratio-1x1 .card-item__media img { aspect-ratio: 1 / 1; }
}

/* Icon: the whole picture, small, rather than a cropped frame -------------
   For logos and symbols, where a crop cuts the thing itself off. It sits on
   the card's own padding and follows the words' alignment. Written after the
   split rules so it wins over the picture filling its half. */
.card-item--ratio-icon .card-item__media {
    display: flex;
    justify-content: flex-start;
    padding: 1.25rem 1.25rem 0;
}

.card-item--align-center.card-item--ratio-icon .card-item__media {
    justify-content: center;
}

.card-item--ratio-icon .card-item__media img {
    width: auto;
    max-width: 100%;
    height: 5rem;
    aspect-ratio: auto;
    object-fit: contain;
}

/* Beside the words it takes only the room it needs, level with them. */
.card-item--split.card-item--ratio-icon .card-item__media {
    flex: 0 0 auto;
    align-items: center;
    padding: 1.25rem 0 1.25rem 1.25rem;
}

.card-item--split.card-item--imageside-right.card-item--ratio-icon .card-item__media {
    padding: 1.25rem 1.25rem 1.25rem 0;
}

@media (max-width: 767.98px) {
    .card-item--split.card-item--ratio-icon .card-item__media,
    .card-item--split.card-item--imageside-right.card-item--ratio-icon .card-item__media {
        padding: 1.25rem 1.25rem 0;
    }
}

/* A post title inside a feed is a link, and should not look like one until
   you reach for it. */
.card-item__title a {
    color: inherit;
    text-decoration: none;
}

.card-item__title a:hover,
.card-item__title a:focus-visible {
    text-decoration: underline;
}

/* Full bleed ---------------------------------------------------------------
   A row of cards is content, not a backdrop, so it keeps the site band when
   the page runs edge to edge. Every child of the section is banded rather than
   the section itself, which leaves the section free to carry a background that
   does reach the edges. The category feed shares these classes and so this
   behaviour. */
.page-full .cardgroup > * {
    max-width: var(--cms-band);
    margin-inline: auto;
    padding-inline: 0.75rem;
}

/* A band on a photograph ---------------------------------------------------
   The live site's stories band: the section carries a picture, a scrim
   darkens it, and the heading and cards sit over the top in light text.

   Shared by the feed and a hand built group, because both render the same
   .cardgroup markup - the only difference between them is where the cards
   come from.

   The picture is a content field rather than a setting, since it is a file
   somebody chooses. Everything painted over it is a setting. */

.cardgroup--has-bg {
    position: relative;
    /* Room for the picture to read as a band rather than a strip behind the
       words. The live one runs to 100px top and bottom. */
    padding-block: 4rem;
}

.cardgroup__backdrop {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image: var(--cardgroup-image);
    background-repeat: no-repeat;
    background-size: cover;
}

.cardgroup--focal-center .cardgroup__backdrop { background-position: center center; }
.cardgroup--focal-top .cardgroup__backdrop { background-position: center top; }
.cardgroup--focal-bottom .cardgroup__backdrop { background-position: center bottom; }

/* The same strengths the cards use, so a band and a card over a picture
   darken by the same amounts. */
.cardgroup--overlay-none { --cardgroup-scrim: 0; }
.cardgroup--overlay-light { --cardgroup-scrim: 0.25; }
.cardgroup--overlay-medium { --cardgroup-scrim: 0.45; }
.cardgroup--overlay-dark { --cardgroup-scrim: 0.65; }

.cardgroup__backdrop::after {
    content: "";
    position: absolute;
    inset: 0;
    background-color: rgba(0, 0, 0, var(--cardgroup-scrim, 0));
}

.cardgroup--scrim-gradient .cardgroup__backdrop::after {
    background-color: transparent;
    background-image: linear-gradient(to top,
        rgba(0, 0, 0, var(--cardgroup-scrim, 0)) 0%,
        rgba(0, 0, 0, calc(var(--cardgroup-scrim, 0) * 0.55)) 45%,
        rgba(0, 0, 0, 0) 100%);
}

/* Everything the section holds goes above the picture. The header and the row
   are the only children besides the backdrop. */
.cardgroup--has-bg > .cardgroup__header,
.cardgroup--has-bg > .cardgroup__row,
.cardgroup--has-bg > .cardgroup__actions,
.cardgroup--has-bg > .carousel {
    position: relative;
    z-index: 1;
}

/* The words, as opposed to the cards, which carry their own ground. */
.cardgroup--has-bg.cardgroup--text-light > .cardgroup__header { color: #fff; }
.cardgroup--has-bg.cardgroup--text-dark > .cardgroup__header { color: var(--bs-body-color); }

/* On a full bleed page every child of a group is already held to the site's
   band. The backdrop is the one child that must not be: it is the picture,
   and the picture runs to the edges while the words stay in the band. Without
   this it is clamped to 1320px like everything else and the band stops looking
   full bleed however wide the section itself measures. */
.page-full .cardgroup--has-bg > .cardgroup__backdrop {
    max-width: none;
    margin-inline: 0;
    padding-inline: 0;
}

/* Cards straight on the band, with no panel of their own. What the live
   stories band does: the posts are words over the photograph rather than
   boxes on top of it. The picture inside a card still shows. */
.cardgroup--has-bg.cardgroup--cards-bare .card-item {
    background-color: transparent;
}

.cardgroup--has-bg.cardgroup--cards-bare.cardgroup--text-light .card-item {
    color: #fff;
}

.cardgroup--has-bg.cardgroup--cards-bare .card-item__body {
    padding-inline: 0;
}

/* Slider ------------------------------------------------------------------
   One track the cards sit on, slid along a card at a time. The paged carousel
   chunks its cards into rows, so a set that does not divide by "cards across"
   strands the remainder on a page of its own - four across three leaves one
   card alone. Here there are no pages to be left on.

   It is a plain horizontal scroller, so touch, trackpad and keyboard move it
   with no script at all. js/cms/cardSlider.js only adds what a mouse needs. */
.cardgroup__slider {
    position: relative;
}

.cardgroup__track {
    display: flex;
    gap: var(--cardgroup-gap, 1.5rem);
    overflow-x: auto;
    scroll-snap-type: x mandatory;

    /* The cards carry the visible edge, so the bar underneath is noise. The
       arrows, the dots and the drag itself are what say it moves. */
    scrollbar-width: none;
}

.cardgroup__track::-webkit-scrollbar {
    display: none;
}

/* The one measurement in the whole feature: the same share of the row a grid
   cell would have taken, so a slider and a grid of the same width line up.
   Everything else reads its size back from the DOM. */
.cardgroup__track > .cardgroup__cell {
    flex: 0 0 calc(
        (100% - (var(--cardgroup-cols, 3) - 1) * var(--cardgroup-gap, 1.5rem))
        / var(--cardgroup-cols, 3)
    );
    scroll-snap-align: start;
}

/* A focused track scrolls with the arrow keys, so it needs to show that it
   has focus. */
.cardgroup__track:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 4px;
}

/* An arrow with nowhere to go stays in place rather than moving the row, so
   it says so instead of looking available. */
.cardgroup__slider .carousel-control-prev:disabled,
.cardgroup__slider .carousel-control-next:disabled {
    opacity: 0.15;
    cursor: default;
}

/* The dots are the carousel's, without Bootstrap's carousel to position them,
   so they are laid out here rather than inherited. */
.cardgroup__slide-dots {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

.cardgroup__slide-dots button {
    width: 2rem;
    height: 3px;
    padding: 0;
    border: 0;
    background-color: currentColor;
    opacity: 0.4;
}

.cardgroup__slide-dots button.active {
    opacity: 1;
}
