html, body {
    font-family: 'Inter', sans-serif;
}

/* Guests use the site on their phones. No grey flash on tap; no pull-to-refresh (Chrome on Android), which would reload
   the page in the middle of an upload. */
html {
    -webkit-tap-highlight-color: transparent;
}

body {
    overscroll-behavior-y: none;
}

/* The page never scrolls sideways: text wraps (.arena-text-wrap), and whatever still sticks out on the right is cut
   off. clip (unlike hidden) doesn't make html or body a scroll container, so position: sticky keeps working; hidden
   is the fallback for browsers without clip (Safari before 16). */
html,
body {
    max-width: 100%;
    overflow-x: hidden;
    overflow-x: clip;
}

/* No double-tap zoom on controls, so taps respond at once. */
a,
button,
label,
input,
.mud-button-root {
    touch-action: manipulation;
}

/* iOS zooms into inputs with text under 16px when they're focused. */
input,
textarea,
select,
.mud-input > input.mud-input-root,
.mud-input > textarea.mud-input-root {
    font-size: max(16px, 1rem);
}

a, .btn-link {
    color: inherit;
}

/* Text filled with the palette's gradient (sky blue to lila, see ColorPalette.Gradient), like the titles on
   magicmountainzermatt.ch. The layouts set --arena-gradient. */
.arena-gradient-text {
    background-image: var(--arena-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    font-weight: 700;
}

/* Wraps between words first and only breaks inside a word when it doesn't fit on a line on its own,
   so long words (emails, URLs, names) never push the page wider than the screen.
   Set on <body>; overflow-wrap is inherited, so it applies everywhere. "anywhere" (unlike "break-word")
   also lets flex and grid items shrink below their longest word. */
.arena-text-wrap {
    overflow-wrap: anywhere;
    word-break: normal;
}

/* MudBlazor keeps chips on one line at a fixed height; here their text wraps like everywhere else. (Floating input
   labels stay on one line, cut off with an ellipsis, since a second line would run into the field.) */
.mud-chip {
    height: auto;
    min-height: 32px;
    white-space: normal;
}

:root {
    --arena-radius: 1rem;
    /* The width of every guest page's content (home, welcome, photos, QR code, errors), so they all line up. */
    --arena-page-width: 40rem;
    /* ArenaCard: every card's look, in one place. Built on the MudBlazor palette variables (the theme's colours).
       For example a frosted glass card: --arena-card-background: color-mix(in srgb,
       var(--mud-palette-surface) 60%, transparent); --arena-card-backdrop: blur(12px); */
    --arena-card-background: var(--mud-palette-surface);
    --arena-card-text: var(--mud-palette-text-primary);
    --arena-card-border: 1px solid var(--mud-palette-divider);
    --arena-card-radius: var(--arena-radius);
    --arena-card-shadow: 0 4px 24px -8px rgba(130, 143, 255, 0.18);
    --arena-card-backdrop: none;
    --arena-card-padding: 1rem;
    /* The one vertical spacing between stacked content everywhere (.arena-stack): ArenaSpacing's padding, so
       0.5rem on phones and 1rem from MudBlazor's sm breakpoint. */
    --arena-gap: 0.5rem;
}

@media (min-width: 600px) {
    :root {
        --arena-gap: 1rem;
        --arena-card-padding: 1.5rem;
    }
}

/* Stacked content: a flex column spaced by the shared gap. Vertical spacing always comes from this (or a column
   with the same gap), never from margins on the children. Links and buttons keep their own width instead of
   stretching across the column. */
.arena-stack {
    display: flex;
    flex-direction: column;
    gap: var(--arena-gap);
}

.arena-stack > :is(a, button, .mud-button-root) {
    align-self: flex-start;
}

/* ArenaSpacer: extra room between stacked content, written into the markup where it goes (instead of top or bottom
   padding or margins on the neighbours). As an item of the stack it also gets the gap on either side. */
.arena-spacer {
    flex: none;
    height: var(--arena-gap);
}

.arena-spacer-half {
    height: calc(var(--arena-gap) / 2);
}

.arena-spacer-double {
    height: calc(var(--arena-gap) * 2);
}

/* Tight lines that belong together inside a card (a name and the role under it). */
.arena-stack-tight {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

/* dvh: the height actually visible on phones, without the part the address bar covers (vh where it's unknown). */
/* ArenaCard, styled only through the --arena-card-* variables (see :root). With .mud-paper, to win over MudBlazor's
   own paper background. */
.mud-paper.arena-card {
    padding: var(--arena-card-padding);
    border: var(--arena-card-border);
    border-radius: var(--arena-card-radius);
    background: var(--arena-card-background);
    color: var(--arena-card-text);
    box-shadow: var(--arena-card-shadow);
    -webkit-backdrop-filter: var(--arena-card-backdrop);
    backdrop-filter: var(--arena-card-backdrop);
}

/* Above the glowing spheres (ArenaOrbs). MudMainContent leaves room for an app bar at the top, which the site doesn't
   have: only a small gap there (pt-4), on every page. With .mud-main-content, to win over MudBlazor's rules. */
.mud-main-content.arena-main {
    position: relative;
    z-index: 1;
    min-height: 100vh;
    min-height: 100dvh;
    padding-top: 1rem;
}

/* The page content is capped and centred on very wide screens, and kept clear of the notch and the home indicator
   (viewport-fit=cover in App.razor). */
.arena-content {
    max-width: 120rem;
    margin-inline: auto;
    padding-top: env(safe-area-inset-top);
    padding-right: env(safe-area-inset-right);
    padding-bottom: env(safe-area-inset-bottom);
    padding-left: env(safe-area-inset-left);
}

/* A page of running content (forms, photos): one comfortable column, also on tablets and desktops. */
.arena-page {
    max-width: var(--arena-page-width);
    margin-inline: auto;
}

/* A page that uses the width of a laptop (the admin's review). */
.arena-page-wide {
    max-width: 90rem;
    margin-inline: auto;
}

/* ArenaReconnect: Blazor's reconnect dialog, never shown (by the id, to win over MudBlazor's rules for it). */
#components-reconnect-modal.arena-reconnect {
    display: none !important;
}

/* QR code page: one card centred in the screen (without the gap at the top of .arena-main). */
.arena-home {
    display: flex;
    min-height: calc(100vh - 1rem);
    min-height: calc(100dvh - 1rem - env(safe-area-inset-top) - env(safe-area-inset-bottom));
    align-items: center;
    justify-content: center;
}

/* Home and welcome page: the card's content centred. */
.arena-home-card {
    width: 100%;
    max-width: var(--arena-page-width);
    align-items: center;
    text-align: center;
}

.arena-home-logo {
    width: 100%;
    max-width: 16rem;
    max-height: 30dvh;
    object-fit: contain;
}

.arena-photos-logo {
    align-self: center;
    width: 100%;
    max-width: 12rem;
    max-height: 20dvh;
    object-fit: contain;
}

/* Welcome page: the slogan big, the three steps as a list with their icons, left-aligned in the centred card. */
/* The gradient runs out and back again (sky blue to lila and back, so it loops without a jump) and slides along
   the slogan. */
.arena-welcome-slogan {
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: 0.02em;
    background-image: linear-gradient(90deg, var(--arena-sky), var(--arena-periwinkle), var(--arena-purple),
        var(--arena-lila), var(--arena-purple), var(--arena-periwinkle), var(--arena-sky));
    background-size: 200% 100%;
    animation: arena-gradient-slide 6s linear infinite;
}

@keyframes arena-gradient-slide {
    from {
        background-position: 0% 50%;
    }

    to {
        background-position: -200% 50%;
    }
}

/* Draws the eye to a button: a short wiggle every few seconds, still in between. */
.arena-wiggle {
    animation: arena-wiggle 4s ease-in-out 1s infinite;
}

@keyframes arena-wiggle {
    0%, 15%, 100% {
        transform: rotate(0) scale(1);
    }

    3% {
        transform: rotate(-2deg) scale(1.03);
    }

    6% {
        transform: rotate(2deg) scale(1.03);
    }

    9% {
        transform: rotate(-1.5deg) scale(1.03);
    }

    12% {
        transform: rotate(1deg) scale(1.02);
    }
}

@media (prefers-reduced-motion: reduce) {
    .arena-welcome-slogan,
    .arena-wiggle {
        animation: none;
    }
}

/* The steps well apart, each one compact: its title and text close together. */
.arena-welcome-steps {
    display: flex;
    flex-direction: column;
    gap: calc(var(--arena-gap) * 2.5);
    width: 100%;
    text-align: left;
}

.arena-welcome-step {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.arena-welcome-step-text {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.arena-welcome-step-text .mud-typography {
    line-height: 1.3;
}

/* The lines between the intro, the steps and the outro: across the whole card (it centres its content, which would
   shrink them). */
.arena-welcome-divider.mud-divider {
    align-self: stretch;
    width: auto;
}

/* Photos page: the languages at the bottom, centred like the home page, and the log out button under them, on its own
   (no card). */
.arena-language-card {
    align-items: center;
    text-align: center;
}

.arena-stack > .mud-button-root.arena-logout {
    align-self: center;
}

/* ArenaLanguagePicker: the flags side by side (wrapping on narrow screens), the current one outlined in the accent
   colour. Large enough to tap on a phone. The flag, its thin line and the button share one corner radius, so no corner
   of the picture shows past them; the outline of the current one is a shadow outside the button. */
.arena-flags {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--arena-gap);
}

.arena-flag {
    display: block;
    position: relative;
    width: 4.5rem;
    aspect-ratio: 4 / 3;
    padding: 0;
    overflow: hidden;
    /* Keeps the corners clipped while the flag scales on hover (Safari drops overflow clipping on transformed
       elements otherwise). */
    isolation: isolate;
    border: none;
    border-radius: 0.5rem;
    background: none;
    cursor: pointer;
    opacity: 0.7;
    transition: transform 0.15s, opacity 0.15s, box-shadow 0.15s;
}

/* A thin line around the flag (over the picture, so it shows), so white stripes don't run into a white card. */
.arena-flag::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px var(--mud-palette-divider);
    pointer-events: none;
}

.arena-flag img {
    display: block;
    /* No "save image" menu on a long press. */
    -webkit-touch-callout: none;
    pointer-events: none;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}

.arena-flag:hover,
.arena-flag:focus-visible,
.arena-flag-current {
    opacity: 1;
}

.arena-flag:hover {
    transform: scale(1.06);
}

.arena-flag:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.arena-flag-current {
    box-shadow: 0 0 0 3px var(--mud-palette-primary);
}

@media (min-width: 600px) {
    .arena-flag {
        width: 6rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .arena-flag {
        transition: none;
    }

    .arena-flag:hover {
        transform: none;
    }
}

/* File inputs opened through their labels (the buttons), never shown themselves. Hidden visually rather than with
   display: none, which keeps some iOS versions from opening the picker through the label. */
.arena-hidden-input {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    opacity: 0;
}

/* Photos page: the two buttons stacked, full width, easy to hit with a thumb. */
.arena-photo-actions {
    display: flex;
    flex-direction: column;
    gap: var(--arena-gap);
}

/* Terms: each note with its own icon in front instead of a bullet, with room around and between them. */
.arena-terms-list {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.arena-terms-list li {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.arena-terms-list li .mud-icon-root {
    flex: none;
}

/* Contest email: the field full width, its button full width under it. */
.arena-email {
    display: flex;
    flex-direction: column;
    gap: var(--arena-gap);
}

.arena-email .mud-input-control {
    margin-top: 0;
}

/* The guest's photos as square tiles, as many per row as fit. */
.arena-photos {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
    gap: 0.25rem;
}

/* Each tile with its delete button in the top right corner, on a dark disc so it shows on any photo. */
.arena-photo {
    position: relative;
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 0.5rem;
    background-color: var(--mud-palette-divider);
}

.arena-photo .arena-photo-open {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

.arena-photo .arena-photo-delete {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    background-color: rgba(0, 0, 0, 0.6);
    color: #fff;
}

.arena-photo img {
    display: block;
    -webkit-touch-callout: none;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Admin: the login card narrow and centred; the review with its links, filter and a grid of photos with their
   approve and reject buttons. Approved photos are outlined, rejected ones faded. */
.arena-login {
    width: 100%;
    max-width: 26rem;
    margin-inline: auto;
}

.arena-admin-header,
.arena-admin-links,
.arena-admin-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--arena-gap);
}

.arena-admin-header {
    justify-content: space-between;
}

/* The danger zone at the bottom of the admin area: red, so nobody deletes everything by accident. */
.arena-danger-zone {
    --arena-card-border: 2px solid var(--mud-palette-error);
    --arena-card-background: color-mix(in srgb, var(--mud-palette-error) 15%, var(--mud-palette-surface));
}

.arena-danger-zone .mud-typography-h6 {
    color: var(--mud-palette-error);
}

.arena-reviews {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: var(--arena-gap);
}

.arena-review {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.arena-review-info {
    color: var(--mud-palette-text-secondary);
}

.arena-review-actions {
    display: flex;
    gap: 0.25rem;
}

.arena-review-actions > .mud-button-root {
    flex: 1 1 0;
    min-width: 0;
}

/* Stage: a wall of photos in columns moving up, on plain black, nothing else (Pages/Stage/Page.razor.js builds and
   moves the columns). Every photo rises in from below the screen's bottom edge. */
.arena-stage-screen {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background-color: #000;
    color: #fff;
}

.arena-stage {
    --arena-wall-gap: clamp(0.5rem, 1vw, 1rem);
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    align-items: flex-start;
    gap: var(--arena-wall-gap);
    padding-inline: var(--arena-wall-gap);
}

/* The customer's logo, in the middle above the wall; clicks go through to the screen (full screen). */
.arena-stage-logo {
    position: absolute;
    z-index: 3;
    top: 50%;
    left: 50%;
    width: min(40vw, 60dvh);
    max-height: 40dvh;
    object-fit: contain;
    transform: translate(-50%, -50%);
    pointer-events: none;
    filter: drop-shadow(0 0 2rem rgba(0, 0, 0, 0.8));
}

.arena-stage-hide-cursor {
    cursor: none;
}

.arena-wall-column {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    gap: var(--arena-wall-gap);
    min-width: 0;
    will-change: transform;
}

.arena-wall-tile {
    overflow: hidden;
    border-radius: 0.75rem;
    transition: opacity 0.6s ease-out;
}

.arena-wall-tile canvas {
    display: block;
    width: 100%;
    height: auto;
}

/* A rejected photo fades out where it is, so nothing jumps. */
.arena-wall-tile.arena-wall-tile-removed {
    opacity: 0;
}

.arena-stage-empty {
    position: absolute;
    z-index: 4;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    padding: 2rem;
    text-align: center;
}

/* QR code page: the code as large as the screen allows (but at most 28rem), always black on white with the quiet
   zone around it, as phones don't read a light code on a dark background. Printed, only the card is left. */
/* Dense, so logo, slogan and the code fit on one screen: a smaller gap and logo. */
.arena-code-card {
    gap: 0.5rem;
}

.arena-code-logo {
    max-width: 12rem;
    max-height: 18dvh;
}

.arena-code {
    width: min(100%, 28rem, 60dvh);
    aspect-ratio: 1;
    border-radius: 0.5rem;
    overflow: hidden;
    background-color: #fff;
}

.arena-code svg {
    display: block;
    width: 100%;
    height: 100%;
}

@media print {
    .arena-code-card.mud-paper.arena-card {
        border: none;
        box-shadow: none;
    }
}

/* Theme test page (/test): colour swatches with their names and values, rows of sample components. */
.arena-swatches {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: var(--arena-gap);
}

/* The colour, then its name and value close together under it. */
.arena-swatch {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    min-width: 0;
}

.arena-swatch-text {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.arena-swatch-color {
    height: 4.5rem;
    border: 1px solid var(--mud-palette-divider);
    border-radius: 0.5rem;
}

.arena-swatch-gradient {
    height: 3rem;
}

.arena-swatch-value {
    color: var(--mud-palette-text-secondary);
    font-family: 'JetBrains Mono', monospace;
}

.arena-test-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* ArenaOrbs: big, soft spheres of light in the palette's colours drifting slowly behind the page, fixed to the screen.
   Each is a radial gradient fading out to its edge (looks blurred, costs nothing like a blur filter), moved and scaled
   along one of three paths. */
.arena-orbs {
    position: fixed;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
}

.arena-orb {
    position: absolute;
    /* Centred on (--x, --y). */
    top: calc(var(--y) - var(--size) / 2);
    left: calc(var(--x) - var(--size) / 2);
    width: var(--size);
    height: var(--size);
    border-radius: 50%;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--c) 80%, transparent),
        color-mix(in srgb, var(--c) 35%, transparent) 55%, transparent);
    animation-duration: var(--t);
    animation-delay: var(--delay);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
}

@keyframes arena-orb-path-1 {
    0% {
        transform: translate(0, 0) scale(1);
    }

    50% {
        transform: translate(18vw, 12vh) scale(1.15);
    }

    100% {
        transform: translate(-8vw, 22vh) scale(0.9);
    }
}

@keyframes arena-orb-path-2 {
    0% {
        transform: translate(0, 0) scale(1.1);
    }

    50% {
        transform: translate(-20vw, 15vh) scale(0.9);
    }

    100% {
        transform: translate(-6vw, -12vh) scale(1.2);
    }
}

@keyframes arena-orb-path-3 {
    0% {
        transform: translate(0, 0) scale(0.95);
    }

    50% {
        transform: translate(12vw, -18vh) scale(1.2);
    }

    100% {
        transform: translate(-16vw, -6vh) scale(1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .arena-orb {
        animation: none;
    }
}

/* ArenaPhotoViewer: one photo on black, as large as fits the screen; the count and close button in a bar at the top,
   previous and next at the sides on dark discs, all clear of the safe-area insets. touch-action: pan-y leaves the
   sideways swipes to the viewer. */
.arena-viewer-dialog.mud-dialog {
    background-color: #000;
}

.arena-viewer-dialog .arena-viewer-content {
    padding: 0;
    margin: 0;
    height: 100dvh;
    overflow: hidden;
}

.arena-viewer {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    outline: none;
    touch-action: pan-y;
    user-select: none;
}

.arena-viewer-image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    -webkit-touch-callout: none;
}

.arena-viewer-preload {
    display: none;
}

.arena-viewer-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: calc(env(safe-area-inset-top) + 0.25rem) calc(env(safe-area-inset-right) + 0.25rem) 0.25rem
        calc(env(safe-area-inset-left) + 1rem);
    background: linear-gradient(rgba(0, 0, 0, 0.6), transparent);
    color: #fff;
}

.arena-viewer-bar .mud-icon-button {
    color: #fff;
}

.arena-viewer .arena-viewer-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background-color: rgba(0, 0, 0, 0.6);
    color: #fff;
}

.arena-viewer .arena-viewer-previous {
    left: calc(env(safe-area-inset-left) + 0.5rem);
}

.arena-viewer .arena-viewer-next {
    right: calc(env(safe-area-inset-right) + 0.5rem);
}
