/*
 * Base styles for the linktree. Selectors are class based, so they win over
 * element resets (e.g. Bootstrap reboot) while fonts and colors are inherited
 * from the website. Adjust the look via the custom properties below or enter
 * the website's button classes (e.g. "btn btn-primary") in the backend.
 */
.linktree {
    --linktree-max-width: 36rem;
    --linktree-gap: 1.5rem;
    --linktree-image-size: 8rem;
    --linktree-image-max-height: 8rem;
    --linktree-link-gap: 1rem;
    --linktree-links-spacing: 1rem;
    --linktree-group-gap: 0.5rem;
    --linktree-form-gap: 1rem;
    --linktree-group-border: currentColor;
    --linktree-group-radius: 0.75rem;
    --linktree-link-min-height: 3.5rem;
    --linktree-link-radius: 999px;
    --linktree-link-bg: #fff;
    --linktree-link-color: #1d1d1f;
    --linktree-link-shadow: 0 1px 3px rgb(0 0 0 / 0.12);
    --linktree-icon-size: 1.75rem;
    --linktree-arrow-size: 0.75em;
    --linktree-arrow-weight: 2.75;
    --linktree-card-radius: 1rem;
    --linktree-banner-height: clamp(8rem, 25vw, 20rem);
    --linktree-image-ring: var(--linktree-bg, #fff);
    --linktree-image-link-max-height: 6rem;

    --linktree-padding-inline: 1rem;

    box-sizing: border-box;
    width: 100%;
    padding: 2.5rem var(--linktree-padding-inline);
}

.linktree__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--linktree-gap);
    max-width: var(--linktree-max-width);
    margin-inline: auto;
    text-align: center;
}

/* Two classes, so theme rules setting the alignment on every element (e.g. ".content *") do not win */
.linktree :is(.linktree__headline, .linktree__description, .linktree__group-title) {
    text-align: center;
}

.linktree__profile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
}

.linktree__image {
    margin: 0 0 0.5rem;
}

.linktree__image img {
    display: block;
    max-width: 100%;
    height: auto;
}

/* Banner: full width from the very top, the profile picture overlaps half of it */
/* Two classes, so the larger padding of wider screens does not win */
.linktree.linktree--has-banner {
    padding-top: 0;
}

.linktree__banner {
    margin: 0 calc(var(--linktree-padding-inline) * -1) var(--linktree-gap);
}

.linktree__banner img {
    display: block;
    width: 100%;
    height: var(--linktree-banner-height);
    object-fit: cover;
}

.linktree__banner--video {
    position: relative;
    overflow: hidden;
    height: var(--linktree-banner-height);
}

/* Videos and their posters cover the area; the video lies on top of the poster */
:is(.linktree__banner--video, .linktree__background) :is(.linktree__video, .linktree__video-poster) {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Background video: fixed to the viewport, clipped to the linktree */
.linktree--has-background-video {
    position: relative;
    isolation: isolate;
    clip-path: inset(0);
}

.linktree__background {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
}

.linktree__background::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--linktree-bg-overlay, transparent);
}

.linktree--has-banner .linktree__profile > .linktree__image:first-child {
    position: relative;
    margin-top: calc(var(--linktree-image-size) / -2 - var(--linktree-gap));
}

.linktree--has-banner .linktree__profile > .linktree__image--original:first-child {
    margin-top: calc(var(--linktree-image-max-height) / -2 - var(--linktree-gap));
}

.linktree--has-banner .linktree__profile > .linktree__image--circle:first-child img {
    box-shadow: 0 0 0 4px var(--linktree-image-ring);
}

.linktree__image--circle img {
    width: var(--linktree-image-size);
    height: var(--linktree-image-size);
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: 50%;
}

.linktree__image--original img {
    width: auto;
    max-height: var(--linktree-image-max-height);
}

.linktree__headline {
    margin: 0;
}

.linktree__description {
    margin: 0;
}

.linktree__links,
.linktree__socials {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Every entry takes a full row, consecutive text links share one row (e.g. imprint and privacy policy) */
.linktree__links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--linktree-link-gap);
    width: 100%;
    margin-block: var(--linktree-links-spacing);
}

.linktree__item {
    flex: 0 0 100%;
}

.linktree__item--link {
    flex-basis: auto;
}

/* Form fields are easier to read left-aligned, the website styles the form itself */
.linktree .linktree__form,
.linktree .linktree__form * {
    text-align: start;
}

/*
 * Space between the form fields. A bottom margin instead of a top margin, so
 * fields next to each other in one row (e.g. "col-sm-6") stay aligned.
 */
.linktree .linktree__form .widget {
    margin-bottom: var(--linktree-form-gap);
}

.linktree .linktree__form .widget:last-child {
    margin-bottom: 0;
}

.linktree .linktree__submit {
    box-sizing: border-box;
    width: 100%;
}

/* Collapsed form: the summary is styled as linktree button */
.linktree__form-button {
    cursor: pointer;
    list-style: none;
}

.linktree__form-button::-webkit-details-marker {
    display: none;
}

.linktree__form-toggle[open] > .linktree__form-button .linktree__arrow {
    transform: rotate(90deg);
}

/* Padding instead of margin, so the gap is part of the animated height */
.linktree__form-toggle > .linktree__form {
    box-sizing: border-box;
    padding-top: var(--linktree-link-gap);
}

/* Group: optional title, the links are closer together */
.linktree__links--group {
    gap: var(--linktree-group-gap);
    margin: 0;
}

.linktree__group-title {
    margin: 0 0 0.5rem;
    font-weight: 600;
}

/*
 * Bordered group: the sides and the bottom belong to the list, the top line is
 * drawn left and right of the title. This needs no background color, so it
 * also works on a background image.
 */
.linktree__item--bordered .linktree__links--group {
    box-sizing: border-box;
    padding: 0.75rem 1rem 1rem;
    border: 1px solid var(--linktree-group-border);
    border-top: 0;
    border-radius: 0 0 var(--linktree-group-radius) var(--linktree-group-radius);
}

/* Without a title, the list is closed at the top as well */
.linktree__item--bordered .linktree__links--group:first-child {
    padding-top: 1rem;
    border-top: 1px solid var(--linktree-group-border);
    border-radius: var(--linktree-group-radius);
}

.linktree .linktree__item--bordered .linktree__group-title {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0;
}

.linktree__item--bordered .linktree__group-title::before,
.linktree__item--bordered .linktree__group-title::after {
    content: "";
    flex: 1 1 0;
    align-self: stretch;
    min-width: var(--linktree-group-radius);
    /* The line runs through the middle of the first text line */
    margin-top: 0.65em;
    border-top: 1px solid var(--linktree-group-border);
}

.linktree__item--bordered .linktree__group-title::before {
    border-left: 1px solid var(--linktree-group-border);
    border-top-left-radius: var(--linktree-group-radius);
}

.linktree__item--bordered .linktree__group-title::after {
    border-right: 1px solid var(--linktree-group-border);
    border-top-right-radius: var(--linktree-group-radius);
}

.linktree__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5em;
    box-sizing: border-box;
    width: 100%;
}

.linktree__arrow {
    flex-shrink: 0;
    width: var(--linktree-arrow-size);
    height: var(--linktree-arrow-size);
    fill: none;
    stroke: currentColor;
    stroke-width: var(--linktree-arrow-weight);
    transition: transform 0.15s ease-out;
}

.linktree__link:is(:hover, :focus-visible) .linktree__arrow {
    transform: translateX(0.25em);
}

/* Text link; links in forms (e.g. to the privacy policy) look the same */
.linktree__link--link,
.linktree .linktree__form a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.linktree__link--link {
    display: inline;
    width: auto;
}

/* Image link */
.linktree__link--image {
    display: flex;
    justify-content: center;
}

.linktree__link-image {
    margin: 0;
}

.linktree__link-image img {
    display: block;
    width: auto;
    max-width: 100%;
    max-height: var(--linktree-image-link-max-height);
    height: auto;
}

/* Card */
.linktree__link--card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    overflow: hidden;
    border-radius: var(--linktree-card-radius);
    background: var(--linktree-link-bg);
    box-shadow: var(--linktree-link-shadow);
    color: var(--linktree-link-color);
    text-align: start;
    text-decoration: none;
}

.linktree__card-image {
    margin: 0;
    overflow: hidden;
}

.linktree__card-image :is(img, video) {
    display: block;
    width: 100%;
    height: auto;
    transition: transform 0.4s ease-out;
}

/* The media zooms in slightly, the arrow next to the title moves like on the buttons */
.linktree__link--card:is(:hover, :focus-visible) .linktree__card-image :is(img, video) {
    transform: scale(1.05);
}

/* The video shows its poster itself, the image is only needed for reduced motion */
.linktree__card-video .linktree__video-poster {
    display: none;
}

.linktree__card-body {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 1rem 1.25rem;
}

.linktree__card-title {
    display: flex;
    align-items: center;
    gap: 0.5em;
    font-weight: 600;
    line-height: 1.3;
}

.linktree__link--card:focus-visible,
.linktree__link--image:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
}

/* Default button look, skipped as soon as website button classes are configured */
.linktree:not(.linktree--custom-buttons) :is(.linktree__link--button, .linktree__submit) {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--linktree-link-min-height);
    padding: 0.75rem 1.5rem;
    border-radius: var(--linktree-link-radius);
    background: var(--linktree-link-bg);
    box-shadow: var(--linktree-link-shadow);
    color: var(--linktree-link-color);
    font-weight: 500;
    line-height: 1.3;
    text-decoration: none;
    transition: transform 0.15s ease-out;
}

.linktree:not(.linktree--custom-buttons) :is(.linktree__link--button, .linktree__submit):focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
}

.linktree__socials {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
}

.linktree__social {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    color: inherit;
    text-decoration: none;
    transition: opacity 0.15s ease-out;
}

.linktree__social:hover {
    opacity: 0.7;
}

.linktree__icon {
    width: var(--linktree-icon-size);
    height: var(--linktree-icon-size);
    fill: currentColor;
}

/* Colors chosen in the backend; only active when set, otherwise the website styles apply */
.linktree--has-bg {
    background-color: var(--linktree-bg);
}

.linktree--has-headline-color .linktree__headline {
    color: var(--linktree-headline-color);
}

.linktree--has-description-color .linktree__description {
    color: var(--linktree-description-color);
}

.linktree--has-link-bg :is(.linktree__link--button, .linktree__link--card, .linktree__submit),
.linktree--has-link-bg :is(.linktree__link--button, .linktree__link--card, .linktree__submit):is(:hover, :focus-visible, :active) {
    border-color: var(--linktree-link-bg);
    background-color: var(--linktree-link-bg);
}

.linktree--has-link-color :is(.linktree__link--button, .linktree__link--card, .linktree__submit),
.linktree--has-link-color :is(.linktree__link--button, .linktree__link--card, .linktree__submit):is(:hover, :focus-visible, :active) {
    color: var(--linktree-link-color);
}

.linktree--has-text-link-color :is(.linktree__link--link, .linktree__form a),
.linktree--has-text-link-color :is(.linktree__link--link, .linktree__form a):is(:hover, :focus-visible, :active) {
    color: var(--linktree-text-link-color);
}

.linktree--has-social-color .linktree__social {
    color: var(--linktree-social-color);
}

.linktree--has-group-title-color .linktree__group-title {
    color: var(--linktree-group-title-color);
}

/* Field labels of forms, including the labels of checkboxes and radio buttons, and the confirmation message */
.linktree--has-form-label-color .linktree__form :is(label, legend, .form-confirmation, .form-confirmation *) {
    color: var(--linktree-form-label-color);
}

/* Interactive form elements, overrides website styles like Bootstrap's ".form-check-input:checked" */
.linktree--has-form-accent .linktree__form {
    accent-color: var(--linktree-form-accent);
}

.linktree--has-form-accent .linktree__form :is(input[type="checkbox"], input[type="radio"]):checked {
    border-color: var(--linktree-form-accent);
    background-color: var(--linktree-form-accent);
}

.linktree--has-form-accent .linktree__form :is(input, select, textarea):focus {
    border-color: var(--linktree-form-accent);
    box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--linktree-form-accent) 25%, transparent);
    outline: 0;
}

/* Same image as on the body; fixed to the viewport, both line up seamlessly */
.linktree--has-background-image {
    background-image: var(--linktree-bg-image);
    background-position: center;
    background-size: cover;
}

/* A fixed background is scaled badly on touch devices */
@media (hover: hover) {
    .linktree--has-background-image {
        background-attachment: fixed;
    }
}

/*
 * Entry animations: the contents rise and fade in one after another. With
 * "fade-blur", a background image or video is also blurred slightly.
 */
@keyframes linktree-rise {
    from {
        opacity: 0;
        transform: translateY(1.25rem);
    }
}

@keyframes linktree-fade {
    from {
        opacity: 0;
    }
}

@keyframes linktree-blur {
    to {
        filter: blur(var(--linktree-bg-blur));
    }
}

.linktree--animate {
    --linktree-animation-duration: 0.7s;
    --linktree-animation-stagger: 0.07s;
    --linktree-bg-blur: 6px;
    /* Delay before the links appear, e.g. after the profile moved to its place */
    --linktree-animation-offset: 0s;
}

.linktree--animate .linktree__banner {
    animation: linktree-fade var(--linktree-animation-duration) ease-out both;
}

.linktree--animate :is(.linktree__profile, .linktree__links > li, .linktree__socials) {
    animation: linktree-rise var(--linktree-animation-duration) cubic-bezier(0.22, 1, 0.36, 1) both;
}

.linktree--animate .linktree__socials {
    animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 4);
}

.linktree--animate .linktree__links > li:nth-child(1) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 1); }
.linktree--animate .linktree__links > li:nth-child(2) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 2); }
.linktree--animate .linktree__links > li:nth-child(3) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 3); }
.linktree--animate .linktree__links > li:nth-child(4) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 4); }
.linktree--animate .linktree__links > li:nth-child(5) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 5); }
.linktree--animate .linktree__links > li:nth-child(6) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 6); }
.linktree--animate .linktree__links > li:nth-child(7) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 7); }
.linktree--animate .linktree__links > li:nth-child(8) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 8); }
.linktree--animate .linktree__links > li:nth-child(n+9) { animation-delay: calc(var(--linktree-animation-offset) + var(--linktree-animation-stagger) * 9); }

/* The links inside a group appear together with the group */
.linktree--animate .linktree__links--group > li {
    animation: none;
}

/* Fade: slightly slower and with a short delay before everything starts */
.linktree--animate-fade {
    --linktree-animation-duration: 0.9s;
    --linktree-animation-offset: 0.3s;
}

/* Three classes: ".linktree--animate :is(…, .linktree__links > li)" is more specific than two */
.linktree.linktree--animate-fade :is(.linktree__banner, .linktree__profile) {
    animation-delay: var(--linktree-animation-offset);
}

/*
 * Center: the profile appears in the center of the viewport and moves to its
 * place, afterwards the links rise and fade in one after another. The movement is done by linktree.js,
 * which calculates the distance; without JavaScript the profile only fades in.
 */
.linktree--animate-center {
    --linktree-center-duration: 2.2s;
    --linktree-animation-stagger: 0.1s;
    /* The links only start when the profile has reached its place */
    --linktree-animation-offset: var(--linktree-center-duration);
}

/* Three classes: ".linktree--animate :is(…, .linktree__links > li)" is more specific than two */
.linktree.linktree--animate-center .linktree__profile {
    position: relative;
    z-index: 1;
    animation: linktree-fade 0.6s ease-out both;
}

/*
 * Blur: the background image is painted on a layer of its own, otherwise the
 * contents would be blurred as well. Scaled up, so the blurred edges are hidden.
 */
.linktree--animate-fade-blur:is(.linktree--has-background-image, .linktree--has-background-video) {
    position: relative;
    isolation: isolate;
    clip-path: inset(0);
}

.linktree--animate-fade-blur.linktree--has-background-image::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background-image: var(--linktree-bg-image);
    background-position: center;
    background-size: cover;
}

.linktree--animate-fade-blur.linktree--has-background-image::before,
.linktree--animate-fade-blur .linktree__background > * {
    transform: scale(1.08);
    animation: linktree-blur 1.2s ease-out 0.2s both;
}

@media (prefers-reduced-motion: reduce) {
    .linktree__video {
        display: none;
    }

    /* No movement, but the background stays blurred */
    .linktree.linktree--animate :is(.linktree__banner, .linktree__profile, .linktree__links > li, .linktree__socials) {
        animation: none;
    }

    .linktree--animate-fade-blur.linktree--has-background-image::before,
    .linktree--animate-fade-blur .linktree__background > * {
        animation: none;
        filter: blur(var(--linktree-bg-blur));
    }

    .linktree__link--card:is(:hover, :focus-visible) .linktree__card-image :is(img, video) {
        transform: none;
    }

    .linktree__card-video .linktree__video-poster {
        display: block;
    }

    .linktree__link,
    .linktree__arrow,
    .linktree__social {
        transition: none;
    }
}

@media (min-width: 48em) {
    .linktree {
        padding-block: 4rem;
    }
}
