/*
 * admin.css — shared base styles and brand tokens for the Loran admin area.
 * Page-specific layout (hero split on login, topbar on dashboard, etc.)
 * stays inline in the respective Thymeleaf templates.
 */

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

:root {
    /* Brand palette — Mustard A, decided in task #15, lightened one nuance during the post-Phase-3 demo. */
    --brand-mustard:         #d9b14a;
    --brand-mustard-light:   #e6c365;
    --brand-mustard-dark:    #b58a28;
    --brand-mustard-darker:  #8a6e20;
    --brand-mustard-soft:    #f3eedb;
    --brand-mustard-text:    #5a4f15;

    /* Single :focus-visible outline colour for every admin control: the dark mustard
       (#8a6e20), 3.75:1 or better on every admin surface (WCAG 1.4.11 asks 3:1; the
       former 45 % mustard measured 1.3:1 — B5-02, ADR-0042). Folds together three
       drifted values the admin stylesheets had copied apart (audit D4). The gallery
       family keeps its own --gallery-focus-ring. */
    --admin-focus-ring:      var(--brand-mustard-darker);
    /* The same ring on a mustard surface (topbar, brand buttons), where the dark
       mustard would sit at about 1.9:1 against the gradient. Used by the focus rules
       of .topbar and the brand-gradient buttons. */
    --focus-ring-on-brand:   var(--color-text);

    /* Neutral palette. */
    --color-text:        #1f2937;
    /* 5.06:1 on --color-bg-muted, 6.13:1 on white (was #6b7280: 3.99:1 on --color-bg-muted — B5-06). */
    --color-text-muted:  #5b6270;
    --color-text-strong: #374151;
    --color-bg:          #ffffff;
    --color-bg-subtle:   #fafaf9;
    /* One shade below --color-bg-subtle. Used by the .admin-upload-video placeholder stripe. */
    --color-bg-muted:    #ece9e4;
    --color-border:      #d6d3d1;
    /* Border of form fields and checkboxes only (WCAG 1.4.11 needs 3:1: 4.38:1 on white,
       4.20:1 on --color-bg-subtle). Dividers and cards keep the light --color-border —
       decorative lines are exempt (B5-04). */
    --color-border-field: #7c7873;

    /* Notice surfaces (error / info). */
    --notice-error-bg:     #fff5f3;
    --notice-error-border: #f5c4ba;
    --notice-error-text:   #7a2a1f;
    --notice-info-bg:      #f5efe0;
    --notice-info-border:  #e0d4a8;
    --notice-info-text:    #5b4a17;

    /*
     * Moderation status palette — shared across admin + gallery surfaces.
     * APPROVED uses a warm olive (Hue ~70°, analog to mustard ~43°)
     * instead of the cold Tailwind emerald — keeps the "green = OK"
     * convention while harmonising with the brand's yellow pigment.
     */
    --status-pending-dot:    #d9b14a;
    --status-approved-dot:   #8a9a4a;
    --status-rejected-dot:   #ef4444;
    /* Trash: neutral grey — soft-deleted rows are out of the moderation lifecycle. */
    --status-trashed-dot:    #9b9690;
    --status-pending-bg:     #fff7e0;
    --status-pending-text:   #7a5a17;
    --status-pending-border: #e8d28f;
    --status-approved-bg:    #f3f5dc;
    --status-approved-text:  #4a5a1e;
    --status-approved-border:#c5cf8a;
    --status-rejected-bg:    #fef2f2;
    --status-rejected-text:  #7a2a1f;
    --status-rejected-border:#fca5a5;

    /*
     * Semantic action colours (#469). One colour = one meaning, project-wide,
     * so the same action always looks the same and a button's danger is
     * readable from its colour alone. The five meanings all draw on the
     * existing brand + status palette — nothing new is introduced.
     *
     *   Freigeben / wiederherstellen / zur Familie  → olive  (mirrors --status-approved)
     *   Ablehnen  (reversible hide)                 → amber  (caution, not danger)
     *   Löschen / widerrufen (irreversible)         → red    (the one destructive colour)
     *   Ins Private                                 → plum   (a genuinely separate realm)
     *   bearbeiten / Tags / abbrechen               → neutral ghost (see .secondary-button etc.)
     *
     * Primary/confirm actions stay mustard (the brand) via .button-mustard.
     * The gallery and vault login screens keep their editorial outline button
     * by deliberate exception (the admin login is a normal mustard primary).
     * Superseded the per-action rainbow (blue/teal/terracotta album accents,
     * grey delete, red reject) the earlier #187 treatment introduced.
     */
    /* The -from colours were darkened at the same hue so the white 13 px labels reach
       4.5:1 at the light end of the gradient (B5-05: 3.09 / 3.32 / 3.87 before). */
    --action-approve-from: #6f7c3c;
    --action-approve-to:   #5e6f2d;
    /* Ablehnen = muted amber: warmer/more orange than the mustard primary,
       clearly not the delete-red — reversible, so caution rather than danger. */
    --action-reject-from:  #a4682b;
    --action-reject-to:    #8a561c;
    /* Löschen/widerrufen = the reject-red freed up by the amber move above:
       the single destructive colour, reserved for the one irreversible action. */
    --action-delete-from:  #bd5750;
    --action-delete-to:    #a23f39;
    /* Ins Private (#448) — muted plum, distinct from every function colour above
       so "move to the vault" never reads as approve/reject/delete. Used by
       .ctx-btn.private in dashboard-selection.css. */
    --action-private-from: #7a5a86;
    --action-private-to:   #574063;
    /* The quiet companions of the plum pair, for surfaces that name the private
       realm rather than acting on it: the access-card target badge and the
       picked target option (#477). Same relationship the status palette has
       between its dot and its bg/border. */
    --action-private-soft:   #f2edf5;
    --action-private-border: #cdbcd6;
}

html, body {
    margin: 0;
    padding: 0;
    min-height: 100vh;
    color: var(--color-text);
    font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 1rem;
    line-height: 1.5;
}

.notice {
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 0.875rem;
    margin-bottom: 20px;
}
.notice-error {
    background: var(--notice-error-bg);
    border: 1px solid var(--notice-error-border);
    color: var(--notice-error-text);
}
.notice-info {
    background: var(--notice-info-bg);
    border: 1px solid var(--notice-info-border);
    color: var(--notice-info-text);
}
/* Success uses the same olive palette as the APPROVED moderation
   status — analog harmony with the brand-mustard hue. */
.notice-success {
    background: var(--status-approved-bg);
    border: 1px solid var(--status-approved-border);
    color: var(--status-approved-text);
}

/*
 * Filled Mustard call-to-action — shared base for primary buttons
 * (login submit, error-page back-to-login, future admin actions).
 * Page-specific layout (width, padding, font-size, display mode)
 * stays in the consuming stylesheet.
 */
.button-mustard {
    color: var(--color-text);
    background: linear-gradient(180deg, var(--brand-mustard) 0%, var(--brand-mustard-dark) 100%);
    border: none;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 600;
    font-family: inherit;
    text-decoration: none;
    transition: filter 120ms ease, transform 80ms ease;
}
.button-mustard:hover { filter: brightness(1.05); }
.button-mustard:active { transform: translateY(1px); }
.button-mustard:focus-visible {
    outline: 3px solid var(--admin-focus-ring);
    outline-offset: 2px;
}

/*
 * Visually hides an element while keeping it readable by screen
 * readers — the standard WebAIM clip-path recipe. Used by the admin
 * dashboard to expose a page-level <h1> to assistive tech without
 * altering the visual topbar design.
 */
.screen-reader-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/*
 * Application-wide footer (issue #260) — editorial style C, identical on every
 * page across both visual families. Logo + copyright year cluster on the left,
 * build version on the right. Lives here because admin.css is the one
 * stylesheet every page loads. Sits at the end of content, never sticky.
 *
 * --paper and --ink-muted belong to the gallery family; the literal fallbacks
 * keep the footer identical on admin-only pages where those tokens are absent.
 */
.app-footer {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 24px;
    background: var(--paper, #f7f1e3);
    border-top: 2px solid var(--brand-mustard-dark);
    color: var(--ink-muted, #6b6760);
}

.app-footer__logo {
    height: 30px;
    width: auto;
    display: block;
}

.app-footer__copyright {
    font-size: 0.75rem;
}

.app-footer__version {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    text-transform: uppercase;
    font-size: 0.75rem;
    letter-spacing: 0.16em;
}

@media (max-width: 480px) {
    .app-footer {
        padding: 14px 16px;
        gap: 10px;
    }
}

/* ---------- Skip link (#561, WCAG 2.4.1) ----------
   The first tab stop of every page that has navigation to skip: admin pages, the vault and
   the gallery. Hidden above the viewport until it has focus. The gallery overrides only the
   background (gallery-shell.css) to keep its warm ink. Its target is the page's <main>, which
   takes programmatic focus (tabindex="-1") and needs no focus ring of its own. */
.skip-link {
    position: absolute;
    top: -100px;
    left: 8px;
    background: var(--color-text);
    color: #ffffff;
    padding: 12px 16px;
    border-radius: 6px;
    text-decoration: none;
    z-index: 100;
    font-weight: 500;
}
.skip-link:focus { top: 8px; }
main[tabindex="-1"]:focus { outline: none; }

/* ---------- Reduced motion (#561, ADR-0050, WCAG 2.3.3) ----------
   One rule for every page: under the OS setting every transition and animation collapses to
   (almost) nothing and smooth scrolling is off. It needs !important because the declarations it
   overrides sit in class selectors of other stylesheets. The one named exception is the toast
   window (dashboard-detail.css): the toast disappears through its own animation, so it keeps a
   fade without the slide instead. A new animation whose end state hides content belongs there too. */
@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;
    }
}

/* ---------- Language switcher (#362, legibility #561) ----------
   Shared across both visual families; admin.css is loaded by every page (same
   pattern as .app-footer). Flags are same-origin SVG <img> (CSP img-src 'self').
   The state is a ring in the text colour: thin and slightly desaturated when inactive, thick
   and full colour when active. No opacity: it would fade the ring too, and the ring is what has
   to reach 3:1 on the mustard topbar (7.2:1 at its light end, 4.6:1 at its dark end) and on
   paper. The old mustard ring was invisible on the mustard topbar. Guarded by
   LanguageSwitcherRulesTest. */
.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: 9px;
}

.lang-switch a {
    display: inline-block;
    line-height: 0;
    padding: 2px;
    border-radius: 4px;
    text-decoration: none;
}

.lang-switch .flag {
    display: block;
    width: 28px;
    height: 19px;
    border-radius: 3px;
    object-fit: cover;
    box-shadow: 0 0 0 1px var(--color-text);
    filter: grayscale(0.5);
}

.lang-switch a:hover .flag {
    filter: grayscale(0.2);
}

.lang-switch a[aria-current="true"] .flag {
    box-shadow: 0 0 0 2px var(--color-text);
    filter: none;
}

.lang-switch a:focus-visible {
    outline: 3px solid var(--admin-focus-ring);
    outline-offset: 2px;
}

/* Header-less pages (logins, paused, error) pin the switcher to the corner. */
.lang-switch--corner {
    position: fixed;
    top: 14px;
    right: 18px;
    z-index: 5;
}

/* On the admin topbar the switcher sits next to the logout button; the gallery
   browse topbar has no .inner wrapper, so this margin only applies to admin. */
.topbar .inner .lang-switch {
    margin-right: 14px;
}

/*
 * Show/hide-password toggle (#548). login.js wraps every password field of a
 * login form in .password-field and appends the button; the field gets room on
 * the right so typed text never runs under the icon. The button is 44x44 px
 * (touch target) and sits inside the 48 px field. The attribute selector on the
 * input lifts its specificity above the per-page input rules (.wrapper input[...],
 * .gallery-field input) that would otherwise reset the padding.
 */
.password-field { position: relative; display: block; }
.password-field > input.has-toggle[type] { padding-right: 52px; }
.password-toggle {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--color-text-strong);
    cursor: pointer;
}
.password-toggle svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.password-toggle:hover { background: rgba(0, 0, 0, 0.06); }
.password-toggle:focus-visible {
    outline: 3px solid var(--admin-focus-ring);
    outline-offset: -3px;
}

/* Touch targets (#552, ADR-0043): each flag keeps its drawn size inside its own 44×44 box. */
@media (any-pointer: coarse) {
    .lang-switch { gap: 0; }
    .lang-switch a {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 44px;
        height: 44px;
        padding: 0;
    }
}
