/* ============================================================
   Dingo flat design layer (Sliced-inspired restyle)
   ------------------------------------------------------------
   Replaces MudBlazor's Material elevation look with a flat,
   bordered aesthetic: no shadows on surfaces, 1px subtle
   borders, 6px radius, calmer tables and buttons.

   Identity colors are NOT defined here: they flow from the
   per-tenant BrandingConfiguration through MudBlazor's CSS
   variables (--mud-palette-*). This file only owns neutral
   structure tokens.
   ============================================================ */

/* Cerebri Sans — UI typeface of the flat design (licensed with the
   Sliced template). Weights map 1:1 to the typography in DingoTheme.cs. */
@font-face {
    font-family: "Cerebri Sans";
    src: url('../fonts/cerebrisans-regular.woff') format('woff');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Cerebri Sans";
    src: url('../fonts/cerebrisans-medium.woff') format('woff');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Cerebri Sans";
    src: url('../fonts/cerebrisans-semibold.woff') format('woff');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Cerebri Sans";
    src: url('../fonts/cerebrisans-bold.woff') format('woff');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Structure tokens derive from the MudBlazor palette variables so the whole
   layer follows the active theme: DingoTheme sets their light and dark values
   (AB#3613), this file never hardcodes a light-only color. */
:root {
    --dingo-border: var(--mud-palette-lines-default);
    --dingo-border-hover: var(--mud-palette-lines-inputs);
    --dingo-radius: 6px;
    --dingo-head-bg: var(--mud-palette-table-hover); /* table headers / row hover */
    --dingo-overlay-hover: var(--mud-palette-action-default-hover);
}

/* ---------- Surfaces: flat cards & panels ----------
   Floating surfaces (dialogs, popovers, pickers, snackbars,
   alerts) keep their shadow so they still read as overlays. */
.mud-paper:not(.mud-dialog):not(.mud-popover):not(.mud-picker-paper):not(.mud-snackbar):not(.mud-alert),
.mud-card {
    box-shadow: none !important;
    border: 1px solid var(--dingo-border);
    border-radius: var(--dingo-radius);
}

.mud-dialog {
    border-radius: 8px;
}

/* ---------- App bar & drawer ---------- */
.mud-appbar {
    box-shadow: none !important;
    border-bottom: 1px solid var(--dingo-border);
}

.mud-drawer {
    box-shadow: none !important;
}

/* ---------- Buttons ---------- */
.mud-button {
    border-radius: var(--dingo-radius);
    text-transform: none;
    letter-spacing: normal;
    font-weight: 500;
    transition: background-color .3s ease, color .3s ease, border-color .3s ease, filter .3s ease;
}

.mud-button-filled {
    box-shadow: none !important;
}

    .mud-button-filled:hover {
        box-shadow: none !important;
        filter: brightness(0.92);
    }

.mud-button-filled-size-medium,
.mud-button-outlined-size-medium,
.mud-button-text-size-medium {
    padding: 8px 20px;
}

/* Inputs: outlined border color comes from the theme palette
   (LinesInputs in DingoTheme.cs), no CSS override needed. */

/* ---------- Tables ---------- */
.mud-table {
    box-shadow: none !important;
    border: 1px solid var(--dingo-border);
    border-radius: var(--dingo-radius);
}

    .mud-table .mud-table-head .mud-table-cell {
        background-color: var(--dingo-head-bg);
        font-weight: 600;
    }

.mud-table-hover .mud-table-body .mud-table-row:hover {
    background-color: var(--dingo-head-bg);
}

/* ---------- Shell: topbar + sidebar + footer ---------- */

/* The sidebar is full-height (logo lives inside it). MudBlazor already
   offsets the app bar (margin-left) while the responsive drawer is open —
   no extra positioning needed here. */

/* Surfaces nested inside floating overlays (menus, popovers, pickers)
   must not get the flat card border — the overlay already frames them. */
.mud-popover .mud-paper,
.mud-popover .mud-card {
    border: none;
    border-radius: 0;
}

.mud-popover .mud-list-item {
    padding-top: 8px;
    padding-bottom: 8px;
}

.dingo-user-activator {
    cursor: pointer;
    padding: 4px 8px;
    border-radius: var(--dingo-radius);
}

    .dingo-user-activator:hover {
        background-color: var(--dingo-overlay-hover);
    }

/* User-account menu: soft primary-tinted initials avatar and a compact identity
   header aligned to the dense menu metrics (no card paddings, no margin hacks). */
.dingo-user-avatar {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 15%, transparent);
    color: var(--mud-palette-primary);
    font-weight: 500;
}

.dingo-user-menu-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    min-width: 230px;
}

.dingo-user-menu-email {
    color: var(--mud-palette-text-secondary);
}

.dingo-sidebar {
    border-right: 1px solid var(--dingo-border);
    z-index: calc(var(--mud-zindex-appbar, 1300) + 1);
}

    /* The brand mark stays put while the menu scrolls under it (Sliced does the same). The drawer
       content itself no longer scrolls: it is a column whose header is fixed and whose nav takes
       the remaining height and owns the overflow. Scrolling the whole content instead pushed the
       logo off the top as soon as the menu was taller than the viewport. */
    .dingo-sidebar .mud-drawer-content {
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    .dingo-sidebar .dingo-sidebar-header {
        flex: 0 0 auto;
    }

    /* The menu owns the vertical overflow: never scroll sideways, slim scrollbar for the rest.

       Addressed through `dingo-sidebar-menu`, the class the layout puts on the first-level menu,
       and never through `.mud-navmenu`: MudNavGroup renders another `.mud-navmenu` inside every
       group to hold its children, and an overflow other than visible turns each of those into a
       scroll container of its own. MudBlazor's own stylesheet gives `.mud-navmenu` an
       overscroll-behavior of contain, so those inner containers — which never overflow, and so have
       nothing to scroll — kept the wheel instead of handing it to the menu that does scroll: the
       sidebar only answered the wheel over a group header or a top-level link, the two places with
       no inner container between the pointer and the scroller.

       Our own class also survives MudBlazor's markup: reaching the menu through the drawer's
       internals would break silently the day the component nests one more element. */
    .dingo-sidebar-menu {
        flex: 1 1 auto;
        overflow-x: hidden;
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: var(--mud-palette-action-disabled) transparent;
    }

        .dingo-sidebar-menu::-webkit-scrollbar {
            width: 6px;
        }

        .dingo-sidebar-menu::-webkit-scrollbar-thumb {
            background-color: var(--mud-palette-action-disabled);
            border-radius: 3px;
        }

        .dingo-sidebar-menu::-webkit-scrollbar-track {
            background: transparent;
        }

/* The mark is centered in both drawer states, so expanding the rail slides the sidebar open
   without the logo jumping from the middle to the left edge. */
.dingo-sidebar-header {
    padding: 16px 20px;
    justify-content: center;
    align-items: center;
}

/* The inset belongs to the menu, not to each item.

   It used to be a 10px horizontal margin on every nav link. MudBlazor also gives those links
   width:100%, so the margin did not shrink them — it pushed them past their container, and group
   headers ran 10px wider than the items beneath them. Compensating with a width calc then broke
   the rail from the other end.

   Putting the inset on the menu and leaving the items at MudBlazor's own full width removes the
   overflow at the source. One value governs both drawer widths — expanded and rail — so neither
   needs an override, and it stays right at any width in between (a tablet, a zoomed browser, a
   longer label). It rides on the first-level menu's own class, like the overflow above: MudBlazor
   nests another menu inside each group, and insetting both would indent children twice.

   That inset is the scrollbar's own width, reserved on both sides, which a padding cannot do: the
   scrollbar is laid out inside the padding and takes from the right only, so the rows sit half a
   scrollbar left of centre. Against left-aligned labels that is invisible, but in the 68px rail it
   is what pulls the icons off the rail's axis. Reserving both gutters also stops the rows shifting
   sideways when expanding a group makes the menu overflow.
   The padding below is the fallback for browsers without scrollbar-gutter: same inset, still
   left-of-centre when it overflows, which is where we already were. */
.dingo-sidebar-menu {
    padding-left: 10px;
    padding-right: 10px;
}

@supports (scrollbar-gutter: stable) {
    .dingo-sidebar-menu {
        padding-left: 0;
        padding-right: 0;
        scrollbar-gutter: stable both-edges;
    }
}

.dingo-sidebar .mud-nav-link {
    border-radius: var(--dingo-radius);
    margin: 2px 0;
    width: 100%;
    transition: background-color .15s ease, color .15s ease;
}

/* Primary action (e.g. "Nueva Invitación"): a nav link so it collapses to icon-only in
   the mini rail like the rest, accented so it still reads as the main action. */
.dingo-sidebar .dingo-nav-primary-action .mud-nav-link,
.dingo-sidebar .mud-nav-link.dingo-nav-primary-action {
    color: var(--mud-palette-primary);
    font-weight: 500;
}

.dingo-sidebar .dingo-nav-primary-action .mud-icon-root {
    color: var(--mud-palette-primary);
}

    .dingo-sidebar .mud-nav-link:hover {
        background-color: var(--dingo-overlay-hover);
        color: var(--mud-palette-text-primary);
    }

        .dingo-sidebar .mud-nav-link:hover .mud-icon-root {
            color: var(--mud-palette-text-primary);
        }

    .dingo-sidebar .mud-nav-link.active {
        color: var(--mud-palette-primary);
        background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
        font-weight: 500;
    }

        .dingo-sidebar .mud-nav-link.active .mud-icon-root {
            color: var(--mud-palette-primary);
        }

/* Tenant logos are ink-on-white artwork: on the dark theme they turn invisible against the
   dark drawer. A light plate behind them keeps every logo readable — monochrome or full
   color — without asking each customer for a dark-mode variant (AB#3613).
   The hook is `dingo-dark`, set by MainLayout from the theme state we own: MudBlazor 9
   signals dark mode only through CSS variables, so there is no framework class to target. */
.dingo-dark .dingo-sidebar-header .dingo-logo-wordmark,
.dingo-dark .dingo-sidebar-header .dingo-logo-icon:not(.dingo-logo-monogram) {
    background-color: #FFFFFF;
    border-radius: var(--dingo-radius);
    padding: 4px 8px;
}

/* Collapsed (mini) state: icon rail. The wordmark gives way to a square mark — the
   tenant's isotype, or a monogram when they have none (a wide wordmark squeezed into
   68px is unreadable, and an empty header just looks broken). */
.dingo-logo-icon {
    display: none;
}

.mud-drawer-mini.mud-drawer--closed.dingo-sidebar .dingo-sidebar-header {
    justify-content: center;
    padding: 12px 6px;
}

    .mud-drawer-mini.mud-drawer--closed.dingo-sidebar .dingo-sidebar-header.has-logo-icon .dingo-logo-wordmark {
        display: none;
    }

    .mud-drawer-mini.mud-drawer--closed.dingo-sidebar .dingo-sidebar-header.has-logo-icon .dingo-logo-icon {
        display: block;
        width: 28px;
        height: 28px;
        object-fit: contain;
    }

        .mud-drawer-mini.mud-drawer--closed.dingo-sidebar .dingo-sidebar-header.has-logo-icon .dingo-logo-icon.dingo-logo-monogram {
            display: flex;
        }

/* Monogram fallback: the tenant's initials on their own primary — no asset required, so
   a new tenant is presentable from day one.
   No `display` here: the base `.dingo-logo-icon` keeps the mark hidden while the drawer is
   expanded, and giving the monogram one of its own would out-cascade that and show it next
   to the wordmark. The collapsed-rail rule above switches it to flex. */
.dingo-logo-monogram {
    align-items: center;
    justify-content: center;
    border-radius: var(--dingo-radius);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 15%, transparent);
    color: var(--mud-palette-primary);
    font-weight: 600;
    font-size: 0.75rem;
    letter-spacing: .5px;
    user-select: none;
}

/* The icon rail is a layout of its own, not a narrowed copy of the expanded menu.

   MudBlazor keeps a group's expand chevron here, and it has nothing left to disclose: the label it
   would open is already hidden, and pointing at the rail opens the whole drawer anyway. Rendering
   it cost the three group rows their alignment — centring placed icon *and* chevron as a pair, so
   the icon sat 9.6px left of the rail's axis with the chevron clipped by the rail's edge, which is
   the "cut off" the rail looked like.

   A nav link is also a flex item that shrinks to its contents, so each row was as wide as whatever
   it happened to hold — 32px, 36.8px, 47.2px — and the hover pill hugged the icon instead of
   reading as a target. Here the row *is* the target: it fills the rail and centres its icon, so
   every row is one shape and the icon sits on the rail's axis at any MiniWidth.

   That is also why MudBlazor's own inset cannot stay. Its 16px is half of 56 - 24: the padding is
   how it centres the icon, and it only centres at its default 56px MiniWidth. Ours is 68px, so the
   same number centres nothing — the row's own width has to do that job instead. The second
   selector repeats the nesting MudBlazor uses for links inside a group, which is the only way to
   outweigh it. */
.mud-drawer-mini.mud-drawer--closed.dingo-sidebar .mud-nav-link,
.mud-drawer-mini.mud-drawer--closed.dingo-sidebar .mud-nav-group .mud-navmenu .mud-nav-item .mud-nav-link {
    justify-content: center;
    flex-shrink: 0;
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
}

.mud-drawer-mini.mud-drawer--closed.dingo-sidebar .mud-nav-link-expand-icon {
    display: none;
}

/* Full-screen cover for transitional states (e.g. the OIDC login
   redirect) — sits above the sidebar (appbar z + 1) and topbar. */
.dingo-redirect-overlay {
    position: fixed;
    inset: 0;
    z-index: calc(var(--mud-zindex-appbar, 1300) + 2);
    background-color: var(--mud-palette-background, #f9fbfd);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Detail/edit form surface. The width cap is per instance rather than per stylesheet
   (SPEC 91): 22 screens render this component, so lifting the cap globally would have
   released all of them to 1920px at once. Screens opt into the full width as they are
   migrated to the standard, and the default flips when the last one has. */
.dingo-form-card--constrained {
    max-width: 1080px;
}

/* Only cards using the Tabs/Body/Footer slots become a column. Screens still rendering
   ChildContent keep the block layout they have always had. */
.dingo-form-card--slots {
    display: flex;
    flex-direction: column;
}

/* The tab strip is the one part of the card that can be wider than the card: five labels with
   icons and counts do not fit a phone. It clips itself so MudTabs falls back to its own scroll
   arrows, which is the behaviour that keeps every tab reachable.
   Without this the strip escaped the card and dragged the whole page sideways — measured at 654px
   of content on a 377px viewport. The card deliberately carries no overflow of its own (D-91-3),
   so the clipping has to live here, on the one slot that needs it. */
.dingo-form-card__tabs {
    flex: none;
    min-width: 0;
    overflow: hidden;
}

/* The footer slot is a pass-through, not a box: the action bar is the card's last child, laid
   out by the card's own column, with no wrapper of its own to add height or a border of its own. */
.dingo-form-card__footer {
    display: contents;
}

/* No internal scrolling: the page scrolls, and the action bar sits where the form ends. Sticky
   was tried and rejected — see .dingo-action-bar below. */
.dingo-form-card__body {
    flex: 1 1 auto;
    padding: 26px 28px;
}

/* A card whose content is a tab set puts the strip flush against its top edge and insets the
   panels instead, so the strip reads as part of the card rather than as a floating row. */
.dingo-form-card--slots .mud-tabs-panels {
    padding: 26px 28px;
}

/* On a phone, 28px a side is a tenth of the screen spent on nothing. The standard is
   desktop-first; that is not a licence to be unusable on a handset. */
@media (max-width: 599px) {
    .dingo-form-card--slots .mud-tabs-panels,
    .dingo-form-card__body {
        padding: 16px 12px;
    }
}

/* ---------- Reusable surfaces (AB#3612)
   Replace the light-only inline backgrounds that dialogs and forms used to
   hardcode; these follow the active theme instead of breaking in dark mode. */

/* Dashboard KPI tile: label and icon on one line, the value below — the Sliced stat-card
   reading order, which scans faster than a centered icon-over-number stack. The slot for a
   period-delta badge and a sparkline is deliberate; both need data we do not compute yet. */
.dingo-stat-card {
    height: 100%;
}

    .dingo-stat-card .mud-typography-body2 {
        color: var(--mud-palette-text-secondary);
    }

    /* The tile sparkline supports the number above it; it never takes the pointer. */
    .dingo-stat-sparkline {
        pointer-events: none;
        color: var(--mud-palette-primary);
    }

.dingo-sparkline {
    display: block;
    width: 100%;
    height: 34px;
    opacity: .75;
}

/* Read-only detail panel: raw payloads, error dumps, log content. */
.dingo-detail-panel {
    background-color: var(--dingo-head-bg);
    border: 1px solid var(--dingo-border);
    border-radius: var(--dingo-radius);
}

/* File drop target. */
.dingo-dropzone {
    width: 100%;
    height: 100px;
    border: 2px dashed var(--dingo-border-hover);
    border-radius: var(--dingo-radius);
}

/* Placeholder box for an image that has not been uploaded yet. */
.dingo-photo-placeholder {
    background-color: var(--dingo-head-bg);
    border-radius: var(--dingo-radius);
    min-height: 300px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Semantic row tints (import results, validation summaries). */
.dingo-row-info {
    background-color: color-mix(in srgb, var(--mud-palette-info) 12%, transparent);
}

.dingo-row-success {
    background-color: color-mix(in srgb, var(--mud-palette-success) 12%, transparent);
}

.dingo-row-warning {
    background-color: color-mix(in srgb, var(--mud-palette-warning) 12%, transparent);
}

.dingo-row-error {
    background-color: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
}

/* ---------- Photo surfaces ----------
   These were redeclared as page-level <style> in a dozen screens, and the two
   meanings of "avatar-photo-transparent" collided: a small transparent table
   avatar vs. a 250px form preview. The preview now has its own name. */

/* Small avatar showing an uploaded photo (tables, lists): the size comes from
   the component, this only drops the placeholder background. */
.avatar-photo-transparent {
    background-color: transparent;
}

/* Large photo preview inside forms and detail dialogs. */
.dingo-photo-preview {
    height: 250px !important;
    width: 250px !important;
}

    /* Despite the name, this modifier means "no backplate", not "no photo": every screen applies
       it when a picture IS being shown, so the avatar's grey fill does not sit behind a cut-out
       photo and square off its edges. A dashed border was added here for the missing-photo case
       and drew itself around every real photo instead — the state that carries this class is the
       opposite one. The cue for a photo that is absent or failed to load is the icon the control
       renders in its place (camera, or crossed-out camera), which needs no frame. */
    .dingo-photo-preview.dingo-photo-preview-empty {
        background-color: transparent;
    }

/* Compact preview used by the gatehouse approval screens. */
.dingo-photo-visitor {
    height: 170px !important;
    width: 170px !important;
}

/* Both photo surfaces are click-to-change targets. */
.dingo-photo-preview:hover,
.avatar-photo-transparent:hover {
    cursor: pointer;
}

    .dingo-photo-preview:hover {
        background-color: var(--dingo-overlay-hover);
    }

    .dingo-photo-preview:hover > img,
    .avatar-photo-transparent:hover > img {
        opacity: 0.7;
    }

/* Selected row in the selection dialogs — tenant primary, not a fixed blue. */
.dingo-selected-row {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 18%, transparent) !important;
}

/* Confirmation check shown next to validated fields (approval screens, forms). */
.dingo-field-check {
    padding: 0;
    color: var(--mud-palette-success);
}

    .dingo-field-check > span > svg {
        font-size: xx-large;
    }

/* Oversized value display in the gatehouse approval screens. */
.dingo-value-xl {
    font-size: xx-large;
}

/* Tables inside dialogs scroll instead of overflowing the dialog. */
.mud-dialog .mud-table-container {
    overflow: auto;
}

/* Search field of the relationship picker. */
.dingo-picker-search {
    min-width: 260px;
    max-width: 420px;
}

/* Gatehouse approval screens: fixed-height stage so the layout does not jump
   while the visitor data loads. */
.dingo-approval-stage {
    position: relative;
    min-height: 400px;
}

/* SPEC 103 D7 — the approval dialog's frame is the framework's, not ours. The size is
   `MaxWidth.Medium` + `FullWidth` at the call site (960 px, gutters at 64), the bounded height
   and the body-only scroll are what `.mud-dialog` and `.mud-dialog-content` already do, and the
   body's wider gutter is `ContentClass="px-8 pb-4"`. What used to live here — a width, a
   max-height, and re-declarations of Mud's own flex — is gone: the rules the framework already
   applies do not need a copy of themselves in this file to maintain.

   The face the officer compares against the document in hand. Large enough to compare, small
   enough that the decision still fits on one screen (D7 replaces the 300 px of step 3).
   MudBlazor sizes an avatar by its `Size` enum, which stops at 60 px, and it has no arbitrary
   width utility — so this one is ours. It is qualified with `.mud-avatar` to outrank
   `.mud-avatar.mud-avatar-medium`, which is how the size that had to be fought with two
   `!important`s is won by specificity instead. */
.mud-avatar.dingo-approval-photo {
    height: 160px;
    width: 160px;
}

/* The visitor's own note is escaped text (SPEC 103 D8), so its line breaks are the only shape it
   has left, and MudBlazor has no white-space utility. That is the whole of what either site
   needs: inside the alert the note is a paragraph under a bold label, not a bordered block of its
   own (D13 — a box inside a box read as two alerts). */
.dingo-text-lines {
    white-space: pre-wrap;
}

/* Scanned document preview. */
.dingo-document-image {
    max-width: 100%;
    max-height: 500px;
    object-fit: contain;
}

/* Field label of a read-only detail pair (incident detail and friends). */
.dingo-detail-label {
    text-transform: uppercase;
    letter-spacing: .5px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

/* ---------- Detail/edit screen standard (SPEC 91)
   The rules a migrated detail screen needs that no component can own on its own. */

/* The body of a detail screen: a fixed aside for what the system generates, and the rest for
   what the administrator fills in. MudGrid cannot express "fixed column plus fluid column",
   which is why this is a grid rule and not a MudItem width. */
.dingo-detail-layout {
    display: grid;
    grid-template-columns: 236px 1fr;
    gap: 32px;
    align-items: start;
}

@media (max-width: 1439px) {
    .dingo-detail-layout {
        grid-template-columns: 200px 1fr;
    }
}

/* Below the tablet breakpoint the aside stops being a column and becomes a row above the
   form, so the fields keep the full width instead of a 200px bite out of it. */
@media (max-width: 1023px) {
    .dingo-detail-layout {
        grid-template-columns: 1fr;
        gap: 24px;
    }

    .dingo-detail-aside {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-start;
        gap: 24px;
    }
}

/* The avatar is a fixed 250px square shared with other screens, and the aside track is 200px
   below 1440px — so the photo drew itself 18px over the Identificación column. The aside wins
   here: the photo scales to whatever track it is given and stays square. Scoped to this layout so
   the screens still using the fixed size are untouched. */
.dingo-detail-aside .dingo-photo-preview {
    width: 100% !important;
    height: auto !important;
    max-width: 250px;
    aspect-ratio: 1;
}

.dingo-detail-main > section {
    margin-bottom: 26px;
}

.dingo-detail-note {
    display: block;
    color: var(--mud-palette-text-disabled);
}

/* A tab panel listing related people: header, then the table. The panel used to open with a lone
   button in an empty band, which is why the top margin is gone and the header carries the action. */
.dingo-related-panel {
    padding-top: 4px;
}

.dingo-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 48px 16px;
    color: var(--mud-palette-text-secondary);
    text-align: center;
}

.dingo-empty-state-description {
    max-width: 440px;
    line-height: 1.6;
}

/* The Favoritos / Frecuentes / Proveedores list of a partner or beneficiary
   (VisitorRelationshipTable): one line per relationship, a badge per fact, the reason in a popover.
   Colour marks only what the administrator has to fix — the amber below. What works stays in ink,
   not green: a list that paints every healthy row gives the one row that needs attention nowhere to
   stand out. The amber is the one the old fast-access badge used, lifted for the dark theme. */
:root {
    --dingo-attention: #B45309;
}

.dingo-dark {
    --dingo-attention: #F0A94B;
}

.dingo-attention-text {
    color: var(--dingo-attention) !important;
}

/* One drawing per width: the table from 600px up, cards below. */
.dingo-relationship-mobile {
    display: none;
}

@media (max-width: 599.98px) {
    .dingo-relationship-desktop {
        display: none;
    }

    .dingo-relationship-mobile {
        display: flex;
        flex-direction: column;
        gap: 10px;
    }
}

.dingo-relationship-table .dingo-relationship-col-id {
    width: 16%;
}

.dingo-relationship-table .dingo-relationship-col-schedule {
    width: 24%;
}

.dingo-relationship-table .dingo-relationship-col-access {
    width: 30%;
}

.dingo-relationship-table .dingo-relationship-col-actions {
    width: 56px;
}

.dingo-relationship-name {
    font-weight: 500;
}

.dingo-relationship-id {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The badges: a flat pill that is a button, because it opens its popover. */
.dingo-badge-anchor {
    position: relative;
    display: inline-block;
    max-width: 100%;
}

.dingo-access-badges {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    max-width: 100%;
}

.dingo-access-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    max-width: 100%;
    padding: 2px 10px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 20px;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: .75rem;
    font-weight: 500;
    line-height: 1.6;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease;
}

    .dingo-access-badge:hover {
        background-color: var(--dingo-overlay-hover);
    }

    .dingo-access-badge:focus-visible {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
    }

    .dingo-access-badge .mud-icon-root {
        flex: none;
        font-size: 1rem;
    }

.dingo-access-badge-text {
    overflow: hidden;
    text-overflow: ellipsis;
}

.dingo-access-badge-state.mud-icon-root {
    font-size: .9rem;
}

.dingo-access-badge--attention {
    border-color: color-mix(in srgb, var(--dingo-attention) 45%, transparent);
    background: color-mix(in srgb, var(--dingo-attention) 8%, transparent);
    color: var(--dingo-attention);
    font-weight: 600;
}

.dingo-access-badge--off {
    border-style: dashed;
    border-color: var(--mud-palette-lines-default);
    color: var(--mud-palette-text-disabled);
}

/* The popover a badge opens. */
.dingo-access-popover.mud-popover {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 300px;
    padding: 12px 14px;
}

.dingo-access-popover-title {
    font-size: .84rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.dingo-access-popover-text {
    font-size: .8rem;
    line-height: 1.5;
    white-space: normal;
    color: var(--mud-palette-text-secondary);
}

.dingo-access-popover-line {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    font-size: .8rem;
}

    .dingo-access-popover-line > span:first-child {
        color: var(--mud-palette-text-secondary);
    }

    .dingo-access-popover-line > span:last-child {
        flex: none;
        font-weight: 500;
        text-align: right;
        white-space: nowrap;
    }

.dingo-access-popover-line--separated {
    margin-top: 2px;
    padding-top: 6px;
    border-top: 1px solid var(--dingo-border);
}

.dingo-access-popover-actions {
    display: flex;
    justify-content: flex-end;
    margin: 2px -6px -6px 0;
}

/* Below 600px: the same line as a card. */
.dingo-relationship-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 14px 12px;
    border: 1px solid var(--dingo-border);
    border-radius: var(--dingo-radius);
    background: var(--mud-palette-surface);
}

.dingo-relationship-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
}

.dingo-relationship-card-name {
    flex: 1;
    font-size: .94rem;
    font-weight: 600;
    line-height: 1.3;
}

/* A value that does not fit beside its label drops under it instead of pushing past the card. */
.dingo-rel-pair {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 4px 12px;
    min-width: 0;
}

    .dingo-rel-pair > .dingo-access-badges,
    .dingo-rel-pair > .dingo-badge-anchor {
        min-width: 0;
        max-width: 100%;
    }

.dingo-rel-label {
    flex: none;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.dingo-group-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 24px;
}

/* The read-mode panel keeps the editor's height, so mounting the editor when edit mode
   starts does not push everything below it down the page. */
.dingo-observations-read {
    min-height: 250px;
    border: 1px solid var(--dingo-border);
}

/* Section header inside a form: icon, title, and a rule filling out the row. */
.dingo-section-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
}

    .dingo-section-head .dingo-rule {
        flex: 1;
        height: 1px;
        background: var(--mud-palette-divider);
    }

/* A field the screen is showing but not letting you edit yet. ReadOnly rather than Disabled:
   disabled greys the text toward illegibility, and most visits to a detail screen are lookups,
   not edits. Only the underline dims, so the control keeps its position, its height and its
   label, and pressing "edit" changes the affordance and nothing else. */
.dingo-field-readonly .mud-input-underline:before {
    border-bottom-color: color-mix(in srgb, var(--mud-palette-lines-inputs) 55%, transparent);
}

.dingo-field-readonly .mud-input-adornment {
    opacity: .5;
}

/* Action row at the end of the form. It was sticky at first — built, measured, pinned correctly,
   and rejected on sight: a permanent full-width band, mostly empty at 1600px, with its text at one
   end and its buttons at the other. The actions now live in the page header as well, so this one
   is simply where the form ends (SPEC 91, D-91-3 and D-91-4). No shadow: it overlays nothing. */
.dingo-action-bar {
    /* One height whatever the mode's buttons are, so the card's bottom edge does not move when
       the screen switches from reading to editing. MudBlazor's outlined button measures 2px taller
       than its filled one, and that difference would otherwise land on the next screen too. */
    min-height: 64px;
    border-top: 1px solid var(--dingo-border);
    background: var(--mud-palette-surface);
}

/* Tab labels in sentence case, on one line. Without nowrap a two-word label breaks in two as
   soon as the strip gets crowded, and the active tab's underline sits under a ragged label. */
.mud-tab {
    text-transform: none;
    white-space: nowrap;
}

/* A panel reachable only from the "Historiales" menu: registered with MudTabs so it can be
   activated, but with no tab of its own in the strip. MudTabPanel.Visible cannot do this — it
   also blocks activation, so the menu selected a history and the screen kept showing the first
   panel. Hiding the button is the part we actually wanted. */
.mud-tab:has(.dingo-tab-hidden) {
    display: none;
}

/* Icon, label and count on one baseline inside a tab. */
.dingo-tab-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Tabs inside a standard detail card are tighter than MudBlazor's default. Measured at 1280px
   with the navigation drawer open: five tabs plus the Historiales button needed 968px of a 962px
   card, so the strip fell back to scroll arrows over six pixels. MudTabs' 160px floor is already
   removed by MinimumTabWidth; this reclaims the rest from padding that the labels do not need.
   Scoped to the migrated card so the tabs on every other screen keep their own metrics. */
.dingo-form-card--slots .mud-tab {
    padding-left: 10px;
    padding-right: 10px;
}

.dingo-form-card--slots .dingo-tab-count.mud-chip {
    padding-left: 6px;
    padding-right: 6px;
}

/* The count rides along with the label, so it must not add height to the strip. */
.dingo-tab-count.mud-chip {
    margin: 0;
    height: 20px;
}

/* The grouped-history button sits in the tab strip but is not a tab, so it does not inherit
   the rule above: without nowrap its label breaks in two and makes the whole strip taller
   than the tabs beside it. */
.dingo-tabs-overflow .mud-button-root {
    white-space: nowrap;
}

/* While a history is showing, the overflow button is the active "tab": no visible tab is
   selected, so it borrows the strip's own underline. The label itself never changes (D-91-31). */
.dingo-tabs-overflow--active .mud-button-root {
    box-shadow: inset 0 -2px 0 var(--mud-palette-primary);
    border-radius: 0;
}

/* Attachment thumbnail. */
.dingo-thumb {
    border: 1px solid var(--dingo-border);
    transition: box-shadow .15s ease;
}

    .dingo-thumb:hover {
        box-shadow: var(--mud-elevation-4);
    }

/* Long free text (observations, timelines) wraps instead of overflowing. */
.dingo-wrap-text {
    max-width: 100%;
    word-wrap: break-word;
    word-break: break-word;
    overflow-wrap: break-word;
    white-space: normal;
}

.dingo-overflow-hidden {
    max-width: 100%;
    overflow: hidden;
}

/* Rendered rich-text/HTML content (observations, imported descriptions). */
.dingo-html-content img {
    max-width: 100%;
    height: auto;
}

.dingo-html-content table {
    width: 100%;
    border-collapse: collapse;
}

    .dingo-html-content th,
    .dingo-html-content td {
        border: 1px solid var(--dingo-border);
        padding: 8px;
    }

/* ============================================================
   Syncfusion alignment (AB#3612)
   ------------------------------------------------------------
   Syncfusion ships its Material theme (material.css, loaded
   before this file) so its components arrive with Material
   elevation, ripple accents and their own font stack. These
   rules bring them onto the flat canon: hairline borders, 6px
   radius, no shadows, tenant primary for accents and the app
   typeface. Scoped to .e-* so nothing else is touched.
   ============================================================ */

.e-richtexteditor,
.e-schedule,
.e-input-group,
.e-control {
    font-family: var(--mud-typography-default-family, inherit);
}

/* ---------- Rich text editor ---------- */
.e-richtexteditor {
    border: 1px solid var(--dingo-border);
    border-radius: var(--dingo-radius);
    box-shadow: none;
}

    .e-richtexteditor .e-rte-toolbar,
    .e-richtexteditor .e-toolbar-wrapper {
        border: none;
        border-bottom: 1px solid var(--dingo-border);
        border-radius: var(--dingo-radius) var(--dingo-radius) 0 0;
        background-color: transparent;
        box-shadow: none;
    }

    /* Flat 40x40 toolbar buttons (Sliced-style): no fill, primary on hover. */
    .e-richtexteditor .e-toolbar .e-toolbar-item .e-tbar-btn {
        background: transparent;
        box-shadow: none;
        border-radius: var(--dingo-radius);
    }

        .e-richtexteditor .e-toolbar .e-toolbar-item .e-tbar-btn:hover {
            background-color: var(--dingo-overlay-hover);
        }

            .e-richtexteditor .e-toolbar .e-toolbar-item .e-tbar-btn:hover .e-icons {
                color: var(--mud-palette-primary);
            }

    .e-richtexteditor .e-toolbar .e-toolbar-item.e-active .e-tbar-btn .e-icons {
        color: var(--mud-palette-primary);
    }

    .e-richtexteditor .e-rte-content,
    .e-richtexteditor .e-source-content {
        border-radius: 0 0 var(--dingo-radius) var(--dingo-radius);
        background-color: var(--mud-palette-surface);
    }

    /* The editing surface takes its ink from the app palette, not from the Syncfusion theme.
       Swapping material.css for material-dark.css restyles the chrome but leaves the writing area
       at the theme's own muted grey, which on the dark canvas reads as disabled text — the
       administrator is typing legal copy they can barely see. Covers both modes at once, and both
       editors: .e-content is the HTML surface, the textarea is Markdown mode. */
    .e-richtexteditor .e-rte-content .e-content,
    .e-richtexteditor .e-source-content .e-content,
    .e-richtexteditor textarea.e-content {
        background-color: var(--mud-palette-surface);
        color: var(--mud-palette-text-primary);
    }

    .e-richtexteditor .e-rte-placeholder {
        color: var(--mud-palette-text-disabled);
    }

    .e-richtexteditor.e-focused {
        border-color: var(--mud-palette-primary);
        box-shadow: none;
    }

/* ---------- Scheduler ---------- */
.e-schedule {
    border: 1px solid var(--dingo-border);
    border-radius: var(--dingo-radius);
    box-shadow: none;
}

    .e-schedule .e-schedule-toolbar,
    .e-schedule .e-schedule-toolbar .e-toolbar-items {
        background-color: transparent;
        box-shadow: none;
        border-bottom: 1px solid var(--dingo-border);
    }

    .e-schedule .e-schedule-toolbar .e-tbar-btn {
        background: transparent;
        box-shadow: none;
    }

    /* Header / cell grid lines match the flat table rules. */
    .e-schedule .e-date-header-wrap table td,
    .e-schedule .e-work-cells,
    .e-schedule .e-header-cells {
        border-color: var(--dingo-border);
    }

    .e-schedule .e-header-cells {
        background-color: var(--dingo-head-bg);
        font-weight: 600;
    }

    /* Today and selection use the tenant primary instead of Material purple. */
    .e-schedule .e-current-day,
    .e-schedule .e-current-date .e-date-header {
        color: var(--mud-palette-primary);
    }

    .e-schedule .e-appointment {
        border-radius: var(--dingo-radius);
        box-shadow: none;
    }

    .e-schedule .e-work-cells.e-selected-cell {
        background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
    }

/* ---------- Inputs (text boxes, date/time pickers) ----------
   AB#3609 keeps every form input on the underline (Text) style;
   Syncfusion's boxed Material inputs are flattened to match. */
.e-input-group:not(.e-outline),
.e-float-input:not(.e-outline) {
    box-shadow: none;
}

    .e-input-group:not(.e-outline):not(.e-disabled)::before,
    .e-input-group:not(.e-outline):not(.e-disabled)::after {
        background: var(--mud-palette-primary);
    }

.e-input-group .e-input-group-icon:hover {
    color: var(--mud-palette-primary);
}

.dingo-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 24px;
    color: var(--mud-palette-text-secondary);
}

/* Image inside the shared photo control: fills its round preview the way MudImage did before
   (AB#3835). Global rather than scoped because the preview itself is styled here too. */
.dingo-image-fill {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
