/* =============================================================================
   Page: home  (pages/home.php)
   -----------------------------------------------------------------------------
   Auto-loaded by app/layout.php because the file exists - nothing registers it.
   One block per section of the page, in the order the page renders them.
   ============================================================================= */


/* =============================================================================
   Section "Radiologie at it´s best"
   -----------------------------------------------------------------------------
   The page's opening headline, then a slider of four claims. One slide is a
   photograph on the left with a dark panel overlapping its right half, offset
   downwards - number top left, arrows top right, claim in the middle, dots and
   the link along the foot.

   Two states, and both have to work:

     no JavaScript   the four slides stack in the track's grid, each in the same
                     overlapping layout, the controls stay hidden
     .is-enhanced    assets/js/pages/home.js takes over: every slide moves into
                     the SAME grid cell, so the track is as tall as the tallest
                     one and the height never jumps, and the script cross-fades
                     between them

   Everything below the .is-enhanced selector belongs to the second state only -
   the rules above it must stand on their own.

   The geometry is four custom properties: how wide the panel is, how far below
   the image it starts, and its two paddings. The controls are placed from those
   same four numbers rather than from a second set, so the panel is described
   once and the arrows cannot drift away from it.
   ============================================================================= */

.intro {

    /* Shares of the wide container. Stacked below 1024px, overlapping above it -
       measured off the design: the panel covers about a third of the image. */
    --intro-media-width: 100%;
    --intro-panel-width: 100%;

    /* How far below the image's top edge the panel begins, and how far past its
       bottom edge it runs. Both zero while the two are stacked.

       The overhang is carried by the image's own bottom margin, not by a height
       on the panel: the panel is stretched to the row, and the row is as tall as
       the image plus that margin, so the panel ends up exactly this far below
       the photograph without anything having to be measured. */
    --intro-panel-offset: 0px;
    --intro-panel-overhang: 0px;

    --intro-panel-pad-inline: var(--space-md);
    --intro-panel-pad-block: var(--space-lg);

    /* The design crops the photograph to 3:2 - which is what the placeholder
       already is, but the ones that replace it will not be. */
    --intro-ratio: 3 / 2;

    /* The big number is larger than --font-size-h1 ever gets (56px), so it
       cannot come from a token: 36 -> 88px. */
    --intro-number-size: clamp(2.25rem, 1.1rem + 5vw, 5.5rem);

    /* Controls sit on the page below 1024px and inside the dark panel above it,
       so they cannot have one fixed colour. */
    --intro-control: var(--color-primary);
    --intro-control-dim: var(--color-line);

    /* A slide change is a dissolve, far longer than any hover - the shared
       transition tokens are all shorter. DURATION in assets/js/pages/home.js
       repeats this number; the two have to be changed together. */
    --intro-duration: 700ms;
    --intro-ease: cubic-bezier(0.22, 1, 0.36, 1);

    /* How far the text of an arriving slide travels. */
    --intro-lead: var(--space-lg);

    /* 1 forward, -1 back. Set on the slider by the script before each change,
       so the leaving slide and the arriving one never travel the same way. */
    --intro-dir: 1;
}

@media (min-width: 768px) {
    .intro {
        --intro-panel-pad-inline: var(--space-xl);
        --intro-panel-pad-block: var(--space-xl);
    }
}

@media (min-width: 1024px) {
    .intro {
        --intro-media-width: 62%;
        --intro-panel-width: 57%;
        --intro-panel-offset: var(--space-2xl);
        --intro-panel-overhang: var(--space-3xl);
        --intro-panel-pad-inline: clamp(var(--space-xl), 5vw, var(--space-3xl));
        --intro-panel-pad-block: var(--space-3xl);

        --intro-control: var(--color-text-inverse);
        --intro-control-dim: rgba(var(--rgb-white), 0.35);
    }
}

/* --- Head ------------------------------------------------------------------
   Headline, rule and the two columns are the shared .section-head - see
   base/components.css. The headline is short, so the text column takes about
   half the row, which is where the design puts the rule.
   -------------------------------------------------------------------------- */

@media (min-width: 1024px) {
    .intro__head {
        --section-head-aside: 38rem;
    }
}

/* The slider is anchored to the wide container while the head keeps the default
   one, so the photograph starts outside the headline - as in the design. */
.intro__stage {
    margin-block-start: var(--space-3xl);
}

/* --- Slider ----------------------------------------------------------------- */

.intro__slider {
    position: relative;
}

.intro__track {
    display: grid;
    gap: var(--space-3xl);
}

/* --- Slide: image and panel -------------------------------------------------
   Below 1024px two rows, above it one cell the two share: the image pinned to
   the left and kept at its own height, the panel pinned to the right, pushed
   down by --intro-panel-offset and stretched to the foot of the row. The row is
   as tall as the image plus its bottom margin, so that margin is what the panel
   overhangs the photograph by.
   -------------------------------------------------------------------------- */

.intro__slide {
    display: grid;
}

.intro__media {
    width: var(--intro-media-width);
    margin-block-end: var(--intro-panel-overhang);
}

.intro__image {
    display: block;
    width: 100%;
    aspect-ratio: var(--intro-ratio);
    object-fit: cover;
}

.intro__panel {
    position: relative;
    z-index: 1;   /* over the image, which comes first */
    display: flex;
    flex-direction: column;
    padding: var(--intro-panel-pad-block) var(--intro-panel-pad-inline);
    background-color: var(--color-surface-invert);
    color: var(--color-text-inverse);
}

@media (min-width: 1024px) {
    .intro__slide > * {
        grid-area: 1 / 1;
    }

    .intro__media {
        align-self: start;
        justify-self: start;
    }

    .intro__panel {
        justify-self: end;
        width: var(--intro-panel-width);
        margin-block-start: var(--intro-panel-offset);
    }

    /* The soft light that bleeds out of the panel's lower left corner in the
       design, over the part that overhangs the image. Decorative, so it is a
       pseudo-element and never in the markup. */
    .intro__panel::before {
        content: '';
        position: absolute;
        inset-block: 55% 0;
        inset-inline-end: 100%;
        width: var(--space-3xl);
        background-image: linear-gradient(to left,
                          rgba(var(--rgb-blue-light), 0.22),
                          rgba(var(--rgb-blue-light), 0));
        pointer-events: none;
    }
}

/* --- Panel content ----------------------------------------------------------
   Number at the top, claim in the middle, foot at the bottom: the two `auto`
   margins split whatever height is left over between them, so the three sit
   where the design has them at any panel height.
   -------------------------------------------------------------------------- */

.intro__number {
    margin: 0;
    font-size: var(--intro-number-size);
    font-weight: var(--font-weight-bold);
    line-height: 1;
    letter-spacing: var(--letter-spacing-tight);
}

.intro__title {
    max-width: 26rem;
    margin: 0;
    margin-block-start: auto;
    padding-block-start: var(--space-lg);
    color: var(--color-text-inverse);
    font-size: var(--font-size-h3);
    font-weight: var(--font-weight-bold);
    line-height: var(--line-height-heading);
}

/* Rendered on every slide, with or without a link: it is what holds the foot of
   each panel at the same height, and from 1024px up it is also the row the dots
   are laid over. */
.intro__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    min-height: 44px;
    margin-block-start: auto;
    padding-block-start: var(--space-lg);
}

/* The padding is what makes this a 44px touch target; --link-underline-inset
   puts the animated rule back under the text - see base/components.css. */
.intro__more {
    --link-underline-inset: var(--space-xs);

    padding-block: var(--space-xs);
    color: rgba(var(--rgb-white), 0.75);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    transition: color var(--transition-base);
}

.intro__more:hover,
.intro__more:focus-visible {
    color: var(--color-text-inverse);
}

/* --- Controls ---------------------------------------------------------------
   One element holding both groups, so a single [hidden] covers all of them.
   Below 1024px it is a bar under the slider - dots left, arrows right. From
   1024px up it becomes an exact copy of the panel's box (same width, same top
   offset, same padding, and the panel is what sets the foot of the slider), and
   the two groups take their corners inside it.
   -------------------------------------------------------------------------- */

.intro__controls {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin-block-start: var(--space-md);
    padding-inline: var(--intro-panel-pad-inline);
}

/* JavaScript removes the attribute; until then there is no dead control. */
.intro__controls[hidden] {
    display: none;
}

@media (min-width: 1024px) {
    .intro__controls {
        position: absolute;

        /* Over the active slide, which raises itself to 1 so that it covers the
           one it replaced. */
        z-index: 2;
        inset-block: var(--intro-panel-offset) 0;
        inset-inline-end: 0;
        width: var(--intro-panel-width);
        margin-block-start: 0;
        padding: var(--intro-panel-pad-block) var(--intro-panel-pad-inline);

        /* The copy covers the panel, so only the two groups inside it may take
           a pointer - everything else has to reach the panel below. */
        pointer-events: none;
    }

    .intro__dots,
    .intro__arrows {
        position: absolute;
    }

    .intro__dots {
        inset-block-end: var(--intro-panel-pad-block);
        inset-inline-start: var(--intro-panel-pad-inline);
    }

    .intro__arrows {
        inset-block-start: var(--intro-panel-pad-block);
        inset-inline-end: var(--intro-panel-pad-inline);
    }
}

/* --- Dots ------------------------------------------------------------------- */

.intro__dots {
    display: flex;
    align-items: center;
}

.intro__dot {
    display: flex;
    align-items: center;
    justify-content: center;

    /* The mark is 8px; the button around it is the 44px touch target. */
    width: var(--space-md);
    height: 44px;
    padding: 0;
    pointer-events: auto;
}

.intro__dot-mark {
    display: block;
    width: var(--space-2xs);
    height: var(--space-2xs);
    border-radius: var(--radius-pill);
    background-color: var(--intro-control-dim);
    transition: background-color var(--transition-base), transform var(--transition-base);
}

.intro__dot:hover .intro__dot-mark,
.intro__dot:focus-visible .intro__dot-mark {
    background-color: var(--intro-control);
}

.intro__dot[aria-current='true'] .intro__dot-mark {
    background-color: var(--color-accent);
    transform: scale(1.6);
}

/* --- Arrows ----------------------------------------------------------------- */

.intro__arrows {
    display: flex;
    align-items: center;
    gap: var(--space-2xs);
}

.intro__arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    color: var(--intro-control);
    pointer-events: auto;
    transition: color var(--transition-fast);
}

.intro__arrow:hover,
.intro__arrow:focus-visible {
    color: var(--color-accent);
}

.intro__chevron {
    width: auto;
    height: var(--space-md);
    transition: transform var(--transition-base);
}

.intro__arrow[data-intro-prev]:hover .intro__chevron {
    transform: translateX(calc(var(--space-3xs) * -1));
}

.intro__arrow[data-intro-next]:hover .intro__chevron {
    transform: translateX(var(--space-3xs));
}

/* --- Enhanced state ----------------------------------------------------------
   Set by assets/js/pages/home.js once it has taken control. Every slide moves
   into the same grid cell; which one is seen is a class, not a position, so
   nothing is ever measured.

   Three states per slide, and the direction of travel comes from --intro-dir:

     (neither)     waiting off screen, on the side the movement comes from
     .is-active    arrived: number, claim and foot land 70ms apart
     .is-leaving   going the other way, so the two never travel together

   Only opacity and transform, both of which stay on the compositor. The global
   reduced-motion rule in base/reset.css already flattens the whole thing to an
   instant swap.
   -------------------------------------------------------------------------- */

.intro__slider.is-enhanced .intro__track {
    gap: 0;
}

.intro__slider.is-enhanced .intro__slide {
    grid-area: 1 / 1;

    /* Taken out of the page entirely, so a transparent slide can neither be
       read nor clicked. The one that is leaving keeps its visibility until the
       script drops .is-leaving, which it does once the fade is over - hence no
       transition here: the class is the timer. */
    visibility: hidden;
}

.intro__slider.is-enhanced .intro__slide.is-active {
    z-index: 1;   /* over the slide it is replacing */
    visibility: visible;
}

.intro__slider.is-enhanced .intro__slide.is-leaving {
    visibility: visible;
}

.intro__slider.is-enhanced :is(.intro__image, .intro__number, .intro__title, .intro__foot) {
    opacity: 0;
    transition: opacity var(--intro-duration) var(--intro-ease),
                transform var(--intro-duration) var(--intro-ease);
}

.intro__slider.is-enhanced .intro__image {
    transform: scale(1.05) translateX(calc(var(--intro-dir) * 2%));
}

.intro__slider.is-enhanced :is(.intro__number, .intro__title, .intro__foot) {
    transform: translateX(calc(var(--intro-dir) * var(--intro-lead)));
}

.intro__slider.is-enhanced .intro__slide.is-active :is(.intro__image, .intro__number, .intro__title, .intro__foot) {
    opacity: 1;
    transform: none;
}

.intro__slider.is-enhanced .intro__slide.is-active .intro__title {
    transition-delay: 70ms;
}

.intro__slider.is-enhanced .intro__slide.is-active .intro__foot {
    transition-delay: 140ms;
}

.intro__slider.is-enhanced .intro__slide.is-leaving .intro__image {
    transform: scale(0.98) translateX(calc(var(--intro-dir) * -2%));
}

.intro__slider.is-enhanced .intro__slide.is-leaving :is(.intro__number, .intro__title, .intro__foot) {
    transform: translateX(calc(var(--intro-dir) * -1 * var(--intro-lead)));
}


/* =============================================================================
   Section "High-Tech Ausstattung"
   -----------------------------------------------------------------------------
   The headline and its intro are the shared .section-head (base/components.css);
   below them the machines, three columns of a name and its short form, each
   under a blue rule.

   That rule is two layers, because a gradient cannot be transitioned: a static
   one that fades out towards the right, and a solid one over it that draws
   itself in from the left when the item is hovered - the same movement as
   .link-underline, so a filling rule means the same thing everywhere on the
   site.
   ============================================================================= */

/* The aside here is a paragraph, not the caption the default column is sized
   for, so it takes about half the row - which is where the design puts the
   rule. Only from 1024px up: narrower than that the headline needs the space
   more than the paragraph does. */
@media (min-width: 1024px) {
    .ausstattung__head {
        --section-head-aside: 38rem;
    }
}

/* Two classes: base/reset.css zeroes the margin of every ul[class], and an
   element plus an attribute outweighs a single class no matter which file comes
   last - the same reason .aerzte .aerzte__track is written that way. */
.ausstattung .ausstattung__list {
    display: grid;
    gap: var(--space-xl);
    margin-block-start: var(--space-3xl);
}

@media (min-width: 480px) {
    .ausstattung .ausstattung__list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--space-xl) var(--space-2xl);
    }
}

@media (min-width: 1024px) {
    .ausstattung .ausstattung__list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: var(--space-2xl) var(--space-3xl);
    }
}

.ausstattung__item {
    position: relative;
    padding-block-start: var(--space-sm);
}

/* 2px, like the rule beside a doctor's name: at --border-width the line
   disappears next to the type above it. */
.ausstattung__item::before,
.ausstattung__item::after {
    content: '';
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    height: 2px;
}

.ausstattung__item::before {
    background-image: linear-gradient(to right,
                      var(--color-accent),
                      rgba(var(--rgb-blue-light), 0.25));
}

.ausstattung__item::after {
    background-color: var(--color-accent);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--transition-base);
}

/* :focus-within as well: nothing inside an item is focusable today, but the day
   a name becomes a link the keyboard gets the same answer as the pointer. */
.ausstattung__item:hover::after,
.ausstattung__item:focus-within::after {
    transform: scaleX(1);
}

.ausstattung__name,
.ausstattung__note {
    display: block;
    font-size: var(--font-size-sm);
}

/* Upper case in CSS, not in the markup, so screen readers still get the name as
   it is written. */
.ausstattung__name {
    font-weight: var(--font-weight-bold);
    text-transform: uppercase;
}


/* =============================================================================
   Section "Unsere Technik"
   -----------------------------------------------------------------------------
   A feature card for the 3-Tesla MRT, then the AI text beside a video still,
   both on a blue backdrop that starts part way down the card so the card
   overlaps the light page above it.

   The backdrop is .technik__band, an element rather than a background on the
   section: it has to start below the section's top edge, and the glow on its
   left edge has to be hoverable, which only an element can be.

   The claim over the feature image slides up the first time the section is
   seen. Like the row below it that is a second state - everything under
   .is-enhanced belongs to assets/js/pages/home.js, and without the script the
   claim is simply there.
   ============================================================================= */

.technik {

    /* How far below the section's top edge the blue band begins. Above it the
       feature card sits on the light page - the overlap in the design. */
    --technik-band-offset: clamp(2.5rem, 5vw, 7rem);

    /* Reach of the glow along the left edge. It is painted behind the content,
       so only the strip beside the container is ever hovered. The gradient
       fades out well before this width, so the value is roughly half again as
       wide as the light the design shows. */
    --technik-glow-width: min(22rem, 30%);

    /* The design crops the photograph far wider than its own 3:2. */
    --technik-ratio: 4 / 3;

    /* Both text columns are narrower than --measure would allow: the design
       sets them against the images, not against a page of running text. */
    --technik-measure: 34rem;

    position: relative;
}

@media (min-width: 768px) {
    .technik {
        --technik-ratio: 16 / 9;
    }
}

/* --- Backdrop ---------------------------------------------------------------- */

.technik__band {
    position: absolute;

    /* .section supplies the top padding, so the offset is measured from the top
       of the feature card. The band runs from there to the end of the section. */
    inset-block: calc(var(--space-section) + var(--technik-band-offset)) 0;
    inset-inline: 0;
    background-color: var(--color-surface-invert);
    pointer-events: none;
}

.technik__glow {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--technik-glow-width);
    background-image: linear-gradient(to right,
                      rgba(var(--rgb-blue-light), 0.30),
                      rgba(var(--rgb-blue-light), 0));
    opacity: 0.75;

    /* Grows to the right on hover, so the light reads as coming from the edge.
       Scale and opacity only - both stay on the compositor, and the global
       reduced-motion rule in base/reset.css already stops them. */
    transform-origin: left center;
    transition: opacity var(--transition-slow), transform var(--transition-slow);

    /* The one part of the backdrop that answers the pointer. */
    pointer-events: auto;
}

.technik__glow:hover {
    opacity: 1;
    transform: scaleX(1.12);
}

/* --- Content -----------------------------------------------------------------
   The container spans the full width and would otherwise sit between the
   pointer and the glow, so it passes pointers through and the two blocks
   inside it take them back. Everything around them - the gutters, the gap
   between the blocks - reaches the glow.
   -------------------------------------------------------------------------- */

.technik__inner {
    position: relative;   /* paints over the band, which comes first */
    z-index: 1;
    pointer-events: none;
}

.technik__feature,
.technik__split {
    pointer-events: auto;
}

/* --- Feature card ------------------------------------------------------------ */

.technik__feature {
    position: relative;
}

.technik__stage {
    position: relative;
}

.technik__image {
    display: block;
    width: 100%;
    aspect-ratio: var(--technik-ratio);
    object-fit: cover;
}

/* The placeholder is dark at the bottom, but the photograph that replaces it
   may not be, and the body block over it has to stay readable. */
.technik__stage::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: linear-gradient(to top,
                      rgba(var(--rgb-black), 0.55),
                      rgba(var(--rgb-black), 0) 70%);
    pointer-events: none;
}

.technik__claim {
    position: absolute;
    z-index: 1;   /* over the scrim */
    inset-block-start: 46%;
    inset-inline: var(--space-md);
    margin: 0;
    color: var(--color-text-inverse);
    font-size: var(--font-size-h3);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--letter-spacing-wide);
    text-align: center;
    text-transform: uppercase;
    text-shadow: 0 1px 12px rgba(var(--rgb-black), 0.45);
}

/* Below 1024px this block follows the image, on the band. From there up it
   moves into the card's bottom left corner, where the design has it. */
.technik__feature-body {
    padding-block-start: var(--space-lg);
    color: var(--color-text-inverse);
}

@media (min-width: 1024px) {
    .technik__feature-body {
        position: absolute;
        inset-block-end: var(--space-2xl);
        inset-inline-start: var(--space-2xl);
        padding-block-start: 0;
    }
}

.technik__feature-title {
    margin: 0;
    color: var(--color-text-inverse);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-bold);
    letter-spacing: var(--letter-spacing-wide);
}

.technik__feature-text {
    max-width: var(--technik-measure);
    margin-block: var(--space-md) 0;
    font-size: var(--font-size-sm);
}

/* --- MRT + KI ---------------------------------------------------------------- */

.technik__split {
    display: grid;
    gap: var(--space-xl);
    margin-block-start: var(--space-2xl);
    color: var(--color-text-inverse);
}

@media (min-width: 1024px) {
    .technik__split {
        grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);

        /* The text sits at the foot of the still, not beside its middle. */
        align-items: end;
        gap: var(--space-3xl);
        margin-block-start: var(--space-3xl);
    }
}

.technik__intro-title {
    margin: 0;
    color: var(--color-text-inverse);
    font-size: var(--font-size-h3);
    font-weight: var(--font-weight-bold);
    line-height: var(--line-height-heading);
}

.technik__intro-accent {
    color: var(--color-accent);
}

.technik__intro-text {
    max-width: var(--technik-measure);
    margin-block: var(--space-md) 0;
}

/* The padding is what makes this a 44px touch target; --link-underline-inset
   puts the animated rule back under the text - see base/components.css. */
.technik__more {
    --link-underline-inset: var(--space-xs);

    margin-block-start: var(--space-lg);
    padding-block: var(--space-xs);
    color: var(--color-accent);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
}

.technik__video {
    position: relative;
    margin: 0;
}

.technik__video-image {
    display: block;
    width: 100%;
    height: auto;
}

/* --- Information and Play ----------------------------------------------------
   Play is a <span>: there is no video yet, so it is decorative and must not
   answer a hover. The states are therefore bound to [href], not to the class.
   -------------------------------------------------------------------------- */

.technik__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    margin-block-start: var(--space-lg);
    padding: var(--space-2xs) var(--space-lg);
    border: var(--border-width) solid var(--color-accent);
    border-radius: var(--radius-pill);
    background-color: var(--color-black);
    box-shadow: 0 0 var(--space-sm) rgba(var(--rgb-blue-light), 0.55);
    color: var(--color-text-inverse);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    transition: background-color var(--transition-base), box-shadow var(--transition-base),
                color var(--transition-base);
}

.technik__action[href]:hover,
.technik__action[href]:focus-visible {
    background-color: var(--color-accent);
    box-shadow: 0 0 var(--space-lg) rgba(var(--rgb-blue-light), 0.75);
    color: var(--color-blue);
}

.technik__action--play {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    margin-block-start: 0;
    transform: translate(-50%, -50%);
}

/* --- Intro -------------------------------------------------------------------
   The claim slides up the first time the section is on screen, once. The CSS
   does the movement; assets/js/pages/home.js only decides when.
   -------------------------------------------------------------------------- */

.technik.is-enhanced .technik__claim {
    opacity: 0;
    transform: translate3d(0, var(--space-lg), 0);
    transition: opacity var(--transition-slow), transform var(--transition-slow);
}

.technik.is-revealed .technik__claim {
    opacity: 1;
    transform: none;
}


/* =============================================================================
   Section "Unsere Ärzte"
   -----------------------------------------------------------------------------
   A full-bleed row of portraits that is dragged sideways. Two states, and both
   have to work:

     no JavaScript   .aerzte__viewport scrolls natively (overflow-x +
                     scroll-snap), the dots stay hidden
     .is-enhanced    assets/js/pages/home.js takes over: the track is moved with
                     transform, the dots appear and the cards fly in once

   Everything under .is-enhanced belongs to the second state only - the rules
   above it must stand on their own.
   ============================================================================= */

.aerzte {

    /* One "step" is a card plus the gap after it. --aerzte-per-view is how many
       steps fit in the space left of the lead, so it is the only number the
       breakpoints have to change. Fractional on purpose: the cut-off card at
       the right edge is what says the row continues. */
    --aerzte-per-view: 1.15;
    --aerzte-gap: var(--space-md);

    /* Empty space before the first card. From 1024px up this is the room the
       headline sits in - the first card overlaps its right half, as designed. */
    --aerzte-lead: var(--container-padding);

    /* A drag settling into place is a longer movement than a hover; the shared
       transition tokens are all far shorter than this. */
    --aerzte-duration: 520ms;

    overflow: hidden;
}

@media (min-width: 480px) {
    .aerzte {
        --aerzte-per-view: 1.4;
    }
}

@media (min-width: 768px) {
    .aerzte {
        --aerzte-per-view: 1.8;
        --aerzte-gap: var(--space-lg);
    }
}

@media (min-width: 1024px) {
    .aerzte {
        --aerzte-per-view: 2.2;
        --aerzte-gap: var(--space-2xl);

        /* The lead is measured from the container's own left edge, not as a
           share of the window. The headline is anchored to the 1300px
           container, which stops growing while the window does not - a
           percentage would overtake it on a wide screen and swallow the
           headline whole. This way the first card starts --aerzte-overlap into
           the headline at every width. */
        --aerzte-gutter: max(var(--container-padding), calc((100% - var(--width-default)) / 2));
        --aerzte-overlap: 10rem;
        --aerzte-lead: calc(var(--aerzte-gutter) + var(--aerzte-overlap));
    }
}

/* --- Head ------------------------------------------------------------------- */

.aerzte__eyebrow {
    margin-block-end: var(--space-2xl);
    padding-inline: var(--container-padding);
    color: var(--color-accent);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wide);
    text-align: center;
    text-transform: uppercase;
}

.aerzte__stage {
    position: relative;
}

/* Type and colour come from .section-title (base/components.css); this is only
   where the headline sits. */
.aerzte__title {
    margin-block-end: var(--space-lg);
    padding-inline: var(--container-padding);
}

/* From 1024px the headline moves behind the row: it is pinned to the left of
   the stage and the first card, which starts at --aerzte-lead, covers its right
   half. pointer-events: none so the text never swallows a drag that starts on
   it. Below this width the headline keeps its own row - on a phone the card
   would hide it completely. */
@media (min-width: 1024px) {
    .aerzte__title {
        position: absolute;
        inset-block-start: var(--space-lg);
        inset-inline: 0;
        width: 100%;
        max-width: var(--width-default);
        margin-block-end: 0;
        margin-inline: auto;
        pointer-events: none;
    }
}

/* --- Viewport and track ------------------------------------------------------
   The row is full-bleed: it runs off the right edge of the window, so it lives
   outside .container. The lead and the trailing gutter are padding on the track
   itself, which means the item widths - percentages of the track's content box -
   already exclude them.
   -------------------------------------------------------------------------- */

.aerzte__viewport {
    position: relative;   /* paints over the headline, which comes first */
    z-index: 1;

    /* Without JavaScript this is the whole interaction: a scrollable,
       swipeable row. .is-enhanced turns it off again. */
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;

    /* The lead is padding on the track, so a snap area that ignored it would
       align the first card with the window edge - the browser would scroll the
       lead away by itself, on load, before the script has switched snapping
       off. Insetting the snapport by the same amount keeps the first card where
       the headline needs it, in both states. */
    scroll-padding-inline-start: var(--aerzte-lead);
}

.aerzte__track {
    display: flex;
    align-items: flex-start;
    gap: var(--aerzte-gap);
}

/* Two classes on purpose. base/reset.css zeroes the padding of every ul[class],
   and an element plus an attribute outweighs a single class no matter which
   file comes last - the same reason .aerzte__pagination is written that way. */
.aerzte .aerzte__track {
    padding-inline: var(--aerzte-lead) var(--container-padding);
}

.aerzte__item {
    flex: 0 0 calc(100% / var(--aerzte-per-view) - var(--aerzte-gap));

    /* Past roughly 1500px the proportional width would make a card taller than
       most windows. The cap lets the extra width become extra cards instead. */
    max-width: 32rem;
    scroll-snap-align: start;
}

/* --- Card ------------------------------------------------------------------- */

/* The card itself is a module - assets/css/modules/arzt.css - because the grid
   on /praxis/aerzteteam shows the same one. What is left here is what belongs
   to THIS ROW and would be wrong in that grid.

   The opacity is on the whole card, not on the image inside it: the card's own
   surface has to be see-through as well, or it would hide the headline behind
   it. Hovering one card makes that card solid and the headline disappears
   behind it - which is the point, the person comes forward. */
.aerzte .arzt {
    opacity: 0.82;
    transition: opacity var(--transition-base);
}

.aerzte .arzt:hover,
.aerzte .arzt:focus-within {
    opacity: 1;
}

/* The image is the drag surface, so the browser's own image dragging has to be
   off - see [draggable] in the markup for the other half of it. */
.aerzte .arzt__image {
    user-select: none;
    -webkit-user-select: none;
    -webkit-user-drag: none;
}

/* --- Pagination --------------------------------------------------------------
   One dot per person. Revealed by the script, because without it the row is
   scrolled natively and the dots would have nothing to drive.
   -------------------------------------------------------------------------- */

/* Two classes: see the note on .aerzte .aerzte__track above. */
.aerzte .aerzte__pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-block-start: var(--space-lg);
}

.aerzte__pagination[hidden] {
    display: none;
}

.aerzte__dot {
    display: flex;
    align-items: center;
    justify-content: center;

    /* The mark is 8px; the button around it is the 44px touch target. */
    width: var(--space-md);
    height: 44px;
    padding: 0;
}

.aerzte__dot-mark {
    display: block;
    width: var(--space-2xs);
    height: var(--space-2xs);
    border-radius: var(--radius-pill);
    background-color: var(--color-line);
    transition: background-color var(--transition-base), transform var(--transition-base);
}

.aerzte__dot:hover .aerzte__dot-mark,
.aerzte__dot:focus-visible .aerzte__dot-mark {
    background-color: var(--color-primary);
}

.aerzte__dot[aria-current='true'] .aerzte__dot-mark {
    background-color: var(--color-accent);
    transform: scale(1.6);
}

/* --- Enhanced state ----------------------------------------------------------
   Set by assets/js/pages/home.js once it has taken control of the row.
   -------------------------------------------------------------------------- */

.aerzte.is-enhanced .aerzte__viewport {
    overflow: hidden;
    scroll-snap-type: none;
    cursor: grab;

    /* Horizontal movement is ours, vertical stays the page's - without this the
       browser would claim the gesture and scrolling past the row on a phone
       would be a fight. */
    touch-action: pan-y;
}

.aerzte.is-enhanced .aerzte__viewport.is-dragging {
    cursor: grabbing;
}

/* No transition by default: during a drag the track has to follow the pointer
   exactly. The script switches it on only for the movement after release and
   for a jump from the dots. */
.aerzte.is-enhanced .aerzte__track {
    will-change: transform;
}

.aerzte.is-enhanced .aerzte__track.is-settling {
    transition: transform var(--aerzte-duration) cubic-bezier(0.22, 1, 0.36, 1);
}

/* Nothing is selectable while dragging, or the pointer would paint a selection
   across the names instead of moving the row. */
.aerzte.is-enhanced .aerzte__viewport.is-dragging {
    user-select: none;
    -webkit-user-select: none;
}

/* --- Intro -------------------------------------------------------------------
   The cards fly in from the right, once, the first time the row is on screen -
   the direction the row is dragged back from, so the movement reads as the row
   arriving rather than rewinding. It animates the ITEMS; the drag animates the
   TRACK - two different elements, so the two transforms never fight. --i is set
   per item in the markup.
   -------------------------------------------------------------------------- */

.aerzte.is-enhanced .aerzte__item {
    opacity: 0;
    transform: translate3d(45vw, var(--space-md), 0);
    transition: opacity 600ms ease,
                transform 900ms cubic-bezier(0.16, 1, 0.3, 1);
    transition-delay: calc(var(--i, 0) * 70ms);
}

.aerzte.is-revealed .aerzte__item {
    opacity: 1;
    transform: none;
}
