/* ABL File Share — shared design system.
 *
 * One rule set for both UIs (admin + recipient), so the same control in the same role
 * looks the same everywhere. The register: deep black canvas running toward the ABL
 * brand navy, glass panels floating with real space around them, candy-bright accents
 * identifying regions, and soft coloured glow where a lesser design would put grey
 * chrome. Not sterile dark mode, and not a grey slab.
 *
 * Loaded first; each page's own stylesheet layers layout on top and may override, but
 * tokens, buttons, inputs, panels, tables, scrollbars, toasts and skeletons live here. */

*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    /* --- Ground -----------------------------------------------------------------
       Canvas is the dominant colour and the majority of the pixels. Anchor is the ABL
       brand navy (--dark on the marketing site): the far end of the canvas gradient and
       the base of atmospheric glow. Dark-valued, so it gives the black direction
       without lightening it. Chrome sits *on* the canvas; nothing fills it with grey. */
    --canvas: #0C0C0C;
    --anchor: #2B4080;

    /* --- Accents ----------------------------------------------------------------
       ABL blue leads. Each hue carries semantic load: region identity or state, never
       decoration. Region hues are blue / purple / teal / yellow; green, coral and
       magenta are reserved for state, so a region never wears a state's colour.
       Every hue keeps a bright/deep pair even where no rule reads one yet: the crafted
       icons in icons.js cannot read a custom property, so they hard-code these values,
       and this block is where the value a glyph was drawn to actually lives. */
    --blue: #6EC1E4;             /* primary: buttons, active states, focus, upload */
    --blue-bright: #A6DCF0;
    --blue-deep: #2E9BC9;

    /* --purple is the fill, border and glow; --purple-bright is the *text* variant, and it
       is this light because purple text has to clear the floor against the brightest part
       of the canvas gradient, not only against black (#B07CD0 there is 3.0:1). */
    --purple: #B07CD0;           /* secondary: links, share chips, the Shares region */
    --purple-bright: #D6B4EA;
    --purple-deep: #8B52B0;

    --teal: #3FD9D4;             /* the Users region */
    --teal-bright: #7FE9E5;
    --teal-deep: #16A9A4;

    --yellow: #FFD700;           /* folders, pending invites, playful details */
    --yellow-bright: #FFE566;
    --yellow-deep: #D9B300;

    --green: #46D97A;            /* state: success, positive, download progress */
    --green-bright: #7BE8A2;
    --green-deep: #22B457;

    --magenta: #E91E63;          /* state: attention — expired, needs a decision */
    --magenta-bright: #FF5C90;
    --magenta-pale: #FF8FB4;     /* the fill a magenta badge uses: see --on-magenta */
    --magenta-deep: #B01047;

    --danger: #FF6B6B;           /* state: destructive */
    --danger-bright: #FF9494;
    --danger-deep: #D94A4A;

    /* Label colour on an accent fill. Picked per hue as whichever extreme clears the
       contrast floor against that specific fill — never assumed. */
    --on-blue: #04202F;
    --on-purple: #1B0A26;
    --on-teal: #02231F;
    --on-yellow: #2A2000;
    --on-green: #05210E;
    /* Near-black, not white: white on magenta clears the floor at neither end of the
       hue's usable range (2.9:1 on --magenta-pale), so a magenta fill carries dark
       text and the fill itself stays at the pale end. */
    --on-magenta: #2A0011;
    --on-danger: #2A0000;

    /* Region colour. Each named region sets --region once; components read it, so a
       panel's identity follows it everywhere it appears. Defaults to the primary. */
    --region: var(--blue);

    /* --- Text -------------------------------------------------------------------
       Never mid-grey on dark. Hierarchy is size and weight, not dimming. */
    --text: #ECECEC;
    --text-strong: #FFFFFF;
    --text-secondary: #E2E2E2;

    /* --- Glass ------------------------------------------------------------------
       A panel is translucent light over whatever is behind it, blurred, hairline-edged
       and lifted off the ground by a shadow. The scrim under the fill keeps text
       legible where the backdrop is bright (the share page's video). */
    --panel-scrim: rgba(13, 19, 40, 0.42);
    --panel-scrim-strong: rgba(10, 15, 32, 0.62);
    --panel-fill: rgba(255, 255, 255, 0.055);
    --panel-fill-raised: rgba(255, 255, 255, 0.09);
    --panel-fill-high: rgba(255, 255, 255, 0.13);
    --panel-border: rgba(255, 255, 255, 0.14);
    --panel-border-strong: rgba(255, 255, 255, 0.24);
    --panel-blur: 14px;
    --panel-lift: 0 10px 28px rgba(0, 0, 0, 0.55);
    --panel-lift-hover: 0 18px 42px rgba(0, 0, 0, 0.62);
    --panel-lift-high: 0 26px 64px rgba(0, 0, 0, 0.72);

    /* Bevel light/shadow, for the controls that read as physical objects. */
    --edge-light: rgba(255, 255, 255, 0.34);
    --edge-light-soft: rgba(255, 255, 255, 0.16);
    --edge-dark: rgba(0, 0, 0, 0.55);
    --edge-dark-soft: rgba(0, 0, 0, 0.32);

    /* --- Form -------------------------------------------------------------------
       One spacing step; gaps between groups run several, gaps within a group run one. */
    --space: 8px;
    --radius: 10px;
    --radius-lg: 16px;
    --radius-pill: 999px;

    --font: Tahoma, Verdana, Geneva, 'DejaVu Sans', system-ui, -apple-system,
            'Segoe UI', sans-serif;
    --mono: 'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace;

    /* --- Motion -----------------------------------------------------------------
       Unhurried enough to be seen. Hover lifts a control toward the cursor; a colour
       change on its own is under-built. */
    --motion-hover: 180ms;
    --motion-base: 320ms;
    --ease-standard: cubic-bezier(0.22, 0.8, 0.28, 1);
    --ease-entrance: cubic-bezier(0.34, 1.42, 0.64, 1);

    /* Firefox scrollbar (webkit gets the crafted one below). Wide, always visible. */
    scrollbar-color: var(--blue-deep) #050505;
    scrollbar-width: auto;
}

body {
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.45;
    color: var(--text);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;

    /* One gradient: the black runs toward the brand navy at the top of the surface, so
       a long page has direction and atmosphere and still stays dark at both ends. */
    background-color: var(--canvas);
    background-image:
        radial-gradient(150% 110% at 50% -25%,
                        rgba(43, 64, 128, 0.75), rgba(43, 64, 128, 0) 68%);
    background-repeat: no-repeat;
    background-attachment: fixed;
}

.hidden {
    display: none !important;
}

h1, h2, h3 {
    color: var(--text-strong);
    font-weight: 700;
    line-height: 1.2;
}

a {
    color: var(--purple-bright);
    text-decoration-color: color-mix(in srgb, var(--purple) 55%, transparent);
    transition: color var(--motion-hover) var(--ease-standard);
}

a:hover {
    color: color-mix(in srgb, var(--purple-bright) 55%, white);
}

/* --- Glass panel ----------------------------------------------------------------
 * The one depth recipe: translucent light over the canvas, blurred behind, hairline
 * edge on all sides, soft lift beneath. Elevation is more fill, more blur, more shadow;
 * two panels at the same elevation look identical. Recessed things (inputs, thumbnails)
 * invert the reading: darker than their host, tighter radius, no lift. */
.panel {
    background:
        linear-gradient(to bottom, var(--panel-fill-raised), var(--panel-fill)),
        var(--panel-scrim);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--panel-lift), inset 0 1px 0 rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(var(--panel-blur));
    -webkit-backdrop-filter: blur(var(--panel-blur));
}

/* --- Buttons --------------------------------------------------------------------
 * Physical objects: a gloss band over curved glass, a bevel, a lift toward the cursor
 * on hover with the glow brightening to match, and a real sink on press. */
.btn {
    --btn-top: rgba(255, 255, 255, 0.17);
    --btn-bottom: rgba(255, 255, 255, 0.06);
    --btn-text: var(--text-strong);
    --btn-glow: rgba(255, 255, 255, 0.16);
    --btn-bevel:
        inset 0 1px 0 var(--edge-light),
        inset 1px 0 0 var(--edge-light-soft),
        inset 0 -2px 1px var(--edge-dark),
        inset -1px 0 0 var(--edge-dark-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    padding: 0.55rem 1.1rem;
    font-family: var(--font);
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--btn-text);
    background: linear-gradient(to bottom, var(--btn-top) 0%, var(--btn-bottom) 100%);
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
    position: relative;
    box-shadow: var(--btn-bevel), 0 2px 5px rgba(0, 0, 0, 0.5);
    transition:
        transform var(--motion-hover) var(--ease-standard),
        box-shadow var(--motion-hover) var(--ease-standard),
        filter var(--motion-hover) var(--ease-standard);
}

/* Gloss band across the top — the Aero/Luna specular highlight over curved glass. */
.btn::before {
    content: "";
    position: absolute;
    inset: 1px 1px auto 1px;
    height: 42%;
    border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.38), rgba(255, 255, 255, 0));
    pointer-events: none;
}

.btn:hover:not(:disabled) {
    transform: translateY(-2px);
    filter: brightness(1.1);
    box-shadow:
        var(--btn-bevel),
        0 10px 24px rgba(0, 0, 0, 0.55),
        0 0 24px var(--btn-glow);
}

.btn:active:not(:disabled) {
    /* Pressed: the bevel inverts and the whole control sinks. */
    transform: translateY(1px);
    box-shadow:
        inset 0 2px 4px rgba(0, 0, 0, 0.5),
        inset 0 1px 0 rgba(0, 0, 0, 0.4);
    filter: brightness(0.96);
}

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

.btn:disabled {
    cursor: not-allowed;
    filter: grayscale(0.75) brightness(0.7);
    opacity: 0.65;
    transform: none;
}

.btn-primary {
    --btn-top: var(--blue-bright);
    --btn-bottom: var(--blue-deep);
    --btn-text: var(--on-blue);
    --btn-glow: rgba(110, 193, 228, 0.45);
}

.btn-secondary {
    --btn-top: rgba(255, 255, 255, 0.17);
    --btn-bottom: rgba(255, 255, 255, 0.055);
    --btn-text: var(--text-strong);
    --btn-glow: rgba(255, 255, 255, 0.14);
}

.btn-danger {
    --btn-top: var(--danger-bright);
    --btn-bottom: var(--danger-deep);
    --btn-text: var(--on-danger);
    --btn-glow: rgba(255, 107, 107, 0.45);
}

.btn-small {
    padding: 0.32rem 0.72rem;
    font-size: 0.78rem;
}

/* A standalone call to action goes fully pill-shaped. */
.btn-large {
    padding: 0.85rem 1.9rem;
    font-size: 1rem;
    border-radius: var(--radius-pill);
}

.btn-large::before {
    border-radius: var(--radius-pill) var(--radius-pill) 0 0;
}

/* Button carrying a loading spinner. The label is hidden and a spinner shown, so the
   control reads as working rather than dead — never a silent no-op. */
.btn.is-loading {
    color: transparent;
    pointer-events: none;
}

.btn.is-loading::after {
    content: "";
    position: absolute;
    width: 1em;
    height: 1em;
    border: 2px solid rgba(0, 0, 0, 0.35);
    border-top-color: rgba(0, 0, 0, 0.85);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

/* --- Inputs ---------------------------------------------------------------------
 * Recessed: darker than the host panel (more canvas showing through, not less), tighter
 * radius, inset shadow rather than a lift — the field reads as cut into the panel. */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="datetime-local"],
input[type="search"],
select,
textarea {
    width: 100%;
    padding: 0.58rem 0.78rem;
    font-family: var(--font);
    font-size: 0.9rem;
    color: var(--text-strong);
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid rgba(0, 0, 0, 0.65);
    border-radius: var(--radius);
    box-shadow:
        inset 0 2px 4px rgba(0, 0, 0, 0.6),
        inset 0 1px 0 rgba(0, 0, 0, 0.5),
        0 1px 0 rgba(255, 255, 255, 0.06);
    transition: box-shadow var(--motion-hover) var(--ease-standard);
}

input::placeholder,
textarea::placeholder {
    /* Above the mid-grey band: a placeholder is still text a person has to read. */
    color: #C8C8C8;
}

input:focus,
select:focus,
textarea:focus {
    outline: none;
    box-shadow:
        inset 0 2px 4px rgba(0, 0, 0, 0.6),
        0 0 0 2px var(--blue),
        0 0 20px rgba(110, 193, 228, 0.35);
}

input:disabled,
select:disabled {
    filter: brightness(0.7);
    cursor: not-allowed;
}

/* Native checkboxes get the primary accent rather than a default blue tick. */
input[type="checkbox"] {
    width: 1.05rem;
    height: 1.05rem;
    accent-color: var(--blue-deep);
    cursor: pointer;
}

input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--blue-bright);
    outline-offset: 1px;
}

/* --- Badges --------------------------------------------------------------------- */
.badge {
    display: inline-block;
    padding: 0.2rem 0.5rem;
    font-size: 0.72rem;
    font-weight: 700;
    border-radius: var(--radius-pill);
    color: var(--on-green);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 1px 2px rgba(0, 0, 0, 0.45);
}

.badge-yes { background: linear-gradient(to bottom, var(--green-bright), var(--green-deep)); }

/* The neutral badge carries its own dark backing rather than translucent white alone: it
   appears on glass cards over a gradient, and white-on-unknown put its label at 4.0:1. */
.badge-no {
    background:
        linear-gradient(to bottom, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.06)),
        rgba(0, 0, 0, 0.5);
    color: var(--text-strong);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14);
}

/* A classification, not a state: outlined in the region's colour rather than filled like
   the state badges, so a role and a status sitting in adjacent columns cannot be read as
   the same kind of fact. */
.badge-role {
    background: color-mix(in srgb, var(--region) 16%, transparent);
    color: color-mix(in srgb, var(--region) 65%, white);
    border: 1px solid color-mix(in srgb, var(--region) 45%, transparent);
    box-shadow: none;
}

/* --- Toasts --------------------------------------------------------------------
 * In-page feedback replacing alert(). Stacked bottom-right, auto-dismiss, colour +
 * icon by kind. Success gets a visible acknowledgement rather than a silent refresh. */
#toast-region {
    position: fixed;
    bottom: calc(var(--space) * 2.5);
    right: calc(var(--space) * 2.5);
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: calc(var(--space) * 1.25);
    max-width: min(92vw, 420px);
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.8rem 0.95rem;
    color: var(--text-strong);
    background:
        linear-gradient(to bottom, var(--panel-fill-high), var(--panel-fill)),
        var(--panel-scrim-strong);
    border: 1px solid var(--panel-border);
    border-left: 4px solid var(--blue);
    border-radius: var(--radius);
    box-shadow: var(--panel-lift), inset 0 1px 0 rgba(255, 255, 255, 0.12);
    backdrop-filter: blur(var(--panel-blur));
    -webkit-backdrop-filter: blur(var(--panel-blur));
    animation: toast-in var(--motion-base) var(--ease-entrance);
}

.toast.leaving {
    animation: toast-out var(--motion-hover) var(--ease-standard) forwards;
}

.toast-success { border-left-color: var(--green); }
.toast-error { border-left-color: var(--danger); }
.toast-info { border-left-color: var(--blue); }

.toast-icon { flex-shrink: 0; margin-top: 1px; }

.toast-body { flex: 1; min-width: 0; }
.toast-title { font-weight: 700; margin-bottom: 0.1rem; }
.toast-message { font-size: 0.85rem; color: var(--text-secondary); white-space: pre-line; }

.toast-close {
    flex-shrink: 0;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 0.15rem;
    transition: color var(--motion-hover) var(--ease-standard);
}

.toast-close:hover { color: var(--text-strong); }

@keyframes toast-in {
    from { opacity: 0; transform: translateX(26px); }
    to { opacity: 1; transform: translateX(0); }
}

@keyframes toast-out {
    to { opacity: 0; transform: translateX(26px); }
}

/* --- Skeletons ----------------------------------------------------------------
 * A loading placeholder that shows structure rather than a bare spinner. */
.skeleton {
    background: linear-gradient(90deg,
        rgba(255, 255, 255, 0.05) 25%,
        rgba(255, 255, 255, 0.13) 50%,
        rgba(255, 255, 255, 0.05) 75%);
    background-size: 200% 100%;
    border-radius: var(--radius);
    animation: shimmer 1.3s ease-in-out infinite;
}

@keyframes shimmer {
    from { background-position: 200% 0; }
    to { background-position: -200% 0; }
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* --- Scrollbars ---------------------------------------------------------------
 * Traditional, always visible, wide enough to grab. A raised bevelled thumb on a
 * recessed track — a desktop scrollbar, not the auto-hiding mobile sliver. */
::-webkit-scrollbar {
    width: 16px;
    height: 16px;
}

::-webkit-scrollbar-track {
    background: #050505;
    box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.8);
}

::-webkit-scrollbar-thumb {
    border: 1px solid #000;
    border-radius: 5px;
    background: linear-gradient(to right, var(--blue-bright), var(--blue-deep));
    box-shadow:
        inset 1px 1px 0 rgba(255, 255, 255, 0.4),
        inset -1px -1px 0 rgba(0, 0, 0, 0.4);
    min-height: 40px;
}

::-webkit-scrollbar-thumb:hover {
    filter: brightness(1.12);
}

::-webkit-scrollbar-corner {
    background: #050505;
}

/* Reduced motion: every flourish collapses to an instant state change. The state
   itself still lands (a lift, a colour, a progress width) — motion never carries
   information on its own. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
