/* ─────────────────────────────────────────────────────────────────────────
   xOptics.Ui.Kit — the styles the brand-neutral components depend on.

   These rules ship with the components rather than with the host app: a kit
   component moved into a new app without them compiles, renders, and looks
   subtly wrong, with nothing in any build output to say so. Everything here
   is expressed over MudBlazor's own --mud-palette-* variables, so the kit
   needs no palette or token layer of its own and follows whatever theme the
   host applies, light or dark.

   Link this ahead of the host's own stylesheet so app-level rules still win:
       <link rel="stylesheet" href="_content/xOptics.Ui.Kit/kit.css" />
   ───────────────────────────────────────────────────────────────────────── */

/* Keyboard-accessible clickable surfaces (cards, rows) that aren't native
   buttons/links. Pairs with role="button" tabindex="0" @onkeydown so mouse,
   keyboard, and screen-reader users get the same affordance. focus-visible
   shows the same lift/outline as hover so Tab navigation is discoverable. */
.xo-clickable {
    cursor: pointer;
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
    outline: none;
}
.xo-clickable:hover,
.xo-clickable:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
    border-color: var(--mud-palette-primary);
}

/* StatCard's clickable variant manages hover elevation via mouse events,
   which never fire for keyboard focus — give it an explicit focus ring. */
.stat-card-clickable:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Respect users who've asked the OS to reduce motion: drop the lift. */
@media (prefers-reduced-motion: reduce) {
    .xo-clickable {
        transition: none;
    }
    .xo-clickable:hover,
    .xo-clickable:focus-visible {
        transform: none;
    }
}

/* DetailDrawer: header over a body that scrolls, filling the drawer's height. The width itself
   is capped at the viewport in DetailDrawer.EffectiveWidth, so these rules only need to keep the
   panel's content inside it: min-width:0 lets a long title or an unbroken object name wrap
   instead of widening the panel, and the body scrolls in both directions as a last resort.
   The panel takes focus on open (detailDrawer.js) so Esc reaches it; it is a focus target for
   the keyboard, not a control, so it draws no focus ring of its own. */
.xo-detail-drawer__panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-width: 0;
    overflow: hidden;
    outline: none;
}
.xo-detail-drawer__header {
    border-bottom: 1px solid var(--mud-palette-divider);
    flex: 0 0 auto;
}
.xo-detail-drawer__titles {
    min-width: 0;
    overflow-wrap: anywhere;
}
.xo-detail-drawer__body {
    flex: 1 1 auto;
    min-width: 0;
    overflow: auto;
}

/* Tabular numerals: a cell marked Class="xo-numeric" keeps its digits at a
   fixed width so a column of figures lines up instead of jittering.
   (The host app may extend this to MudBlazor's right-aligned cell classes;
   that pairing is the app's choice, not the kit's.) */
.xo-numeric {
    font-variant-numeric: tabular-nums;
}

/* Text that only a screen reader reads: present in the accessibility tree, absent from
   the page. LoadingSkeleton's Rows layout needs it because a live region announces its
   CONTENT and not its accessible name, and that layout's own content is blank blocks —
   an aria-label on the region named something with nothing to say, so the label was
   never read. The clip/clip-path pair rather than display:none or visibility:hidden,
   both of which remove the element from the accessibility tree along with the pixels.

   Mirrors the pattern MudBlazor moved its own collapsed mini-rail labels to in 9.9
   (#13525), which xOptics.Web/app.css copies for that one selector. This is the kit's
   own reusable utility: a kit component must not depend on a rule that lives in a host
   app's stylesheet, or it renders subtly wrong in the next app with nothing to say so. */
.xo-visually-hidden {
    position: absolute;
    clip: rect(1px, 1px, 1px, 1px);
    clip-path: inset(50%);
    white-space: nowrap;
    padding: 0;
    border: 0;
    height: 1px;
    width: 1px;
    overflow: hidden;
}

/* Phone-content swap (issue #1029, LayoutBreakpoints.PhoneContent = 480): a screen that draws two
   genuinely different markups — the full desktop layout and the phone content rule's reduced one —
   renders BOTH branches unconditionally and lets these two classes decide which is visible. This is
   what keeps the switch purely visual: LayoutBreakpoints' own rule is that a component must never
   carry a breakpoint of its own that can disagree with a shared decision (MobileTabBar.razor.css's
   own remarks are the worked failure this follows), so no page re-implements this pair — it exists
   once, here, spelled at exactly the PhoneContent tier LayoutBreakpointStaticAnalysisTests pins. */
.xo-above-phone-only {
    display: block;
}
.xo-phone-only {
    display: none;
}
@media (max-width: 479.98px) {
    .xo-above-phone-only {
        display: none;
    }
    .xo-phone-only {
        display: block;
    }
}
