/* Recipient-facing UI: the share page, sign-in and portal. The design system (tokens,
 * buttons, inputs, glass panel, badges, toasts, skeletons, scrollbars, Tahoma) is in
 * /static/shared/theme.css, loaded first. This file carries the page layout: the media
 * backdrop, the glass card floating on it, the file list, and the preview lightbox. */

body {
    /* The video backdrop is the atmosphere here, so the body itself stays pure ground —
       no gradient competing with the clip playing behind the card. */
    background-image: none;
    background-color: #050505;
    overflow-x: hidden;
}

#app {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* Media backdrop — the site-wide background pool (index.html) sits behind everything.
   It holds Bunny Stream player iframes: one while a clip plays, two across a cross-fade.
   pointer-events is off for the whole stack — a background must never take a click, and
   an iframe would otherwise swallow one on its way to the card. */
#background-container {
    position: fixed;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
}

/* Scale-to-cover by hand: an iframe has no object-fit, so the frame is sized to the
   smallest 16:9 box that overflows the viewport on both axes, then centred. This is why
   a background must be 16:9 — the player letterboxes any other aspect *inside* the
   iframe, where no rule here can reach.

   Frames start transparent and are faded in by .bg-visible: the next clip is loaded and
   held behind the current one, so cross-fading is what hides the swap. */
#background-container iframe {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: max(100vw, 177.78vh);
    height: max(100vh, 56.25vw);
    border: 0;
    opacity: 0;
    transition: opacity 700ms ease-in-out;
}

#background-container iframe.bg-visible {
    opacity: 1;
}

/* Overlay. With no media it is a deep vignette washed toward the brand navy, so the
   canvas reads as considered dark space rather than an off screen; over media it darkens
   for legibility. */
#overlay {
    position: fixed;
    inset: 0;
    z-index: 1;
    background:
        radial-gradient(120% 90% at 50% 0%, rgba(43, 64, 128, 0.42), transparent 62%),
        radial-gradient(140% 120% at 50% 120%, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.55));
}

#content {
    position: relative;
    z-index: 2;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: calc(var(--space) * 4);
}

/* Screens */
.screen {
    width: 100%;
    max-width: 620px;
    text-align: center;
}

.screen-narrow {
    max-width: 430px;
}

/* Loading — a crafted spinner with mass, not a hairline ring. */
.spinner {
    width: 52px;
    height: 52px;
    border: 5px solid rgba(255, 255, 255, 0.12);
    border-top-color: var(--blue);
    border-right-color: var(--blue-bright);
    border-radius: 50%;
    animation: spin 0.9s linear infinite;
    margin: 0 auto calc(var(--space) * 2);
    box-shadow: 0 0 24px rgba(110, 193, 228, 0.4);
}

#loading-screen p {
    color: var(--text-secondary);
}

/* Error */
.error-icon {
    width: 64px;
    height: 64px;
    line-height: 60px;
    font-size: 2rem;
    font-weight: 700;
    color: var(--on-danger);
    background: linear-gradient(to bottom, var(--danger-bright), var(--danger-deep));
    border-radius: 50%;
    margin: 0 auto calc(var(--space) * 3);
    box-shadow:
        inset 0 2px 0 rgba(255, 255, 255, 0.45),
        0 6px 18px rgba(0, 0, 0, 0.6),
        0 0 40px -8px var(--danger);
}

#error-screen h1 {
    font-size: 1.6rem;
    margin-bottom: 0.5rem;
}

#error-screen p {
    color: var(--text-secondary);
}

/* --- The card ------------------------------------------------------------------
 * One glass island floating on the media backdrop. The scrim under the translucent fill
 * is deliberately heavy and the blur wide: the backdrop is a moving, sometimes bright
 * video, and the composited background behind this text is what has to clear the
 * contrast floor — not the panel's nominal fill. */
.card {
    --region: var(--blue);
    /* Heavier than any admin panel's scrim, and deliberately so: those sit on a known
       black canvas, this sits on whatever the background pool is playing. A near-white
       frame behind 0.62 alpha composites to about rgb(118,120,130), which puts body text
       at 3.5:1 — under the floor. At 0.78 the same frame lands near rgb(76,80,95) and the
       text clears it, while the blur and the hairline keep the panel reading as glass. */
    --card-scrim: rgba(10, 15, 32, 0.78);
    position: relative;
    background:
        linear-gradient(to bottom, var(--panel-fill-high), var(--panel-fill)),
        var(--card-scrim);
    border: 1px solid var(--panel-border-strong);
    border-radius: var(--radius-lg);
    padding: calc(var(--space) * 4);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.18),
        var(--panel-lift-high),
        /* The bloom the black around the card reads as space rather than as an off
           screen. Wide and diffuse, and only around the panel — nowhere near the
           file list's text. */
        0 0 140px -30px var(--anchor),
        0 0 70px -34px var(--blue);
    backdrop-filter: blur(20px) saturate(1.1);
    -webkit-backdrop-filter: blur(20px) saturate(1.1);
    text-align: left;
    animation: card-in var(--motion-base) var(--ease-entrance);
}

@keyframes card-in {
    from { opacity: 0; transform: translateY(16px) scale(0.99); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Specular highlight band across the top of the card. */
.card::before {
    content: "";
    position: absolute;
    inset: 1px 1px auto 1px;
    height: 96px;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0));
    pointer-events: none;
}

/* The largest thing on a recipient's screen. Large type with space around it is what
   makes the page read as open rather than as a form. */
.card h1 {
    font-size: clamp(1.7rem, 3.6vw, 2.35rem);
    letter-spacing: -0.02em;
    line-height: 1.05;
    margin-bottom: 0.4rem;
}

.card > p {
    color: var(--text-secondary);
    margin-bottom: calc(var(--space) * 2.5);
}

/* Password form */
#password-form {
    display: flex;
    gap: var(--space);
    margin-top: calc(var(--space) * 2.5);
}

#password-input {
    flex: 1;
}

.error-text {
    color: var(--danger-bright);
    font-size: 0.875rem;
    margin-top: calc(var(--space) * 2);
}

/* Sign-in / portal */
.stacked-form {
    display: flex;
    flex-direction: column;
    gap: calc(var(--space) * 2);
    margin-top: calc(var(--space) * 2.5);
}

.field {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    text-align: left;
}

.field > span {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--text-secondary);
}

/* Staff entry: recessive by size, weight and placement rather than by dimming the text
   below the contrast floor. A recipient's eye passes over it; someone looking for it can
   still read it. */
.staff-entry {
    margin-top: calc(var(--space) * 2.5);
    text-align: center;
}

.link-muted {
    background: none;
    border: none;
    padding: 0;
    font-family: var(--font);
    font-size: 0.8rem;
    color: var(--text-secondary);
    text-decoration: underline;
    text-decoration-color: rgba(255, 255, 255, 0.35);
    text-underline-offset: 3px;
    cursor: pointer;
    transition: color var(--motion-hover) var(--ease-standard);
}

.link-muted:hover {
    color: var(--text-strong);
    text-decoration-color: var(--blue);
}

.link-muted:focus-visible {
    outline: 2px solid var(--blue-bright);
    outline-offset: 2px;
    border-radius: 3px;
}

#staff-panel {
    margin-top: calc(var(--space) * 2);
}

.card-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: calc(var(--space) * 2);
    margin-bottom: calc(var(--space) * 2.5);
}

.card-header p {
    color: var(--text-secondary);
    font-size: 0.875rem;
    margin-top: 0.25rem;
}

/* Portal share rows. A share wears the same purple here that the admin's share chips do. */
.share-item {
    --region: var(--purple);
    display: flex;
    align-items: center;
    gap: calc(var(--space) * 2);
    padding: 0.9rem 1rem;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: var(--radius);
    margin-bottom: var(--space);
    text-decoration: none;
    color: inherit;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
    transition:
        background var(--motion-hover) var(--ease-standard),
        border-color var(--motion-hover) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard),
        transform var(--motion-hover) var(--ease-standard);
}

.share-item:hover {
    background: color-mix(in srgb, var(--purple) 16%, rgba(0, 0, 0, 0.3));
    border-color: color-mix(in srgb, var(--purple) 55%, transparent);
    transform: translateY(-2px);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.1),
        0 10px 24px rgba(0, 0, 0, 0.5),
        0 0 28px -8px var(--purple);
}

.share-item:active {
    transform: translateY(1px);
}

.share-item:focus-visible {
    outline: 2px solid var(--purple-bright);
    outline-offset: 2px;
}

.share-item:last-child {
    margin-bottom: 0;
}

.share-info {
    flex: 1;
    min-width: 0;
}

.share-title {
    font-weight: 700;
    color: var(--text-strong);
    margin-bottom: 0.2rem;
}

.share-meta {
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.share-open {
    color: var(--purple-bright);
    font-size: 0.85rem;
    font-weight: 700;
    flex-shrink: 0;
}

/* Characterful empty state — crafted art, a title, a friendly line, and glow. Nothing
   here competes with it, which is what makes it the right place for atmosphere. */
.empty-state {
    color: var(--text-secondary);
    padding: calc(var(--space) * 4) calc(var(--space) * 2);
    text-align: center;
    border-radius: var(--radius);
    background:
        radial-gradient(80% 120% at 50% 0%,
            color-mix(in srgb, var(--blue) 14%, transparent), transparent 70%);
}

.empty-state .empty-art {
    margin: 0 auto calc(var(--space) * 2);
    filter:
        drop-shadow(0 8px 16px rgba(0, 0, 0, 0.6))
        drop-shadow(0 0 22px rgba(110, 193, 228, 0.35));
}

.empty-state .empty-title {
    color: var(--text-strong);
    font-weight: 700;
    font-size: 1.05rem;
    margin-bottom: 0.3rem;
}

/* File list + download toolbar */
.file-toolbar {
    display: flex;
    align-items: center;
    gap: calc(var(--space) * 1.5);
    margin: calc(var(--space) * 2) 0;
    flex-wrap: wrap;
}

.select-all {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--text-secondary);
    cursor: pointer;
    user-select: none;
}

.file-toolbar .spacer {
    flex: 1;
}

#files-list {
    margin: calc(var(--space) * 2) 0;
    max-height: 46vh;
    overflow-y: auto;
    padding-right: 4px;
}

.file-item {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.7rem 0.85rem;
    background: rgba(0, 0, 0, 0.32);
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: var(--radius);
    margin-bottom: 0.55rem;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    transition:
        background var(--motion-hover) var(--ease-standard),
        border-color var(--motion-hover) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard),
        transform var(--motion-hover) var(--ease-standard);
}

.file-item:hover {
    background: color-mix(in srgb, var(--blue) 14%, rgba(0, 0, 0, 0.32));
    border-color: color-mix(in srgb, var(--blue) 50%, transparent);
    transform: translateY(-2px);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.09),
        0 10px 22px rgba(0, 0, 0, 0.5),
        0 0 26px -8px var(--blue);
}

.file-item:active {
    transform: translateY(1px);
}

.file-item:last-child {
    margin-bottom: 0;
}

.file-item .file-select {
    flex-shrink: 0;
}

.file-thumbnail {
    width: 56px;
    height: 56px;
    border-radius: var(--radius);
    object-fit: cover;
    background: rgba(0, 0, 0, 0.5);
    box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.65);
    flex-shrink: 0;
}

/* A type icon rather than a real thumbnail: recessed, so it reads as a slot the icon
   sits in rather than a tile floating on the row. */
.file-thumbnail.icon {
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        linear-gradient(to bottom, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0)),
        rgba(0, 0, 0, 0.5);
}

.file-thumbnail.icon svg {
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
}

.file-info {
    flex: 1;
    min-width: 0;
    text-align: left;
}

.file-name {
    font-weight: 700;
    color: var(--text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 0.2rem;
}

.file-meta {
    font-size: 0.82rem;
    color: var(--text-secondary);
}

.file-download {
    flex-shrink: 0;
}

.download-actions {
    margin-top: calc(var(--space) * 2.5);
}

#file-count {
    color: var(--text-secondary);
    margin-bottom: 0.5rem;
}

/* Download progress (client-side zip). Green: this is a success in progress, and the
   accent matches the download glyph. */
.dl-progress {
    margin-top: calc(var(--space) * 2);
}

.dl-progress .progress-bar {
    height: 0.75rem;
    background: rgba(0, 0, 0, 0.55);
    border-radius: var(--radius-pill);
    overflow: hidden;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.7);
}

.dl-progress .progress-fill {
    height: 100%;
    width: 0%;
    background:
        linear-gradient(to bottom, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0) 55%),
        linear-gradient(to right, var(--green-bright), var(--green-deep));
    box-shadow: 0 0 14px rgba(70, 217, 122, 0.55);
    transition: width var(--motion-hover) var(--ease-standard);
}

#dl-text {
    display: block;
    margin-top: 0.4rem;
    font-size: 0.8rem;
    color: var(--text-secondary);
}

/* Preview lightbox */
.modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(4, 6, 10, 0.9);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.preview-content {
    position: relative;
    max-width: 90vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    animation: card-in var(--motion-base) var(--ease-entrance);
}

.preview-close {
    position: absolute;
    top: -44px;
    right: 0;
    background: none;
    border: none;
    color: var(--text-strong);
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
    transition:
        color var(--motion-hover) var(--ease-standard),
        transform var(--motion-hover) var(--ease-standard);
}

.preview-close:hover {
    color: var(--blue-bright);
    transform: translateY(-2px);
}

.preview-close:focus-visible {
    outline: 2px solid var(--blue-bright);
    outline-offset: 2px;
}

#preview-container {
    max-width: 100%;
    max-height: 70vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

#preview-image,
#preview-video {
    max-width: 100%;
    max-height: 70vh;
    border-radius: var(--radius);
    box-shadow: var(--panel-lift-high);
}

#preview-audio {
    width: 400px;
    max-width: 100%;
}

#preview-pdf {
    width: 80vw;
    height: 70vh;
    border: none;
    border-radius: var(--radius);
}

.preview-info {
    margin-top: calc(var(--space) * 2.5);
    text-align: center;
}

.preview-info h3 {
    margin-bottom: calc(var(--space) * 1.5);
    font-size: 1rem;
    color: var(--text-secondary);
}

/* Branding. Sits over whatever the backdrop is playing, so it carries its own shadow
   rather than relying on the video being dark. */
#branding {
    position: fixed;
    bottom: calc(var(--space) * 2);
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.78rem;
    color: var(--text-secondary);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
    z-index: 2;
}

/* Responsive */
@media (max-width: 640px) {
    #content { padding: calc(var(--space) * 1.5); }
    .card { padding: calc(var(--space) * 2.5); }
    #password-form { flex-direction: column; }
    .file-item { padding: 0.6rem; }
    .file-thumbnail { width: 46px; height: 46px; }
    .file-download { display: none; }
}
