/* Maestro brand palette migrated from the previous Web.App MaestroTheme. */
/* The variables below override Radzen theme tokens so the material theme adopts the Gapfy brand. */
/* Shared --gapfy-* tokens are loaded from css/brand.css (single source of truth across Website/Maestro/Harmony). */

:root {
    --rz-text-font-family: var(--gapfy-font-sans);

    /* Primary -> --gapfy-action (slate-800 light / slate-200 dark). Used for
       all interactive UI surfaces: primary CTAs, active states, focus halos,
       tab underlines. The cyan brand colour stays on the logo + charts +
       informational accents only. */
    --rz-primary: var(--gapfy-action);
    --rz-primary-light: #374151;
    --rz-primary-lighter: #4B5563;
    --rz-primary-dark: var(--gapfy-action-strong);
    --rz-primary-darker: var(--gapfy-action-darker);

    /* Secondary -> Gapfy cyan. Used for the small set of components that
       call for a brand pop on top of the slate UI (info badges, the
       active chart series, dot indicators). */
    --rz-secondary: var(--gapfy-primary);
    --rz-secondary-light: #5DB9E8;
    --rz-secondary-lighter: #88CAF0;
    --rz-secondary-dark: var(--gapfy-primary-strong);
    --rz-secondary-darker: var(--gapfy-accent);

    /* Surfaces match Gapfy soft surface tokens. */
    --rz-base-200: var(--gapfy-bg-elevated);
    --rz-base-100: var(--gapfy-bg-soft);

    /* Repointing --rz-base-100/200 to surface tokens (above) hijacks any Radzen
       TEXT token that derives from the base scale. The Radzen base scale inverts
       between themes, so in material-dark the secondary/tertiary text tokens
       resolve to var(--rz-base-100) / var(--rz-base-200) -- both now dark surface
       colours -> unselected RadzenTabs labels, empty-state icons, and muted
       captions rendered dark-on-dark and became unreadable. Remap both to
       --gapfy-muted, which carries readable light + dark variants. Sibling of
       the --rz-base-200 / .rz-variant-text.rz-light fix below. */
    --rz-text-secondary-color: var(--gapfy-muted);
    --rz-text-tertiary-color: var(--gapfy-muted);

    /* Status colors aligned with Gapfy brand tokens. */
    --rz-success: var(--gapfy-success);
    --rz-success-light: #4ADE80;
    --rz-success-dark: #15803D;

    /* Info reads as the cyan brand colour (gentle, helpful tone). */
    --rz-info: var(--gapfy-primary);
    --rz-info-light: #5DB9E8;
    --rz-info-dark: var(--gapfy-primary-strong);

    --rz-warning: var(--gapfy-warning);
    --rz-warning-light: #FBBF24;
    --rz-warning-dark: #D97706;

    --rz-danger: var(--gapfy-danger);
    --rz-danger-light: #EF4444;
    --rz-danger-dark: #B91C1C;

    /* Charts series: cyan leads (brand pop on data), slate sits second so
       charts don't read as pure greyscale. */
    --rz-series-1: var(--gapfy-primary);
    --rz-series-2: var(--gapfy-action);
    --rz-series-3: var(--gapfy-success);
    --rz-series-4: var(--gapfy-warning);
    --rz-series-5: var(--gapfy-danger);
    --rz-series-6: #8B5CF6;
}

/* ============================================================
   Accent colour (cor de destaque) — premium custom theme.

   When the user picks an accent, <html> gets a `theme-preset-{name}` class
   (10 named presets) or `theme-preset-custom` (+ an inline --gapfy-accent-pick
   from the colour picker). We remap the action tokens (--gapfy-action*, which
   already feed --rz-primary and every interactive surface) from a single
   --gapfy-accent-pick using color-mix to derive hover/darker/soft variants.

   Specificity note: the generic remap is :root[class*="theme-preset-"] (0,2,0),
   equal to :root.theme-dark (0,2,0). app.css loads AFTER brand.css, so the
   remap wins in source order. The dark variants below use (0,3,0) so they sit
   on top of both. Colour buttons keep white foreground in both modes.
   color-mix support: Chrome 111+, Firefox 113+, Safari 16.2+ (already used
   elsewhere in this file). Values mirror Harmony.WebApp for cross-suite parity.
   ============================================================ */
:root[class*="theme-preset-"] {
    --gapfy-action: var(--gapfy-accent-pick, #1F2937);
    --gapfy-action-strong: color-mix(in srgb, var(--gapfy-accent-pick, #1F2937) 82%, #000);
    --gapfy-action-darker: color-mix(in srgb, var(--gapfy-accent-pick, #1F2937) 66%, #000);
    --gapfy-action-soft:   color-mix(in srgb, var(--gapfy-accent-pick, #1F2937) 12%, transparent);
    --gapfy-action-on: #FFFFFF;
}

:root.theme-dark[class*="theme-preset-"] {
    --gapfy-action-strong: color-mix(in srgb, var(--gapfy-accent-pick, #E2E8F0) 80%, #fff);
    --gapfy-action-darker: color-mix(in srgb, var(--gapfy-accent-pick, #E2E8F0) 64%, #fff);
    --gapfy-action-soft:   color-mix(in srgb, var(--gapfy-accent-pick, #E2E8F0) 22%, transparent);
}

/* Each named preset only defines --gapfy-accent-pick (light + dark shade). The
   generic remap above turns it into the full action palette. theme-preset-custom
   does NOT define a pick here — JS sets --gapfy-accent-pick inline on <html>. */
:root.theme-preset-blue   { --gapfy-accent-pick: #6366F1; }
:root.theme-preset-cyan   { --gapfy-accent-pick: #06B6D4; }
:root.theme-preset-green  { --gapfy-accent-pick: #10B981; }
:root.theme-preset-amber  { --gapfy-accent-pick: #F59E0B; }
:root.theme-preset-orange { --gapfy-accent-pick: #F97316; }
:root.theme-preset-rose   { --gapfy-accent-pick: #F43F5E; }
:root.theme-preset-pink   { --gapfy-accent-pick: #EC4899; }
:root.theme-preset-purple { --gapfy-accent-pick: #A855F7; }
:root.theme-preset-slate  { --gapfy-accent-pick: #475569; }
:root.theme-preset-brown  { --gapfy-accent-pick: #92724C; }

:root.theme-dark.theme-preset-blue   { --gapfy-accent-pick: #818CF8; }
:root.theme-dark.theme-preset-cyan   { --gapfy-accent-pick: #22D3EE; }
:root.theme-dark.theme-preset-green  { --gapfy-accent-pick: #34D399; }
:root.theme-dark.theme-preset-amber  { --gapfy-accent-pick: #FBBF24; }
:root.theme-dark.theme-preset-orange { --gapfy-accent-pick: #FB923C; }
:root.theme-dark.theme-preset-rose   { --gapfy-accent-pick: #FB7185; }
:root.theme-dark.theme-preset-pink   { --gapfy-accent-pick: #F472B6; }
:root.theme-dark.theme-preset-purple { --gapfy-accent-pick: #C084FC; }
:root.theme-dark.theme-preset-slate  { --gapfy-accent-pick: #94A3B8; }
:root.theme-dark.theme-preset-brown  { --gapfy-accent-pick: #B89F7D; }

/* ---- Accent picker swatches (AccentColorPicker.razor) ---------------------- */
.maestro-accent-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.maestro-accent-grid.is-locked {
    opacity: 0.6;
    pointer-events: none;
}

.maestro-accent-swatch {
    position: relative;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 2px solid transparent;
    padding: 0;
    cursor: pointer;
    background: transparent;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.maestro-accent-swatch:hover:not(:disabled) {
    transform: scale(1.08);
    box-shadow: 0 2px 8px rgba(9, 30, 66, 0.16);
}

.maestro-accent-swatch:disabled {
    cursor: not-allowed;
}

.maestro-accent-swatch.is-selected {
    border-color: var(--gapfy-ink);
    box-shadow: 0 0 0 2px var(--gapfy-bg), 0 0 0 4px var(--gapfy-ink);
}

.maestro-accent-swatch-fill {
    position: absolute;
    inset: 4px;
    border-radius: 50%;
    background: var(--gapfy-action);
}

.maestro-accent-swatch.theme-preset-blue   .maestro-accent-swatch-fill { background: #6366F1; }
.maestro-accent-swatch.theme-preset-cyan    .maestro-accent-swatch-fill { background: #06B6D4; }
.maestro-accent-swatch.theme-preset-green   .maestro-accent-swatch-fill { background: #10B981; }
.maestro-accent-swatch.theme-preset-amber   .maestro-accent-swatch-fill { background: #F59E0B; }
.maestro-accent-swatch.theme-preset-orange  .maestro-accent-swatch-fill { background: #F97316; }
.maestro-accent-swatch.theme-preset-rose    .maestro-accent-swatch-fill { background: #F43F5E; }
.maestro-accent-swatch.theme-preset-pink    .maestro-accent-swatch-fill { background: #EC4899; }
.maestro-accent-swatch.theme-preset-purple  .maestro-accent-swatch-fill { background: #A855F7; }
.maestro-accent-swatch.theme-preset-slate   .maestro-accent-swatch-fill { background: #475569; }
.maestro-accent-swatch.theme-preset-brown   .maestro-accent-swatch-fill { background: #92724C; }

html.theme-dark .maestro-accent-swatch.theme-preset-blue   .maestro-accent-swatch-fill { background: #818CF8; }
html.theme-dark .maestro-accent-swatch.theme-preset-cyan    .maestro-accent-swatch-fill { background: #22D3EE; }
html.theme-dark .maestro-accent-swatch.theme-preset-green   .maestro-accent-swatch-fill { background: #34D399; }
html.theme-dark .maestro-accent-swatch.theme-preset-amber   .maestro-accent-swatch-fill { background: #FBBF24; }
html.theme-dark .maestro-accent-swatch.theme-preset-orange  .maestro-accent-swatch-fill { background: #FB923C; }
html.theme-dark .maestro-accent-swatch.theme-preset-rose    .maestro-accent-swatch-fill { background: #FB7185; }
html.theme-dark .maestro-accent-swatch.theme-preset-pink    .maestro-accent-swatch-fill { background: #F472B6; }
html.theme-dark .maestro-accent-swatch.theme-preset-purple  .maestro-accent-swatch-fill { background: #C084FC; }
html.theme-dark .maestro-accent-swatch.theme-preset-slate   .maestro-accent-swatch-fill { background: #94A3B8; }
html.theme-dark .maestro-accent-swatch.theme-preset-brown   .maestro-accent-swatch-fill { background: #B89F7D; }

.maestro-accent-swatch.is-custom .maestro-accent-swatch-fill {
    background: conic-gradient(
        from 0deg,
        #F43F5E, #F97316, #F59E0B, #84CC16, #10B981,
        #06B6D4, #6366F1, #A855F7, #EC4899, #F43F5E
    );
}

.maestro-accent-swatch-check {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #FFFFFF;
    font-size: 20px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}

.maestro-accent-custom-picker {
    margin-top: 0.75rem;
    padding: 0.75rem;
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius);
    background: var(--gapfy-bg-soft);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: 280px;
}

/* Layout helpers reused from the previous maestro.css. */
html,
body {
    height: 100%;
    font-family: var(--gapfy-font-sans);
    color: var(--gapfy-ink);
    background: var(--gapfy-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* Stripe-style heading scale: Inter at 700/800 weights with slightly
   negative letter-spacing. Display sizes (h1/h2) tighten further so the
   rhythm reads as confident rather than soft. */
.rz-text-h1,
.rz-text-h2,
.rz-text-h3,
.rz-text-h4,
.rz-text-display-h1,
.rz-text-display-h2,
.rz-text-display-h3,
h1, h2, h3, h4 {
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--gapfy-ink);
    line-height: 1.25;
}

.rz-text-display-h1,
h1.rz-text-h1,
h1 {
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.15;
}

.rz-text-display-h2,
h2.rz-text-h2,
h2 {
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.2;
}

/* Subtitle / caption / muted helpers, used liberally across Settings,
   admin pages and platform dashboards. */
.rz-text-subtitle1,
.rz-text-subtitle2,
.maestro-text-muted,
.text-muted {
    color: var(--gapfy-muted);
}

.maestro-text-lead {
    color: var(--gapfy-ink-soft);
    font-size: var(--gapfy-text-lg);
    line-height: 1.55;
}

/* Code / monospace fallback. Inline `<code>` and Stripe-style snippet
   blocks should not inherit Inter -- monospace reads as a "thing the
   computer says". */
code, kbd, samp, pre,
.rz-text-mono {
    font-family: "JetBrains Mono", "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
    font-size: 0.875em;
}

/* Inline code chip (e.g. for "PersonId = X" displays). */
:not(pre) > code {
    background: var(--gapfy-bg-soft);
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius-sm, 3px);
    padding: 0.1em 0.4em;
}

/* Hide helper text under text inputs to keep the dense form layout the team is used to. */
.rz-input-helper {
    display: none !important;
}

/* Stripe-style card elevation:
     - Resting: 1px border + tiny shadow. Reads as "paper on surface".
     - Hover lift is OPT-IN, reserved for genuinely interactive cards. Static
       container and list-item cards stay put so a hover never implies a click
       that isn't there. Mark a card with the `is-clickable` class (or render
       it as <a class="rz-card">) to get the translateY lift. Plan tiles opt in
       via their own page stylesheet.
     - Active card (e.g. selected tab card): tinted border. */
.rz-card {
    background: var(--gapfy-bg-elevated);
    box-shadow: var(--gapfy-shadow-sm);
    border-radius: var(--gapfy-radius-lg, 12px);
    border: 1px solid var(--gapfy-line);
    transition:
        box-shadow 180ms ease,
        border-color 180ms ease,
        transform 180ms ease;
}

.rz-card.is-clickable,
a.rz-card {
    cursor: pointer;
}

.rz-card.is-clickable:hover,
a.rz-card:hover {
    box-shadow: var(--gapfy-shadow);
    border-color: color-mix(in srgb, var(--gapfy-action) 30%, var(--gapfy-line));
    transform: translateY(-2px);
}

/* "Soft" surface variant: tinted background, no border. Used for inset
   blocks like usage breakdowns or summary tiles. */
.rz-card.maestro-card-soft {
    background: var(--gapfy-bg-soft);
    border-color: transparent;
    box-shadow: none;
}

/* Selected card (e.g. plan tile, active subscription card). Cyan border
   + soft cyan wash inside. */
.rz-card.is-current,
.rz-card.is-selected {
    border-color: var(--gapfy-action);
    background: color-mix(in srgb, var(--gapfy-action) 4%, var(--gapfy-bg-elevated));
    box-shadow:
        0 0 0 1px color-mix(in srgb, var(--gapfy-action) 40%, transparent),
        var(--gapfy-shadow-sm);
}

/* Right pane sidebar tweaks: respect the layout width while still feeling like a drawer. */
.rz-sidebar.maestro-right-pane {
    box-shadow: -8px 0 24px rgba(0, 0, 0, 0.08);
    transition:
        width 250ms cubic-bezier(0.4, 0, 0.2, 1),
        opacity 250ms cubic-bezier(0.4, 0, 0.2, 1),
        box-shadow 250ms ease,
        border-color 250ms ease;
}

/* Closed state is driven explicitly by an `is-closed` class on the
   wrapper so the first render (before any Radzen state class is set)
   is already 0-width + invisible — no sliver against the page edge.
   The transition is preserved by setting only width / opacity here. */
.rz-sidebar.maestro-right-pane.is-closed {
    width: 0 !important;
    opacity: 0;
    pointer-events: none;
    border-color: transparent !important;
    box-shadow: none !important;
    overflow: hidden;
}

.maestro-right-pane-header {
    border-bottom: 1px solid var(--rz-base-200, rgba(0, 0, 0, 0.08));
}

@media (max-width: 768px) {
    .rz-sidebar.maestro-right-pane {
        width: 100% !important;
    }
}

/* Drop zone for file upload via drag and drop. */
.maestro-drop-zone {
    position: relative;
    display: block;
    cursor: pointer;
    border: 2px dashed var(--rz-base-300, rgba(0, 0, 0, 0.16));
    border-radius: 6px;
    background: var(--rz-base-50, rgba(0, 0, 0, 0.02));
    transition: border-color 150ms ease, background-color 150ms ease;
    overflow: hidden;
}

.maestro-drop-zone:hover {
    border-color: var(--gapfy-action);
    background: color-mix(in srgb, var(--gapfy-action) 6%, transparent);
}

.maestro-drop-zone-active {
    border-color: var(--gapfy-action);
    background: color-mix(in srgb, var(--gapfy-action) 10%, transparent);
}

.maestro-drop-zone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* Make the file preview tabs fill the available height. */
.maestro-preview-tabs {
    flex: 1;
    min-height: 0;
}

.maestro-preview-tabs .rz-tabview-panels {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.maestro-preview-tabs .rz-tabview-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* Text transform off on tabs and buttons matches the previous typography. */
.rz-tabview-nav-link,
.rz-button .rz-button-text,
.rz-badge {
    text-transform: none;
}

/* Auth layout: full viewport with the form centered. Uses the Gapfy
   gradient (lighter cyan -> primary -> deeper) for a brand-coherent wash. */
.maestro-auth-layout {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--gapfy-gradient-primary);
    padding: 1.5rem;
}

.maestro-auth-layout-content {
    width: 100%;
    max-width: 420px;
}

.maestro-auth-card {
    padding: 2rem;
}

.maestro-auth-brand {
    display: flex;
    justify-content: center;
}

/* ============================================================
   Auth split brand stage (login / invite / logout).
   Animation pane on the left, page content on the right. The
   stage stays vivid in both themes (it is the brand); the form
   pane follows the theme + accent tokens. The logo float and the
   music notes are driven by maestro/js/maestro-login.js; the
   mesh, echo rings and equalizer are CSS-only.
   ============================================================ */
.auth-split {
    --m-green: #8BC63F;
    --m-gold: #D9C13C;
    --m-orange: #F39A3D;
    --m-coral: #EE6F6A;
    --m-magenta: #D24C97;
    --m-purple: #9A33B4;
    --m-sky: #5DB9E8;
    --auth-ease: cubic-bezier(0.16, 1, 0.3, 1);
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    min-height: 100vh;
}

.auth-form {
    order: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 48px;
    background: var(--gapfy-bg);
}

.auth-form-inner {
    width: 100%;
    max-width: 420px;
}

/* Neutralise card chrome so the page content sits cleanly on the form pane. */
.auth-form .rz-card {
    background: transparent;
    box-shadow: none;
    border: none;
}

.auth-stage {
    order: 1;
    position: relative;
    overflow: hidden;
    background: linear-gradient(160deg, #1B1330 0%, #241A33 100%);
    display: flex;
    align-items: center;
    justify-content: center;
}

.auth-mesh {
    position: absolute;
    border-radius: 50%;
    filter: blur(70px);
    opacity: 0.55;
    pointer-events: none;
    will-change: transform;
}

.auth-mesh-1 { width: 46%; height: 46%; top: -8%; left: -6%; background: radial-gradient(circle, var(--m-green), transparent 68%); animation: authDrift1 24s var(--auth-ease) infinite alternate; }
.auth-mesh-2 { width: 52%; height: 52%; top: 18%; left: 22%; background: radial-gradient(circle, var(--m-orange), transparent 66%); animation: authDrift2 28s var(--auth-ease) infinite alternate; }
.auth-mesh-3 { width: 48%; height: 48%; bottom: -10%; right: 4%; background: radial-gradient(circle, var(--m-magenta), transparent 66%); animation: authDrift3 26s var(--auth-ease) infinite alternate; }
.auth-mesh-4 { width: 40%; height: 40%; bottom: 6%; left: 6%; background: radial-gradient(circle, var(--m-purple), transparent 68%); animation: authDrift1 30s var(--auth-ease) infinite alternate-reverse; }

@keyframes authDrift1 { from { transform: translate(0, 0) scale(1); } to { transform: translate(8%, 6%) scale(1.12); } }
@keyframes authDrift2 { from { transform: translate(0, 0) scale(1); } to { transform: translate(-7%, 9%) scale(1.08); } }
@keyframes authDrift3 { from { transform: translate(0, 0) scale(1); } to { transform: translate(6%, -8%) scale(1.1); } }

.auth-stage::after {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(120% 120% at 50% 45%, transparent 55%, rgba(12, 6, 24, 0.45) 100%);
    pointer-events: none;
    z-index: 3;
}

.auth-notes {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}

.auth-note {
    position: absolute;
    left: 0;
    top: 0;
    display: block;
    opacity: 0;
    line-height: 1;
    font-family: "Segoe UI Symbol", "Apple Symbols", "Noto Music", sans-serif;
    text-shadow: 0 0 10px currentColor;
    transform-origin: center;
    will-change: transform, opacity;
    user-select: none;
}

.auth-family {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(28px, 4vw, 46px);
}

.auth-conductor {
    position: relative;
    display: grid;
    place-items: center;
}

.auth-glow {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 135%;
    height: 135%;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, rgba(243, 154, 61, 0.45), rgba(210, 76, 151, 0.25) 45%, transparent 70%);
    filter: blur(42px);
    pointer-events: none;
}

.auth-rings {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    z-index: 1;
    pointer-events: none;
}

.auth-ring {
    grid-area: 1 / 1;
    width: 76%;
    aspect-ratio: 1;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.40);
    opacity: 0;
    animation: authEcho 4.2s var(--auth-ease) infinite;
}

.auth-ring:nth-child(2) { animation-delay: 1.4s; }
.auth-ring:nth-child(3) { animation-delay: 2.8s; }

@keyframes authEcho {
    0% { transform: scale(0.82); opacity: 0; }
    14% { opacity: 0.45; }
    100% { transform: scale(2); opacity: 0; }
}

.auth-logo {
    position: relative;
    z-index: 2;
    width: clamp(104px, 15vw, 152px);
    height: auto;
    filter: drop-shadow(0 18px 36px rgba(18, 6, 38, 0.5));
    transform-origin: center;
    will-change: transform;
}

.auth-ensemble {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: clamp(20px, 4vw, 52px);
}

.auth-product {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    animation: authFloaty 4.4s ease-in-out infinite;
}

.auth-product:nth-child(2) { animation-delay: 0.7s; }
.auth-product:nth-child(3) { animation-delay: 1.4s; }

.auth-product img {
    width: clamp(52px, 7vw, 72px);
    height: auto;
    border-radius: 28%;
    filter: drop-shadow(0 14px 26px rgba(18, 6, 38, 0.5));
}

.auth-product-label {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: rgba(255, 255, 255, 0.78);
}

@keyframes authFloaty {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-7px); }
}

.auth-eq {
    position: absolute;
    bottom: 6%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: flex-end;
    gap: 7px;
    height: 44px;
    z-index: 2;
    pointer-events: none;
}

.auth-eq span {
    width: 7px;
    height: 100%;
    border-radius: 6px;
    transform: scaleY(0.3);
    transform-origin: bottom;
    opacity: 0.9;
    animation: authEq 0.9s ease-in-out infinite alternate;
}

@keyframes authEq {
    from { transform: scaleY(0.22); }
    to { transform: scaleY(1); }
}

@media (max-width: 880px) {
    .auth-split { grid-template-columns: 1fr; }
    .auth-stage { min-height: 42vh; }
    .auth-family { gap: 22px; }
    .auth-logo { width: clamp(80px, 20vw, 120px); }
    .auth-ensemble { gap: clamp(16px, 5vw, 32px); }
    .auth-product img { width: clamp(42px, 11vw, 58px); }
    .auth-product-label { font-size: 11px; }
    .auth-form { padding: 40px 28px; }
}

@media (prefers-reduced-motion: reduce) {
    .auth-mesh,
    .auth-ring,
    .auth-eq span,
    .auth-product { animation: none !important; }
    .auth-notes { display: none; }
}

/* Cookies consent banner: bottom centered floating card. */
.maestro-cookies-banner {
    position: fixed;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    width: min(720px, calc(100vw - 2rem));
    z-index: 1100;
}

/* ============================================================================
   Toasts (Radzen notifications) -- theme-aware elevated cards.

   Radzen paints the whole toast in a solid severity colour by default (an
   all-green card for success, all-red for error). Instead we render a neutral
   card that follows the active theme and signal severity through three
   redundant cues so it reads at a glance: a 4px left accent strip, a tinted
   icon chip and the icon glyph itself. A strong shadow plus a hairline border
   lift the toast off the page content.

   Severity classes: success / warn / error / info. Every colour resolves to a
   --gapfy-* token, so light and dark are covered automatically.

   The theme-dependent colours (surface, ink, shadow) are set DIRECTLY on the
   toast elements -- NOT via redefined --rz-notification-* variables. A custom
   property whose value is var(--gapfy-*) resolves its inner var against the
   :root that declares it, which would freeze the toast to a single theme.
   Resolving on the element keeps it in step with the active theme scope.
   ============================================================================ */

/* Only theme-independent niceties may ride on Radzen's own variables safely. */
:root {
    --rz-notification-gap: 0.75rem;
    --rz-notification-container-background-color: transparent;
}

/* Container: pinned to the bottom-left corner. Radzen.Blazor 10.x has no
   per-message or global Position API, so the container is repositioned here.
   The component uses logical insets (inset-block-start / inset-inline-end). */
.rz-notification {
    inset-block-start: auto !important;
    inset-inline-end: auto !important;
    inset-block-end: 1rem !important;
    inset-inline-start: 1rem !important;
}

/* One accent hue per severity, inherited by the strip / chip / progress bar. */
.rz-notification-success { --toast-accent: var(--gapfy-success); }
.rz-notification-warn { --toast-accent: var(--gapfy-warning); }
.rz-notification-error { --toast-accent: var(--gapfy-danger); }
.rz-notification-info { --toast-accent: var(--gapfy-primary); }

/* The card shell: shape, elevation, hairline border + the severity strip down
   the start side. --gapfy-* resolve on this element, so the shadow tracks the
   active theme too. */
.rz-notification-item {
    padding: 0.875rem 1rem;
    border-radius: var(--gapfy-radius-lg);
    border: 1px solid var(--gapfy-line);
    border-inline-start: 4px solid var(--toast-accent, var(--gapfy-line-strong));
    box-shadow: var(--gapfy-shadow-lg);
}

/* Neutral surface + ink per severity. Specificity (0,2,0) ties Radzen's solid
   severity fill and app.css loads after the Radzen theme, so this wins -- in
   both light and dark, because --gapfy-* resolve on the element itself. */
.rz-notification-success .rz-notification-item,
.rz-notification-warn .rz-notification-item,
.rz-notification-error .rz-notification-item,
.rz-notification-info .rz-notification-item {
    background-color: var(--gapfy-bg-elevated);
    color: var(--gapfy-ink);
}

/* Icon chip: a tinted circle carrying the severity colour -- the single most
   scannable cue. The compound selector (0,2,0) beats Radzen's icon-colour
   rule, so the glyph adopts the accent too. */
.rz-notification-item .rz-notification-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    inline-size: 2rem;
    block-size: 2rem;
    margin: 0;
    border-radius: 50%;
    font-size: 1.125rem;
    color: var(--toast-accent, var(--gapfy-muted));
    background-color: color-mix(in srgb, var(--toast-accent, var(--gapfy-muted)) 16%, transparent);
}

/* Summary stands out, detail recedes one tone. */
.rz-notification-title {
    font-weight: 600;
    color: var(--gapfy-ink);
    line-height: 1.35;
}

.rz-notification-message {
    color: var(--gapfy-ink-soft);
    font-size: var(--gapfy-text-sm);
    line-height: 1.4;
}

/* Close affordance: muted at rest, strengthens on hover. */
.rz-notification-close {
    color: var(--gapfy-muted);
    opacity: 1;
    border-radius: var(--gapfy-radius-sm);
    transition: color 120ms ease, background-color 120ms ease;
}

.rz-notification-close:hover {
    color: var(--gapfy-ink);
    background-color: var(--gapfy-bg-soft);
}

/* Auto-dismiss countdown: tint the fill to match the severity. */
.rz-notification-item-wrapper > .rz-progressbar {
    --rz-progressbar-value-background-color: var(--toast-accent, var(--gapfy-primary));
}

/* ============================================================================
   Atlassian-style polish over Radzen Material defaults.
   Pure CSS, scoped to component classes. Reversible by removing this block.
   ============================================================================ */

/* --- Inputs: soft focus halo ----------------------------------------------
   Stripe-style 3px slate halo around focused inputs. Reads as "this is the
   active field" without being loud. Uses --gapfy-action (slate-800 in light,
   slate-200 in dark) so the halo always contrasts with the surface. */
.rz-textbox:not(.rz-state-disabled).rz-state-focused,
.rz-textarea:not(.rz-state-disabled).rz-state-focused,
.rz-dropdown:not(.rz-state-disabled).rz-state-focused,
.rz-listbox:not(.rz-state-disabled).rz-state-focused,
.rz-datepicker:not(.rz-state-disabled).rz-state-focused,
.rz-numeric:not(.rz-state-disabled).rz-state-focused,
.rz-multiselect:not(.rz-state-disabled).rz-state-focused,
.rz-mask:not(.rz-state-disabled).rz-state-focused,
.rz-textbox:not(.rz-state-disabled):focus,
.rz-textarea:not(.rz-state-disabled):focus,
.rz-textbox:not(.rz-state-disabled):focus-visible,
.rz-textarea:not(.rz-state-disabled):focus-visible {
    outline: none !important;
    border-color: var(--gapfy-action) !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gapfy-action) 25%, transparent) !important;
}

/* --- Inputs: subtle resting border, soft hover tint ---------------------
   Stripe-style inputs have a faint border at rest, hint border on hover,
   strong primary border + halo on focus (handled above). The combination
   makes form fields read as interactive surfaces rather than empty boxes. */
.rz-textbox:not(.rz-state-disabled):not(.rz-state-focused),
.rz-textarea:not(.rz-state-disabled):not(.rz-state-focused),
.rz-dropdown:not(.rz-state-disabled):not(.rz-state-focused),
.rz-listbox:not(.rz-state-disabled):not(.rz-state-focused),
.rz-datepicker:not(.rz-state-disabled):not(.rz-state-focused),
.rz-numeric:not(.rz-state-disabled):not(.rz-state-focused),
.rz-multiselect:not(.rz-state-disabled):not(.rz-state-focused),
.rz-mask:not(.rz-state-disabled):not(.rz-state-focused) {
    border-color: var(--gapfy-line);
    transition: border-color 120ms ease, box-shadow 120ms ease, background 120ms ease;
}

.rz-textbox:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-textarea:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-dropdown:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-listbox:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-datepicker:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-numeric:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-multiselect:not(.rz-state-disabled):not(.rz-state-focused):hover,
.rz-mask:not(.rz-state-disabled):not(.rz-state-focused):hover {
    border-color: var(--gapfy-line-strong);
}

/* --- Switch / Checkbox / Radio: accent cyan when on/checked.
   Radzen ships Material defaults (blue/indigo). Force the active state to
   adopt the Gapfy primary so brand consistency carries through into forms. */
.rz-switch.rz-state-active .rz-switch-circle,
.rz-switch.rz-state-active .rz-switch-circle-bar {
    background-color: var(--gapfy-action);
}

.rz-switch.rz-state-active .rz-switch-circle::after {
    background: var(--gapfy-action-strong);
}

.rz-checkbox-box.rz-state-active,
.rz-radiobutton-icon.rz-state-active {
    background-color: var(--gapfy-action);
    border-color: var(--gapfy-action);
}

.rz-checkbox-box.rz-state-active:focus-visible,
.rz-radiobutton-icon.rz-state-active:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gapfy-action) 25%, transparent);
}

/* --- Form labels: ink colour, slight weight for hierarchy. */
.rz-label,
.rz-form-field-label,
label.rz-required-marker {
    color: var(--gapfy-ink);
    font-weight: 500;
}

/* --- DataGrid: clearer header, subtle row hover --------------------------
   Header weight 600 over a slightly tinted background separates rows
   from headers without bold borders. Hovered rows get a soft tint so
   the cursor position is always obvious.
*/
.rz-datatable thead.rz-datatable-thead > tr > th,
.rz-grid-table thead > tr > th {
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--gapfy-ink, #172B4D);
    background: var(--gapfy-bg-soft, #F4F5F7);
}

.rz-datatable tbody.rz-datatable-tbody > tr:not(.rz-state-highlight):hover,
.rz-grid-table tbody > tr:not(.rz-state-highlight):hover {
    background: var(--gapfy-bg-soft, #F4F5F7);
}

/* --- Dialogs / popups: borderless, soft elevation ------------------------
   Radzen dialogs/popups sit on the page; deeper shadow makes them feel
   anchored above the dimmer rather than glued to the surface.
*/
.rz-dialog,
.rz-popup,
.rz-overlaypanel {
    border-radius: var(--gapfy-radius-lg);
    box-shadow: var(--gapfy-shadow-lg);
}

/* --- Buttons: Stripe-style elevation + brand gradient on primary. -------
   Resting: subtle shadow that suggests an interactive surface (not flat).
   Hover: lift 1px + deeper shadow + slightly more saturated primary.
   Active: press back to baseline.
   Focus-visible: 3px brand-coloured halo, matches input focus halo. */
.rz-button {
    border-radius: var(--gapfy-radius, 6px);
    font-weight: 600;
    letter-spacing: -0.005em;
    transition:
        background 150ms ease,
        box-shadow 150ms ease,
        transform 120ms ease,
        border-color 150ms ease,
        color 150ms ease;
}

.rz-button:not(.rz-state-disabled):focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gapfy-action) 35%, transparent);
}

/* Primary CTA: cyan gradient + soft resting shadow + lift on hover.
   Stripe-style "wash" gradient (lighter top -> darker bottom) reads as
   a physical button rather than a flat tile. */
.rz-button.rz-button-primary,
.rz-button.rz-primary {
    background: linear-gradient(180deg, color-mix(in srgb, var(--gapfy-action) 92%, white) 0%, var(--gapfy-action) 100%);
    color: var(--gapfy-action-on);
    border: 1px solid var(--gapfy-action-strong);
    box-shadow:
        0 1px 0 0 color-mix(in srgb, white 15%, transparent) inset,
        0 1px 2px rgba(9, 30, 66, 0.10),
        0 1px 1px rgba(9, 30, 66, 0.08);
}

.rz-button.rz-button-primary:not(.rz-state-disabled):hover,
.rz-button.rz-primary:not(.rz-state-disabled):hover {
    background: linear-gradient(180deg, var(--gapfy-action) 0%, var(--gapfy-action-strong) 100%);
    border-color: var(--gapfy-action-strong);
    box-shadow:
        0 1px 0 0 color-mix(in srgb, white 10%, transparent) inset,
        0 4px 10px rgba(9, 30, 66, 0.14),
        0 2px 3px rgba(9, 30, 66, 0.08);
    transform: translateY(-1px);
}

.rz-button.rz-button-primary:not(.rz-state-disabled):active,
.rz-button.rz-primary:not(.rz-state-disabled):active {
    background: var(--gapfy-action-strong);
    box-shadow:
        0 1px 2px rgba(9, 30, 66, 0.18) inset,
        0 1px 1px rgba(9, 30, 66, 0.04);
    transform: translateY(0);
}

/* Secondary / Light: clean grey surface with subtle border, ink text.
   Excludes Variant.Text (.rz-variant-text), which must stay borderless
   and transparent — used for in-row icon shortcuts (edit / share /
   etc) that should sit on whatever background the row has. */
.rz-button.rz-button-light:not(.rz-variant-text),
.rz-button.rz-light:not(.rz-variant-text),
.rz-button.rz-button-secondary:not(.rz-variant-text),
.rz-button.rz-secondary:not(.rz-variant-text) {
    background: var(--gapfy-bg-elevated);
    color: var(--gapfy-ink);
    border: 1px solid var(--gapfy-line-strong);
    box-shadow: 0 1px 2px rgba(9, 30, 66, 0.06);
}

.rz-button.rz-button-light:not(.rz-variant-text):not(.rz-state-disabled):hover,
.rz-button.rz-light:not(.rz-variant-text):not(.rz-state-disabled):hover,
.rz-button.rz-button-secondary:not(.rz-variant-text):not(.rz-state-disabled):hover,
.rz-button.rz-secondary:not(.rz-variant-text):not(.rz-state-disabled):hover {
    background: var(--gapfy-bg-soft);
    border-color: var(--gapfy-action);
    color: var(--gapfy-action-strong);
    box-shadow: 0 2px 6px rgba(9, 30, 66, 0.10);
    transform: translateY(-1px);
}

.rz-button.rz-button-light:not(.rz-variant-text):not(.rz-state-disabled):active,
.rz-button.rz-light:not(.rz-variant-text):not(.rz-state-disabled):active,
.rz-button.rz-button-secondary:not(.rz-variant-text):not(.rz-state-disabled):active,
.rz-button.rz-secondary:not(.rz-variant-text):not(.rz-state-disabled):active {
    background: var(--gapfy-bg-soft);
    transform: translateY(0);
    box-shadow: 0 1px 1px rgba(9, 30, 66, 0.04) inset;
}

/* Light + Text variant: hover gives a subtle tint without taking on
   border / shadow. Used by icon shortcuts inside rows. */
.rz-button.rz-button-light.rz-variant-text:not(.rz-state-disabled):hover,
.rz-button.rz-light.rz-variant-text:not(.rz-state-disabled):hover {
    background: color-mix(in srgb, var(--gapfy-action) 8%, transparent);
    color: var(--gapfy-ink);
}

/* Danger / Success / Warning kept Radzen-coloured but adopt the same
   lift-on-hover idiom for consistency. */
.rz-button.rz-button-danger:not(.rz-state-disabled):hover,
.rz-button.rz-danger:not(.rz-state-disabled):hover,
.rz-button.rz-button-success:not(.rz-state-disabled):hover,
.rz-button.rz-success:not(.rz-state-disabled):hover,
.rz-button.rz-button-warning:not(.rz-state-disabled):hover,
.rz-button.rz-warning:not(.rz-state-disabled):hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 10px rgba(9, 30, 66, 0.14);
}

/* Text variant: no surface, only a hover tint. */
.rz-button.rz-button-text:not(.rz-state-disabled):hover,
.rz-button.rz-text:not(.rz-state-disabled):hover {
    background: color-mix(in srgb, var(--gapfy-action) 8%, transparent);
    color: var(--gapfy-action-strong);
}

/* --- Sidebar / Footer: clean 1px divider over the Radzen default border */
.rz-sidebar {
    border-color: var(--gapfy-line, #DFE1E6) !important;
}

/* --- Left sidebar resize ----------------------------------------------------
   CSS variable controls the width. Defaults to 280px (Radzen default). The
   value is set by `window.maestro.sidebar.apply()` on first render and during
   the drag. Persistence (server + localStorage) lives in MainLayout. */
:root {
    --maestro-sidebar-width: 280px;
}

/* Apply the variable to the Radzen left sidebar specifically. The selector is
   scoped enough not to clash with the right pane (which lives in
   `.maestro-right-pane`) or any sidebars Radzen may render in dialogs.
   Crucial: include `.rz-sidebar-expanded` so the rule does NOT apply when
   the user toggles the burger and Radzen adds `.rz-sidebar-collapsed`
   (which sets `width: 0 !important`). Without the expanded gate, our
   higher-specificity selector would override the collapse and leave an
   empty column occupying the user's chosen width. */
.rz-sidebar.rz-sidebar-left.rz-sidebar-expanded {
    width: var(--maestro-sidebar-width) !important;
}

.maestro-sidebar-resize-handle {
    /* Absolute over the sidebar's right edge — the 1px line is the visible
       cue, the wider hit area (8px) gives the user room to grab. */
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--maestro-sidebar-width) - 4px);
    width: 8px;
    cursor: col-resize;
    background: transparent;
    z-index: 1100;
    transition: background-color 120ms ease;
    user-select: none;
    touch-action: none;
}

.maestro-sidebar-resize-handle::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 3px;
    width: 1px;
    background: transparent;
    transition: background-color 120ms ease;
}

.maestro-sidebar-resize-handle:hover::before,
.maestro-sidebar-resizing .maestro-sidebar-resize-handle::before {
    background: var(--gapfy-action);
}

/* While dragging, the entire document should keep the col-resize cursor and
   suppress text selection — pointer events on the handle alone are not
   enough because the cursor often leaves the 8px hit area mid-drag. */
body.maestro-sidebar-resizing,
body.maestro-sidebar-resizing * {
    cursor: col-resize !important;
    user-select: none !important;
}

@media (max-width: 768px) {
    /* On mobile the sidebar collapses into a drawer; resizing makes no
       sense there. Hide the handle entirely. */
    .maestro-sidebar-resize-handle {
        display: none;
    }
}

.rz-footer {
    border-top: 1px solid var(--gapfy-line, #DFE1E6);
}

/* --- Suppress browser focus outline on page headings ---------------------
   Routes.razor uses <FocusOnNavigate Selector="h1" /> for screen-reader
   accessibility. The browser paints a default rectangular outline when
   focusing a heading (h1 is not normally focusable). Suppress the visual
   ring on h1/h2 anywhere — the programmatic focus stays intact. */
h1:focus,
h1:focus-visible,
h2:focus,
h2:focus-visible,
.rz-text-h1:focus,
.rz-text-h1:focus-visible,
.rz-text-h2:focus,
.rz-text-h2:focus-visible {
    outline: none;
}

/* --- Normalise input font-size with body text ---------------------------
   Radzen Material defaults to 1rem (16px) inside text inputs, which reads
   visibly larger than the surrounding 14px body copy on form-heavy pages
   (Settings, Admin, Booking, Timesheet). Drop input value text to 14px so
   labels, captions and values share a single rhythm. Padding stays at the
   Material default so input height does not shift unexpectedly. */
.rz-textbox,
.rz-textarea,
.rz-inputtext,
.rz-dropdown .rz-dropdown-label,
.rz-numeric .rz-spinner-input,
.rz-datepicker .rz-inputtext,
.rz-multiselect .rz-multiselect-label {
    font-size: 0.875rem;
}

/* --- ThemeSwitcher (3-button segmented control in the navbar) ---------
   Tokened on the --gapfy-* scale. The earlier version used --rz-base-50 for
   the container (which inverts to a light grey in dark -> a foreign pale pill
   on the dark navbar) and var(--rz-on-primary, #fff) for the selected
   foreground (white in both themes) over var(--rz-primary) = --gapfy-action,
   which flips light in dark -> white-on-near-white selected icon. --gapfy-action
   + --gapfy-action-on flip together, so the selected pill stays readable. */
.maestro-theme-switcher {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    border-radius: var(--gapfy-radius-pill);
    border: 1px solid var(--gapfy-line);
    background: transparent;
}

.maestro-theme-switcher-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: var(--gapfy-radius-pill);
    color: var(--gapfy-muted);
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease;
}

.maestro-theme-switcher-button:hover {
    color: var(--gapfy-ink);
    background: var(--gapfy-bg-soft);
}

.maestro-theme-switcher-button.is-selected {
    background: var(--gapfy-action);
    color: var(--gapfy-action-on);
}

.maestro-theme-switcher-button.is-selected:hover {
    background: var(--gapfy-action-strong);
    color: var(--gapfy-action-on);
}

/* ============================================================================
   Custom scrollbars. The browser default (chunky grey on Windows/Chrome) clashes
   with the Stripe-minimal chrome, especially on the narrow side panes, the
   command palette, and dialog bodies -- and in dark mode the default reads light
   on a dark surface. A thin track-less scrollbar tinted with --gapfy-line-strong
   (which already adapts to both themes) keeps the chrome calm. Firefox uses the
   standard properties; Chromium/WebKit uses the pseudo-elements.
   ============================================================================ */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--gapfy-line-strong) transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background: var(--gapfy-line-strong);
    border-radius: var(--gapfy-radius-pill);
    border: 2px solid transparent;
    background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--gapfy-muted);
    background-clip: padding-box;
}

::-webkit-scrollbar-corner {
    background: transparent;
}

/* Stripe-style header: white surface, thin 1px bottom border, ~64px tall.
   No module tab strip anymore — sidebar is the single navigation. */
.rz-header {
    height: 64px !important;
    min-height: 64px;
    background: var(--gapfy-bg) !important;
    color: var(--gapfy-ink) !important;
    border-bottom: 1px solid var(--gapfy-line);
    box-shadow: none !important;
    padding: 0 !important;
}

/* Make sure header links / text read with the right contrast on white.
   The :hover/:focus variants are required because Radzen's material theme
   ships `.rz-header a:hover { color: var(--rz-on-primary) }` (specificity
   0,2,1) for the old coloured app-bar -- it outranks both the plain
   `.rz-header a` override (0,1,1) and `.maestro-profile-menu-item:hover`
   (0,2,0), so without matching it the avatar dropdown links flipped to the
   near-white on-primary colour on hover. Matching the selector here (same
   specificity, later in the cascade) keeps every header link ink-coloured. */
.rz-header a,
.rz-header a:hover,
.rz-header a:focus,
.rz-header .rz-text,
.rz-header .rz-profile-menu .rz-profile-menu-user {
    color: var(--gapfy-ink);
}

/* Profile menu trigger: kill the Radzen Material default brand-coloured
   background (it picks up --rz-primary which is now cyan, and the result
   was a bright cyan pill behind the avatar). Stripe-style: transparent
   resting state, subtle hover surface, ink-coloured text. */
.rz-header .rz-profile-menu,
.rz-header .rz-profile-menu .rz-profile-menu-user {
    background: transparent !important;
    box-shadow: none !important;
    color: var(--gapfy-ink) !important;
    border-radius: var(--gapfy-radius, 6px);
    transition: background-color 120ms ease;
}

.rz-header .rz-profile-menu:hover,
.rz-header .rz-profile-menu:focus-within,
.rz-header .rz-profile-menu .rz-profile-menu-user:hover {
    background: var(--gapfy-bg-soft) !important;
}

.rz-header .rz-profile-menu .rz-profile-menu-user {
    padding: 0.375rem 0.625rem;
}

.rz-header .rz-profile-menu .rzi-chevron-down,
.rz-header .rz-profile-menu .rz-profile-menu-icon {
    color: var(--gapfy-muted);
    font-size: 16px;
}

.maestro-navbar-profile-trigger .rzi {
    color: var(--gapfy-ink-soft);
}

/* Profile menu popup itself stays on the elevated surface, not the brand. */
.rz-profile-menu-items,
.rz-profile-menu-popup {
    background: var(--gapfy-bg-elevated) !important;
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius-lg, 12px);
    box-shadow: var(--gapfy-shadow-lg);
}

.rz-profile-menu-item {
    color: var(--gapfy-ink) !important;
}

.rz-profile-menu-item:hover {
    background: var(--gapfy-bg-soft) !important;
}

/* Dark theme: header is the same colour as the body bg (not pure black) to
   sit "inside" the surface rather than float above it. */
:root.theme-dark .rz-header {
    background: var(--gapfy-bg) !important;
    border-bottom-color: var(--gapfy-line);
}

/* ---------------------------------------------------------------------- */
/* Home dashboard                                                         */
/* ---------------------------------------------------------------------- */

.maestro-home {
    max-width: 1200px;
    margin: 0 auto;
}

.maestro-home-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 1rem;
}

.maestro-home-card {
    display: block;
    padding: 1.25rem;
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius-lg, 12px);
    background: var(--gapfy-bg-elevated);
    text-decoration: none;
    color: var(--gapfy-ink);
    transition: border-color 150ms ease, transform 150ms ease, box-shadow 150ms ease;
}

.maestro-home-card:hover {
    border-color: color-mix(in srgb, var(--gapfy-action) 30%, var(--gapfy-line));
    transform: translateY(-2px);
    box-shadow: var(--gapfy-shadow);
}

.maestro-home-card:focus-visible {
    outline: 2px solid var(--gapfy-action);
    outline-offset: 2px;
}

.maestro-home-card-icon {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Compact counter row for the tenant-overview section. Auto-fit so it
   stacks gracefully on mobile without needing media queries. */

.maestro-home-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
}

.maestro-home-stat {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    padding: 1rem 1.25rem;
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius-lg, 12px);
    background: var(--gapfy-bg-elevated);
}

/* Icon becomes a circular tinted chip; the tint derives from the icon's own
   inline colour (var(--rz-info)/success/warning) via currentColor, so each
   tile reads as a distinct accent without hardcoding three backgrounds. */
.maestro-home-stat .rzi {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    border-radius: 50%;
    background: color-mix(in srgb, currentColor 14%, transparent);
}

.maestro-home-stat-body {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

/* The KPI number is the hero of the tile -- big, tight, ink. */
.maestro-home-stat-body .rz-text-h4 {
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: var(--gapfy-ink);
}

/* The caption reads as a small uppercase label, not body copy. */
.maestro-home-stat-body .rz-text-caption {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--gapfy-muted);
}

/* ---------------------------------------------------------------------- */
/* MaestroPageHeader: shared Stripe-style page header used as the top     */
/* block of every interior page (Settings, Admin, Platform, Modules).     */
/* Renders breadcrumb + H1 + caption + actions slot in a consistent rhythm */
/* with a subtle bottom divider. Caller picks whichever slots are needed. */
/* ---------------------------------------------------------------------- */

.maestro-page-header {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0 0 1.25rem 0;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--gapfy-line);
}

.maestro-page-header-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem;
    font-size: 0.8125rem;
    line-height: 1.2;
    color: var(--gapfy-muted);
}

.maestro-page-header-breadcrumb-link {
    color: var(--gapfy-muted);
    text-decoration: none;
    transition: color 150ms ease;
}

.maestro-page-header-breadcrumb-link:hover,
.maestro-page-header-breadcrumb-link:focus-visible {
    color: var(--gapfy-ink);
    text-decoration: underline;
    text-underline-offset: 2px;
    outline: none;
}

.maestro-page-header-breadcrumb-current {
    color: var(--gapfy-ink-soft);
    font-weight: 500;
}

.maestro-page-header-breadcrumb-separator {
    color: var(--gapfy-muted);
    opacity: 0.5;
}

.maestro-page-header-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.maestro-page-header-text {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
    flex: 1 1 auto;
}

.maestro-page-header-title {
    margin: 0;
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.2;
    color: var(--gapfy-ink);
}

.maestro-page-header-caption {
    margin: 0;
    font-size: 0.9375rem;
    line-height: 1.5;
    color: var(--gapfy-muted);
}

.maestro-page-header-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}

@media (max-width: 640px) {
    .maestro-page-header-row {
        flex-direction: column;
        align-items: flex-start;
    }

    .maestro-page-header-actions {
        width: 100%;
    }

    .maestro-page-header-title {
        font-size: 1.5rem;
    }
}

/* ---------------------------------------------------------------------- */
/* MaestroEmptyState: shared Stripe-style empty placeholder. Drop-in for  */
/* RadzenDataGrid EmptyText and ad-hoc "no records" @if blocks. Renders   */
/* a centered icon + title + optional description + optional action.      */
/* ---------------------------------------------------------------------- */

.maestro-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2.5rem 1.5rem;
    text-align: center;
    color: var(--gapfy-muted);
}

.maestro-empty-state-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--gapfy-action-soft);
    color: var(--gapfy-ink-soft);
    margin-bottom: 0.5rem;
}

.maestro-empty-state-icon .rzi {
    font-size: 28px;
    line-height: 1;
}

.maestro-empty-state-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--gapfy-ink);
}

.maestro-empty-state-description {
    margin: 0;
    max-width: 36rem;
    font-size: 0.875rem;
    line-height: 1.5;
    color: var(--gapfy-muted);
}

.maestro-empty-state-action {
    margin-top: 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    justify-content: center;
}

@media (max-width: 640px) {
    .maestro-empty-state {
        padding: 2rem 1rem;
    }

    .maestro-empty-state-icon {
        width: 48px;
        height: 48px;
    }

    .maestro-empty-state-icon .rzi {
        font-size: 24px;
    }
}

/* ---------------------------------------------------------------------- */
/* Sidebar collapse toggle (lives at the bottom of the left sidebar).     */
/* When the sidebar is collapsed entirely a floating button takes over.   */
/* ---------------------------------------------------------------------- */

.maestro-sidebar-footer {
    border-top: 1px solid var(--gapfy-line);
    padding: 0.5rem;
    display: flex;
    justify-content: flex-end;
}

.maestro-sidebar-collapse-button {
    width: 32px;
    height: 32px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--gapfy-muted);
    border-radius: var(--gapfy-radius);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease;
}

.maestro-sidebar-collapse-button:hover {
    background: var(--gapfy-bg-soft);
    color: var(--gapfy-ink);
}

.maestro-sidebar-collapse-button:focus-visible {
    outline: 2px solid var(--gapfy-action);
    outline-offset: 2px;
}

.maestro-sidebar-expand-floating {
    position: fixed;
    left: 0.5rem;
    bottom: 1rem;
    z-index: 1000;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--gapfy-line);
    background: var(--gapfy-bg-elevated);
    color: var(--gapfy-muted);
    border-radius: var(--gapfy-radius);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: var(--gapfy-shadow-sm);
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}

.maestro-sidebar-expand-floating:hover {
    background: var(--gapfy-action);
    color: var(--gapfy-action-on);
    border-color: var(--gapfy-action);
}

.maestro-sidebar-expand-floating:focus-visible {
    outline: 2px solid var(--gapfy-action);
    outline-offset: 2px;
}

/* ============================================================================
   Dark mode tweaks. brand.css already covers the --gapfy-* tokens (ink, bg,
   line, shadow). What remains here is component-level polish that needs
   subtle adjustments in dark surroundings -- gradients that were "primary
   over white" don't translate one-to-one because white-on-dark glows too
   much, and a few elevation cues need stronger shadows to read.
   ============================================================================ */

:root.theme-dark .rz-button.rz-button-primary,
:root.theme-dark .rz-button.rz-primary {
    background: var(--gapfy-action);
    color: var(--gapfy-action-on);
    border-color: var(--gapfy-line-strong);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.40);
}

:root.theme-dark .rz-button.rz-button-primary:not(.rz-state-disabled):hover,
:root.theme-dark .rz-button.rz-primary:not(.rz-state-disabled):hover {
    background: var(--gapfy-action-strong);
    box-shadow:
        0 4px 10px rgba(0, 0, 0, 0.55),
        0 2px 3px rgba(0, 0, 0, 0.35);
}

/* Light/secondary buttons in dark: surface should sit clearly above bg.
   Variant.Text excluded — keeps transparent surface for in-row icons. */
:root.theme-dark .rz-button.rz-button-light:not(.rz-variant-text),
:root.theme-dark .rz-button.rz-light:not(.rz-variant-text),
:root.theme-dark .rz-button.rz-button-secondary:not(.rz-variant-text),
:root.theme-dark .rz-button.rz-secondary:not(.rz-variant-text) {
    background: var(--gapfy-bg-elevated);
    color: var(--gapfy-ink);
    border-color: var(--gapfy-line-strong);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.40);
}

:root.theme-dark .rz-button.rz-button-light:not(.rz-variant-text):not(.rz-state-disabled):hover,
:root.theme-dark .rz-button.rz-light:not(.rz-variant-text):not(.rz-state-disabled):hover,
:root.theme-dark .rz-button.rz-button-secondary:not(.rz-variant-text):not(.rz-state-disabled):hover,
:root.theme-dark .rz-button.rz-secondary:not(.rz-variant-text):not(.rz-state-disabled):hover {
    background: color-mix(in srgb, var(--gapfy-action) 10%, var(--gapfy-bg-elevated));
    border-color: var(--gapfy-action);
    color: var(--gapfy-action);
}

/* Card in dark: surface + border tweaks. Shadows use the tonal --gapfy-shadow-*
   tokens (which already carry their own dark values from brand.css) instead of
   hand-rolled black so they stay consistent with every other elevation. The
   hover lift is opt-in, scoped to clickable cards just like the light theme. */
:root.theme-dark .rz-card {
    background: var(--gapfy-bg-elevated);
    border-color: var(--gapfy-line);
    box-shadow: var(--gapfy-shadow-sm);
}

:root.theme-dark .rz-card.is-clickable:hover,
:root.theme-dark a.rz-card:hover {
    box-shadow: var(--gapfy-shadow);
    border-color: color-mix(in srgb, var(--gapfy-action) 40%, var(--gapfy-line));
}

:root.theme-dark .rz-card.is-current,
:root.theme-dark .rz-card.is-selected {
    background: color-mix(in srgb, var(--gapfy-action) 8%, var(--gapfy-bg-elevated));
    border-color: var(--gapfy-action);
    box-shadow:
        0 0 0 1px color-mix(in srgb, var(--gapfy-action) 50%, transparent),
        var(--gapfy-shadow-sm);
}

/* DataGrid header background gets brand-aware tint in dark. */
:root.theme-dark .rz-datatable thead.rz-datatable-thead > tr > th,
:root.theme-dark .rz-grid-table thead > tr > th {
    background: var(--gapfy-bg-soft);
    color: var(--gapfy-ink);
}

:root.theme-dark .rz-datatable tbody.rz-datatable-tbody > tr:not(.rz-state-highlight):hover,
:root.theme-dark .rz-grid-table tbody > tr:not(.rz-state-highlight):hover {
    background: color-mix(in srgb, var(--gapfy-action) 6%, var(--gapfy-bg-elevated));
}

/* Inline code chip in dark needs a higher contrast surface. */
:root.theme-dark :not(pre) > code {
    background: var(--gapfy-bg-soft);
    border-color: var(--gapfy-line-strong);
    color: var(--gapfy-ink);
}

/* ============================================================================
   Selected / active state on Radzen menus + trees + listboxes.

   Radzen 10's Material theme exposes dedicated CSS variables for each
   component's selected state (e.g. --rz-menu-item-selected-*,
   --rz-tree-node-selected-*). Redefining them at :root is the cleanest
   way to retheme these states — no need to chase selectors or rely on
   !important wars against the upstream theme.

   Stripe-style result: subtle 10% (light) / 18% (dark) tint of the
   action colour, with the default ink text colour preserved. Contrast
   is always safe because the foreground never inverts.

   Note: the previous selectors targeted .rz-state-highlight /
   .rz-state-active, which Radzen does NOT use for these widgets —
   selected tree nodes carry .rz-treenode-content-selected and active
   panel-menu links carry .active (from NavLink). Hence the older
   override did nothing visible.
   ============================================================================ */

:root {
    /* RadzenPanelMenu (SettingsSidebar) uses its OWN token family —
       --rz-panel-menu-item-active-* — separate from --rz-menu-* which is
       only the RadzenMenu top bar component. Verified against
       radzen.blazor/10.4.3/staticwebassets/css/material.css. */
    --rz-panel-menu-item-active-color: var(--gapfy-ink);
    --rz-panel-menu-item-active-background-color: color-mix(in srgb, var(--gapfy-action) 10%, transparent);
    --rz-panel-menu-item-active-indicator: var(--gapfy-action);
    --rz-panel-menu-item-hover-color: var(--gapfy-ink);
    --rz-panel-menu-item-hover-background-color: color-mix(in srgb, var(--gapfy-action) 5%, transparent);

    /* RadzenMenu (top horizontal bar — not currently used in Maestro
       but kept in sync so it inherits the same palette if ever added). */
    --rz-menu-item-selected-color: var(--gapfy-ink);
    --rz-menu-item-selected-background-color: color-mix(in srgb, var(--gapfy-action) 10%, transparent);
    --rz-menu-top-item-selected-color: var(--gapfy-ink);
    --rz-menu-top-item-selected-background-color: color-mix(in srgb, var(--gapfy-action) 10%, transparent);

    /* RadzenTree node selected + hover (DocuVault folders list). */
    --rz-tree-node-selected-color: var(--gapfy-ink);
    --rz-tree-node-selected-background-color: color-mix(in srgb, var(--gapfy-action) 10%, transparent);
    --rz-tree-node-hover-color: var(--gapfy-ink);
    --rz-tree-node-hover-background-color: color-mix(in srgb, var(--gapfy-action) 5%, transparent);

    /* RadzenDropDown / RadzenListBox / RadzenAutoComplete option selected. */
    --rz-dropdown-item-selected-color: var(--gapfy-ink);
    --rz-dropdown-item-selected-background-color: color-mix(in srgb, var(--gapfy-action) 10%, transparent);
    --rz-dropdown-item-selected-hover-color: var(--gapfy-ink);
    --rz-dropdown-item-selected-hover-background-color: color-mix(in srgb, var(--gapfy-action) 14%, transparent);

    /* RadzenDataGrid row selected. */
    --rz-grid-selected-color: var(--gapfy-ink);
    --rz-grid-selected-background-color: color-mix(in srgb, var(--gapfy-action) 8%, transparent);

    /* RadzenTabs active tab. */
    --rz-tabs-tab-selected-color: var(--gapfy-action);
    --rz-tabs-tab-selected-background-color: transparent;
    --rz-tabs-tab-selected-top-border-color: var(--gapfy-action);

    /* RadzenSelectBar selected segment + RadzenAccordion expanded header. */
    --rz-selectbar-selected-color: var(--gapfy-action-on);
    --rz-selectbar-selected-background-color: var(--gapfy-action);
    --rz-accordion-selected-color: var(--gapfy-action);

    /* RadzenDatePicker selected day. */
    --rz-datepicker-calendar-selected-color: var(--gapfy-action-on);
    --rz-datepicker-calendar-selected-background-color: var(--gapfy-action);
    --rz-datepicker-calendar-selected-hover-color: var(--gapfy-action-on);
    --rz-datepicker-calendar-selected-hover-background-color: var(--gapfy-action-strong);

    /* RadzenPager numeric button selected. */
    --rz-pager-numeric-button-selected-color: var(--gapfy-action-on);
    --rz-pager-numeric-button-selected-background-color: var(--gapfy-action);
}

:root.theme-dark {
    --rz-panel-menu-item-active-background-color: color-mix(in srgb, var(--gapfy-action) 18%, transparent);
    --rz-panel-menu-item-hover-background-color: color-mix(in srgb, var(--gapfy-action) 8%, transparent);
    --rz-menu-item-selected-background-color: color-mix(in srgb, var(--gapfy-action) 18%, transparent);
    --rz-menu-top-item-selected-background-color: color-mix(in srgb, var(--gapfy-action) 18%, transparent);
    --rz-tree-node-selected-background-color: color-mix(in srgb, var(--gapfy-action) 18%, transparent);
    --rz-tree-node-hover-background-color: color-mix(in srgb, var(--gapfy-action) 8%, transparent);
    --rz-dropdown-item-selected-background-color: color-mix(in srgb, var(--gapfy-action) 18%, transparent);
    --rz-dropdown-item-selected-hover-background-color: color-mix(in srgb, var(--gapfy-action) 24%, transparent);
    --rz-grid-selected-background-color: color-mix(in srgb, var(--gapfy-action) 14%, transparent);
}

/* ============================================================================
   ButtonStyle.Light + Variant.Text — icon-only shortcuts inside rows.

   Radzen's material theme sets `.rz-variant-text.rz-light { color: var(--rz-base-200) }`.
   Maestro redefines --rz-base-200 as --gapfy-bg-elevated (#FFFFFF in light), so
   these icon buttons turn invisible-white-on-light. Override directly so the
   icon reads at the muted-ink tone (and gets a subtle slate hover tint).
   ============================================================================ */

.rz-variant-text.rz-light {
    color: var(--gapfy-ink-soft) !important;
}

.rz-variant-text.rz-light:not(.rz-state-disabled):hover {
    background-color: color-mix(in srgb, var(--gapfy-action) 8%, transparent) !important;
    color: var(--gapfy-ink) !important;
}

.rz-variant-text.rz-light:not(.rz-state-disabled):active {
    background-color: color-mix(in srgb, var(--gapfy-action) 14%, transparent) !important;
    color: var(--gapfy-ink) !important;
}

:root.theme-dark .rz-variant-text.rz-light {
    color: var(--gapfy-ink-soft) !important;
}

:root.theme-dark .rz-variant-text.rz-light:not(.rz-state-disabled):hover {
    background-color: color-mix(in srgb, var(--gapfy-action) 14%, transparent) !important;
    color: var(--gapfy-ink) !important;
}

/* ============================================================================
   Tonal badges — Stripe / Linear style status chips.

   Radzen paints `.rz-badge-{status}` as a SOLID var(--rz-{status}) fill with
   white text. On the lighter status hues (info/secondary cyan, success green,
   warning amber) white text fails WCAG AA in both themes (ratios 2.1-3.3), and
   after --rz-primary was remapped to the slate action colour -- which flips
   LIGHT in dark mode -- the primary badge rendered white-on-white (ratio 1.23).

   A tonal fill (status colour at low alpha + the status colour as the text,
   shifted darker in light / lighter in dark) holds a strong contrast in both
   themes and reads as a calm, modern chip instead of a saturated block. Radzen
   exposes no per-badge colour token, so the class is overridden directly; the
   two-class selector (0,2,0) beats the upstream single-class rule and loads
   after it, so no !important is needed. Covers Shade.* variants too. */
.rz-badge.rz-badge-primary {
    background-color: color-mix(in srgb, var(--gapfy-action) 14%, transparent);
    color: var(--gapfy-ink);
}
.rz-badge.rz-badge-secondary,
.rz-badge.rz-badge-info {
    background-color: color-mix(in srgb, var(--gapfy-primary) 16%, transparent);
    color: var(--gapfy-accent-strong);
}
.rz-badge.rz-badge-success {
    background-color: color-mix(in srgb, var(--gapfy-success) 14%, transparent);
    color: #166534;
}
.rz-badge.rz-badge-warning {
    background-color: color-mix(in srgb, var(--gapfy-warning) 16%, transparent);
    color: #92400E;
}
.rz-badge.rz-badge-danger {
    background-color: color-mix(in srgb, var(--gapfy-danger) 14%, transparent);
    color: #B91C1C;
}
.rz-badge.rz-badge-light,
.rz-badge.rz-badge-base {
    background-color: var(--gapfy-bg-soft);
    color: var(--gapfy-muted);
    border: 1px solid var(--gapfy-line);
}

:root.theme-dark .rz-badge.rz-badge-primary {
    background-color: color-mix(in srgb, var(--gapfy-action) 24%, transparent);
    color: var(--gapfy-ink);
}
:root.theme-dark .rz-badge.rz-badge-secondary,
:root.theme-dark .rz-badge.rz-badge-info {
    background-color: color-mix(in srgb, var(--gapfy-primary) 26%, transparent);
    color: #7CC4EC;
}
:root.theme-dark .rz-badge.rz-badge-success {
    background-color: color-mix(in srgb, var(--gapfy-success) 26%, transparent);
    color: #4ADE80;
}
:root.theme-dark .rz-badge.rz-badge-warning {
    background-color: color-mix(in srgb, var(--gapfy-warning) 26%, transparent);
    color: #FBBF24;
}
:root.theme-dark .rz-badge.rz-badge-danger {
    background-color: color-mix(in srgb, var(--gapfy-danger) 26%, transparent);
    color: #F87171;
}
:root.theme-dark .rz-badge.rz-badge-light,
:root.theme-dark .rz-badge.rz-badge-base {
    background-color: var(--gapfy-bg-elevated);
    color: var(--gapfy-muted);
    border-color: var(--gapfy-line-strong);
}

/* ============================================================================
   Tonal alerts — the same modern treatment as the badges above.

   Radzen's flat alert paints a solid, saturated var(--rz-{status}) block with
   white text: the amber warning + white fails WCAG, and the saturated blocks
   now clash with the tonal badges. Re-point the per-status --rz-alert-* tokens
   to a soft tint background + ink body text (max contrast, both themes) + a
   status-coloured icon and a left accent bar (Stripe / Linear pattern). The
   icon and bar carry the urgency colour while the copy stays readable.

   Scoped to .rz-variant-flat (0,3,0) so the outlined/text variants keep their
   own transparent treatment, and it beats the upstream .rz-alert.rz-{status}
   (0,2,0) token rule. Tints + ink adapt to dark automatically; the icon gets a
   lighter shade in dark so it still reads on the dark tint. */
.rz-alert.rz-variant-flat.rz-info {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-primary) 12%, transparent);
    --rz-alert-color: var(--gapfy-ink);
    --rz-alert-title-color: var(--gapfy-ink);
    --rz-alert-icon-color: var(--gapfy-primary-strong);
    border-left: 3px solid var(--gapfy-primary);
}
.rz-alert.rz-variant-flat.rz-success {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-success) 12%, transparent);
    --rz-alert-color: var(--gapfy-ink);
    --rz-alert-title-color: var(--gapfy-ink);
    --rz-alert-icon-color: #15803D;
    border-left: 3px solid var(--gapfy-success);
}
.rz-alert.rz-variant-flat.rz-warning {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-warning) 16%, transparent);
    --rz-alert-color: var(--gapfy-ink);
    --rz-alert-title-color: var(--gapfy-ink);
    --rz-alert-icon-color: #B45309;
    border-left: 3px solid var(--gapfy-warning);
}
.rz-alert.rz-variant-flat.rz-danger {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-danger) 12%, transparent);
    --rz-alert-color: var(--gapfy-ink);
    --rz-alert-title-color: var(--gapfy-ink);
    --rz-alert-icon-color: var(--gapfy-danger);
    border-left: 3px solid var(--gapfy-danger);
}

:root.theme-dark .rz-alert.rz-variant-flat.rz-info {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-primary) 18%, transparent);
    --rz-alert-icon-color: #5DB9E8;
}
:root.theme-dark .rz-alert.rz-variant-flat.rz-success {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-success) 20%, transparent);
    --rz-alert-icon-color: #4ADE80;
}
:root.theme-dark .rz-alert.rz-variant-flat.rz-warning {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-warning) 22%, transparent);
    --rz-alert-icon-color: #FBBF24;
}
:root.theme-dark .rz-alert.rz-variant-flat.rz-danger {
    --rz-alert-background-color: color-mix(in srgb, var(--gapfy-danger) 22%, transparent);
    --rz-alert-icon-color: #F87171;
}

/* ============================================================================
   Stripe-style sidebar.

   Used by MaestroSidebar.razor. Renders a single navigation panel with
   uppercase section headers (Modules / My account / Tenant administration /
   Platform administration) and items grouped flat underneath. The module
   the user is currently inside renders its sub-items expanded below the
   module's own row; other modules stay collapsed to a single line.

   Layout principles borrowed from Stripe Dashboard:
     - Dense (~32px row height, 14px font, generous icon→text gap).
     - Subtle hover (bg tint only, no border / box-shadow).
     - Active row uses the same bg tint as hover plus stronger text colour
       and slightly bolder font — never an outline or chunky left bar.
     - Section headers are uppercase 11px with letter-spacing, in the muted
       tone — they read as "label, not click target".
   ============================================================================ */

.maestro-sidebar-nav {
    padding: 0.5rem 0.5rem 1rem;
    background: var(--gapfy-bg);
}

.maestro-sidebar-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.maestro-sidebar-section-header {
    padding: 1rem 0.75rem 0.35rem;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--gapfy-muted);
    user-select: none;
}

.maestro-sidebar-section-header.is-platform {
    color: color-mix(in srgb, var(--gapfy-warning) 70%, var(--gapfy-muted));
}

.maestro-sidebar-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.375rem 0.625rem;
    margin: 0;
    border-radius: var(--gapfy-radius, 6px);
    color: var(--gapfy-ink-soft);
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.4;
    transition: background-color 120ms ease, color 120ms ease;
    cursor: pointer;
}

.maestro-sidebar-item .rzi {
    color: var(--gapfy-muted);
    transition: color 120ms ease;
    flex-shrink: 0;
}

.maestro-sidebar-item:hover {
    background: var(--gapfy-bg-soft);
    color: var(--gapfy-ink);
}

.maestro-sidebar-item:hover .rzi {
    color: var(--gapfy-ink-soft);
}

/* NavLink applies .active when the route matches. Stripe-style: subtle
   primary-tinted bg + stronger text colour + brand-tinted icon. */
.maestro-sidebar-item.active {
    background: color-mix(in srgb, var(--gapfy-action) 10%, transparent);
    color: var(--gapfy-ink);
    font-weight: 600;
}

.maestro-sidebar-item.active .rzi {
    color: var(--gapfy-action);
}

.maestro-sidebar-item:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--gapfy-action) 35%, transparent);
}

/* Module root row (DocuVault / Timesheet / Booking / Harmony).
   When the user is inside that module, the row inherits a subtle
   highlight even when the exact URL is a child route — visible cue
   that a section is "open". The NavLink .active class kicks in for the
   actual current page below. */
.maestro-sidebar-module-root.is-active-module {
    color: var(--gapfy-ink);
}

.maestro-sidebar-module-root.is-active-module .rzi {
    color: var(--gapfy-action);
}

.maestro-sidebar-sublist {
    list-style: none;
    margin: 0.125rem 0 0.25rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.maestro-sidebar-subitem {
    padding-left: 2.25rem;
    font-size: 0.8125rem;
    font-weight: 400;
}

.maestro-sidebar-subitem .rzi {
    font-size: 16px;
}

/* Platform section's active state uses the orange/warning tint — flag that
   the user is operating cross-tenant. The colour treatment is otherwise
   identical to the default sidebar item. */
.maestro-sidebar-list.is-platform .maestro-sidebar-item.active {
    background: color-mix(in srgb, var(--gapfy-warning) 15%, transparent);
    color: var(--gapfy-ink);
}

.maestro-sidebar-list.is-platform .maestro-sidebar-item.active .rzi {
    color: var(--gapfy-warning);
}

/* Dark mode coverage. brand.css already swaps --gapfy-bg / ink / muted; the
   color-mix() expressions resolve automatically. Only need to soften the
   active highlight a touch so it doesn't read as a chunky bar in dark. */
:root.theme-dark .maestro-sidebar-item.active {
    background: color-mix(in srgb, var(--gapfy-action) 18%, transparent);
}

:root.theme-dark .maestro-sidebar-list.is-platform .maestro-sidebar-item.active {
    background: color-mix(in srgb, var(--gapfy-warning) 22%, transparent);
}

/* ============================================================================
   Stripe-style navbar (MaestroNavbar.razor).

   3-column grid: logo + breadcrumb (left), search input (center),
   tenant picker + notifications + profile menu (right). Centre column
   stays anchored to the viewport mid-point even when the left grows.
   ============================================================================ */

.maestro-navbar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 480px) minmax(0, 1fr);
    align-items: center;
    width: 100%;
    height: 100%;
    padding: 0 1.25rem;
    gap: 1rem;
}

.maestro-navbar-left {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-width: 0;
}

.maestro-navbar-logo {
    height: 24px;
    width: auto;
    display: block;
}

/* The wordmark has dark text -> swap to the negative (white text) wordmark in
   dark theme. Mirrors the three theme states in brand.css: explicit theme-dark,
   explicit theme-light, and System (no class -> prefers-color-scheme). */
.maestro-navbar-logo-dark {
    display: none;
}

:root.theme-dark .maestro-navbar-logo-light {
    display: none;
}

:root.theme-dark .maestro-navbar-logo-dark {
    display: block;
}

@media (prefers-color-scheme: dark) {
    :root:not(.theme-light):not(.theme-dark) .maestro-navbar-logo-light {
        display: none;
    }

    :root:not(.theme-light):not(.theme-dark) .maestro-navbar-logo-dark {
        display: block;
    }
}

.maestro-navbar-breadcrumb {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.maestro-navbar-center {
    display: flex;
    justify-content: center;
    align-items: center;
    min-width: 0;
}

.maestro-navbar-search {
    position: relative;
    width: 100%;
    max-width: 480px;
    display: flex;
    align-items: center;
}

.maestro-navbar-search-icon {
    position: absolute;
    left: 0.75rem;
    font-size: 18px !important;
    color: var(--gapfy-muted);
    pointer-events: none;
}

.maestro-navbar-search-input {
    width: 100%;
    padding: 0.5rem 0.75rem 0.5rem 2.25rem;
    background: var(--gapfy-bg-soft);
    border: 1px solid transparent;
    border-radius: var(--gapfy-radius, 6px);
    color: var(--gapfy-ink);
    font-family: var(--gapfy-font-sans);
    font-size: 0.875rem;
    line-height: 1.4;
    transition: background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}

.maestro-navbar-search-input::placeholder {
    color: var(--gapfy-muted);
}

.maestro-navbar-search-input:not(:disabled):hover {
    background: color-mix(in srgb, var(--gapfy-ink) 4%, var(--gapfy-bg-soft));
}

.maestro-navbar-search-input:not(:disabled):focus {
    outline: none;
    background: var(--gapfy-bg);
    border-color: var(--gapfy-action);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gapfy-action) 25%, transparent);
}

.maestro-navbar-search-input:disabled {
    cursor: not-allowed;
    opacity: 0.85;
}

/* Readonly variant: the input is a click-target that opens the Cmd+K palette.
   Cursor and padding-right (room for the shortcut hint pill) reflect that. */
.maestro-navbar-search-input[readonly] {
    cursor: pointer;
    padding-right: 3.5rem;
}

/* Shortcut hint pill sitting at the right edge of the search input. */
.maestro-navbar-search-shortcut-hint {
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    padding: 0.125rem 0.4rem;
    background: var(--gapfy-bg);
    border: 1px solid var(--gapfy-line);
    border-radius: 4px;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--gapfy-muted);
    pointer-events: none;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    line-height: 1;
}

.maestro-navbar-right {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    min-width: 0;
}

.maestro-navbar-profile-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--gapfy-ink);
}

.maestro-navbar-profile-name {
    font-size: 0.875rem;
    font-weight: 600;
}

.maestro-navbar-profile-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    border: 1px solid var(--rz-base-300, rgba(0, 0, 0, 0.08));
}

/* Mobile: collapse the search bar (hide) and let the left/right items take
   the available width. The search will reappear via Cmd+K palette later. */
@media (max-width: 900px) {
    .maestro-navbar {
        grid-template-columns: minmax(0, 1fr) minmax(0, auto);
    }

    .maestro-navbar-center {
        display: none;
    }
}

:root.theme-dark .maestro-navbar-search-input {
    background: var(--gapfy-bg-soft);
}

:root.theme-dark .maestro-navbar-search-input:not(:disabled):hover {
    background: color-mix(in srgb, var(--gapfy-action) 10%, var(--gapfy-bg-soft));
}

/* ============================================================================
   Density adjustments — Stripe-like dense surfaces without breaking layout.
   Limited to component-level CSS that doesn't change padding utilities
   (.rz-p-*) so existing pages keep their explicit spacing intact.
   ============================================================================ */

/* Badges: tighter padding, slightly smaller font, 500 weight. */
.rz-badge {
    font-size: 0.75rem;
    font-weight: 500;
    padding: 0.125rem 0.5rem;
    border-radius: var(--gapfy-radius-pill, 9999px);
    letter-spacing: 0;
}

/* Tabs: thin 2px underline (Stripe-style), tighter padding. */
.rz-tabview-nav-link {
    padding: 0.625rem 0.875rem !important;
    font-size: 0.875rem;
    font-weight: 500;
    border-bottom-width: 2px !important;
}

.rz-tabview-nav-link.rz-state-active {
    color: var(--gapfy-action) !important;
    border-bottom-color: var(--gapfy-action) !important;
}

/* Data grids: tighter cell padding, smaller font, more rows visible.       */
.rz-data-grid-data > tr > td,
.rz-grid-table > tbody > tr > td,
.rz-datatable tbody.rz-datatable-tbody > tr > td {
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
}

.rz-data-grid-data > thead > tr > th,
.rz-grid-table > thead > tr > th,
.rz-datatable thead.rz-datatable-thead > tr > th {
    padding: 0.5rem 0.75rem;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Dialogs: header tighter, generous body padding. */
.rz-dialog-titlebar {
    padding: 0.875rem 1.25rem;
    font-size: 1rem;
    font-weight: 600;
}

.rz-dialog-content {
    padding: 1.25rem;
}

/* Form field labels: small + medium weight, Stripe-style. */
.rz-form-field-label {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--gapfy-ink-soft);
    margin-bottom: 0.25rem;
}

/* ============================================================================
   Command palette (Cmd+K / Ctrl+K) overlay.

   Mounted at the root of MainLayout next to <CookiesConsentPopup />, floats
   above the sidebar, right pane and any RadzenDialog (z-index 10000+). Stripe
   / Linear-style: top-anchored card, backdrop click closes, keyboard owns it.
   ============================================================================ */
.maestro-command-palette-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 10000;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding-top: 12vh;
    padding-inline: 1rem;
    animation: maestroCommandPaletteFadeIn 180ms cubic-bezier(0.4, 0, 0.2, 1);
}

:root.theme-dark .maestro-command-palette-backdrop {
    background: rgba(0, 0, 0, 0.6);
}

@keyframes maestroCommandPaletteFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.maestro-command-palette-container {
    background: var(--gapfy-bg);
    color: var(--gapfy-ink);
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius-lg);
    box-shadow: var(--gapfy-shadow-lg);
    width: min(640px, 100%);
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: maestroCommandPaletteScaleIn 180ms cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes maestroCommandPaletteScaleIn {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.maestro-command-palette-input-wrapper {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.875rem 1rem;
    border-bottom: 1px solid var(--gapfy-line);
    background: var(--gapfy-bg);
}

.maestro-command-palette-input-icon {
    color: var(--gapfy-muted);
    font-size: 20px !important;
    flex-shrink: 0;
}

.maestro-command-palette-input {
    flex: 1 1 auto;
    border: none;
    outline: none;
    background: transparent;
    color: var(--gapfy-ink);
    font-size: 1rem;
    line-height: 1.5;
    padding: 0;
    margin: 0;
}

.maestro-command-palette-input::placeholder {
    color: var(--gapfy-muted);
}

.maestro-command-palette-results {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.5rem 0;
}

.maestro-command-palette-section {
    padding: 0.25rem 0;
}

.maestro-command-palette-section-header {
    padding: 0.5rem 1rem 0.25rem;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--gapfy-muted);
}

.maestro-command-palette-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 1rem;
    cursor: pointer;
    color: var(--gapfy-ink);
    border-left: 2px solid transparent;
    transition: background-color 80ms ease, border-color 80ms ease;
    user-select: none;
}

.maestro-command-palette-item:hover {
    background: var(--gapfy-bg-soft);
}

.maestro-command-palette-item.is-selected {
    background: var(--gapfy-action-soft);
    border-left-color: var(--gapfy-action);
}

.maestro-command-palette-item-icon {
    color: var(--gapfy-ink-soft);
    font-size: 18px !important;
    flex-shrink: 0;
}

.maestro-command-palette-item.is-selected .maestro-command-palette-item-icon {
    color: var(--gapfy-action);
}

.maestro-command-palette-item-text {
    flex: 1 1 auto;
    font-size: 0.875rem;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.maestro-command-palette-empty {
    padding: 2rem 1rem;
    text-align: center;
    color: var(--gapfy-muted);
    font-size: 0.875rem;
}

@media (max-width: 640px) {
    .maestro-command-palette-backdrop {
        padding-top: 5vh;
        padding-inline: 0.5rem;
    }

    .maestro-command-palette-container {
        max-height: 85vh;
    }
}


/* --- Profile dropdown (Item 5: Recent + Favorites + standard actions) ------
   Custom dropdown replaces RadzenProfileMenu so we can render sections with
   uppercase headers above the standard nav items. Backdrop catches clicks
   outside the panel to close. */
.maestro-profile-menu {
    position: relative;
}

.maestro-profile-menu .maestro-navbar-profile-trigger {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    border-radius: 6px;
    transition: background-color 120ms ease;
}

.maestro-profile-menu .maestro-navbar-profile-trigger:hover {
    background: var(--gapfy-bg-soft);
}

.maestro-profile-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 998;
    background: transparent;
}

.maestro-profile-menu-panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 999;
    min-width: 240px;
    max-width: 320px;
    background: var(--gapfy-bg-elevated, var(--gapfy-bg));
    border: 1px solid var(--gapfy-line);
    border-radius: var(--gapfy-radius-lg);
    box-shadow: var(--gapfy-shadow-lg);
    padding: 0.375rem 0;
    overflow: hidden;
    animation: maestroProfileMenuIn 140ms cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes maestroProfileMenuIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.maestro-profile-menu-section {
    padding: 0.25rem 0;
}

.maestro-profile-menu-section + .maestro-profile-menu-section {
    border-top: 1px solid var(--gapfy-line);
}

.maestro-profile-menu-section-header {
    padding: 0.5rem 0.875rem 0.25rem;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--gapfy-muted);
}

.maestro-profile-menu-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.875rem;
    color: var(--gapfy-ink);
    text-decoration: none;
    transition: background-color 80ms ease;
    cursor: pointer;
    font-size: 0.875rem;
}

.maestro-profile-menu-item:hover {
    background: var(--gapfy-bg-soft);
    color: var(--gapfy-ink);
    text-decoration: none;
}

.maestro-profile-menu-item-icon {
    color: var(--gapfy-muted);
    font-size: 18px !important;
    flex-shrink: 0;
}

.maestro-profile-menu-item-text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Page header pin star button -------------------------------------------
   Subtle ghost button that becomes filled (and accent-coloured) when the
   page is currently pinned. Stays inline with the other actions to the
   right of the title. */
.maestro-page-header-pin-button .rzi {
    color: var(--gapfy-muted);
    transition: color 120ms ease;
}

.maestro-page-header-pin-button:hover .rzi {
    color: var(--gapfy-action, var(--gapfy-primary));
}

/* Note: pinned/unpinned state is communicated by swapping the icon name
   (star_border <-> star) in the Razor markup. No additional CSS hook
   needed -- the muted ghost colour applies to both states uniformly. */

/* ---------------------------------------------------------------------------
   Profile picture crop dialog (Cropper.Blazor host + file-picker label).
   Global (not scoped) because cropperjs reparents the <img> at runtime, which
   strips Blazor's scoped-CSS attribute from the generated crop UI.
--------------------------------------------------------------------------- */
.profile-picture-cropper-host {
    position: relative;
    width: 100%;
    height: 360px;
    border-radius: var(--gapfy-radius-lg, 12px);
    overflow: hidden;
    background: var(--gapfy-bg-soft);
}

.profile-picture-cropper-img {
    display: block;
    width: 100%;
    height: 360px;
    max-width: 100%;
}

.profile-picture-cropper-empty {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1rem;
    pointer-events: none;
    background: var(--gapfy-bg-soft);
}

.profile-picture-choose {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    height: 2.25rem;
    padding: 0 1rem;
    border: 1px solid var(--gapfy-line-strong);
    border-radius: var(--gapfy-radius, 6px);
    background: transparent;
    color: var(--gapfy-ink);
    font-size: 0.875rem;
    cursor: pointer;
    user-select: none;
}

.profile-picture-choose:hover {
    background: var(--gapfy-bg-soft);
}

/* ---------------------------------------------------------------------------
   Polish utilities (2026-06-13 design backlog close-out).
   Small reusable building blocks that finish the deferred polish items:
   section-header count chips, skeleton placeholders, the tag remove
   affordance, and a shared compact-inset-card padding. All theme-token based,
   so they adapt to dark with no extra override.
--------------------------------------------------------------------------- */

/* Count chip sitting next to a section H5 on the Home dashboard. Subtle muted
   pill that gives the section headers rhythm without competing with the
   warning badge the pending-tasks section uses for genuine attention. */
.maestro-section-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.4rem;
    border-radius: var(--gapfy-radius-pill, 9999px);
    background: var(--gapfy-bg-soft);
    color: var(--gapfy-muted);
    font-size: var(--gapfy-text-xs, 0.75rem);
    font-weight: 600;
    line-height: 1;
}

/* Skeleton placeholder: a shimmering bar shown while a value loads instead of
   a spinner, so the layout doesn't jump when the real content arrives. The
   gradient stops are theme tokens (dark values come from brand.css), so no
   theme override is needed. Motion is suppressed for reduced-motion users. */
@keyframes maestroSkeletonShimmer {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}

.maestro-skeleton {
    display: block;
    border-radius: var(--gapfy-radius, 6px);
    background-image: linear-gradient(
        90deg,
        var(--gapfy-bg-soft) 25%,
        color-mix(in srgb, var(--gapfy-line) 55%, var(--gapfy-bg-soft)) 37%,
        var(--gapfy-bg-soft) 63%);
    background-size: 200% 100%;
    animation: maestroSkeletonShimmer 1.4s ease-in-out infinite;
}

.maestro-skeleton-number {
    width: 3.5rem;
    height: 2rem;
}

.maestro-skeleton-row {
    width: 100%;
    height: 3.25rem;
}

@media (prefers-reduced-motion: reduce) {
    .maestro-skeleton {
        animation: none;
    }
}

/* Remove affordance for a selected tag chip (DocuVault TagsPicker). The X sits
   in a circular hit area that tints red on hover, so it reads as "remove"
   rather than a static glyph. */
.maestro-tag-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.1rem;
    height: 1.1rem;
    margin-left: 0.1rem;
    border-radius: 50%;
    cursor: pointer;
    color: var(--gapfy-muted);
    transition: background-color 120ms ease, color 120ms ease;
}

.maestro-tag-remove:hover {
    background: color-mix(in srgb, var(--gapfy-danger) 16%, transparent);
    color: var(--gapfy-danger);
}

.maestro-tag-remove .rzi {
    font-size: 14px;
}

/* Shared padding for compact "inset row" cards (list rows, sub-blocks). Was
   hand-rolled as inline `padding: 0.75rem 1rem` across many components; this
   class owns the canonical value so the dominant density stays consistent.
   Denser one-off blocks keep their own padding intentionally. */
.maestro-card-compact {
    padding: 0.75rem 1rem;
}
