/* =============================================================================
   Module: diagnostik  (modules/diagnostik.php)
   -----------------------------------------------------------------------------
   The grid of fields of diagnostics: a dark square per field with its letter
   mark on it and two label lines underneath.

   A tile has one state and it is the pointer's. Nothing is marked active: the
   page a visitor is on is left OUT of the row rather than highlighted in it,
   and a tile lit at rest would claim a "you are here" that is not true.

   THE HOVER IS TWO MOVEMENTS, played just out of step so the tile reads as one
   gesture rather than as two properties changing at once:

     the square   ::before is the resting light along the left edge, the same
                  gradient as .technik__glow on the home page. It cannot be
                  transitioned, so .diagnostik__fill is a second, solid layer
                  over it that wipes across from the left - the same movement as
                  .link-underline, .button--quiet and the rule over an
                  .ausstattung__item, so a thing filling from the left means the
                  same everywhere on the site. What you see is the light growing
                  until it has taken the whole tile.

     the letter   two files, not one restyled: rpu_x.svg is the blue outline,
                  rpu_x_aktiv.svg the black filled letter, and CSS cannot reach
                  into either to recolour it. Both are stacked in the same place
                  and the hover crosses them over - the outline leaves upwards
                  while the filled letter rises into its place behind it, so the
                  swap has a direction instead of being a dissolve.

   The letter is held back by --diagnostik-glyph-delay, which is roughly as long
   as the wipe takes to clear it. The mark therefore lands on a tile that is
   already lit rather than racing the light across it.

   No JavaScript is involved in any of it, and without CSS the section is a
   heading, a paragraph and a list of links.
   ============================================================================= */

.diagnostik {

    /* Height of the letter inside the square, as a share of the square - the
       marks are all full-bleed in their own viewBox, so height alone sizes them.
       About a third, which is where the design sets them. */
    --diagnostik-glyph-size: 30%;

    /* How far the two letters travel past each other. A share of the letter's
       own height, so it stays proportional as the tile scales. */
    --diagnostik-glyph-travel: 16%;

    /* The two never cross-fade THROUGH each other: the delay below is as long as
       the exit, so the outline has gone before the filled letter starts. Two
       letters dissolving into one another just reads as a smudge. */
    --diagnostik-glyph-out: 120ms ease-in;
    --diagnostik-glyph-in: 280ms cubic-bezier(0.22, 1, 0.36, 1);
    --diagnostik-glyph-delay: 120ms;
}

/* On the home page the aside is a paragraph rather than a caption, so it takes
   about half the row - the same treatment and the same width as
   .ausstattung__head, which is the section it is paired with visually. */
@media (min-width: 1024px) {
    .diagnostik__head {
        --section-head-aside: 38rem;
    }
}

/* Only positioned here, not restyled: the headline itself is the shared
   .section-title from base/components.css. */
.diagnostik--center .diagnostik__head {
    text-align: center;
}

/* Two classes, for the reason given at .ausstattung__list: base/reset.css zeroes
   the margin of every ul[class] with an element-plus-attribute selector. */
.diagnostik .diagnostik__list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-lg) var(--space-md);
    margin-block-start: var(--space-2xl);
}

@media (min-width: 768px) {
    .diagnostik .diagnostik__list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .diagnostik .diagnostik__list {
        grid-template-columns: repeat(5, minmax(0, 1fr));
        margin-block-start: var(--space-3xl);
    }
}

/* --- One row at every width --------------------------------------------------
   What "Weitere Kompetenzbereiche" adds. The module is given five tiles and the
   grid above already narrows from five columns to three to two - so the only
   thing missing is that the tiles which no longer fit must LEAVE rather than
   wrap onto a second row.

   Hidden and not left out of the markup, because the width is not known when
   the page is built. All five are always in the document; which of them a
   narrow window shows is the browser's to decide, and it decides it with one
   rule per step.
   -------------------------------------------------------------------------- */
.diagnostik--row .diagnostik__item:nth-child(n+3) {
    display: none;
}

@media (min-width: 768px) {
    .diagnostik--row .diagnostik__item:nth-child(3) {
        display: block;
    }
}

@media (min-width: 1024px) {
    .diagnostik--row .diagnostik__item:nth-child(n+4) {
        display: block;
    }
}

/* --- The tile ---------------------------------------------------------------- */

/* One link around the square and its labels, so the whole card is a single tab
   stop and a single touch target rather than two. */
.diagnostik__tile {
    display: block;
    color: var(--color-text);
    text-decoration: none;
}

/* display is not decoration here: the box is a <span>, and aspect-ratio does
   nothing on an inline box. */
.diagnostik__box {
    position: relative;
    display: block;
    aspect-ratio: 1;

    /* Nothing currently escapes the square - the wipe stops at its edges and the
       letters move a few pixels - but the tile is a hard-edged block in the
       design, so anything added later should be cut off by it too. */
    overflow: hidden;

    background-color: var(--color-surface-invert);
}

/* The light along the left edge at rest. It is out by a third of the way across:
   the tile has to stay a dark surface with a lit edge, not a blue panel, or the
   contrast with the filled state on hover is lost. */
.diagnostik__box::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: linear-gradient(to right,
                      rgba(var(--rgb-blue-light), 0.60),
                      rgba(var(--rgb-blue-light), 0) 34%);
}

.diagnostik__fill {
    position: absolute;
    inset: 0;
    background-color: var(--color-accent);
    transform: scaleX(0);
    transform-origin: left center;

    /* Transform only, so the wipe stays on the compositor and the global
       prefers-reduced-motion guard in base/reset.css can flatten it. */
    transition: transform var(--transition-base);
}

/* --- The letter --------------------------------------------------------------
   The stack fills the square rather than being centred in it, so the percentage
   height on the marks has something definite to resolve against. It comes after
   .diagnostik__fill in the markup, which is what puts it over the light.
   -------------------------------------------------------------------------- */

.diagnostik__glyphs {
    position: absolute;
    inset: 0;
    display: grid;

    /* Definite, and that is the point: an auto row would be sized BY the marks,
       so their percentage height would have nothing to resolve against and they
       would fall back to the SVG's intrinsic size. */
    grid-template-rows: 100%;

    place-items: center;
}

.diagnostik__glyph {
    /* Both marks in one cell, so they occupy exactly the same place. */
    grid-area: 1 / 1;

    display: block;
    width: auto;
    height: var(--diagnostik-glyph-size);

    /* Transform and opacity only: both stay on the compositor, and the global
       prefers-reduced-motion guard in base/reset.css flattens them to a cut. */
    transition: opacity var(--diagnostik-glyph-in),
                transform var(--diagnostik-glyph-in);
}

/* The filled letter waits below its place until the pointer arrives. */
.diagnostik__glyph--active {
    opacity: 0;
    transform: translateY(var(--diagnostik-glyph-travel));
}

/* --- The labels -------------------------------------------------------------- */

.diagnostik__label {
    display: block;
    margin-block-start: var(--space-sm);
}

.diagnostik__title,
.diagnostik__subtitle {
    display: block;
    font-size: var(--font-size-sm);
    transition: color var(--transition-base);
}

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

/* --- Hover and focus ---------------------------------------------------------
   :focus-visible is listed beside :hover throughout, so the keyboard gets the
   same answer as the pointer. The focus ring itself comes from base/elements.css.
   -------------------------------------------------------------------------- */

.diagnostik__tile:hover .diagnostik__fill,
.diagnostik__tile:focus-visible .diagnostik__fill {
    transform: scaleX(1);
}

/* The outline leaves upwards, and quickly - it has to be gone before the filled
   letter settles into the same place. */
.diagnostik__tile:hover .diagnostik__glyph--rest,
.diagnostik__tile:focus-visible .diagnostik__glyph--rest {
    opacity: 0;
    transform: translateY(calc(var(--diagnostik-glyph-travel) * -1));
    transition: opacity var(--diagnostik-glyph-out),
                transform var(--diagnostik-glyph-out);
}

/* The filled letter rises into the place the outline just left, held back until
   the wipe has lit the tile under it. */
.diagnostik__tile:hover .diagnostik__glyph--active,
.diagnostik__tile:focus-visible .diagnostik__glyph--active {
    opacity: 1;
    transform: none;
    transition: opacity var(--diagnostik-glyph-in) var(--diagnostik-glyph-delay),
                transform var(--diagnostik-glyph-in) var(--diagnostik-glyph-delay);
}

.diagnostik__tile:hover :is(.diagnostik__title, .diagnostik__subtitle),
.diagnostik__tile:focus-visible :is(.diagnostik__title, .diagnostik__subtitle) {
    color: var(--color-accent);
}
