/* Inter, self-hosted. Origin and licence: see wwwroot/fonts/README.md.
   Inter v20 on Google Fonts is a variable font, so one file per subset serves every weight the
   site uses (400 regular, 500 medium, 700 bold) via the weight axis. No runtime call to any
   third-party origin: the page must not depend on Google to render its own text. */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('fonts/inter-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
        U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('fonts/inter-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
        U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
        U+2C60-2C7F, U+A720-A7FF;
}

/* The reference's Tailwind theme (index.html), translated once. */
:root {
    --background: #0f0f0f;
    --surface: #1a1a1a;
    --primary: #3b82f6;
    --muted: #262626;
    --muted-foreground: #a3a3a3;
    --shell: #09090b;
    --text: #e5e5e5;
    --text-strong: #f3f4f6;
    --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

    /* ---- public first-fold layout tokens ------------------------------------------------------
       One source of truth for the public shell's spacing and the fold budget. Scoped CSS cannot
       declare :root custom properties, so — like the --adm- vocabulary below — the public layout
       vocabulary lives here and every public component consumes it instead of hardcoding a gutter,
       a gap or a showcase height.

       --admin-toolbar-height is the single administrative offset: 0 for a visitor, and the compact
       toolbar height for an administrator (derived once, just below, via :has()). The first fold
       (hero + primary showcase) is sized from 100dvh minus this — and nothing accumulates it a
       second time per component. */
    --admin-toolbar-height: 0px;
    --page-inline: clamp(1rem, 4vw, 2rem);
    --hero-gap: clamp(0.75rem, 2.2vh, 1.75rem);
    /* The album band's height budget. On desktop the band grows to fill the height the hero leaves in
       the fold (so it sits right under the hero, not floating in a centred void) and this is only its
       upper bound; on a tall screen the band caps here and the small remainder pools quietly at the
       bottom of the fold. On mobile it is the band's own height. */
    --showcase-height: clamp(18rem, 72vh, 44rem);
}

/* The administrative offset, computed a single time from the presence of the one toolbar the shared
   layout renders. A visitor has no [data-testid='admin-bar'] in the tree, so the token stays 0px and
   the fold reserves nothing; an administrator gets the compact bar's height. The value inherits down
   into .shell/.fold, which is where the first fold subtracts it. */
body:has([data-testid='admin-bar']) {
    --admin-toolbar-height: clamp(2.75rem, 6vh, 3.25rem);
}

html {
    box-sizing: border-box;
}

*,
*::before,
*::after {
    box-sizing: inherit;
}

body {
    margin: 0;
    background-color: var(--background);
    color: var(--text);
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
}

::selection {
    background: #fff;
    color: #000;
}

/* `Routes.razor` uses <FocusOnNavigate Selector="h1" /> to move a screen reader to the new page
   after client-side navigation. That gives the heading a focus ring, which a reader cannot act on
   and which the reference does not have — so the hero would render with a white box drawn round it.
   Suppressed only for the heading, which is not operable; every real control keeps its ring. */
h1:focus,
h1:focus-visible {
    outline: none;
}

/* The Identity pages under /Account are plain server-rendered forms that still use Bootstrap; the
   loader below is scoped to them. These few rules keep them legible on the dark background without
   pulling the template's stylesheet back into the public page. */
.validation-message,
.text-danger {
    color: #ef4444;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

/* ---------------------------------------------------------------------------------------------
   Admin workspace tokens. Scoped CSS cannot declare :root custom properties, so the admin's
   design vocabulary lives here, prefixed --adm- to stay out of the public site's way. Every admin
   component consumes these; none hardcodes its own colour, radius, shadow, focus or motion. */
:root {
    --adm-surface: #101013;
    --adm-surface-raised: #17171b;
    --adm-line: rgba(255, 255, 255, 0.12);
    --adm-line-strong: rgba(255, 255, 255, 0.24);
    --adm-text: #e5e5e5;
    --adm-text-strong: #ffffff;
    --adm-text-dim: rgba(255, 255, 255, 0.58);
    --adm-text-faint: rgba(255, 255, 255, 0.44);
    --adm-ok: #4ade80;
    --adm-danger: #ef4444;
    --adm-accent: #ffffff;
    --adm-radius: 0.875rem;
    --adm-radius-s: 0.5rem;
    --adm-shadow-lift: 0 16px 40px rgba(0, 0, 0, 0.55);
    --adm-shadow-pop: 0 10px 30px rgba(0, 0, 0, 0.5);
    --adm-focus-ring: 0 0 0 2px #09090b, 0 0 0 4px rgba(255, 255, 255, 0.9);
    --adm-motion: 180ms;

    /* --- mobile-first layout system --------------------------------------------------------- --
       These are the phone's values. The min-width blocks below raise them for tablet and desktop;
       nothing else in the admin hardcodes a gutter, a max width, a card padding or a tap size, so
       the whole workspace breathes from one place. Safe-area insets keep every surface off the
       notch, the home indicator and rounded corners. */
    --adm-safe-top: env(safe-area-inset-top, 0px);
    --adm-safe-right: env(safe-area-inset-right, 0px);
    --adm-safe-bottom: env(safe-area-inset-bottom, 0px);
    --adm-safe-left: env(safe-area-inset-left, 0px);

    /* Real 16px lateral gutter on the smallest phones (no surface touches the screen edge). */
    --adm-gutter: 16px;
    /* The workspace is a full-bleed column on the phone; desktop reins it in below. */
    --adm-page-max: 100%;
    /* Vertical rhythm between cards/sections, and the padding inside a card. */
    --adm-section-gap: 16px;
    --adm-card-padding: 16px;
    /* Space between the end of the navigation and the first surface. */
    --adm-content-top: 16px;
    /* How far a surface's own sticky element sits from the top (admin bar height). 0 on mobile:
       section heads are static in flow there and the Save lives in a bottom action bar instead. */
    --adm-sticky-offset: 0px;
    /* Touch ergonomics: 44px minimum target, 48px input height, 16px input font (no iOS zoom),
       13px auxiliary text (labels/hints stay legible for frequent one-handed use). */
    --adm-tap: 44px;
    --adm-input-h: 48px;
    --adm-input-font: 16px;
    --adm-label-font: 13px;
    --adm-hint-font: 13px;
    /* Bottom action bar height, so content can reserve a matching tail and never hide behind it. */
    --adm-actionbar-h: 60px;
}

/* Tablet: a little more air, and section heads can begin to stick under the bar. */
@media (min-width: 768px) {
    :root {
        --adm-gutter: 24px;
        --adm-page-max: 46rem;
        --adm-section-gap: 20px;
        --adm-card-padding: 20px;
        --adm-content-top: 28px;
    }
}

/* Desktop: a centred column that uses the width without becoming an edge-to-edge band, and a
   sticky offset equal to the admin bar so inset actions clear it. Inputs relax back to 15px. */
@media (min-width: 1024px) {
    :root {
        --adm-gutter: 32px;
        --adm-page-max: 80rem;
        --adm-section-gap: 24px;
        --adm-card-padding: 24px;
        --adm-content-top: 32px;
        --adm-sticky-offset: 3.5rem;
        --adm-input-h: 44px;
        --adm-input-font: 15px;
    }
}

/* One switch turns the admin's motion off everywhere: every transition and animation in the admin
   derives its duration from this token. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --adm-motion: 0ms;
    }
}

/* The one save/status bar, defined once and shared by settings and the album editor (global, not
   scoped, so both surfaces reposition the same element instead of duplicating a Save button). On
   the phone it is a full-width bottom bar over the safe area; on desktop it becomes a centred
   floating pill that never bleeds to the screen edges. Content reserves a matching tail via the
   admin workspace's bottom padding, so it never hides the last field. */
.adm-actionbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 70;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-top: 0.625rem;
    padding-bottom: calc(0.625rem + var(--adm-safe-bottom));
    padding-left: calc(var(--adm-gutter) + var(--adm-safe-left));
    padding-right: calc(var(--adm-gutter) + var(--adm-safe-right));
    background: rgba(9, 9, 11, 0.94);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--adm-line);
}

.adm-actionbar__spacer {
    flex: 1;
    min-width: 0;
}

@media (min-width: 1024px) {
    .adm-actionbar {
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        bottom: 1.25rem;
        width: min(var(--adm-page-max), calc(100vw - 2 * var(--adm-gutter)));
        padding: 0.5rem 0.625rem 0.5rem 1.375rem;
        border: 1px solid var(--adm-line);
        border-radius: 9999px;
        box-shadow: var(--adm-shadow-pop);
    }
}
