﻿html, body {
    padding: 0;
    margin: 0;
    height: 100dvh;
    /* Nothing here is meant to scroll at the document level - every scrollable area (dashboard
       list, dialogs, panels) has its own overflow. Without this, touch/trackpad drag still
       triggers the browser's elastic overscroll bounce even though there's nothing to scroll to,
       which visibly drags fixed-position elements (the app bar's loading bar, tooltips) along
       with it - most noticeable in the installed PWA, which has no browser chrome to absorb it. */
    overflow: hidden;
    overscroll-behavior: none;
}

.appbar {
    padding-top: 4px;
    padding-left: 0 !important;
    color: black;
}

.main-content {
    height: calc(100dvh - var(--mud-appbar-height));
    width: 100dvw;
    position: fixed;
    top: var(--mud-appbar-height);
    padding: 0;
    margin: 0;
}

/* The app bar goes to two rows here (--appbar-bp-two-row in AppBar.razor.css); everything offset by the bar follows. */
@media (max-width: 840px) {
    :root:has(.appbar-project-open) {
        --mud-appbar-height: 100px;
    }
}

/* SharedViewLayout has no AppBar, so it doesn't need to offset for one. */
.shared-view-content {
    height: 100dvh;
    width: 100dvw;
    position: fixed;
    top: 0;
    padding: 0;
    margin: 0;
}

.sync-icon-spinning {
    animation: spin 1s linear infinite;
    transform-origin: center center;
    will-change: transform;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(-360deg);
    }
}

#form-container {
    margin-left: auto;
    margin-right: auto;
    max-width: 600px;
    text-align: center;
    padding-top: 20px;
}

.mud-appbar .mud-toolbar-appbar {
    padding-left: 0.5rem !important;
}
.mud-toolbar-appbar {
    padding-left: 0.5rem !important;
    padding-right: 0.0rem !important;
}

.appbar-menu-btn {

}

.mud-tab {
    color: #4A4A4A;
    /* MudBlazor hardcodes uppercase on .mud-tab, so the theme's Typography.Button.TextTransform
       (which drops it for buttons) has no effect here. Same specificity as MudBlazor's own rule -
       this only wins because customStyles.css is linked after MudBlazor.min.css in App.razor. */
    text-transform: none;
    letter-spacing: normal;
}

.toolbar-main {
    position: absolute;
    top: 4rem;
    left: 1rem;
}

.icon-large{
/*    font-size: 2rem !important;
*/}

.selected-button {
    background-color: #e0e0e0 !important;
    color: var(--mud-palette-primary) !important;
    transform: scale(1.1);
    border-radius: 6px;
    transition: transform 0.2s ease, background-color 0.2s ease;
}

.selected-button-wo-scale {
    background-color: #e0e0e0 !important;
    color: var(--mud-palette-primary) !important;
    border-radius: 6px;
    transition: transform 0.2s ease, background-color 0.2s ease;
}

/* Single owner of the "selected tool" look for every toolbar: a red edge marker like the MudTabs
   slider, on the edge the button group runs along. The icon keeps its normal Color.Primary.
   Global (not scoped) because the 3D view's toolbars are plain JS-rendered markup.
   Background and size are deliberately left alone, so a selected button keeps its group's
   standard hover and footprint - only the marker distinguishes it. */
.mud-button-root.toolbar-btn-selected,
.mud-toggle-item.toolbar-btn-selected,
.mud-button-root.system-type-selected,
.viewer3d-toggle-button.selected,
.viewer3d-btn.viewer3d-btn-selected {
    position: relative;
}

/* Mud icon buttons are circles, so square the selected one off or the marker curves away from the
   edge. The 3D buttons are already square and keep their group's end-cap radii. */
.mud-button-root.toolbar-btn-selected,
.mud-button-root.system-type-selected {
    border-color: transparent !important;
    border-radius: 0 !important;
}

/* A pseudo-element rather than an inset box-shadow, which can only ever span the full edge: inset
   from both ends, two adjacent selected buttons read as two markers instead of one long line.
   Absolute so it adds no height and can't shift the button when selection changes.
   ::before, not ::after - MudBlazor's ripple owns .mud-ripple-icon:after and scales it 10x. */
.mud-button-root.toolbar-btn-selected::before,
.mud-toggle-item.toolbar-btn-selected::before,
.mud-button-root.system-type-selected::before,
.viewer3d-toggle-button.selected::before,
.viewer3d-btn.viewer3d-btn-selected::before {
    content: "";
    position: absolute;
    pointer-events: none;
    border-radius: 1px;
    background-color: var(--mud-palette-error, rgb(225, 9, 21));
    left: 18%;
    right: 18%;
    bottom: 0;
    height: 2px;
}

/* Vertical toolbars stack downwards, so the marker moves to the right edge. */
.mud-button-root.toolbar-btn-selected-vertical::before {
    left: auto;
    bottom: 18%;
    height: auto;
    top: 18%;
    right: 0;
    width: 2px;
}

:root {
    /* Measured width of the elevation/plan top-right property-tab button row (three medium icon
       buttons + card border) - shared with ValidationPanel.razor so its badge lines up with a
       consistent gap whether that button row or the property window is showing. */
    --top-right-button-width: 121.5px;

    /* Fixed width of the top-right property window (GenericPropertiesWindow) - shared with
       ValidationPanel.razor for the same reason. */
    --property-window-width: 18rem;
}

.top-right-button {
    position: absolute;
    right: 1rem;
    top: 1rem;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

.top-right-button.split-button-card {
    width: var(--top-right-button-width);
}

/* While the Babylon Inspector is open (viewer3d.debug.js), keep the 3D overlays between its side panes.
   !important beats the inline left/width viewer3DUI.core.js puts on #viewer3DUI. */
.inspector-open #viewer3DUI {
    left: var(--inspector-left, 0px) !important;
    width: calc(100% - var(--inspector-left, 0px) - var(--inspector-right, 0px)) !important;
}

.inspector-open .top-right-button,
.inspector-open .generic-properties {
    right: calc(1rem + var(--inspector-right, 0px));
}

/* Shared look for every split-button toolbar (properties, bottom-left settings, zoom/fit,
   system-type selector, etc.) - a plain bordered wrapper around the button group directly, with
   no MudCard/MudCardActions padding added around it, so they all read as one family regardless
   of which view renders them. */
.split-button-card {
    display: inline-flex;
    align-items: center;
    background: #fff;
    border: 1px solid #A9A9A9;
    border-radius: 6px;
}

/* MudButtonGroup draws its own divider between grouped buttons (via its "override styles" CSS,
   colored off each button's Color). We don't want dividers inside these cards at all - the card
   border alone frames the group - so make them transparent regardless of variant (Text or
   Outlined) or which side MudBlazor put the border on. */
.split-button-card .mud-button-root {
    border-color: transparent !important;
}

/* ---- MudBlazor tabs: hover tab → icon lifts ---- */
.mud-tab:hover .mud-icon-root,
.mud-tab:hover .mud-svg-icon {
    transform: translateY(-1px);
    transition: transform 160ms ease, filter 160ms ease;
}

/* ---- Respect reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
    .mud-tab .mud-icon-root,
    .mud-tab .mud-svg-icon {
        transition: none !important;
        animation: none !important;
        transform: none !important;
        filter: none !important;
    }
}

/* ---- Elevation part fill highlight (elevation2d.highlight.js fillGeometryHighlight) ---- */
.geometry-fill-hl {
    transition: opacity 150ms ease-out;
}

/* ---- Elevation comp highlight: framed yellow inset border (elevation2d.highlight.js highlightComp) ---- */
.geometry-comp-hl {
    transition: opacity 150ms ease-out;
}

/* ---- Parts a hovered door hides underneath it: stroke-only clone, no fill
   (elevation2d.highlight.js _highlightHiddenPartStroke) ---- */
.geometry-hidden-stroke-hl {
    transition: opacity 150ms ease-out;
}

/* White-fill highlights (obstruction/skirting/opening/wire) recolour the real element's fill
   in place; this transitions that colour change so they fade white<->yellow like the part fill. */
.geometry-fill-transition {
    transition: fill 150ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
    .geometry-fill-hl,
    .geometry-comp-hl,
    .geometry-fill-transition,
    .geometry-hidden-stroke-hl {
        transition: none !important;
    }
}

/* ---- Elevation selection visual (elevation2d.select.js) ---- */
/* Fade applies to every style's container, regardless of which style is active. */
.geometry-select {
    transition: opacity 150ms ease-out;
}

/* Marching-ants style: crawl the dash pattern. dashoffset is in screen px (non-scaling-stroke),
   so -10 == one dash+gap cycle (dasharray "6 4") for a seamless loop. */
@keyframes marching-ants {
    to {
        stroke-dashoffset: -12;
    }
}

.geometry-select-ants {
    animation: marching-ants 0.5s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .geometry-select {
        transition: none !important;
    }

    .geometry-select-ants {
        animation: none !important;
    }
}

/* ---- Validation badges (ValidationBadgeLayer) ---- */
/* Both the count marker (in place inside its badge) and the tooltip (in a second pass, after every
   badge, so it can never paint under a later badge - see badgeTooltips) always render server-side;
   ValidationBadgeLayer's own mouseover/mouseout/mousedown handlers toggle a class rather than the
   element's presence, so a CSS transition always has something in the DOM to animate to/from. This
   is also pure C# display state, not JS-owned, which is what lets a future caller open a specific
   badge's tooltip programmatically (e.g. from the design-issues panel) instead of only ever reacting
   to the mouse. */

/* SvgIcon's foreignObject only paints a small circle inside its Size x Size box (see the CustomIcons
   viewBox), and a nested <svg>'s default pointer-events is visiblePainted - only that painted circle,
   not the transparent padding around it, is hit-tested. That left most of the icon's box a dead zone
   the mouseover/mousedown listeners below never saw. `all` hit-tests the whole box regardless of
   paint. Excludes the tooltip, which stays click/hover-through even while open. */
.validation-badge foreignObject:not(.validation-badge-tooltip) {
    pointer-events: all;
}

/* Scales the whole badge group (icon + count marker) rather than the foreignObject itself, which
   already carries its own SVG transform attribute (position) that a CSS transform would replace. */
.validation-badge {
    transform-box: fill-box;
    transform-origin: center;
    transition: transform 120ms ease;
}

/* validation-badge-open covers both hover and pinned (selected) - so a pinned badge stays enlarged
   and its tooltip stays open even after the mouse leaves, not just on live :hover. */
.validation-badge:hover,
.validation-badge-open {
    transform: scale(1.2);
}

/* Opacity/transform rather than display:none - display can't transition, and a plain fade read as a
   glitch for something swapping in the exact same spot the tooltip takes over. */
.validation-badge-count {
    transform-box: fill-box;
    transform-origin: center;
    transition: opacity 140ms ease, transform 140ms ease;
}

.validation-badge-open .validation-badge-count {
    opacity: 0;
    transform: scale(0.5);
    pointer-events: none;
}

.validation-badge-tooltip {
    opacity: 0;
    pointer-events: none;
    transform: scale(0.85);
    /* Grows from the arrow tip (the box's top edge, x-centred) rather than its own centre, matching
       how a real tooltip unfurls from its anchor instead of ballooning outward in both directions. */
    transform-box: fill-box;
    transform-origin: top;
    transition: opacity 120ms ease, transform 120ms ease;
}

/* .validation-badge-tooltip-open is a real Razor-authored <g> wrapping the (otherwise unvarying)
   MarkupString TooltipSvg returns - a descendant selector off it, rather than a class embedded
   directly in that string, is what lets Blazor patch just this class attribute in place instead of
   tearing down and reinserting the whole raw-HTML blob (opaque to its diffing) on every toggle. That
   in-place patch is what a CSS transition needs to have something to animate from. */
.validation-badge-tooltip-open .validation-badge-tooltip {
    opacity: 1;
    transform: scale(1);
}

/* Each line fades/slides in on its own - ValidationBadgeLayer.TooltipSvg staggers them with an inline
   transition-delay (line index x 30ms) so they read as a small cascade rather than popping in at once. */
.validation-badge-tooltip text {
    opacity: 0;
    transform: translateY(-3px);
    transform-box: fill-box;
    transform-origin: center;
    transition: opacity 140ms ease, transform 140ms ease;
}

.validation-badge-tooltip-open .validation-badge-tooltip text {
    opacity: 1;
    transform: translateY(0);
}

/* ---- Part labels (PartLabelComponent) ---- */
/* Hidden entirely during a live comp-resize drag - see body.comp-resizing in viewerStyles.css. */

/* ---- Radial menus (Plan / Elevation / DWG GenericRadialMenu) ---- */
/* Covers both the menu's own SVG chrome and the button icons, which live once in the
   RadialMenuIconSprite <defs> and are styled there: <use> clones take the original's styles.
   The icons need it for the same reason the toolbars do: they're authored with stroke-width:1
   meaning one screen pixel, but their viewBoxes range from 24x24 to 123x104, so a plain 1 would
   render five times thinner on the latter. The DWG and 3D menus also rely on this rule - they
   render outside Viewer2D's #drawingGroup, so the scoped rule there never reaches them. */
.radial-menu :is(path, line, circle, ellipse, rect, polygon, polyline),
.radial-menu-icons :is(path, line, circle, ellipse, rect, polygon, polyline) {
    vector-effect: non-scaling-stroke;
}

.radial-menu-animation-wrapper {
    transition: transform 0.3s ease, opacity 0.3s ease;
    transform: scale(0.8);
    transform-origin: 0 0;
    opacity: 0;
}

.radial-menu[visibility="visible"] .radial-menu-animation-wrapper {
    transform: scale(1);
    opacity: 1;
}

/* Safari: fade in without the grow - not all of its position:fixed icons track the grow, so some lag and snap. */
html.webkit-safari .radial-menu .radial-menu-animation-wrapper {
    transform: none;
    transition: opacity 0.3s ease;
}

.radial-menu .menu-circle {
    transition: transform 0.2s ease, fill 0.2s ease;
}

/* Skipped while the last input was a finger or pen: touch browsers keep a tapped element in :hover
   until something else is tapped, so the red ring would stay lit on the button long after the tap.
   radialMenu.common.js maintains data-pointer-type on <html> (a (hover: hover) media query can't
   tell the two apart on a touchscreen laptop). :where() keeps the guard at zero specificity, so
   the disabled-button rule below still overrides this by one class as it always did. */
:where(html:not([data-pointer-type="touch"], [data-pointer-type="pen"])) .radial-menu .menu-item:hover .menu-circle {
    filter: drop-shadow(2px 2px 3px rgba(0, 0, 0, 0.4));
    stroke: #E10915;
    transform: scale(1.2);
}

.radial-menu .menu-item.menu-item-disabled .menu-circle {
    fill: #ececec;
    stroke: #bdbdbd;
}

.radial-menu .menu-item.menu-item-disabled:hover .menu-circle {
    filter: none;
    stroke: #bdbdbd;
    transform: none;
}

.radial-menu .menu-item.menu-item-disabled .menu-icon {
    color: #9e9e9e !important;
    filter: grayscale(1);
    opacity: 0.75;
}

/*
 * Adjust-collapse: while stepping a value with the +/- pair, every other button folds into the
 * menu centre so the geometry being edited stays visible behind the menu. Pressing +/- latches
 * .radial-menu-adjusting on via radialMenu.common.js, which also decides when to release it.
 * There is deliberately no :hover trigger: touch browsers leave the tapped hex in :hover after the
 * finger lifts, which left the menu folded with nothing to unfold it.
 *
 * The standalone translate/scale properties compose on top of each item's transform="translate(x, y)"
 * presentation attribute - a CSS `transform` would replace it and knock the button off its slot.
 * --item-x/--item-y carry that same slot offset (set in GenericRadialMenu.razor), so negating them
 * walks a button back to (0, 0).
 */
.radial-menu .menu-item {
    transform-box: fill-box;
    transform-origin: center;
    transition: translate 0.25s ease, scale 0.25s ease, opacity 0.25s ease;
}

/* Exactly one button stays visible at the centre and the rest fade out completely, so the folded
   cluster reads as a single button rather than a heap of overlapping hexes. The anchor is the first
   folding button in DOM order: a centre button (back/more/parent-comp) when the menu has one - they
   render before the ring and are already at (0, 0), so they don't travel - otherwise the first ring
   button. Set as custom props rather than override rules so the collapse below stays one selector. */
.radial-menu .menu-item:not([data-action="plus"], [data-action="minus"]) {
    --collapse-scale: 0.75;
    --collapse-opacity: 0.45;
}

/* ...and every folding button after the first loses that treatment again. `~` matches "has an
   earlier folding sibling", which is as close as CSS gets to "every match except the first". */
.radial-menu .menu-item:not([data-action="plus"], [data-action="minus"])
~ .menu-item:not([data-action="plus"], [data-action="minus"]) {
    --collapse-scale: 0.3;
    --collapse-opacity: 0;
}

.radial-menu.radial-menu-adjusting .menu-item:not([data-action="plus"], [data-action="minus"]) {
    /* The offset is walked back SCALED, not whole. css-transforms-2 composes these as
       translate -> rotate -> scale -> transform, so `transform="translate(x, y)"` is applied first
       and `scale` then shrinks that offset along with the hex - the button is already only
       0.3 * (x, y) from the centre by the time `translate` runs. Subtracting the full (x, y) would
       shoot it past the centre and out the other side. */
    translate: calc(var(--item-x, 0px) * -1 * var(--collapse-scale, 0.3))
               calc(var(--item-y, 0px) * -1 * var(--collapse-scale, 0.3));
    scale: var(--collapse-scale, 0.3);
    opacity: var(--collapse-opacity, 0);
}

/* Safari paints the position:fixed icons on their own layer, outside the item's opacity, so the icon
   fades itself. Safari-only (class from radialMenu.common.js): elsewhere it would fade twice. */
html.webkit-safari .radial-menu .menu-item .menu-icon {
    transition: opacity 0.25s ease, scale 0.25s ease;
}

html.webkit-safari .radial-menu.radial-menu-adjusting .menu-item:not([data-action="plus"], [data-action="minus"]) .menu-icon {
    opacity: var(--collapse-opacity, 0);
}

/* That layer also scales about the wrong point, so here the item only slides and hex and icon scale in place. */
html.webkit-safari .radial-menu .menu-item .menu-circle {
    transition: transform 0.2s ease, fill 0.2s ease, scale 0.25s ease;
}

html.webkit-safari .radial-menu.radial-menu-adjusting .menu-item:not([data-action="plus"], [data-action="minus"]) {
    translate: calc(var(--item-x, 0px) * -1) calc(var(--item-y, 0px) * -1);
    scale: none;
}

html.webkit-safari .radial-menu.radial-menu-adjusting .menu-item:not([data-action="plus"], [data-action="minus"]) :is(.menu-circle, .menu-icon) {
    scale: var(--collapse-scale, 0.3);
}

/*
 * Blazor can re-render after invokeMethodAsync("UpdateSelectionFromRadialMenu") and reset Razor markup:
 * .menu-item pointer-events="none". JS setAttribute runs before that and is lost — especially when
 * swapping parent → child radial menus. Force the visible menu only.
 */
.radial-menu[visibility="visible"] .menu-item {
    pointer-events: all !important;
}

.radial-menu[visibility="visible"] .menu-item.menu-item-disabled {
    cursor: not-allowed;
}

.radial-menu[visibility="hidden"] .menu-item {
    pointer-events: none !important;
}

/* layerPicker.js pick mode - global, since a note's radial Pick layer runs it with the Layers panel closed - and a
   note's Add arrow (textNoteEditing.js). */
body.layer-pick-active #svgContainer,
body.layer-pick-active #svgContainer *,
body.text-note-arrow-active #svgContainer,
body.text-note-arrow-active #svgContainer * {
    cursor: crosshair !important;
}

/* Pressing a menu button hides its tooltip, which otherwise covers the very geometry the press is
   about to change - and on touch lingers there afterwards. The shared radial tooltip lives on <body>
   (radialMenu.common.js), outside the SVG, so it can't be reached through a .radial-menu ancestor;
   the press is flagged on <html> instead. The rule is unscoped, but a tooltip is anchored to its
   trigger, so while the pointer is pressing a menu button there is no other tooltip legitimately on
   screen to catch. */
html[data-radial-tooltip-off] .mud-tooltip {
    visibility: hidden !important;
}

@media (prefers-reduced-motion: reduce) {
    .radial-menu-animation-wrapper {
        transition: none !important;
        transform: none !important;
        opacity: 1 !important;
    }

    .radial-menu .menu-circle {
        transition: none !important;
    }

    .radial-menu .menu-item:hover .menu-circle {
        transform: none !important;
        filter: none !important;
    }

    /* The adjust-collapse still happens - it's a function, not decoration - just without the
       animation. */
    .radial-menu .menu-item,
    .radial-menu .menu-icon {
        transition: none !important;
    }
}

/* DwgImagePickerDialog: shimmer lives in global CSS so Razor <style> does not need @@keyframes (CSS tools flag that as invalid). */
@keyframes dwg-shimmer {
    0% {
        transform: translateX(-100%);
    }

    100% {
        transform: translateX(100%);
    }
}

/* DWG skeleton overlays (::after); pair with delayed dwg-shimmer for a softer entry. */
@keyframes dwg-skeleton-shimmer-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* Drawer page preview: meet-box tint target opacity. */
@keyframes dwg-preview-skel-fill-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 0.22;
    }
}


/* ---- Material Symbols weight ----
   Google's css2 response ships its own ".material-symbols-outlined" rule pinning
   font-variation-settings to 'wght' 400. That's the family's thinnest instance, and next to our
   custom SVG icons - which stroke at ~13% of icon width (see Icons/Plan/Lock_Walls.svg) - the
   glyphs read as a lighter grey even though both inherit the same currentColor. Bumping to 500
   closes the stroke-weight gap so a toolbar mixing both sources looks like one set.

   The ":root" prefix is load-bearing: customStyles.css is linked before the fonts.googleapis.com
   stylesheets in App.razor, so a bare single-class selector would lose the cascade to Google's.
   The extra element in the selector outweighs it regardless of order. */
:root .material-symbols-outlined,
:root .material-symbols-rounded,
:root .material-symbols-sharp {
    font-variation-settings: 'FILL' 0, 'wght' 500, 'GRAD' 0, 'opsz' 24;
}

/* ---- Elevation system-type menu ----
   The expanded icon list lives in the popover provider at the document root, so it's out of
   reach of SystemTypeTopRightMenu's scoped CSS and has to be styled globally. */
.system-type-popover .system-type-list {
    display: flex;
    flex-direction: row;
    align-items: center;
}

.system-type-popover {
    padding: 2px;
    margin-right: 4px;
    border: 1px solid #A9A9A9;
    border-radius: 6px;
}

.system-type-popover .mud-icon-button {
    border: none !important;
    padding: 6px 8px;
    border-radius: var(--mud-default-borderradius);
}

.system-type-popover .mud-icon-button .mud-icon-root {
    font-size: 1.516rem;
}

.system-type-popover .mud-icon-button.mud-ripple-icon:after {
    transform: scale(10, 10);
}

.system-type-popover .mud-icon-button.mud-ripple-icon:active:after {
    transform: scale(0, 0);
    opacity: .1;
    transition: 0s;
}

/* Tooltips render into the popover provider at the document root, out of reach of any wrapper's
   user-select rule, so a double-click on the trigger selects (and highlights) the tooltip text. */
.mud-tooltip {
    user-select: none;
}

/* Here rather than in DimensionComponent.razor.css: isolated CSS stamps its scope attribute on every
   node the component renders - 16 per dimension - to reach one input. */
.dimension-edit-input {
    text-align: center;
    color: #000;
    font-weight: 400;
    font-family: Arial, sans-serif;
    -webkit-text-fill-color: #000;
}


/* Red reason label pinned to the cursor while a placement is invalid - see
   elevation2d.placementReason.js. Fixed/viewport-positioned so the design zone's zoom and Y-flip
   don't touch it. */
#placementReasonLabel {
    position: fixed;
    z-index: 2000;
    display: none;
    pointer-events: none;
    user-select: none;
    max-width: 22rem;
    color: #C62828;
    font-family: var(--mud-typography-default-family, inherit);
    font-size: 0.75rem;
    font-weight: 400;
    line-height: 1.25;
    white-space: nowrap;
    /* Same white halo as on-drawing SVG text (TextHalo.cs), done with text-shadow because HTML text has
       no paint-order guarantee - a -webkit-text-stroke would paint over the glyphs, not behind them. */
    text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff, 0 0 2px #fff;
}

#placementReasonLabel.visible {
    display: block;
}

/* Popovers render outside .generic-properties, so the editable-select options are sized here to match
   the body2 property rows and MudSelect items. */
.editable-select-popover .mud-button-root {
    font-size: var(--mud-typography-body2-size);
    min-height: 0;
    padding: 4px 12px;
}
