/* Application-specific styles that are not represented by Tailwind utilities. */

/* Fixed columns reserve their width before rows arrive. Wrap descriptive content
   and badges, while individual identifiers/names use explicit truncation. */
[data-table-flexible] {
    container-type: inline-size;
}
[data-table-layout="fixed"] th,
[data-table-layout="fixed"] td {
    overflow-wrap: anywhere;
}
[data-table-layout="fixed"] [data-badge] {
    max-width: 100%;
    min-width: 0;
    white-space: normal;
}
[data-table-layout="fixed"] td .whitespace-nowrap {
    white-space: normal;
}
[data-table-layout="fixed"] input,
[data-table-layout="fixed"] select {
    max-width: 100%;
    min-width: 0;
}

/* The selected tab is already known before JS measures the sliding indicator.
   Match that indicator until it is ready, including during circuit startup. */
[data-tabs] [role="tablist"]:not([data-tabs-ready]) [role="tab"][aria-selected="true"]::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 10;
    border-radius: inherit;
    background: var(--text-primary);
    mix-blend-mode: difference;
    pointer-events: none;
}

/* Segmented tabs: one thumb, 1/N of the track, under the selected segment. Like the theme
   picker's [data-toggle-thumb] it slides with translateX(index * 100%), but it is driven by
   the tabs themselves (the thumb comes after them), so the first paint is already right. */
[data-tabs-appearance="segmented"] > [data-tabs-thumb] {
    width: calc(100% - 2 * var(--tabs-pad, 3px));
}

/* Up to eight segments (catalog filters have five or six). More than that does not fit a
   segmented control; use a Select instead. */
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(2) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 2); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(3) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 3); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(4) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 4); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(5) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 5); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(6) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 6); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(7) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 7); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(8) ~ [data-tabs-thumb] { width: calc((100% - 2 * var(--tabs-pad, 3px)) / 8); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(2)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(100%); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(3)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(200%); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(4)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(300%); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(5)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(400%); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(6)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(500%); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(7)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(600%); }
[data-tabs-appearance="segmented"] > [role="tab"]:nth-of-type(8)[aria-selected="true"] ~ [data-tabs-thumb] { transform: translateX(700%); }

.dpp-editor-field {
    padding: 2px;
    outline: 2px solid transparent;
    outline-offset: 4px;
    border-radius: var(--radius-control);
    transition: background-color 180ms ease, outline-color 180ms ease;
}

.dpp-editor-field.dpp-field-highlight {
    outline-color: var(--accent);
    background-color: var(--accent-subtle);
}

@media (prefers-reduced-motion: reduce) {
    .dpp-editor-field {
        transition: none;
    }
}

html:has(.app-shell),
body:has(.app-shell) {
    overflow: hidden;
}

.app-shell {
    --app-sidebar-width: var(--sidebar-w);
}

.app-sidebar {
    position: relative;
    z-index: var(--z-sidebar);
    width: var(--app-sidebar-width);
    transition: width var(--duration-slow) var(--ease-in-out);
}

/*
 * Sidebar collapse. One navigation tree that narrows in place: the rail width
 * carries the motion and every label collapses into it. The values are read
 * from custom properties so a single attribute on the shell drives the whole
 * sidebar, and each property still animates on the element that owns it.
 *
 * Defined on the nav rather than the shell because MainLayout renders the same
 * NavMenu inside the mobile Sheet, which is never collapsed.
 */
.sidebar-nav {
    --sb-row-px: var(--control-px-md);
    --sb-brand-px: var(--space-3);

    /* Per-row, so a taller row can keep its own spacing; the scale is what the
       collapse drives, which lets every gap close without flattening them first. */
    --sb-row-gap: var(--space-1-5);
    --sb-gap-scale: 1;
    --sb-fade-opacity: 1;
    --sb-fade-max-width: 240px;
    --sb-section-height: 20px;
    --sb-section-pb: var(--space-1-5);

    /* Expanding: the rail leads, the labels catch up once there is room. */
    --sb-fade-transition:
        opacity var(--duration-normal) var(--ease-standard) var(--duration-instant),
        max-width var(--duration-slow) var(--ease-in-out);
}

/* Labels, badges and the brand wordmark: everything that only exists at full width. */
.sidebar-nav [data-sb-fade] {
    opacity: var(--sb-fade-opacity);
    max-width: var(--sb-fade-max-width);
    overflow: hidden;
    white-space: nowrap;
    transition: var(--sb-fade-transition);
}

/* Section headings collapse their own box, so the rows above and below close up. */
.sidebar-nav [data-sb-section] {
    height: var(--sb-section-height);
    padding-bottom: var(--sb-section-pb);
    opacity: var(--sb-fade-opacity);
    overflow: hidden;
    white-space: nowrap;
    box-sizing: content-box;
    transition:
        height var(--duration-slow) var(--ease-in-out),
        padding var(--duration-slow) var(--ease-in-out),
        opacity var(--duration-fast) var(--ease-standard);
}

/*
 * The row's own padding and gap animate too: that is what walks the icon to the
 * centre of the rail instead of leaving it pinned to the left edge.
 */
.sidebar-nav [data-sb-row] {
    padding-inline: var(--sb-row-px);
    transition:
        padding var(--duration-slow) var(--ease-in-out),
        var(--transition-control);
}

.sidebar-nav [data-sb-row] > span {
    gap: calc(var(--sb-row-gap) * var(--sb-gap-scale));
    transition: gap var(--duration-slow) var(--ease-in-out);
}

/* size-7 avatar — same inset as the brand mark, not the 16px nav glyph. */
.sidebar-nav .sidebar-account-trigger {
    padding-inline: var(--sb-brand-px);
}

/* Collapsed: labels must leave the flex flow or the avatar stays left-biased. */
.app-shell[data-sidebar-collapsed="true"] .app-sidebar .sidebar-nav .sidebar-account-trigger [data-sb-fade] {
    display: none;
}

.app-shell[data-sidebar-collapsed="true"] .app-sidebar .sidebar-nav .sidebar-account-trigger {
    /* Geometric centre still reads heavy-right (presence + border); bias 2px left. */
    padding-inline-start: calc(var(--sb-brand-px) - 2px);
    padding-inline-end: calc(var(--sb-brand-px) + 2px);
    overflow: visible;
    /* Presence ring must match the trigger, not surface-card. */
    --avatar-ring: var(--surface-raised);
}

/*
 * Presence defaults to -bottom-px / -end-px so it hangs off the avatar. On the
 * compact rail that reads as a downward shift — sit it on the corner instead.
 */
.app-shell[data-sidebar-collapsed="true"] .app-sidebar .sidebar-nav .sidebar-account-trigger [role="img"] > .absolute {
    bottom: 0;
    inset-inline-end: 0;
}

/*
 * Nav gutters shrink with the rail so each row stays w-full of a control-sized
 * column — no width tween on the button (that bounced against the rail motion).
 * Icon stays justify-start; padding walks it on X (centering via justify snaps
 * mid-collapse while the rail is still wide).
 */
.sidebar-nav > .flex > nav,
.sidebar-nav > .flex > .min-h-0 {
    --sb-nav-px: var(--space-2);
    padding-inline: var(--sb-nav-px);
    transition: padding-inline var(--duration-slow) var(--ease-in-out);
}

.sidebar-nav [data-sb-brand] {
    /* Gap collapses with --sb-gap-scale so the mark stays centred in the rail. */
    gap: calc(var(--space-2) * var(--sb-gap-scale));
    padding-inline: var(--sb-brand-px);
    transition:
        gap var(--duration-slow) var(--ease-in-out),
        padding var(--duration-slow) var(--ease-in-out);
}

/* The label is already on screen when the sidebar is open; a tooltip repeating it is noise. */
.app-shell:not([data-sidebar-collapsed="true"]) .app-sidebar [data-tooltip-root] [role="tooltip"] {
    display: none;
}

.sidebar-summary::-webkit-details-marker,
.sidebar-account-summary::-webkit-details-marker {
    display: none;
}

.sidebar-summary::marker,
.sidebar-account-summary::marker {
    content: "";
}

[data-search-dialog] {
    transform-origin: center;
}

[data-search-dialog][data-overlay-motion="entering"] {
    animation: dpp-dialog-enter var(--duration-normal) var(--ease-out) both;
}

[data-search-dialog][data-overlay-motion="exiting"] {
    animation: dpp-dialog-exit var(--duration-fast) var(--ease-in) both;
}

[data-search-dialog]::backdrop {
    background: var(--surface-scrim);
    backdrop-filter: blur(2px);
}

[data-search-dialog][data-overlay-motion="entering"]::backdrop {
    animation: dpp-overlay-enter var(--duration-normal) var(--ease-out) both;
}

[data-search-dialog][data-overlay-motion="exiting"]::backdrop {
    animation: dpp-overlay-exit var(--duration-fast) var(--ease-in) both;
}

[data-modal][data-overlay-motion="entering"] {
    animation: dpp-dialog-enter var(--duration-normal) var(--ease-out) both;
}

[data-modal][data-overlay-motion="exiting"] {
    animation: dpp-dialog-exit var(--duration-fast) var(--ease-in) both;
}

[data-modal]::backdrop {
    background: var(--surface-scrim);
    backdrop-filter: blur(2px);
}

[data-modal][data-overlay-motion="entering"]::backdrop {
    animation: dpp-overlay-enter var(--duration-normal) var(--ease-out) both;
}

[data-modal][data-overlay-motion="exiting"]::backdrop {
    animation: dpp-overlay-exit var(--duration-fast) var(--ease-in) both;
}

[data-sheet][data-overlay-motion="entering"]::backdrop {
    animation: dpp-overlay-enter var(--duration-slow) var(--ease-out) both;
}

[data-sheet][data-overlay-motion="exiting"]::backdrop {
    animation: dpp-overlay-exit var(--duration-slow) var(--ease-in) both;
}

[data-sheet].sheet-start[data-overlay-motion="entering"] {
    animation: dpp-sheet-start-enter var(--duration-slow) var(--ease-out) both;
}

[data-sheet].sheet-start[data-overlay-motion="exiting"] {
    animation: dpp-sheet-start-exit var(--duration-slow) var(--ease-in) both;
}

[data-sheet].sheet-end[data-overlay-motion="entering"] {
    animation: dpp-sheet-end-enter var(--duration-slow) var(--ease-out) both;
}

[data-sheet].sheet-end[data-overlay-motion="exiting"] {
    animation: dpp-sheet-end-exit var(--duration-slow) var(--ease-in) both;
}

@keyframes dpp-dialog-enter {
    from {
        opacity: 0;
        transform: translateY(4px) scale(.98);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

@keyframes dpp-dialog-exit {
    from {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
    to {
        opacity: 0;
        transform: translateY(4px) scale(.98);
    }
}

@keyframes dpp-overlay-enter {
    from {
        opacity: 0;
        backdrop-filter: blur(0);
    }
    to {
        opacity: 1;
        backdrop-filter: blur(2px);
    }
}

@keyframes dpp-overlay-exit {
    from {
        opacity: 1;
        backdrop-filter: blur(2px);
    }
    to {
        opacity: 0;
        backdrop-filter: blur(0);
    }
}

@keyframes dpp-sheet-start-enter {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
}

@keyframes dpp-sheet-start-exit {
    from { transform: translateX(0); }
    to { transform: translateX(-100%); }
}

@keyframes dpp-sheet-end-enter {
    from { transform: translateX(100%); }
    to { transform: translateX(0); }
}

@keyframes dpp-sheet-end-exit {
    from { transform: translateX(0); }
    to { transform: translateX(100%); }
}

[data-toast][data-toast-state="entering"] {
    animation: dpp-toast-enter var(--duration-slower) var(--ease-out) both;
}

[data-toast][data-toast-state="exiting"] {
    animation: dpp-toast-exit var(--duration-fast) var(--ease-in) both;
}

@keyframes dpp-toast-enter {
    from {
        opacity: 0;
        transform: translateX(100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes dpp-toast-exit {
    from {
        opacity: 1;
        transform: translateX(0);
    }
    to {
        opacity: 0;
        transform: translateX(100%);
    }
}

.progress-indeterminate {
    animation: dpp-progress-indeterminate 1100ms var(--ease-out) infinite;
}

@keyframes dpp-progress-indeterminate {
    0% { transform: translateX(-100%); }
    55% { transform: translateX(115%); }
    100% { transform: translateX(260%); }
}

.theme-controls-pending {
    visibility: hidden;
}

[data-theme-group] [data-toggle-thumb] {
    width: calc((100% - 0.25rem) / 3);
    transform: translateX(100%);
}

[data-toggle-group] > [data-toggle-key] {
    flex: 1 1 0%;
    min-width: 0;
    justify-content: center;
}

.theme-choice[data-theme-selected="true"] {
    background: transparent;
    color: var(--accent-text);
}

.theme-choice[data-theme-selected="true"]:hover {
    background: transparent;
    color: var(--accent-text);
}

[data-popover-content] {
    opacity: 0;
    transform: translateY(4px);
    pointer-events: none;
    transition: opacity var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard);
}

[data-popover-root][data-open="true"] [data-popover-content],
[data-popover-content][data-popover-state="open"] {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

[data-popover-content][data-popover-state="entering"] {
    opacity: 0;
    transform: translateY(4px);
}

[data-popover-content][data-popover-state="exiting"] {
    opacity: 0;
    transform: translateY(4px);
}

.sidebar-account-expanded-trigger {
    width: 100%;
}

.sidebar-account[data-open="true"] .sidebar-account-trigger {
    background: var(--surface-hover);
}

/* Match frontend Tooltip.css + OverlayArrow placement (offset 10px). */
[data-tooltip-root] [role="tooltip"] {
    --tooltip-origin: translate3d(-4px, -50%, 0);
    --tooltip-shown: translate3d(0, -50%, 0);
    visibility: hidden;
    opacity: 0;
    inset-inline-start: calc(100% + 10px);
    top: 50%;
    transform: var(--tooltip-origin);
    transition: transform 150ms var(--ease-out), opacity 150ms var(--ease-out), visibility 0s linear 150ms;
}

/* Hover, or keyboard focus (:focus-visible). Plain :focus-within after a mouse
   click would keep the bubble up until the next click elsewhere. */
[data-tooltip-root]:not([data-tooltip-floating]):not([data-tooltip-dismissed]):hover [role="tooltip"],
[data-tooltip-root]:not([data-tooltip-floating]):not([data-tooltip-dismissed]):focus-within:has(:focus-visible) [role="tooltip"] {
    visibility: visible;
    opacity: 1;
    transform: var(--tooltip-shown);
    transition-delay: 0s;
}

[data-tooltip-root] [data-tooltip-arrow] {
    position: absolute;
    width: 8px;
    height: 8px;
    background: var(--surface-tooltip);
    border-right: 1px solid var(--border-default);
    border-bottom: 1px solid var(--border-default);
    pointer-events: none;
}

.tooltip-left [role="tooltip"] {
    --tooltip-origin: translate3d(4px, -50%, 0);
    --tooltip-shown: translate3d(0, -50%, 0);
    inset-inline-start: auto;
    inset-inline-end: calc(100% + 10px);
}

.tooltip-left [data-tooltip-arrow] {
    inset-inline-end: -4px;
    top: 50%;
    transform: translateY(-50%) rotate(-45deg);
}

.tooltip-right [data-tooltip-arrow] {
    inset-inline-start: -4px;
    top: 50%;
    transform: translateY(-50%) rotate(135deg);
}

.tooltip-top [role="tooltip"] {
    --tooltip-origin: translate3d(-50%, 4px, 0);
    --tooltip-shown: translate3d(-50%, 0, 0);
    inset-inline-start: 50%;
    top: auto;
    bottom: calc(100% + 10px);
}

.tooltip-top [data-tooltip-arrow] {
    inset-inline-start: 50%;
    bottom: -4px;
    transform: translateX(-50%) rotate(45deg);
}

.tooltip-bottom [role="tooltip"] {
    --tooltip-origin: translate3d(-50%, -4px, 0);
    --tooltip-shown: translate3d(-50%, 0, 0);
    inset-inline-start: 50%;
    top: calc(100% + 10px);
}

.tooltip-bottom [data-tooltip-arrow] {
    inset-inline-start: 50%;
    top: -4px;
    transform: translateX(-50%) rotate(225deg);
}

@media (prefers-reduced-motion: reduce) {
    [data-tooltip-root] [role="tooltip"] {
        transition: none;
    }
}

[data-breadcrumbs] li + li::before {
    content: "/";
    margin-inline: 8px;
    color: var(--text-muted);
}

.sheet-panel {
    position: fixed;
    z-index: var(--z-modal);
    margin: 0;
    min-height: 100dvh;
    max-height: 100dvh;
    overflow-y: auto;
    border: 0;
    background: var(--surface-sidebar);
    color: var(--text-primary);
}

.sheet-start {
    inset: 0 auto 0 0;
    width: min(var(--sidebar-w), 100vw);
}

.sheet-end {
    inset: 0 0 0 auto;
    width: min(var(--panel-w), 100vw);
}

.sheet-panel::backdrop {
    background: var(--surface-scrim);
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }

    [data-popover-content],
    .app-sidebar,
    .sidebar-nav [data-sb-fade],
    .sidebar-nav [data-sb-section],
    .sidebar-nav [data-sb-row],
    .sidebar-nav [data-sb-row] > span,
    .sidebar-nav [data-sb-brand],
    .sidebar-nav > .flex > nav,
    .sidebar-nav > .flex > .min-h-0 {
        transition: none;
    }
}

.app-sidebar-scrim {
    display: none;
}

@media (min-width: 840px) {
    .app-shell[data-sidebar-collapsed="true"] {
        --app-sidebar-width: var(--sidebar-w-collapsed);
    }

    .app-shell[data-sidebar-collapsed="true"] .app-sidebar .sidebar-nav {
        /*
         * Aside is border-box with border-e, so the usable rail is 1px narrower
         * than --sidebar-w-collapsed (52 → 51). Pads are measured against that.
         */
        --sb-rail-inner: calc(var(--sidebar-w-collapsed) - var(--border-width));
        --sb-nav-px: calc((var(--sb-rail-inner) - var(--control-h-md)) / 2);
        --sb-row-px: 8px;
        /* size-7 mark / avatar (1.75rem). */
        --sb-brand-px: calc((var(--sb-rail-inner) - 1.75rem) / 2);
        --sb-gap-scale: 0;
        --sb-fade-opacity: 0;
        --sb-fade-max-width: 0px;
        --sb-section-height: 0px;
        --sb-section-pb: 0px;

        /*
         * Collapsing runs the other way round: the labels go first and without a
         * delay, so the text is gone before the rail has finished narrowing and
         * never gets clipped mid-word.
         */
        --sb-fade-transition:
            opacity var(--duration-fast) var(--ease-standard),
            max-width var(--duration-slow) var(--ease-in-out);
    }

    /* overflow-x-hidden on the middle pane clips side tooltips; top/bottom nav
       escape because they sit outside that scroller. Collapsed rail fits without
       it, so open the overflow and let the bubbles through. */
    .app-shell[data-sidebar-collapsed="true"] .sidebar-nav [data-sb-scroll] {
        overflow: visible;
    }
}

@media (max-width: 839px) {
    .app-sidebar {
        display: none;
    }
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #16a34a;
}

.invalid {
    outline: 1px solid #dc2626;
}

.validation-message {
    color: #dc2626;
}

.blazor-error-boundary {
    background: #b91c1c;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* Table values need the top layer so their tooltip escapes the scroll container. */
[data-tooltip-root][data-tooltip-floating] [role="tooltip"] {
    position: fixed;
    inset: auto;
    margin: 0;
    width: max-content;
    max-width: min(24rem, calc(100vw - 16px));
    white-space: normal;
    overflow-wrap: anywhere;
    overflow: visible;
    transform: none;
    visibility: visible;
    opacity: 1;
    transition: none;
}
[data-tooltip-floating] [data-tooltip-arrow] {
    inset: auto;
}
[data-tooltip-floating] [data-tooltip-side="bottom"] [data-tooltip-arrow] {
    top: -4px;
    left: var(--tooltip-arrow-x);
    transform: translateX(-50%) rotate(225deg);
}
[data-tooltip-floating] [data-tooltip-side="top"] [data-tooltip-arrow] {
    bottom: -4px;
    left: var(--tooltip-arrow-x);
    transform: translateX(-50%) rotate(45deg);
}
[data-tooltip-floating] [data-tooltip-side="left"] [data-tooltip-arrow] {
    right: -4px;
    top: var(--tooltip-arrow-y);
    transform: translateY(-50%) rotate(-45deg);
}
[data-tooltip-floating] [data-tooltip-side="right"] [data-tooltip-arrow] {
    left: -4px;
    top: var(--tooltip-arrow-y);
    transform: translateY(-50%) rotate(135deg);
}

@media (forced-colors: active) {
    [data-tooltip-root] [data-tooltip-arrow] {
        forced-color-adjust: none;
        background: Canvas;
        border-color: ButtonBorder;
    }
}
