/*
 * CffVaultManager base theme — "Glow & Mesh Gradient", the design system shared by CffVaultManager,
 * Resource Scheduler and NIS2 Assessment. This repo is its reference implementation:
 * docs/ui-guidelines.md documents the tokens, light/dark values, components and motion rules to
 * port into the other two products. The shield logo and the wordmark stay the only elements of
 * CffVaultManager's own identity.
 *
 * Token names describe ROLES, not hues (--brand-primary, not --brand-blue): the values have
 * moved three times already, and a name that spells out a color starts lying the moment the palette
 * changes.
 *
 * Every text color below is checked for WCAG AA (4.5:1) not just against --brand-bg but against
 * the brightest point of the mesh background behind it (two sphere peaks overlapping): that is
 * what sets --brand-mesh-alpha per theme, not taste. Change a sphere's alpha or a text color and
 * the check has to be redone (docs/ui-guidelines.md, "Contrasto sopra le sfumature").
 *
 * Motion: the mesh is static. Only selected/active elements animate (.glow-select, once, on
 * becoming active — never looping, to stay within WCAG 2.2.2) plus hover/focus of the main
 * action button. prefers-reduced-motion removes all of it (end of this file).
 *
 * Loaded after lib/bootstrap/css/bootstrap.min.css.
 */

/* Plus Jakarta Sans, self-hosted (fontsource-variable 5.3.0, OFL — fonts/plus-jakarta-sans-OFL.txt).
   The app ships a Content-Security-Policy (Caddyfile, currently Report-Only) with
   `default-src 'self'` and no `font-src`: a CDN font would report a violation on a policy that
   today reports zero, and enforcement is deferred, not declined (docs/pentest-report-2026-08-20.md,
   finding 4). A password manager should not hand a third party a request on every page load
   either. Variable font: one file per subset covers weights 200-800. */
@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url('fonts/plus-jakarta-sans-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: 'Plus Jakarta Sans';
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url('fonts/plus-jakarta-sans-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;
}

:root,
[data-bs-theme="light"] {
    --brand-primary: #0F628C;
    --brand-primary-rgb: 15, 98, 140;
    --brand-primary-hover: #0C4876;
    --brand-primary-active: #033360;
    --brand-secondary: #475569;
    --brand-secondary-rgb: 71, 85, 105;
    --brand-accent: #8A5200;
    --brand-accent-rgb: 138, 82, 0;
    --brand-ink: #0B1E33;
    --brand-bg: #F5F8FB;
    --brand-bg-rgb: 245, 248, 251;

    /* Surfaces are translucent "glass" over the static mesh — no backdrop-filter: the mesh is
       already blurred, so blurring it again per card would cost GPU time for no visible change.
       Anything that floats OVER other content (modal, drawer, dropdown, cookie notice) uses the
       -solid variant instead, or the page would show through it. */
    --brand-surface: rgba(255, 255, 255, 0.82);
    --brand-surface-solid: #FFFFFF;
    --brand-surface-border: rgba(15, 98, 140, 0.12);
    --brand-hover-bg: rgba(15, 98, 140, 0.07);
    --brand-topbar-bg: rgba(245, 248, 251, 0.86);
    --brand-overlay: rgba(3, 20, 40, 0.45);
    --brand-field-bg: #FFFFFF;
    --brand-field-border: #7D8BA0;
    --brand-on-primary: #FFFFFF;

    /* Text, icons and links take the logo's darker blue even in light: it keeps AA (6.6:1) at the
       worst point of the mesh, where the fill blue would drop to 4.6. */
    --brand-primary-contrast: #0C4876;
    --brand-secondary-contrast: var(--brand-secondary);

    /* Mesh background (Layout/MainLayout.razor). Three glow hues sampled from the shield logo —
       deep blue, teal-blue, cyan — shared by the spheres, the gradient borders and the glow
       shadows. On light the spheres are painted with a normal blend at a lower alpha (pastel);
       `screen` only brightens, which on a near-white canvas means nothing shows at all. */
    --brand-glow-1-rgb: 15, 98, 140;
    --brand-glow-2-rgb: 31, 140, 167;
    --brand-glow-3-rgb: 64, 193, 200;
    --brand-mesh-alpha: 0.24;
    --brand-mesh-opacity: 0.8;
    --brand-mesh-blend: normal;

    /* Gradients. Text and action gradients stay inside a range that passes AA at every stop
       (white on the action gradient, the gradient on --brand-bg and on the mesh); the logo's
       teal-blue and cyan never carry text in the light theme (white on #1F8CA7 is 3.9:1). */
    --brand-gradient-text: linear-gradient(135deg, #033360 0%, #0F628C 55%, #0E6E8A 100%);
    --brand-gradient-action: linear-gradient(90deg, #0C4876 0%, #0F628C 50%, #0C4876 100%);
    --brand-gradient-border: linear-gradient(135deg, rgb(var(--brand-glow-3-rgb)), rgb(var(--brand-glow-1-rgb)), rgb(var(--brand-glow-2-rgb)), rgb(var(--brand-glow-3-rgb)));
    --brand-selection-bg: linear-gradient(90deg, rgba(var(--brand-glow-1-rgb), 0.10), rgba(var(--brand-glow-2-rgb), 0.05) 60%, rgba(var(--brand-glow-3-rgb), 0.10));
    --brand-glow-shadow: 0 0.5rem 1.5rem -0.5rem rgba(var(--brand-glow-1-rgb), 0.4), 0 0.25rem 0.75rem -0.25rem rgba(var(--brand-glow-3-rgb), 0.3);
    --brand-selection-shadow: 0 0.25rem 1rem -0.35rem rgba(var(--brand-glow-1-rgb), 0.4);
    --brand-glow-border-opacity: 0.45;

    --brand-shadow-sm: 0 0.125rem 0.5rem rgba(3, 20, 40, 0.06);
    --brand-shadow-md: 0 0.5rem 1.25rem -0.25rem rgba(3, 20, 40, 0.14);
    --brand-shadow-lg: 0 1rem 3rem -1rem rgba(3, 20, 40, 0.3);

    /* Shapes and measures: controls 8px, cards/menus 12px, dialogs 14px, content sheet 16px,
       glow cards 24px, minimum touch target 44px. */
    --brand-radius-control: 0.5rem;
    --brand-radius-card: 0.75rem;
    --brand-radius-dialog: 0.875rem;
    --brand-radius-sheet: 1rem;
    --brand-radius-glow: 1.5rem;
    --brand-touch-target: 2.75rem;

    --bs-font-sans-serif: "Plus Jakarta Sans", "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;

    --bs-body-bg: var(--brand-bg);
    --bs-body-color: var(--brand-ink);
    --bs-secondary-color: #475569;
    --bs-border-color: #DCE3EA;
    --bs-secondary-bg: #E8EEF4;
    --bs-tertiary-bg: #EFF3F7;

    --bs-primary: var(--brand-primary);
    --bs-primary-rgb: var(--brand-primary-rgb);
    --bs-primary-text-emphasis: var(--brand-primary-contrast);
    --bs-primary-bg-subtle: #DCEBF3;
    --bs-primary-border-subtle: #A9CDE0;

    --bs-secondary: var(--brand-secondary);
    --bs-secondary-rgb: var(--brand-secondary-rgb);
    --bs-secondary-text-emphasis: var(--brand-secondary);
    --bs-secondary-bg-subtle: #E8EEF4;
    --bs-secondary-border-subtle: #C5D0DC;

    /* Info is indigo, not blue: next to a blue primary, a blue info alert or chip would read as a
       primary-tinted element. */
    --bs-info: #4338CA;
    --bs-info-rgb: 67, 56, 202;
    --bs-info-text-emphasis: #3730A3;
    --bs-info-bg-subtle: #E3E2F8;
    --bs-info-border-subtle: #BDB9EE;

    --bs-success: #1A6B3D;
    --bs-success-rgb: 26, 107, 61;
    --bs-success-text-emphasis: #165B34;
    --bs-success-bg-subtle: #DCEEE4;
    --bs-success-border-subtle: #A9D6BE;

    --bs-warning: #A23F07;
    --bs-warning-rgb: 162, 63, 7;
    --bs-warning-text-emphasis: #8A3606;
    --bs-warning-bg-subtle: #FAE6D8;
    --bs-warning-border-subtle: #EEC0A0;

    --bs-danger: #B02E25;
    --bs-danger-rgb: 176, 46, 37;
    --bs-danger-text-emphasis: #932921;
    --bs-danger-bg-subtle: #F7DEDC;
    --bs-danger-border-subtle: #E9B0AC;

    --bs-link-color: var(--brand-primary-contrast);
    --bs-link-color-rgb: 12, 72, 118;
    --bs-link-hover-color: #033360;
    --bs-link-hover-color-rgb: 3, 51, 96;

    --bs-border-radius: var(--brand-radius-control);
    --bs-border-radius-sm: var(--brand-radius-control);
    --bs-border-radius-lg: var(--brand-radius-card);
    --bs-border-radius-xl: var(--brand-radius-sheet);
}

/*
 * Dark theme: the canvas of the original "Glow & Mesh" sample. Own values, lighter and less
 * saturated than the light ones, so text keeps AA on a near-black canvas lit by the spheres.
 * Declared after the `:root, [data-bs-theme="light"]` block on purpose: `:root` always matches
 * (it's what makes that block double as the no-JS fallback), so on equal specificity the block
 * that comes later in the file has to be this one.
 */
[data-bs-theme="dark"] {
    --brand-bg: #07111F;
    --brand-bg-rgb: 7, 17, 31;
    --brand-ink: #E6EDF5;
    --brand-accent: #E0A84A;
    --brand-accent-rgb: 224, 168, 74;

    --brand-surface: rgba(12, 27, 46, 0.78);
    --brand-surface-solid: #0C1B2E;
    --brand-surface-border: rgba(255, 255, 255, 0.08);
    --brand-hover-bg: rgba(255, 255, 255, 0.06);
    --brand-topbar-bg: rgba(7, 17, 31, 0.8);
    --brand-overlay: rgba(2, 8, 16, 0.7);
    --brand-field-bg: #091626;
    --brand-field-border: #5E7590;
    --brand-on-primary: #04142A;

    /* The logo's cyan for text, icons and links. Filled buttons flip to dark text on a
       teal-blue -> cyan gradient: white on any blue bright enough to show on this canvas fails AA. */
    --brand-primary-contrast: #40C1C8;
    --brand-secondary-contrast: #A9B6C6;

    --brand-mesh-alpha: 0.32;
    --brand-mesh-blend: screen;

    --brand-gradient-text: linear-gradient(135deg, #98CFD8 0%, #40C1C8 55%, #7AB8D6 100%);
    --brand-gradient-action: linear-gradient(90deg, #2A9DB5 0%, #40C1C8 50%, #2A9DB5 100%);
    --brand-selection-bg: linear-gradient(90deg, rgba(var(--brand-glow-1-rgb), 0.30), rgba(var(--brand-glow-2-rgb), 0.14) 60%, rgba(var(--brand-glow-3-rgb), 0.12));
    --brand-glow-shadow: 0 0.75rem 2rem -0.75rem rgba(var(--brand-glow-3-rgb), 0.35), 0 0.25rem 1rem -0.25rem rgba(var(--brand-glow-2-rgb), 0.35);
    --brand-selection-shadow: 0 0 1rem -0.25rem rgba(var(--brand-glow-3-rgb), 0.4);
    --brand-glow-border-opacity: 0.4;

    --brand-shadow-sm: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.4);
    --brand-shadow-md: 0 0.5rem 1.5rem -0.25rem rgba(0, 0, 0, 0.5);
    --brand-shadow-lg: 0 1rem 3rem -0.5rem rgba(0, 0, 0, 0.6);

    --bs-body-bg: var(--brand-bg);
    --bs-body-color: var(--brand-ink);
    --bs-secondary-color: #A9B6C6;
    --bs-border-color: #1C2D42;
    --bs-secondary-bg: #13233A;
    --bs-tertiary-bg: #0F1D31;

    --bs-primary: var(--brand-primary-contrast);
    --bs-primary-rgb: 64, 193, 200;
    --bs-primary-text-emphasis: var(--brand-primary-contrast);
    --bs-primary-bg-subtle: #0B2A3D;
    --bs-primary-border-subtle: #134560;

    --bs-secondary-text-emphasis: var(--brand-secondary-contrast);
    --bs-secondary-bg-subtle: #13233A;
    --bs-secondary-border-subtle: #22354D;

    --bs-info: #A5B4FC;
    --bs-info-rgb: 165, 180, 252;
    --bs-info-text-emphasis: #C7D2FE;
    --bs-info-bg-subtle: #1B1F4B;
    --bs-info-border-subtle: #2E3480;

    --bs-success: #5BC48A;
    --bs-success-rgb: 91, 196, 138;
    --bs-success-text-emphasis: #8BD8AE;
    --bs-success-bg-subtle: #062814;
    --bs-success-border-subtle: #0F4527;

    --bs-warning: #F0A35E;
    --bs-warning-rgb: 240, 163, 94;
    --bs-warning-text-emphasis: #F5C293;
    --bs-warning-bg-subtle: #2E1600;
    --bs-warning-border-subtle: #52290A;

    --bs-danger: #F28B82;
    --bs-danger-rgb: 242, 139, 130;
    --bs-danger-text-emphasis: #F7B0AA;
    --bs-danger-bg-subtle: #3A0B07;
    --bs-danger-border-subtle: #5E1912;

    --bs-link-color: var(--brand-primary-contrast);
    --bs-link-color-rgb: 64, 193, 200;
    --bs-link-hover-color: #98CFD8;
    --bs-link-hover-color-rgb: 152, 207, 216;
}

/* Users who asked the OS for less transparency get opaque surfaces and no glass. */
@media (prefers-reduced-transparency: reduce) {
    :root,
    [data-bs-theme="light"],
    [data-bs-theme="dark"] {
        --brand-surface: var(--brand-surface-solid);
        --brand-topbar-bg: var(--brand-surface-solid);
    }
}

/* The watermark shield needs a lift to stay visible against the near-black canvas — at the light
   theme's 0.05 opacity it would all but disappear here. */
[data-bs-theme="dark"] body::before {
    opacity: 0.09;
    filter: saturate(1.3) brightness(1.7);
}

/* Bootstrap compiles its own colors into .btn-*, .text-bg-* and .form-check-input:checked at Sass
   build time. Unlike .bg-primary/.border-primary/etc, those are NOT wired to the --bs-* custom
   properties above, so overriding a variable alone silently does nothing for them: each one has
   to be pinned explicitly here, in both themes.

   .btn-info is pinned to the PRIMARY role, not to the info role: it was the main action until
   September 2026 and may still turn up in older code or in the other products being ported. */
.btn-info,
.btn-primary {
    --bs-btn-color: var(--brand-on-primary);
    --bs-btn-bg: var(--brand-primary);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-color: var(--brand-on-primary);
    --bs-btn-hover-bg: var(--brand-primary-hover);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-color: var(--brand-on-primary);
    --bs-btn-active-bg: var(--brand-primary-active);
    --bs-btn-active-border-color: transparent;
    --bs-btn-disabled-color: var(--brand-on-primary);
    --bs-btn-disabled-bg: var(--brand-primary);
    --bs-btn-disabled-border-color: transparent;
    --bs-btn-focus-shadow-rgb: var(--brand-primary-rgb);
    /* "btn-gradient" of the shared system: the gradient sits on top of the solid color (which stays
       as the fallback), at 200% width so hover/focus can slide it to its other half. */
    background-image: var(--brand-gradient-action);
    background-size: 200% 100%;
    background-position: 0% 50%;
    background-origin: border-box;
    font-weight: 600;
    transition: background-position 0.45s ease, box-shadow 0.2s ease;
}

.btn-info:not(:disabled):hover,
.btn-info:focus-visible,
.btn-primary:not(:disabled):hover,
.btn-primary:focus-visible {
    background-position: 100% 50%;
    box-shadow: var(--brand-glow-shadow);
}

[data-bs-theme="dark"] .btn-info,
[data-bs-theme="dark"] .btn-primary {
    --bs-btn-bg: #2A9DB5;
    --bs-btn-hover-bg: #2A9DB5;
    --bs-btn-active-bg: #40C1C8;
    --bs-btn-disabled-bg: #2A9DB5;
    --bs-btn-focus-shadow-rgb: 64, 193, 200;
}

.btn-outline-info,
.btn-outline-primary {
    --bs-btn-color: var(--brand-primary-contrast);
    --bs-btn-border-color: var(--brand-primary-contrast);
    --bs-btn-hover-color: var(--brand-primary-contrast);
    --bs-btn-hover-bg: var(--bs-primary-bg-subtle);
    --bs-btn-hover-border-color: var(--brand-primary-contrast);
    --bs-btn-active-color: var(--brand-primary-contrast);
    --bs-btn-active-bg: var(--bs-primary-border-subtle);
    --bs-btn-active-border-color: var(--brand-primary-contrast);
    --bs-btn-disabled-color: var(--brand-primary-contrast);
    --bs-btn-disabled-border-color: var(--brand-primary-contrast);
    --bs-btn-focus-shadow-rgb: var(--brand-primary-rgb);
}

[data-bs-theme="dark"] .btn-outline-info,
[data-bs-theme="dark"] .btn-outline-primary {
    --bs-btn-focus-shadow-rgb: 64, 193, 200;
}

/* Neutral outlined button: buttons attached to a field (Copia, Mostra) and the top bar's own
   controls (theme toggle, notifications, Blocca). Bootstrap's compiled #6c757d grey matches
   neither theme's palette. */
.btn-outline-secondary {
    --bs-btn-color: var(--bs-secondary-color);
    --bs-btn-border-color: var(--brand-field-border);
    --bs-btn-hover-color: var(--brand-ink);
    --bs-btn-hover-bg: var(--bs-secondary-bg);
    --bs-btn-hover-border-color: var(--brand-field-border);
    --bs-btn-active-color: var(--brand-ink);
    --bs-btn-active-bg: var(--bs-secondary-bg);
    --bs-btn-active-border-color: var(--brand-field-border);
    --bs-btn-disabled-color: var(--bs-secondary-color);
    --bs-btn-disabled-border-color: var(--brand-field-border);
    --bs-btn-focus-shadow-rgb: var(--brand-secondary-rgb);
}

.btn-danger {
    --bs-btn-color: #FFFFFF;
    --bs-btn-bg: var(--bs-danger);
    --bs-btn-border-color: var(--bs-danger);
    --bs-btn-hover-color: #FFFFFF;
    --bs-btn-hover-bg: #962720;
    --bs-btn-hover-border-color: #962720;
    --bs-btn-active-color: #FFFFFF;
    --bs-btn-active-bg: #7E211B;
    --bs-btn-active-border-color: #7E211B;
    --bs-btn-disabled-color: #FFFFFF;
    --bs-btn-disabled-bg: var(--bs-danger);
    --bs-btn-disabled-border-color: var(--bs-danger);
    --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

[data-bs-theme="dark"] .btn-danger {
    --bs-btn-color: var(--brand-bg);
    --bs-btn-hover-color: var(--brand-bg);
    --bs-btn-hover-bg: #F5A39C;
    --bs-btn-hover-border-color: #F5A39C;
    --bs-btn-active-color: var(--brand-bg);
    --bs-btn-active-bg: var(--bs-danger-text-emphasis);
    --bs-btn-active-border-color: var(--bs-danger-text-emphasis);
    --bs-btn-disabled-color: var(--brand-bg);
}

.btn-outline-danger {
    --bs-btn-color: var(--bs-danger);
    --bs-btn-border-color: var(--bs-danger);
    --bs-btn-hover-color: var(--bs-danger-text-emphasis);
    --bs-btn-hover-bg: var(--bs-danger-bg-subtle);
    --bs-btn-hover-border-color: var(--bs-danger);
    --bs-btn-active-color: var(--bs-danger-text-emphasis);
    --bs-btn-active-bg: var(--bs-danger-border-subtle);
    --bs-btn-active-border-color: var(--bs-danger);
    --bs-btn-disabled-color: var(--bs-danger);
    --bs-btn-disabled-border-color: var(--bs-danger);
    --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

/* .text-bg-* pin their FOREGROUND at compile time and take the background from the variable, so
   the foreground has to follow the background it actually sits on: white on the light theme's
   dark fills, the canvas color on the dark theme's light fills. */
.text-bg-primary,
.text-bg-success,
.text-bg-danger,
.text-bg-warning,
.text-bg-info {
    color: #FFFFFF !important;
}

[data-bs-theme="dark"] .text-bg-primary,
[data-bs-theme="dark"] .text-bg-success,
[data-bs-theme="dark"] .text-bg-danger,
[data-bs-theme="dark"] .text-bg-warning,
[data-bs-theme="dark"] .text-bg-info {
    color: var(--brand-bg) !important;
}

/* Bootstrap's check mark is a white SVG: the dark theme puts the logo's teal-blue under it (white
   tick 3.9:1, fill 4.8:1 against the canvas) instead of the pale --bs-primary cyan (~2.2:1). */
.form-check-input:checked {
    background-color: var(--brand-primary);
    border-color: var(--brand-primary);
}

[data-bs-theme="dark"] .form-check-input:checked {
    background-color: #1F8CA7;
    border-color: #1F8CA7;
}

/* Field borders are their own role — darker than the divider lines, so an empty input still reads
   as an input (3:1 against the field). Bootstrap has no variable for it. */
.form-control,
.form-select {
    background-color: var(--brand-field-bg);
    border-color: var(--brand-field-border);
}

.form-control:focus,
.form-select:focus {
    background-color: var(--brand-field-bg);
    border-color: var(--brand-primary-contrast);
    box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}

.form-check-input:focus {
    border-color: var(--brand-primary-contrast);
    box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}

.dropdown-menu {
    --bs-dropdown-bg: var(--brand-surface-solid);
    --bs-dropdown-border-color: var(--brand-surface-border);
    --bs-dropdown-box-shadow: var(--brand-shadow-md);
    --bs-dropdown-link-active-bg: var(--brand-primary);
    box-shadow: var(--bs-dropdown-box-shadow);
}

.list-group {
    --bs-list-group-bg: var(--brand-surface);
}

/*
 * Design-system layer on top of the tokens: typography rhythm, elevation, motion and the reusable
 * patterns (glow card, selection glow, empty states, auth shell, vault tiles) shared by every page
 * in Web.Client. Everything here targets Bootstrap's own classes/markup so pages keep using plain
 * `card`/`list-group`/`table`/`btn` — no per-page CSS isolation file just to look consistent.
 * Blazor CSS isolation scopes rules to the *file* that owns them, not to a class name: that is
 * what once made `.login-shell`/`.login-card` apply to Login.razor and silently not to
 * Register.razor. Shared patterns therefore live here.
 */

/* The vertical scrollbar appears and disappears between pages — on Windows the classic scrollbar
   takes width away from the content, so the whole layout narrows by ~15px and snaps back on every
   such navigation. Reserving the gutter permanently keeps the width constant. */
html {
    scrollbar-gutter: stable;
}

/* ---- Typography & page rhythm ------------------------------------------------------------- */

body {
    -webkit-font-smoothing: antialiased;
}

/* Faint brand-mark watermark behind every page — fixed to the viewport, so it stays put
   regardless of scroll position. Sits above the mesh (z-index -2, MainLayout.razor.css). */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    background-image: url("CffVaultmanager.svg");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 34rem;
    opacity: 0.05;
    z-index: -1;
    pointer-events: none;
}

h1, h2, h3, .h1, .h2, .h3 {
    font-weight: 700;
    letter-spacing: -0.02em;
}

/* Gradient page titles. Static: the sample's infinite `shineText` sweep is deliberately not
   carried over (motion only on selection). fit-content keeps the whole gradient on the words
   instead of spreading it across the full width of the line. [class] outranks Bootstrap's
   .h3/.h4 weight, which every page title carries. */
main h1,
main h1[class] {
    width: fit-content;
    max-width: 100%;
    font-weight: 800;
    background-image: var(--brand-gradient-text);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
}

main h1.text-center {
    margin-inline: auto;
}

/* background-clip:text is dropped in Windows High Contrast; without this the title would vanish. */
@media (forced-colors: active) {
    main h1 {
        background-image: none;
        color: CanvasText;
        -webkit-text-fill-color: currentColor;
    }
}

/* Every page's top-level `<h1 class="h3 ...">` gets consistent breathing room from the content
   below it, without every page having to remember a margin utility class. */
main > h1:first-child,
main > .d-flex:first-child > h1 {
    margin-bottom: 0.25rem;
}

main {
    max-width: 75rem;
    margin-inline: auto;
}

/* ---- Page header + breadcrumb (Shared/PageHeader.razor) -------------------------------------
 * Same pattern as .ui-breadcrumb / .ui-page-header in NIS2 Assessment: the way back to the parent
 * page is a muted trail above the title, never a "Torna a…" button competing with the page's
 * actions on the right.
 */
.page-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 0.75rem;
    padding: 0;
    list-style: none;
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
}

.page-breadcrumb li {
    min-width: 0;
    overflow-wrap: anywhere;
}

.page-breadcrumb li + li::before {
    content: "/";
    margin-right: 0.5rem;
    color: var(--bs-border-color);
}

.page-breadcrumb a {
    color: var(--bs-secondary-color);
    text-decoration: none;
    border-radius: 0.25rem;
}

.page-breadcrumb a:hover {
    color: var(--bs-primary-text-emphasis);
    text-decoration: underline;
}

.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem 1.5rem;
    margin-bottom: 1.5rem;
}

.page-header-text {
    flex: 1 1 20rem;
    min-width: 0;
}

main .page-header h1 {
    margin-bottom: 0;
}

.page-header-description {
    max-width: 48rem;
    margin: 0.375rem 0 0;
    color: var(--bs-secondary-color);
    font-size: 0.875rem;
}

.page-header-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Content widths: forms and settings cards read best narrow, lists a little wider. Two steps only,
   so pages line up with each other instead of each picking its own max-width. */
.content-narrow {
    max-width: 32rem;
}

.content-medium {
    max-width: 40rem;
}

/* Settings-style pages made of independent cards (Sicurezza, Abbonamento): one column on phones and
   tablets, then as many 26rem+ columns as the content area fits. CSS columns rather than a grid, so
   cards of very different heights pack without the empty gaps a grid row would leave. */
.settings-columns > * {
    break-inside: avoid;
    margin-bottom: 1rem;
}

@media (min-width: 992px) {
    .settings-columns {
        columns: 26rem;
        column-gap: 1.5rem;
    }
}

/* ---- Top bar + sidebar nav ------------------------------------------------------------------
 * The shell (top bar, mesh background, off-canvas drawer on mobile, icon+label rail) lives in
 * Layout/MainLayout.razor.css: every element it styles is only ever rendered by MainLayout.razor
 * itself, so file-scoped rules can't silently fail to apply elsewhere.
 */

/* ---- Touch targets (mobile) ------------------------------------------------------------------
 * Below md (where a device is overwhelmingly likely to be touch-only) every actionable control
 * gets a floor on its tap area without changing how it looks at rest — padding grows, not font
 * size.
 */
@media (max-width: 767.98px) {
    .btn:not(.btn-link):not(.app-lock-btn):not(.vault-row-action):not(.vault-fab) {
        min-height: var(--brand-touch-target);
        padding-block: 0.5rem;
    }

    .form-control,
    .form-select {
        min-height: var(--brand-touch-target);
    }

    .form-check-input {
        width: 1.25rem;
        height: 1.25rem;
    }

    .vault-row-action {
        width: 2.5rem;
        height: 2.5rem;
    }
}

/* ---- Elevation ------------------------------------------------------------------------------ */

.card {
    background-color: var(--brand-surface);
    border: 1px solid var(--brand-surface-border);
    box-shadow: var(--brand-shadow-sm);
}

a.list-group-item-action,
a.card {
    transition: box-shadow 0.15s ease-in-out, border-color 0.15s ease-in-out;
}

a.list-group-item-action:hover,
a.card:hover {
    box-shadow: var(--brand-shadow-md);
}

.btn:not(:disabled):not(.btn-link):not(.btn-primary):not(.btn-info):hover {
    box-shadow: 0 0.25rem 0.75rem -0.25rem rgba(var(--bs-primary-rgb), 0.35);
}

/* ---- Glow card (shared system) ------------------------------------------------------------------
 * The sample's `.glow-card`: a surface with a thin gradient ring (mask-composite cuts the middle
 * out of a gradient-filled pseudo-element) and a soft colored shadow. Static — the sample's hover
 * lift is not carried over. Used by the auth panel and by every dialog (Shared/Modal.razor). */

.glow-card,
.auth-panel {
    position: relative;
    box-shadow: var(--brand-glow-shadow), var(--brand-shadow-lg);
}

.glow-card::before,
.auth-panel::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
    padding: 1px;
    background: var(--brand-gradient-border);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: var(--brand-glow-border-opacity);
    pointer-events: none;
}

/* ---- Selection glow (shared system) -------------------------------------------------------------
 * Add `glow-select` to anything the user selects (vault rows, nav links). When it carries `.active`
 * it gets the tinted gradient background, a gradient ring and a soft glow; the ring's gradient
 * sweeps across once and the glow flares once, on becoming active. Never looping: a perpetual
 * animation beside the content being read would fail WCAG 2.2.2 and burn GPU for nothing. */

.glow-select {
    position: relative;
}

.glow-select::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: var(--brand-gradient-border);
    background-size: 300% 100%;
    background-position: 0% 50%;
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: 0;
    pointer-events: none;
}

.glow-select.active {
    background-image: var(--brand-selection-bg);
    box-shadow: var(--brand-selection-shadow);
    animation: glow-select-flare 1.1s ease-out 1;
}

.glow-select.active::before {
    opacity: 1;
    animation: glow-select-sweep 1.1s ease-out 1;
}

@keyframes glow-select-sweep {
    from {
        background-position: 100% 50%;
    }

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

@keyframes glow-select-flare {
    0% {
        box-shadow: 0 0 0 0 rgba(var(--brand-glow-3-rgb), 0);
    }

    35% {
        box-shadow: 0 0 1.25rem 0.125rem rgba(var(--brand-glow-3-rgb), 0.45), 0 0 0.5rem 0 rgba(var(--brand-glow-2-rgb), 0.35);
    }

    100% {
        box-shadow: var(--brand-selection-shadow);
    }
}

/* ---- Tables -------------------------------------------------------------------------------- */

.table-responsive {
    border-radius: var(--bs-border-radius);
    border: 1px solid var(--bs-border-color);
    background-color: var(--brand-surface);
}

.table {
    --bs-table-bg: transparent;
    margin-bottom: 0;
}

.table thead th {
    text-transform: uppercase;
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
    border-bottom-width: 1px;
    background-color: var(--brand-hover-bg);
}

/* ---- Data cards (AdminTenants.razor / PasswordHealth.razor / Activity.razor) ---------------
 * A plain HTML `<table>` never reflows — on a phone it forces horizontal scroll by design. Below
 * md, these pages swap their `.table-responsive` for this stacked-card list instead (each page
 * keeps the real `<table>` for md+ via `d-none d-md-block`, and this via `d-md-none`).
 */

.data-card-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.data-card {
    background: var(--brand-surface);
    border: 1px solid var(--brand-surface-border);
    border-radius: var(--bs-border-radius);
    padding: 0.85rem 1rem;
}

.data-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.data-card-title {
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.data-card-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    padding: 0.3rem 0;
    font-size: 0.875rem;
    border-top: 1px solid var(--bs-border-color);
}

.data-card-row:first-of-type {
    border-top: none;
}

.data-card-row-label {
    color: var(--bs-secondary-color);
    flex-shrink: 0;
}

.data-card-row-value {
    text-align: right;
    min-width: 0;
    overflow-wrap: anywhere;
}

.data-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.65rem;
}

/* ---- Badges ---------------------------------------------------------------------------------- */

.badge {
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 0.4em 0.65em;
}

/* ---- Button roles ------------------------------------------------------------------------------
 * One role per button, never a color picked on the spot:
 *   main action of a screen or dialog  -> .btn-primary          (action gradient)
 *   secondary action                   -> .btn-outline-primary  (outlined)
 *   destructive action                 -> .btn-danger / .btn-outline-danger
 *   minor action inside a row          -> .btn-text             (text only, primary color)
 *   Annulla / Chiudi                   -> .btn-cancel           (text only, neutral)
 *   button attached to a field         -> .btn-outline-secondary
 * Always sentence case, weight 600. */
.btn {
    font-weight: 600;
}

.btn-text,
.btn-cancel {
    --bs-btn-border-color: transparent;
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-border-color: transparent;
    --bs-btn-disabled-border-color: transparent;
    --bs-btn-bg: transparent;
    --bs-btn-disabled-bg: transparent;
}

.btn-text {
    --bs-btn-color: var(--bs-primary-text-emphasis);
    --bs-btn-hover-color: var(--bs-primary-text-emphasis);
    --bs-btn-hover-bg: var(--bs-primary-bg-subtle);
    --bs-btn-active-color: var(--bs-primary-text-emphasis);
    --bs-btn-active-bg: var(--bs-primary-bg-subtle);
    --bs-btn-disabled-color: var(--bs-primary-text-emphasis);
}

.btn-cancel {
    --bs-btn-color: var(--bs-secondary-color);
    --bs-btn-hover-color: var(--bs-body-color);
    --bs-btn-hover-bg: var(--bs-secondary-bg-subtle);
    --bs-btn-active-color: var(--bs-body-color);
    --bs-btn-active-bg: var(--bs-secondary-bg-subtle);
    --bs-btn-disabled-color: var(--bs-secondary-color);
}

.btn-text:not(:disabled):hover,
.btn-cancel:not(:disabled):hover {
    box-shadow: none;
}

/* ---- Status chips (Shared/StatusChip.razor) — pill, colored dot, tinted background ------------ */

.status-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.125rem 0.625rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    color: var(--bs-secondary-text-emphasis);
    background: var(--bs-secondary-bg-subtle);
}

.status-chip--dot::before {
    content: "";
    width: 0.375rem;
    height: 0.375rem;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

.status-chip--mono {
    font-family: var(--bs-font-monospace);
    font-size: 0.75rem;
    min-width: 3.25rem;
    justify-content: center;
}

.status-chip--primary { color: var(--bs-primary-text-emphasis); background: var(--bs-primary-bg-subtle); }
.status-chip--info { color: var(--bs-info-text-emphasis); background: var(--bs-info-bg-subtle); }
.status-chip--success { color: var(--bs-success-text-emphasis); background: var(--bs-success-bg-subtle); }
.status-chip--warning { color: var(--bs-warning-text-emphasis); background: var(--bs-warning-bg-subtle); }
.status-chip--danger { color: var(--bs-danger-text-emphasis); background: var(--bs-danger-bg-subtle); }

/* ---- Filter chips (toggle pills, e.g. Pages/Activity.razor) ------------------------------------ */

.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.filter-chip {
    border: 1px solid var(--bs-border-color);
    background: var(--brand-surface);
    color: var(--bs-body-color);
    border-radius: 999px;
    padding: 0.3rem 0.9rem;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.4;
    transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
}

.filter-chip:hover {
    background: var(--bs-secondary-bg-subtle);
}

.filter-chip.active {
    color: var(--bs-primary-text-emphasis);
    background: var(--bs-primary-bg-subtle);
    border-color: var(--bs-primary-text-emphasis);
}

.filter-chip:focus-visible {
    outline: 2px solid var(--bs-primary-text-emphasis);
    outline-offset: 2px;
}

/* ---- Activity feed (Pages/Activity.razor) — grouped by day, one row per event --------------------- */

.activity-feed {
    margin-bottom: 1.5rem;
}

.activity-day + .activity-day {
    margin-top: 1.5rem;
}

.activity-day-title {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
    margin: 0 0 0.5rem;
}

.activity-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    background: var(--brand-surface);
    overflow: hidden;
}

.activity-row {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    padding: 0.75rem 1rem;
}

.activity-row + .activity-row {
    border-top: 1px solid var(--bs-border-color);
}

.activity-icon {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    color: var(--bs-secondary-text-emphasis);
    background: var(--bs-secondary-bg-subtle);
}

.activity-icon svg {
    width: 1.125rem;
    height: 1.125rem;
}

.activity-icon--primary { color: var(--bs-primary-text-emphasis); background: var(--bs-primary-bg-subtle); }
.activity-icon--info { color: var(--bs-info-text-emphasis); background: var(--bs-info-bg-subtle); }
.activity-icon--success { color: var(--bs-success-text-emphasis); background: var(--bs-success-bg-subtle); }
.activity-icon--warning { color: var(--bs-warning-text-emphasis); background: var(--bs-warning-bg-subtle); }
.activity-icon--danger { color: var(--bs-danger-text-emphasis); background: var(--bs-danger-bg-subtle); }

.activity-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.activity-label {
    font-weight: 600;
}

.activity-meta {
    font-size: 0.8125rem;
    color: var(--bs-secondary-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.activity-time {
    flex-shrink: 0;
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color);
}

/* ---- Dialog footer (Shared/ConfirmDialog.razor and every form inside Shared/Modal.razor) ------- */

.cff-modal-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.5rem;
}

/* ---- Empty states (Shared/EmptyState.razor) -------------------------------------------------- */

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 3.5rem 1.5rem;
    color: var(--bs-secondary-color);
    text-align: center;
}

.empty-state-compact {
    padding: 1.5rem 1rem;
}

.empty-state-icon {
    width: var(--brand-touch-target);
    height: var(--brand-touch-target);
    opacity: 0.45;
}

.empty-state-compact .empty-state-icon {
    width: 2rem;
    height: 2rem;
}

/* ---- Brand mark (Shared/BrandMark.razor) ------------------------------------------------------
 * One shared icon+wordmark lockup used by the navbar and every auth page. Sizing is left to the
 * caller's IconClass/TextClass, since the mark is reused at three very different scales. */

.brand-mark-icon {
    height: 2rem;
    width: auto;
}

.brand-mark-text-cff {
    font-weight: 700;
}

.brand-mark-text-vault {
    font-weight: 500;
}

/* ---- Auth pages (Login / Register / Recovery / AcceptInvitation) -------------------------------
 * Split screen: a brand panel beside the actual form, both wrapped in one `.auth-panel` that alone
 * carries the glow ring, shadow and radius — the two halves read as a single glow card. The brand
 * panel runs the logo's navy → deep blue in BOTH themes (white text passes AA at every stop), with a
 * cyan glow kept in the top corner, away from the text. Below lg the brand panel is
 * `d-none d-lg-flex` in markup and the compact BrandMark inside the form panel takes over. */

.auth-shell {
    display: flex;
    min-height: calc(100vh - 8rem);
    align-items: center;
    justify-content: center;
    margin-top: 1rem;
}

.auth-panel {
    display: flex;
    width: 100%;
    max-width: 62rem;
    border-radius: var(--brand-radius-glow);
    overflow: hidden;
}

.auth-brand-panel {
    flex: 0 0 38%;
    position: relative;
    align-items: center;
    justify-content: center;
    padding: 3rem 2rem;
    overflow: hidden;
    background:
        radial-gradient(circle at 100% 0%, rgba(var(--brand-glow-3-rgb), 0.35), rgba(var(--brand-glow-3-rgb), 0) 45%),
        linear-gradient(160deg, #033360 0%, #0C4876 45%, #0F628C 100%);
}

/* Faint oversized shield in the corner — same watermark idea as body::before, scaled up and
   cropped for a tighter composition than a centered repeat would give here. */
.auth-brand-panel::before {
    content: "";
    position: absolute;
    inset: -15% -25% auto auto;
    width: 24rem;
    height: 24rem;
    background: url("CffVaultmanager.svg") no-repeat center / contain;
    opacity: 0.1;
    transform: rotate(-10deg);
    pointer-events: none;
}

.auth-brand-panel-content {
    position: relative;
    max-width: 20rem;
    text-align: center;
    color: #FFFFFF;
}

.auth-brand-icon {
    height: 4rem;
    width: auto;
    filter: drop-shadow(0 0.5rem 1rem rgba(0, 0, 0, 0.25));
}

.auth-brand-text {
    font-size: 1.65rem;
    color: #FFFFFF;
}

.auth-brand-tagline {
    margin: 1rem 0 0;
    color: rgba(255, 255, 255, 0.88);
    font-size: 0.95rem;
    line-height: 1.5;
}

.auth-form-panel {
    flex: 1 1 26rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--brand-surface-solid);
    padding: 2.5rem 2rem;
}

.auth-form-panel-inner {
    width: 100%;
    max-width: 25rem;
}

.login-logo {
    height: var(--brand-touch-target);
    width: auto;
}

@media (max-width: 991.98px) {
    .auth-panel {
        border-radius: var(--brand-radius-sheet);
    }

    .auth-form-panel {
        padding: 2rem 1.25rem;
    }
}

/* ---- Vault tiles (Vault.razor) ---------------------------------------------------------------- */

.vault-tile-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--brand-touch-target);
    height: var(--brand-touch-target);
    border-radius: var(--bs-border-radius);
}

.vault-tile-icon svg {
    width: 1.375rem;
    height: 1.375rem;
}

.vault-tile-icon-personal {
    background-color: var(--bs-primary-bg-subtle);
    color: var(--brand-primary-contrast);
}

.vault-tile-icon-org {
    background-color: var(--bs-secondary-bg-subtle);
    color: var(--brand-secondary-contrast);
}

/* ---- Reduced motion ------------------------------------------------------------------------------
 * Last in the file so it wins. No animation and no transition anywhere: selection glow, button
 * gradient slide, drawer slide, row actions all switch state instantly. Bootstrap's spinners are
 * the one exception — they are the busy indicator itself, and Bootstrap already slows them down
 * under this preference. */
@media (prefers-reduced-motion: reduce) {
    *:not(.spinner-border):not(.spinner-grow),
    *::before,
    *::after {
        animation: none !important;
        transition: none !important;
    }
}
