﻿/* Restore the global border-box model MudBlazor's stylesheet used to provide. Without it, padding and borders add to an element's width/height, which pushes content past its container and produces the overflows and stray horizontal/vertical scrollbars seen across the app after the migration. */
*, *::before, *::after {
    box-sizing: border-box;
}

/* Links inherit the surrounding text colour and carry no underline (restores the reset MudBlazor's stylesheet used to provide; without it browsers fall back to default blue underlined links — e.g. the footer company number). */
a {
    color: inherit;
    text-decoration: none;
}

:root {
    --emsurge-dark-background: rgb(17, 23, 32); /* Make sure this matches the value in the EmsurgeTheme. TODO: We need to find a way to avoid this duplication. */
    --large-font-size: 1.6rem;
    --emsurge-dim-font-color: #d6d7d2;
    --emsurge-golden-bright-color: #9A6D1C;
    --emsurge-url-color: #5b9eeb;
    --emsurge-container-border-dim-color: #2f3746;
    --emsurge-container-border-bright-color: #C7C8C9;
    --emsurge-border-radius: 10px;
    --emsurge-content-font-size: 1rem;
    --emsurge-global-subtitles-font-size: 1.3rem;
    --emsurge-titles-font-size: 1.3rem;
    --emsurge-large-titles-font-size: 1.3rem;
    --emsurge-content-subtitles-font-size: 1rem;
    --emsurge-highlighted-content-font-size: 1.6rem;
    --emsurge-chip-font-size: 1rem;
    --emsurge-figure-description-font-size: 0.8em;
    --emsurge-unit-of-measure-font-size: 0.8em;
    --emsurge-step-navigation-section-title-font-size: 1.3rem;
    --emsurge-step-navigation-subsection-title-font-size: 1.1rem;
    --emsurge-standard-padding: 1rem;
    --emsurge-large-padding: 2rem;
    --emsurge-reduced-padding: 0.3rem;
    --emsurge-minimum-padding: 0.1rem;
    --emsurge-reduced-margin: 0.3rem;
    --emsurge-card-background-color-darker: #182431;
    --emsurge-card-background-color-lighter: #1e2d3a;
    --emsurge-dashboard-section-subheader-background-color: #182431;
    --emsurge-dialog-height: calc(97vh - var(--emsurge-appbar-height));
    --emsurge-dialog-top-margin: calc(var(--emsurge-appbar-height) - var(--emsurge-appbar-height)/4);
    --emsurge-dialog-left-margin: calc(var(--tcc-drawer-mini-width) + var(--emsurge-standard-padding));
    --emsurge-dialog-right-margin: var(--emsurge-standard-padding);
    --emsurge-company-code-color: #6bc4d7;
    --emsurge-main-content-height: calc(100vh - 1lh);
    /* Scrollbar rail is the reserved-and-draggable width (the whole thumb box grabs, even where it paints
       transparent); the thumb sizes are the VISIBLE gold pill at rest and while hovered/dragged (#4378). */
    --scrollbar-rail-size: 12px;
    --scrollbar-thumb-size: 2px;
    --scrollbar-thumb-size-hover: 4px;
    --emsurge-errorboundary-top-background-color: rgba(17, 23, 32, 0.2);
    --emsurge-errorboundary-bottom-background-color: rgba(30, 45, 58, 0.4);
    --emsurge-button-primary-throbber-highlight-color: #ab936a;
    --emsurge-button-secondary-throbber-highlight-color: #4a4a4a;
    /* Theme vars formerly generated at runtime by MudThemeProvider (#3910 Phase F). Values captured from the dark EmsurgeTheme / MudBlazor 8.11 defaults. */
    --emsurge-palette-primary: var(--emsurge-golden-bright-color);
    --emsurge-palette-secondary: #111720;
    --emsurge-palette-background: var(--emsurge-dark-background);
    --emsurge-palette-surface: #373740;
    --emsurge-palette-success: #0bba83;
    --emsurge-palette-info: #3299ff;
    --emsurge-palette-warning: #ffa800;
    --emsurge-palette-error: #f64e62;
    --emsurge-palette-error-text: #fff;
    --emsurge-palette-divider: rgba(255, 255, 255, 0.12);
    --emsurge-palette-lines-default: rgba(255, 255, 255, 0.12);
    --emsurge-palette-table-lines: rgba(255, 255, 255, 0.12);
    --emsurge-palette-table-striped: #141a23;
    --emsurge-appbar-text: rgba(255, 255, 255, 0.70);
    --emsurge-appbar-background: #182431;
    --emsurge-appbar-height: 64px;
    --emsurge-drawer-width: 240px;
    --emsurge-default-border-radius: 4px;
    --emsurge-elevation-1: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12);
    --emsurge-zindex-appbar: 1300;
    --emsurge-zindex-drawer: 1100;
    /* A dialog's close affordance has to clear the overlay a busy dialog draws over its own content, but it must stay
       under a full-screen DataGrid (team.core pins that at 2000): the grid takes over the whole viewport from inside the
       dialog, so a close button above it left a stray ✕ floating over the expanded grid. Modal backdrops sit at 2100. */
    --emsurge-zindex-dialog-close: 1900;
    /**/
    --emsurge-marketplace-red-color: #f84c64;
    --emsurge-marketplace-background-color: #E8E1DC;
    --emsurge-marketplace-background-color-strip: #dfd6cf;
    /* Type scale (best-practice, readable absolutes; clear title-to-body hierarchy). larger = section/page titles, large = emphasised data / sub-headers, body = long-form readable content (e.g. project description), medium = labels / meta / buttons. */
    --emsurge-marketplace-larger-font-size: 1.9rem;
    --emsurge-marketplace-large-font-size: 1.35rem;
    --emsurge-marketplace-body-font-size: 1.25rem;
    --emsurge-marketplace-medium-font-size: 1.05rem;
    /* Card grid tuning, overridden per breakpoint below. */
    --emsurge-marketplace-card-min: 16rem;
    --emsurge-marketplace-card-height: 19.5rem;
    --emsurge-marketplace-card-gap: 1.25rem;
    /* #4296: side gutters are a bounded vw band (see #marketplace-main-container) so cards fill the width and auto-fill adds columns, instead of the old content-max centering that stranded content in a narrow strip on wide monitors. */
    --emsurge-marketplace-gutter-max: 5rem;
    --emsurge-marketplace-content-max: 96rem;
    --emsurge-marketplace-details-max: 82rem;
}

/* Larger monitors (≈ the user's 1920+ desktop): bigger type, wider cards, wider content so the page fills the screen instead of looking small. */
@media (min-width: 1600px) {
    :root {
        --emsurge-marketplace-larger-font-size: 2.2rem;
        --emsurge-marketplace-large-font-size: 1.55rem;
        --emsurge-marketplace-body-font-size: 1.4rem;
        --emsurge-marketplace-medium-font-size: 1.2rem;
        --emsurge-marketplace-card-min: 18rem;
        --emsurge-marketplace-card-height: 21rem;
        --emsurge-marketplace-card-gap: 1.5rem;
        --emsurge-marketplace-gutter-max: 7rem;
        --emsurge-marketplace-content-max: 108rem;
        --emsurge-marketplace-details-max: 92rem;
    }
}

/* #4296: ultra-wide (27" 4K etc.). Keep the relaxed feel by growing the cards rather than the column count, so a 4K screen shows ~8-10 comfortable cards instead of a dozen small ones. */
@media (min-width: 2560px) {
    :root {
        --emsurge-marketplace-card-min: 24rem;
        --emsurge-marketplace-card-height: 23rem;
        --emsurge-marketplace-card-gap: 1.75rem;
        --emsurge-marketplace-gutter-max: 9rem;
    }
}

/*
    Styles for html, body, #app and a few others used in the splash page are embedded in index.html.
    This is so that if for whatever reason we cannot load the CSS, the resulting index.html page at least looks presentable.
    Any changes to html and body styles here in the CSS WILL BE OVERRIDDEN by index.html
*/

/*html, body {
}
*/

#prices-report .flex-grow-1 {
    display: none;
}

#allocation-table td, #allocation-table th {
    font-size: 1.3rem;
}

.full-screen-app-container {
}

header.full-screen-sticky-header {
    box-sizing: border-box;
    width: 100%;
    min-width: 100%;
    position: sticky; /* We want to use sticky here instead of fixed so that the rest of the content flows under the header. Otherwise, the go under the header and the scroll bar does too. */
    top: 0;
    grid-column-start: 1;
    grid-row-start: 1;
}

main.full-screen-app-main-content-container {
    height: 100%;
    width: 100%;
    grid-column-start: 1;
    grid-row-start: 2;
}

/* Dialogs */
dialog::backdrop {
    /*background: repeating-linear-gradient( 45deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2) 1px, rgba(0, 0, 0, 0.3) 1px, rgba(0, 0, 0, 0.3) 20px );*/
    background-color: white;
    backdrop-filter: blur(3px);
}

dialog[open].dialog-full-screen {
    display: flex;
    width: 85vw;
    height: 85vh;
    margin: auto;
    display: flex;
    justify-content: center;
    align-items: center;
    border: none;
    padding: 0;
}

.full-screen-centered-container {
    display: flex;
    height: 100%;
    width: 100%;
    justify-content: center;
    align-items: center;
}

/* CORSIA market interest */

.new-corsia-price > div {
    animation: newCorsiaPriceAnimation 2s ease-in-out 2;
}

@keyframes newCorsiaPriceAnimation {
    0% {
        transform: scale(1);
        color: inherit;
    }

    25% {
        transform: scale(1.1);
        color: var(--emsurge-palette-info);
    }

    50% {
        transform: scale(1);
        color: inherit;
    }

    75% {
        transform: scale(1.1);
        color: var(--emsurge-palette-info);
    }

    100% {
        transform: scale(1);
        color: inherit;
    }
}

#corsia-table td, th {
    padding: 0 1rem;
}

/* Marketplace */
.solid-js-modal {
    border: none;
    outline: none;
    margin: 20rem auto;
    border-radius: var(--emsurge-border-radius);
    background-color: var(--emsurge-marketplace-primary-color);
    padding: 2rem;
    overflow: hidden;
    color: #fff;
}

    .solid-js-modal::backdrop {
        background-color: hsla(0, 0%, 0%, 0.5);
    }

.marketplace-action-button {
    transition: filter 0.3s ease;
    border: 1px solid var(--emsurge-marketplace-highlight-color);
    background-color: var(--emsurge-marketplace-highlight-color);
    color: #fff;
    cursor: pointer;
}

    .marketplace-action-button:hover {
        filter: brightness(0.9);
    }

    .marketplace-action-button:disabled {
        background-color: #444;
        border-color: #444;
        color: #888 !important;
        cursor: default;
    }

/* The one place a Marketplaces-app spinner is allowed to sit: pinned to the centre of the viewport, so a surface that loads in stages keeps its spinner still instead of moving it from one corner of the top bar to the middle of the grid. pointer-events:none keeps whatever is underneath clickable, and the z-index stays below the sticky header's 9999 so the customer's branding is never covered. */
div.loader-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    pointer-events: none;
    z-index: 1000;
}

/* Pre-Blazor / Marketplaces loading indicator. Deliberately unbranded: neutral warm-ink arcs on the beige marketplace background, no logo and no golden accent, so white-label customers never see Emsurge branding before their own marketplace paints. margin:auto centres it inside the flex #non-blazor-app column (before this the bare dots sat in the top-left corner). */
div.loader {
    --loader-ink: #3d352e;
    width: 68px;
    height: 68px;
    aspect-ratio: 1;
    margin: auto;
    position: relative;
    border-radius: 50%;
    background: radial-gradient(circle, var(--loader-ink) 96%, transparent) center no-repeat;
    background-size: 9px 9px;
    animation: loader-fade-in 0.45s ease-out both, loader-core-pulse 1.5s ease-in-out infinite;
}

    div.loader::before,
    div.loader::after {
        content: "";
        position: absolute;
        border-radius: 50%;
        border: 3px solid transparent;
    }

    /* Outer arc: a track ring with two lit quadrants, spinning with an eased, slightly organic cadence. */
    div.loader::before {
        inset: 0;
        border-color: rgba(61, 53, 46, 0.13);
        border-top-color: var(--loader-ink);
        border-right-color: var(--loader-ink);
        animation: loader-spin 1.15s cubic-bezier(0.66, 0.28, 0.34, 0.74) infinite;
    }

    /* Inner arc: thinner reach, counter-rotating and slightly translucent for depth. */
    div.loader::after {
        inset: 12px;
        border-bottom-color: rgba(61, 53, 46, 0.6);
        border-left-color: rgba(61, 53, 46, 0.6);
        animation: loader-spin-reverse 0.9s linear infinite;
    }

@keyframes loader-spin {
    to {
        transform: rotate(360deg);
    }
}

@keyframes loader-spin-reverse {
    to {
        transform: rotate(-360deg);
    }
}

/* The central dot breathes by growing its own radial-gradient rather than scaling the element (which would drag the arcs with it). */
@keyframes loader-core-pulse {
    0%, 100% {
        background-size: 9px 9px;
        opacity: 0.85;
    }

    50% {
        background-size: 15px 15px;
        opacity: 1;
    }
}

@keyframes loader-fade-in {
    from {
        transform: scale(0.82);
    }

    to {
        transform: scale(1);
    }
}

.marketplace-number-field::-webkit-outer-spin-button,
.marketplace-number-field::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.marketplace-number-field {
    -moz-appearance: textfield;
}

#project-search::placeholder {
    font-style: italic;
}

/* Market Interest toolbar search: fills the available width between the Bid and Ask clusters, with the filled
   field's rounded top corners restored (the global --tcc-field-radius:0 squares every field; the search box keeps
   the classic top-rounded / flat-bottom-underline look). */
.market-interest-search {
    flex: 1 1 auto;
    min-width: 0;
    --tcc-field-radius: var(--emsurge-border-radius);
}

#basket-list .selected {
    list-style-type: none;
    font-weight: 600;
}

#basket-list li {
    cursor: pointer;
}

.ordertype-filter-button {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 2.4rem;
    height: 2.4rem;
    font-size: 0.85rem;
    border-radius: 50%;
    border: 1px solid #000;
    color: #000;
    cursor: pointer;
    user-select: none;
}

@media (min-width: 1600px) {
    .ordertype-filter-button {
        width: 2.7rem;
        height: 2.7rem;
        font-size: 0.95rem;
    }
}

/* Responsive product-card grid. Cards stay a comfortable width (≈5 per row on a 13in Mac, wider on large monitors) and pack from the left. */
.marketplace-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--emsurge-marketplace-card-min), 1fr));
    gap: var(--emsurge-marketplace-card-gap);
    justify-content: start;
}

/* #4296: phones — stack the filter sidebar above the cards so the card grid uses the full width, instead of the fixed 14rem sidebar leaving a cramped narrow card column. */
@media (max-width: 768px) {
    #marketplace-main-container { grid-template-columns: 1fr !important; gap: 1.25rem !important; }
}

.marketplace-card {
    height: var(--emsurge-marketplace-card-height);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

    .marketplace-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.28);
    }

    .ordertype-filter-button.selected {
        border: none;
        background-color: var(--emsurge-marketplace-blue-color);
        font-weight: 800;
        color: #fff;
    }

.checked-item {
    appearance: none;
    -webkit-appearance: none;
    width: 15px;
    height: 15px;
    border: 1px solid #000;
    border-radius: 5px;
    display: inline-block;
    position: relative;
    pointer-events: none;
}

    .checked-item::after {
        content: "✔";
        position: absolute;
        top: -8px;
        left: 1px;
        font-size: 18px;
        color: #000;
        font-weight: 800;
    }

.project-highlights-table th {
    width: 33%;
    font-weight: 100;
    text-align: left;
    padding: 0.5rem 0;
    background: var(--emsurge-marketplace-background-color);
}

.project-highlights-table td {
    padding: 0.5rem 0;
}

.project-highlights-table tr:nth-child(odd) {
    background-color: #fff;
}

.project-highlights-table tr:last-child {
    border-bottom: 1px solid #000;
}

.media-item {
    display: block;
    max-width: 100%;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 2px solid var(--emsurge-golden-bright-color);
    border-radius: 0.5rem;
    cursor: pointer;
}

/* Blazor loading progress */
div#loading-linear-progress {
    background: var(--emsurge-card-background-color-darker);
    width: 50vw;
    height: 1.5rem;
    border-radius: 10rem;
    overflow: hidden;
    position: relative;
}

    div#loading-linear-progress:after {
        content: '';
        position: absolute;
        inset: 0;
        background: var(--emsurge-golden-bright-color);
        scale: var(--blazor-load-percentage, 0%) 100%;
        transform-origin: left top;
        transition: scale ease-out 0.5s;
    }

@counter-style dotless-item {
    system: numeric;
    symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
    suffix: " ";
}

/* The plain HTML button shown in the loading splash before Blazor has booted. */
.html-button {
    background-color: rgb(154, 109, 28);
    color: white;
    padding: 6px 16px;
    box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.75;
    letter-spacing: .02857em;
    text-transform: uppercase;
    min-width: 64px;
    box-sizing: border-box;
    transition: background-color 250ms cubic-bezier(.4,0,.2,1) 0ms,box-shadow 250ms cubic-bezier(.4,0,.2,1) 0ms,border 250ms cubic-bezier(.4,0,.2,1) 0ms;
    border-radius: 4px;
    cursor: pointer;
    margin: 0;
    display: inline-flex;
    border: 0;
    outline: 0;
    align-items: center;
    user-select: none;
    vertical-align: middle;
    justify-content: center;
    text-decoration: none;
}

/******* Our own *********/
.venue-enabled-card:hover {
    border-color: var(--emsurge-golden-bright-color) !important;
}

/* #4570 — LNG deal room. The shell pins the summary column at 25rem and both the shell and the main area are fixed-height grids, so anything narrower than a laptop scrolls sideways. Below 1100px the three columns become one stack that scrolls vertically. */
@media (max-width: 1100px) {
    .lng-deal-room {
        display: flex !important;
        flex-direction: column;
        overflow-x: hidden;
        overflow-y: auto;
    }

    /* Every band takes its natural height and the shell does the scrolling, instead of each one claiming 100% of a fixed-height parent. */
    .lng-deal-room > div {
        flex: 0 0 auto;
        /* auto, not 100%: .strict-container pins width to 100%, which overflows for the bands that also carry a 1rem side margin. */
        width: auto !important;
        min-width: 0 !important;
        max-width: none !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        overflow: visible !important;
    }

    .lng-deal-room > [aria-label="left-right-separator"],
    .lng-deal-room > [aria-label="top-bottom-separator"] {
        display: none;
    }

    /* Title and action icons stack and wrap rather than fight over a 2fr/1fr split that no longer fits. */
    .lng-deal-room .lng-deal-room-topbar {
        grid-template-columns: 1fr !important;
    }

    .lng-deal-room .lng-deal-room-title {
        font-size: var(--emsurge-highlighted-content-font-size) !important;
        flex-wrap: wrap !important;
        white-space: normal;
    }

    .lng-deal-room .lng-deal-room-actions {
        flex-wrap: wrap !important;
        justify-content: flex-start !important;
    }

    .lng-deal-room .lng-deal-room-topbar > div:nth-child(2) {
        grid-row: auto !important;
        grid-column: 1 !important;
    }

    .lng-deal-room .lng-deal-room-main {
        grid-template-columns: 1fr !important;
    }

    .lng-deal-room .lng-deal-room-main > div {
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
        overflow: visible !important;
    }
}

/* #4572 — the Broker Confirm tab stands in for Emstream's paper confirmation, so it is deliberately rendered as the document rather than in the app's dark theme: light page, serif type, justified prose, auto-filled values picked out in the document's own brown. */
.lng-trade-confirmation {
    background: #fff;
    color: #1a1a1a;
    border-radius: var(--emsurge-default-border-radius);
    padding: 1.75rem 2.1rem;
    font-family: 'Times New Roman', Georgia, serif;
    max-width: 48rem;
    white-space: normal;
}

.lng-trade-confirmation h2 {
    text-align: center;
    font-size: 1rem;
    font-weight: 700;
    text-decoration: underline;
    letter-spacing: 0.03em;
    margin-bottom: 1rem;
}

.lng-trade-confirmation .header {
    text-align: center;
    font-size: 0.85rem;
    line-height: 1.9;
    margin-bottom: 0.6rem;
}

.lng-trade-confirmation hr {
    border: 0;
    border-top: 1.5px solid #111;
    margin: 0.5rem 0 1rem;
}

.lng-trade-confirmation p {
    font-size: 0.8rem;
    line-height: 1.55;
    margin-bottom: 0.75rem;
    text-align: justify;
}

.lng-trade-confirmation .label {
    font-weight: 700;
}

.lng-trade-confirmation .value {
    color: #7a5516;
    font-weight: 600;
}

.lng-trade-confirmation .field {
    font-size: 0.8rem;
    margin-bottom: 0.6rem;
}

.lng-trade-confirmation .party {
    font-size: 0.8rem;
    margin-bottom: 0.7rem;
}

.lng-trade-confirmation .party .row {
    display: flex;
    flex-wrap: wrap;
    gap: 1.4rem;
    margin-top: 0.15rem;
}

.lng-upserted-content {
    color: var(--emsurge-golden-bright-color);
}

.lng-standard-content {
    color: #777;
}

/* The identity half of an item's header: Order / Transaction ID beside the market side and the shape of the item.
   It lives in a column the shell pins to 25rem, and `div.strict-container` sets white-space:nowrap, so a row that does not fit has to fold - a `1fr 1fr` grid instead laid out
   at its content's min-content width and painted the surplus over the main header beside it (the longest LNG shapes, "Single Cargo Standard" and "Strip Bespoke", always overflowed).
   Wrapping keeps every label whole, which truncating with an ellipsis would not. */
.item-view-header-identity {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    column-gap: var(--emsurge-standard-padding);
    row-gap: var(--emsurge-reduced-padding);
    min-width: 0;
}

/* The LNG order headline: identity, price and cargo terms on three stacked lines, the way the old EOM platform's header read.
   Every line shares one left indent and one padding value with the recap columns underneath, so the whole card reads off a single left edge. */
.lng-order-headline {
    display: flex;
    flex-direction: column;
    gap: var(--emsurge-reduced-padding);
    padding: 0 var(--emsurge-standard-padding);
    min-width: 0;
}

.lng-order-headline__identity,
.lng-order-headline__terms {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--emsurge-standard-padding);
    min-width: 0;
}

.lng-order-headline__identity {
    font-size: var(--emsurge-highlighted-content-font-size);
}

/* The side is a word on this line, not a pill: the one Bid/Offer pill sits in the top bar. */
.lng-order-headline__side {
    text-transform: uppercase;
}

/* Delivery mode and contract are one term ("DES mJKTC"), so they sit closer to each other than to the neighbouring terms - a single typed space between them read as one word. */
.lng-order-headline__contract {
    display: inline-flex;
    align-items: baseline;
    gap: var(--emsurge-reduced-padding);
}

/* Cargo size and its operational tolerance are one figure read together ("3.4-3.6 +/- 5%"), so they pair up the way the delivery mode and the contract do rather than sitting a full term apart. */
.lng-order-headline__size {
    display: inline-flex;
    align-items: baseline;
    gap: var(--emsurge-reduced-padding);
}

/* The price is the figure a trader scans for, so it stays the largest thing in the card. Its unit renders through the shared <small> unit fragments. */
.lng-order-headline__price {
    font-size: 2.2rem;
    line-height: 1.2;
    white-space: nowrap;
}

/* The index explanation is the one piece of prose in the card, and prose has to wrap: `div.strict-container` sets white-space:nowrap, so any header or panel carrying that class turned a 300-character definition into a single line that ran off the card and was clipped without an ellipsis.
   overflow-wrap covers the other end of it - an index code long enough to have no break opportunity would otherwise widen the whole card rather than fold. */
.lng-order-headline__note {
    font-size: var(--emsurge-content-font-size);
    color: var(--emsurge-dim-font-color);
    white-space: normal;
    overflow-wrap: anywhere;
}

.lng-order-headline__terms {
    font-size: var(--emsurge-titles-font-size);
}

/* The grid itself, rather than an inline `style` repeated verbatim on all twelve order-detail views: the separator rules below have to own the gaps between the cells, so the gaps cannot live in twelve places the stylesheet cannot see.
   A `grid-gap` is dead space no child can paint into, so a rule drawn under each cell would break in half at the column boundary; the row and column rhythm is therefore padding on the cells themselves, which the rule then runs through. */
.lng-recap-terms {
    display: grid;
    /* minmax(0, ...) on both tracks: `auto` and `1fr` both floor at their content's min-content width, so a single long
       value - a nomination row, a list of terminals - widened the ledger past the recap panel and the panel scrolled
       sideways rather than the value folding. With the floor at 0 the ledger is never wider than the card that holds it. */
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    padding: 0 var(--emsurge-standard-padding);
}

/* Half the standard padding above and below each cell, so two stacked rows still sit the standard padding apart. */
.lng-recap-terms > * {
    padding-block: calc(var(--emsurge-standard-padding) / 2);
    border-bottom: 1px solid var(--emsurge-palette-lines-default);
}

.lng-recap-terms > *:nth-child(odd) {
    padding-right: var(--emsurge-standard-padding);
}

/* The card's own edge closes the last row, so a rule under it would read as an empty row below the recap. */
.lng-recap-terms > *:nth-last-child(-n+2) {
    border-bottom: none;
}

/* The term-by-term recap reads as a ledger: the `auto 1fr` grid puts every field name in column 1 and every value in column 2, so odd children are names and even children are values.
   Names sit a shade dimmer than the values they introduce, and values run flush to the card's right edge so a trader scans one column of figures instead of a ragged one.
   A name carrying `lng-standard-content` is a sub-row - a country inside LOAD PORT - and keeps its own dimmer tone, otherwise the heading above it and the countries under it come out identical and the block loses its hierarchy. */
.lng-recap-terms > *:nth-child(odd):not(.lng-standard-content) {
    color: var(--emsurge-dim-font-color);
    justify-content: flex-start;
}

.lng-recap-terms > *:nth-child(even) {
    justify-content: flex-end;
    text-align: right;
}

/* A country sub-row inside DISCHARGE PORT / LOAD PORT is the one label that names a value rather than a section, so it reads with the terminals it introduces rather than with the headings above it. */
.lng-recap-terms > .lng-standard-content {
    justify-content: flex-end;
    text-align: right;
}

/* One row per nomination: the terms share a left edge in the first column and the computed dates get a column of their own, and the pair of them is pushed right to sit with the other values. */
.lng-recap-terms > .lng-recap-nominations {
    display: grid;
    /* The terms track may shrink below its max-content width (the row then folds - see the rule below); the date track
       may not, because a date broken across two lines stops reading as a date. */
    grid-template-columns: minmax(0, max-content) max-content;
    column-gap: var(--emsurge-standard-padding);
    row-gap: var(--emsurge-reduced-padding);
    justify-content: end;
    text-align: left;
}

/* Right-aligned inside its column, not left: the nominations differ in length ("Buyer Nominates Delivery Terminal within country" against "Seller Nominates Final Vessel"), so a left edge shared with the column left a ragged gap in front of the dates and read as misalignment. Ending them all flush against the date column puts the two columns back on one edge. */
.lng-recap-nominations__terms {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.2rem;
    /* nowrap on each part, wrap on the row: the longest nomination ("Buyer Nominates Delivery Terminal within country
       - 15 days prior - 1 Day DW") cannot fit a laptop's recap column on one line, and an unbreakable row is what made
       the recap scroll sideways. It folds between its own words instead, and nothing inside a word ever breaks. */
    flex-wrap: wrap;
}

.lng-recap-nominations__terms > * {
    white-space: nowrap;
}

/* Right-aligned, not left: the dates are not all the same width ("SUN 02/Aug/2026" runs wider than "SAT 18/Jul/2026" in the proportional UI font), so a shared left edge left their right edges ragged and read as misalignment against the values above them. #5315 */
.lng-recap-nominations__date {
    white-space: nowrap;
    text-align: right;
}

/* The Strip recap's nominations are whole sentences with no computed date, so they are one column rather than two - same rule: right as a block, left inside it. */
.lng-recap-terms > .lng-recap-nominations-list {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
    /* Sized to its longest sentence, but never past the cell it sits in - beyond that the sentences wrap. */
    width: max-content;
    max-width: 100%;
    margin-left: auto;
    text-align: left;
}

/* LNG order entry: day-count fields never hold more than 3 digits and DW selects a short "N Day DW", but the tcc field chrome defaults to min-width 12rem (plus a 46px right gutter for affordances the numeric input does not use), which overflows their narrow grid columns and covers the neighbouring labels. */
.lng-days-field.tcc-field {
    min-width: 0;
    width: 4.5rem;
}

.lng-days-field .tcc-field__input {
    padding-right: 12px;
    text-align: center;
}

.lng-dw-select.tcc-field {
    min-width: 0;
    width: 9rem;
}

/* ONE width for every measure input in the LNG order flow - cargo sizes, cargo counts, vessel sizes, qualities - whichever contract type and whichever step it appears on. LNG vessel sizes are 6-digit cubic-metre figures, so a field wide enough for ~12 digits shows the whole value at a glance; the tcc default (min-width 12rem, stretched by the row's flex) made two of them span the step panel, and sizing each pair to its own step left the same Min/Max control a different width on every step. #5315 */
.lng-measure-field.tcc-field {
    min-width: 0;
    width: 9rem;
    flex: none;
}

.lng-measure-field .tcc-field__input {
    padding-right: 12px;
}

/* A vessel name and a 7-digit IMO number both sit comfortably in half the width the tcc chrome would stretch a flex row to, and the two read as a pair when they match. */
.lng-vessel-field.tcc-field {
    min-width: 0;
    width: 16rem;
    flex: none;
}

/* The strip cargo month offset (M + N) never holds more than 2 digits, but its label is a whole sentence: sizing the field to its content keeps the label on one line while the input itself stays as narrow as the value it takes. */
.lng-month-offset-field.tcc-field {
    min-width: 0;
    width: max-content;
}

.lng-month-offset-field .tcc-field__control {
    width: 4.5rem;
}

.lng-month-offset-field .tcc-field__input {
    padding-right: 12px;
    text-align: center;
}

/* The nomination timeframe asks for one value at a time, under whichever option was picked, and each is short: a day count, a day of the month, a date. At the tcc default they stretched to the width of the step, so a two-digit answer sat in a field wide enough for a sentence. Sized to content like the month offset, so the label keeps its one line while only the control narrows to what it holds. */
.lng-nomination-timeframe-field.tcc-field {
    min-width: 0;
    width: max-content;
}

.lng-nomination-timeframe-field .tcc-field__control {
    width: 6rem;
}

.lng-nomination-timeframe-field .tcc-field__input {
    padding-right: 12px;
    text-align: center;
}

/* A date carries the whole user-friendly format and the picker's own affordance, so it gets the room for both and keeps the input's default alignment and right gutter. */
.lng-nomination-timeframe-date-field.tcc-field {
    min-width: 0;
    width: max-content;
}

.lng-nomination-timeframe-date-field .tcc-field__control {
    width: 12rem;
}

div.premium {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' opacity='0.6' fill='%239A6D1C' viewBox='0 0 300 300'%3E%3Cpath d='M149.9,0C67.3,0,.33,66.96,.33,149.57s66.96,149.57,149.57,149.57,149.57-66.96,149.57-149.57S232.51,0,149.9,0Zm85.07,179.36c-.11,6.89-.26,13.77-.64,20.68-.19,3.36-2.81,6.07-6.16,6.39-.21,.02-.42,.03-.64,.03-3.09,0-5.84-2.11-6.6-5.16-1.66-6.73-3.1-13.46-4.48-20.21-.91-4.34-1.72-8.7-2.54-13.08l-1.32-7.01c-.22-1.25-.44-2.5-.65-3.73-1.35,2.05-2.7,4.1-4.06,6.14l-24.69,36.06c-5.03,7.24-15.03,9.05-22.28,4.04-.83-.58-1.6-1.25-2.25-1.9-6.52-6.61-12.96-13.22-19.33-19.92l-18.96-20.15c-6.29-6.81-12.49-13.67-18.66-20.56-3.44-3.85-6.83-7.75-10.21-11.66l-18.55,16.99c-3.27,2.89-6.52,5.72-9.84,8.49-2.58,2.17-6.36,2.1-8.88-.15-2.51-2.24-3.01-5.98-1.16-8.8,2.37-3.62,4.8-7.17,7.28-10.7l15-20.69c1.97-2.72,4.05-5.41,6.13-8.11l1.61-2.08c3.9-5.08,11.22-6.06,16.32-2.15l1.14,.96c7.01,6.08,13.97,12.19,20.83,18.42,6.84,6.25,13.64,12.51,20.37,18.86l19.98,19.15c2.06,2,4.1,4.02,6.14,6.04l14.41-19.97c8.69-11.79,17.43-23.48,26.41-34.98,5.18-6.64,13.92-7.72,19.94-3.03,3.23,2.52,5.17,6.31,5.33,10.4l.13,3.47c.23,5.66,.45,11.3,.55,16.98l.14,6.97c.1,4.46,.19,8.93,.25,13.4v7.34c.02,4.41,.03,8.82-.05,13.23Z'%3E%3C/path%3E%3C/svg%3E%0A");
    background-position-x: 3px;
    background-position-y: 5px;
    background-repeat: no-repeat;
    background-size: 1rem;
}

div.vcentered {
    display: flex;
    align-items: center;
}


/* See https://stackoverflow.com/a/33061059/257372 for details */
.clickable {
    cursor: pointer;
}

.strict-data-container {
    /* These conditions are required for text-overflow to work */
    white-space: nowrap;
    overflow: hidden;
    /* ********* */

    text-overflow: ellipsis;
    /* These make it easier to align elements vertically by making sure all data-containers have a 100% height and width */
    width: 100%;
    max-width: 100%;
    min-width: 0;
}

.flex-nowrap {
    flex-wrap: nowrap;
}

/* Use this class to make sure a div takes exactly the space it has been assigned by its parent, and vertically centers all content */
div.strict-container {
    width: 100%;
    min-width: 100%;
    max-width: 100%;
    height: 100%;
    max-height: 100%;
    min-height: 100%;
    align-content: center;
    align-items: center;
    white-space: nowrap;
}

div.full-screen-container {
    max-width: 100%;
    min-width: 100%;
    width: 100%;
    min-height: 100%;
    max-height: 100%;
    height: 100%;
}

div.top-aligned {
    align-content: start;
    align-items: start;
}

/* Use this class to allow a div to expand its **height** (not its width) according to its content, making sure it takes 100% of the available width */
div.fluid-container {
    width: 100%;
    min-width: 100%;
    max-width: 100%;
    min-height: 100%;
    max-height: 100%;
    display: grid;
    /* The implicit column is `auto`, whose floor is the content's min-content width — so a panel whose widest row does not fit lays out a column wider than the container and the surplus disappears underneath the vertical scrollbar (the details panels are the clearest case: the panel chevrons and the per-field edit icons sat behind the golden bar). minmax(0, 1fr) lets the column shrink to the container's content box, which is what "takes 100% of the available width" was always meant to say. */
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
    align-content: start;
    white-space: normal;
}

div.scrollable {
    overflow: auto;
}

/* The dashboard orders panels, the item-details/country summary side panels and the wizard's Order Recap only ever
   scroll vertically — a few pixels of card overflow must clip, not grow a horizontal scrollbar. The recap is the one
   that had to be argued for: a sideways scrollbar there puts the labels and their values on opposite ends of the
   scroll, so the user never sees a term and its value together. Its content is shrinkable now, so this is the
   last-resort guard rather than the mechanism. */
div.scrollable[aria-label="orders-container"],
div.scrollable[aria-label="summary-container"],
div.scrollable[aria-label="recap-content-container"] {
    overflow-x: hidden;
}

/* The order / project creation wizard, hung off `ItemViewLayout`'s `Class` the same way `.lng-deal-room` is.
   Every wizard for every product renders through `ItemMultipleStepView`, so the rules here are the whole of the
   wizard's responsive behaviour: a product or an order shape added later inherits them without layout work of its own.

   The shell used to reserve a flat 25rem for the step list whatever the screen, and split what was left 1fr/1fr
   between the step form and the Order Recap. On a 1920x1080 laptop that left the recap about 691px — less than its
   own content needs — so it grew a horizontal scrollbar and a trader had to scroll sideways to read back what they
   had just typed, with the labels scrolling out of view as they went. */
.multiple-step-shell {
    /* The step list sizes to its own longest label between these bounds instead of reserving a fixed 25rem. At 25rem
       the column was over-wide for the screen and, because the list carried its own 14em floor and 3rem/1rem margins,
       still tight for "Shipping & Nominations". Both numbers had to move together; the ceiling keeps a wide monitor
       from handing the column width it has no use for. */
    --emsurge-item-view-summary-min-width: min-content;
    --emsurge-item-view-summary-max-width: 25rem;
}

/* nowrap is what makes the shell's `auto` first track resolve to the longest step label on one line: without it the
   labels fold and the column collapses to the width of a single word. The list sits on the standard padding at both
   edges — inside a column that is now sized by its content, a 3rem indent is width spent on nothing. */
.multiple-step-shell__steps {
    margin: 0 var(--emsurge-standard-padding);
    white-space: nowrap;
}

/* The recap heading and the SAVE / POST ORDER button share one row that `div.strict-container` holds at nowrap. Left
   to itself the heading's min-content width pushed the button off the right edge of the panel; the heading gives way
   first because "Order Recap" is the half of the row the user can afford to lose characters from. */
.multiple-step-shell [aria-label="recap-header-container"] {
    gap: var(--emsurge-standard-padding);
    min-width: 0;
}

.multiple-step-shell [aria-label="recap-header-container"] > div:first-child {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Below this width the step form and the recap cannot both be read side by side — at 1366px they would get about
   460px each — so the recap moves underneath the form and the main area scrolls vertically. The step list stays in
   its own column: it is content-sized now, and it is how the user moves through the wizard. Stacking is the fallback
   at the narrow end only; from 1440px up the three columns stay side by side and simply size sensibly. */
@media (max-width: 1400px) {
    .multiple-step-shell__main {
        display: flex !important;
        flex-direction: column;
        gap: var(--emsurge-standard-padding);
        overflow-x: hidden;
        overflow-y: auto;
    }

    /* Each band takes its natural height and the stack does the scrolling, instead of every band claiming 100% of a
       fixed-height grid area that no longer exists. auto, not 100%: `.strict-container` pins width to 100%. */
    .multiple-step-shell__main > div {
        flex: 0 0 auto;
        width: auto !important;
        min-width: 0 !important;
        max-width: none !important;
        height: auto !important;
        min-height: 0 !important;
        max-height: none !important;
    }

    /* The step form is the panel the user is working in, so it keeps a usable height of its own rather than collapsing
       to whatever the shortest step happens to contain. */
    .multiple-step-shell__main > div[aria-label="active-step-content-and-title-container"] {
        min-height: 60vh !important;
    }
}

/* Use this class to make sure a div vertically aligns all its content, taking 100% of the available **width** (not height) */
div.strict-card-container {
    white-space: nowrap;
    display: flex; /* flex is necessary for the vertical alignment to work as expected, but it can be replaced by grid using the style property of the div element in question */
    align-content: center;
    align-items: center;
    width: 100%;
    min-width: 100%;
    max-width: 100%;
}

@keyframes loading-card-animation {
    to {
        background-position-x: -200%;
    }
}

.loading-card {
    background: linear-gradient(110deg, var(--emsurge-card-background-color-darker) 8%, var(--emsurge-card-background-color-lighter) 18%, var(--emsurge-card-background-color-darker) 33%);
    background-size: 200% 100%;
    animation: 1.5s loading-card-animation linear infinite;
}

/* Common style for a highlighted div */
div.highlighted {
    border: 2px solid red;
    border-radius: var(--emsurge-border-radius);
}

div.bordered {
    border-width: 1px;
    border-style: solid;
}

table.bordered th, table.bordered td {
    border-bottom: solid 1px var(--emsurge-golden-bright-color);
}

table.striped tr:nth-child(odd) {
    background-color: var(--emsurge-card-background-color-lighter);
}

table.comfortable th, table.comfortable td {
    padding: var(--emsurge-standard-padding);
}

/* A list rendered without any symbols in front of the items*/
ol.dotless {
    list-style: dotless-item;
}

div.rounded-corners {
    border-radius: var(--emsurge-border-radius);
}

.dialog-options-selection {
    padding-top: 10vh;
    padding-left: 35%;
    padding-right: 35%;
}

.dialog-options-selection-option {
    margin-bottom: 2.5rem;
    border-color: var(--emsurge-container-border-dim-color) !important;
}

    .dialog-options-selection-option:hover {
        color: var(--emsurge-golden-bright-color) !important;
        border-color: var(--emsurge-golden-bright-color) !important;
        border-width: 2px;
    }

.non-white-text {
    color: var(--non-white-text-color)
}

/* App shell (the old MudLayout / MudAppBar Dense / MudMainContent). The --emsurge-* shell vars are defined in :root above
   (ported from the old MudThemeProvider in #3910 Phase F). */
.app-layout {
    height: 100%;
    width: 100%;
    position: relative;
}

.app-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    box-sizing: border-box;
    height: calc(var(--emsurge-appbar-height) - var(--emsurge-appbar-height)/4); /* the old Dense bar is ¾ of the var */
    color: var(--emsurge-appbar-text);
    background-color: var(--emsurge-appbar-background);
    box-shadow: var(--emsurge-elevation-1);
    z-index: var(--emsurge-zindex-appbar);
}

.app-main-content {
    box-sizing: border-box;
    padding-top: calc(var(--emsurge-appbar-height) - var(--emsurge-appbar-height)/4); /* clears the fixed Dense app bar */
}

/* Pushes following flex siblings to the far end of the row (the old MudSpacer behaviour). */
.flex-spacer {
    flex: 1 1 auto;
}

/* A small "+" pinned to a create button's top-right corner (the old MudBadge Icon=Add, Origin=TopRight, no background). */
.corner-plus-badge {
    position: relative;
    display: inline-flex;
}

.corner-plus-badge__icon {
    position: absolute;
    top: -2px;
    right: -6px;
    width: 1.1rem;
    height: 1.1rem;
    pointer-events: none;
}

/* Scrollbar customization */
/* #4298: every scrollbar inside the EOM app renders golden, not just the div.scrollable content panels and not just on hover. WebKit/Chromium is styled through the ::-webkit-scrollbar-* pseudo-elements; Firefox through scrollbar-color/scrollbar-width, which inherit from #app down to every descendant. The whole block is scoped to #app (the Blazor app) so the white-label Marketplaces UI (#non-blazor-app) keeps its own per-marketplace highlight colours. */
/* Good documentation available at https://blog.esteetey.dev/make-your-website-stand-out-with-a-custom-scrollbar */
/* #4302: Chromium 121+ honours the standard scrollbar-width property, and once it is set Chromium IGNORES the ::-webkit-scrollbar width below and paints its chunky native bar instead — which is why #4298's scrollbars rendered far thicker than the intended thin bar, everywhere, not just on one view. Confine the standard properties to engines that have NO ::-webkit-scrollbar (i.e. Firefox) so Chromium keeps rendering the thin custom bar defined by the pseudo-elements. Firefox only supports thin|none (no pixel width), so its bar stays as thin as the engine allows. */
@supports not selector(::-webkit-scrollbar) {
    #app {
        scrollbar-width: thin;
        scrollbar-color: var(--emsurge-golden-bright-color) transparent;
    }
}

/* #4302/#4378: the rail is a consistent width on both axes (the horizontal used to render 3x thicker and read as chunky). This is the reserved gutter AND the grab target — the whole thumb box is draggable, so a wider rail makes the previously hairline-thin bar easy to grab even though the visible pill stays thin (see the thumb rule below). Transparent track so only the pill shows across the wide rail. */
#app::-webkit-scrollbar,
#app *::-webkit-scrollbar {
    width: var(--scrollbar-rail-size);
    height: var(--scrollbar-rail-size);
    background: transparent;
}

/* #4378: the pill fills only its content box while a transparent border eats the rest of the rail, so at rest it reads as the same thin golden hairline as before yet the full (wide) rail behind it stays grabbable. On hover the border shrinks and the pill swells OVER the content, giving a clear grab affordance without ever reflowing layout (the rail width is constant). This targets ::-webkit-scrollbar-thumb:hover — the thumb pseudo-element itself — so it does NOT suffer #4302's bubbling problem (that only affects :hover on the scroll-box element, which matches whenever the pointer is anywhere inside the box). #4302's fully-rounded pill reads as more deliberate than a hard-edged bar. */
#app::-webkit-scrollbar-thumb,
#app *::-webkit-scrollbar-thumb {
    background-color: var(--emsurge-golden-bright-color);
    background-clip: content-box;
    border: calc((var(--scrollbar-rail-size) - var(--scrollbar-thumb-size)) / 2) solid transparent;
    border-radius: 999px;
}

#app::-webkit-scrollbar-thumb:hover,
#app *::-webkit-scrollbar-thumb:hover {
    border-width: calc((var(--scrollbar-rail-size) - var(--scrollbar-thumb-size-hover)) / 2);
}

/* No increment/decrement buttons: the 2rem golden squares rendered as blocks at the track ends and clashed badly with rounded scroll containers (the corner showed a square golden nub). */
#app::-webkit-scrollbar-button,
#app *::-webkit-scrollbar-button {
    display: none;
}

/* #4378: keep the corner where a vertical and horizontal rail meet transparent — at the old hairline width it was invisible, but the wider grab rail turns an unstyled corner into a conspicuous native-coloured square. */
#app::-webkit-scrollbar-corner,
#app *::-webkit-scrollbar-corner {
    background: transparent;
}

/* <select> customisation: idea taken from https://moderncss.dev/custom-select-styles-with-pure-css/ -- This doesn't work yet!!! */
.user-entity-select {
    appearance: none;
    border: none;
    background: none;
    font-size: 0.7rem;
    color: var(--emsurge-golden-bright-color);
}

/* SVGChart */
g {
    pointer-events: all;
}

    g.SVGChart-price {
        cursor: pointer;
        opacity: 1;
    }

        g.SVGChart-price:hover {
            opacity: 0.8;
        }

/* Footer Ideas from https://www.codeinwp.com/snippets/sticky-footer-with-css/ */
footer {
    position: fixed;
    width: 100%;
    bottom: 0;
    box-sizing: border-box;
    text-align: center;
    font-size: xx-small;
    color: var(--non-white-text-color);
}

@media screen and (max-width: 900px) {
    footer {
        display: none;
    }
}

@keyframes button-throbber-animation {
    to {
        background-position-x: -200%;
    }
}

/******* Our own - animations! *********/
@property --angle {
    syntax: '<angle>';
    initial-value: 90deg;
    inherits: true;
}

@property --gradX {
    syntax: '<percentage>';
    initial-value: 50%;
    inherits: true;
}

@property --gradY {
    syntax: '<percentage>';
    initial-value: 0%;
    inherits: true;
}

:root {
    --d: 2500ms;
    --angle: 90deg;
    --gradX: 100%;
    --gradY: 50%;
    --c1: var(--emsurge-golden-bright-color);
    --c2: rgba(168, 239, 255, 0.1);
}

.animated-border {
    border: 2px solid;
    border-radius: var(--emsurge-default-border-radius);
    border-image: conic-gradient(from var(--angle), var(--c2), var(--c1) 0.1turn, var(--c1) 0.15turn, var(--c2) 0.25turn) 30;
    animation: borderRotate var(--d) linear infinite forwards;
}

    .animated-border:nth-child(2) {
        border-image: radial-gradient(ellipse at var(--gradX) var(--gradY), var(--c1), var(--c1) 10%, var(--c2) 40%) 30;
        animation: borderRadial var(--d) linear infinite forwards;
    }

@keyframes borderRotate {
    100% {
        --angle: 420deg;
    }
}

@keyframes borderRadial {
    20% {
        --gradX: 100%;
        --gradY: 50%;
    }

    40% {
        --gradX: 100%;
        --gradY: 100%;
    }

    60% {
        --gradX: 50%;
        --gradY: 100%;
    }

    80% {
        --gradX: 0%;
        --gradY: 50%;
    }

    100% {
        --gradX: 50%;
        --gradY: 0%;
    }
}

/********** Our own - Blazor framework ***********/

#blazor-error-ui {
    color: black;
}

    #blazor-error-ui a {
        color: black;
    }


.throbbing-content {
    animation: throbbing-content 1.2s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
}

@keyframes throbbing-content {
    0% {
        transform: scale(0.95);
    }

    5% {
        transform: scale(1.1);
    }

    39% {
        transform: scale(0.85);
    }

    45% {
        transform: scale(1);
    }

    60% {
        transform: scale(0.95);
    }

    100% {
        transform: scale(0.9);
    }
}

/* Full-screen "welcome back / fetching the latest changes" overlay shown while the journal channel catches up after a gap
   or session refresh. Must cover everything it interrupts: above the app chrome (appbar 1300), the full-screen DataGrid
   (tcc-grid--fullscreen 2000) and any open dialog (tcc-dialog-z 2100). Still sits below the toast host (tcc-toast-host
   2200) so the "Whilst you were gone" summary toast stays visible once the overlay closes. On-brand dark backdrop with a
   golden comet racing the screen edge and a spinning orbit ring around the logo. */
.catch-up-overlay {
    position: fixed;
    inset: 0;
    z-index: 2150;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(17, 23, 32, 0.92); /* matches --emsurge-dark-background (rgb(17, 23, 32)) with alpha for the see-through backdrop */
    backdrop-filter: blur(4px);
}

.catch-up-overlay__panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--emsurge-reduced-margin);
}

.catch-up-overlay__title {
    margin-top: var(--emsurge-standard-padding);
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: #fff;
}

.catch-up-overlay__message {
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--emsurge-dim-font-color);
}

/* Logo sits inside a golden ring that spins to suggest active fetching; the logo itself breathes gently. */
.catch-up-overlay__orbit {
    position: relative;
    display: grid;
    place-items: center;
    width: 7rem;
    height: 7rem;
}

.catch-up-overlay__orbit::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    /* rgba(154, 109, 28, …) is --emsurge-golden-bright-color (#9A6D1C) carrying an alpha for the gradient fade; #f4e2b8 is the bright leading-edge highlight. */
    background: conic-gradient(from 0deg, transparent 0deg, transparent 250deg, rgba(154, 109, 28, 0.35) 300deg, var(--emsurge-golden-bright-color) 345deg, #f4e2b8 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    animation: catch-up-spin 1.1s linear infinite;
}

.catch-up-overlay__orbit img {
    animation: catch-up-breathe 2.4s ease-in-out infinite;
    cursor: default; /* the logo is decorative here; suppress the Logo component's default pointer cursor */
}

/* Golden comet that races around the whole screen edge to simulate the fetch travelling across the app. The conic
   gradient is masked to the overlay's border so only the edge lights up, and its angle is animated for the lap. */
@property --catch-up-angle {
    syntax: "<angle>";
    initial-value: 0deg;
    inherits: false;
}

.catch-up-overlay__racer {
    position: absolute;
    inset: 0;
    padding: 4px;
    pointer-events: none;
    /* rgba(154, 109, 28, …) is --emsurge-golden-bright-color (#9A6D1C) with alpha; #f4e2b8 is the bright comet head. */
    background: conic-gradient(from var(--catch-up-angle), transparent 0deg, transparent 250deg, rgba(154, 109, 28, 0.4) 305deg, var(--emsurge-golden-bright-color) 345deg, #f4e2b8 358deg, transparent 360deg);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    animation: catch-up-race 2.8s linear infinite;
}

@keyframes catch-up-race {
    to {
        --catch-up-angle: 360deg;
    }
}

@keyframes catch-up-spin {
    to {
        transform: rotate(360deg);
    }
}

@keyframes catch-up-breathe {
    0%, 100% {
        transform: scale(0.94);
        opacity: 0.85;
    }

    50% {
        transform: scale(1.04);
        opacity: 1;
    }
}

/* Honour reduced-motion: the comet, the spinning ring and the breathing logo all stop, leaving the static overlay. */
@media (prefers-reduced-motion: reduce) {
    .catch-up-overlay__racer,
    .catch-up-overlay__orbit::before,
    .catch-up-overlay__orbit img {
        animation: none;
    }
}

/* team.core's NewVersionOverlay (EOM's bespoke overlay was extracted there) wears the catch-up overlay's exact look:
   same dark backdrop, golden orbit ring around the logo, and the comet racing the screen edge. The neutral team.core
   panel styling (card background, border, shadow) is stripped so the panel floats on the backdrop like the catch-up
   panel does; the racer, a dedicated div in the old markup, is now the overlay's ::before. */
.tcc-newversion-overlay {
    z-index: 2150; /* same slot as the catch-up overlay: above dialogs (2100), below the toast host (2200) */
    background-color: rgba(17, 23, 32, 0.92);
    backdrop-filter: blur(4px);
}

.tcc-newversion-overlay::before {
    content: "";
    position: absolute;
    inset: 0;
    padding: 4px;
    pointer-events: none;
    background: conic-gradient(from var(--catch-up-angle), transparent 0deg, transparent 250deg, rgba(154, 109, 28, 0.4) 305deg, var(--emsurge-golden-bright-color) 345deg, #f4e2b8 358deg, transparent 360deg);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    animation: catch-up-race 2.8s linear infinite;
}

.tcc-newversion-overlay__panel {
    background: none;
    border: none;
    box-shadow: none;
    padding: 0;
    width: auto;
    max-width: none;
    gap: var(--emsurge-reduced-margin);
}

.tcc-newversion-overlay__title {
    margin-top: var(--emsurge-standard-padding);
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: #fff;
}

.tcc-newversion-overlay__message {
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--emsurge-dim-font-color);
}

.tcc-newversion-overlay__note {
    max-width: 26rem;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--emsurge-dim-font-color);
}

.tcc-newversion-overlay__actions {
    gap: var(--emsurge-standard-padding);
}

.tcc-newversion-overlay__orbit {
    position: relative;
    display: grid;
    place-items: center;
    width: 7rem;
    height: 7rem;
    padding: 0;
}

.tcc-newversion-overlay__orbit::before {
    border: none;
    background: conic-gradient(from 0deg, transparent 0deg, transparent 250deg, rgba(154, 109, 28, 0.35) 300deg, var(--emsurge-golden-bright-color) 345deg, #f4e2b8 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    animation: catch-up-spin 1.1s linear infinite;
}

.tcc-newversion-overlay__orbit img {
    animation: catch-up-breathe 2.4s ease-in-out infinite;
    cursor: default;
}

@media (prefers-reduced-motion: reduce) {
    .tcc-newversion-overlay::before,
    .tcc-newversion-overlay__orbit::before,
    .tcc-newversion-overlay__orbit img {
        animation: none;
    }
}

.pt-05,
.py-05 {
    padding-top: 2px !important;
}

.pr-05,
.px-05 {
    padding-right: 2px !important;
}

.pl-05,
.px-05 {
    padding-left: 2px !important;
}

.pb-05,
.py-05 {
    padding-bottom: 2px !important;
}

.ps-05 {
    padding-inline-start: 2px !important;
}

.pe-05 {
    padding-inline-end: 2px !important;
}

.pa-05 {
    padding: 2px !important;
}

.mt-05,
.my-05 {
    margin-top: 2px !important;
}

.mr-05,
.mx-05 {
    margin-right: 2px !important;
}

.ml-05,
.mx-05 {
    margin-left: 2px !important;
}

.mb-05,
.my-05 {
    margin-bottom: 2px !important;
}

.ms-05 {
    margin-inline-start: 2px !important;
}

.me-05 {
    margin-inline-end: 2px !important;
}

.ma-05 {
    margin: 2px !important;
}

/* MudBlazor utility classes the EOM markup relies on (rounding, spacing, display). MudBlazor's stylesheet provided these and they were lost in the migration; the half-unit (-05) variants above assume the same Mud scale of 4px per spacing unit. */
.rounded {
    border-radius: var(--emsurge-default-border-radius) !important;
}

.rounded-pill {
    border-radius: 9999px !important;
}

.rounded-circle {
    border-radius: 50% !important;
}

.d-flex {
    display: flex !important;
}

.pa-0 {
    padding: 0 !important;
}

.ma-0 {
    margin: 0 !important;
}

.ma-3 {
    margin: 12px !important;
}

.ml-2 {
    margin-left: 8px !important;
}

@media print {
    body {
        visibility: hidden;
    }

    div.printable {
        visibility: visible;
        position: fixed;
        left: 0;
        top: 0;
    }
}

@media screen {
    div.printable {
        display: none;
    }
}

/* Live order-grid change cues (#4123, persistence extended in #4166). Applied to grid rows via RowClassFunc from the Orders Report.
   A changed row flashes for ~1 minute and then stays tinted in that colour until the class is removed 24h later by
   OrdersReportViewModel (LiveChangedHighlightMs). Durations must stay in sync with the view model. */
@keyframes ems-order-row-changed-flash {
    0% { background-color: var(--emsurge-palette-warning); }
    100% { background-color: rgba(255, 152, 0, 0.18); }
}

@keyframes ems-order-row-leaving-fade {
    0% { opacity: 1; }
    100% { opacity: 0; }
}

/* Target the cells so we don't fight the grid's row striping/hover background on the <tr>. */
tr.ems-order-row-changed > td {
    /* Steady tint that remains for as long as the row keeps the class (24h, managed by the view model). */
    background-color: rgba(255, 152, 0, 0.18);
    /* Flash for ~1 minute (0.5s x 120 alternate) and then settle on the steady tint above. */
    animation: ems-order-row-changed-flash 0.5s ease-out 120 alternate;
}

tr.ems-order-row-leaving > td {
    animation: ems-order-row-leaving-fade 0.6s ease-in forwards;
}

@media (prefers-reduced-motion: reduce) {
    tr.ems-order-row-changed > td,
    tr.ems-order-row-leaving > td {
        animation: none;
    }
}

/* #4190: an Activity-panel card flashes a few times when its order is newly created/updated, replacing the old pop-up.
   A box-shadow pulse (not a background change) so it reads through the card's own opaque background. */
@keyframes ems-activity-card-changed-flash {
    0% { box-shadow: 0 0 0 0 rgba(255, 152, 0, 0); }
    20% { box-shadow: 0 0 0.7rem 0.2rem rgba(255, 152, 0, 0.85); }
    100% { box-shadow: 0 0 0 0 rgba(255, 152, 0, 0); }
}

.ems-activity-card-changed {
    border-radius: var(--emsurge-reduced-margin);
    animation: ems-activity-card-changed-flash 1s ease-out 3;
}

@media (prefers-reduced-motion: reduce) {
    .ems-activity-card-changed {
        animation: none;
    }
}

/* #4376: Abaxx values flash "warning amber" while the connection to Abaxx is lost, so a stale price is never mistaken for a live one.
   We pulse the background (not the text colour) so the cue shows regardless of the value's own colour, and it keeps flashing
   until the connection is confirmed back up (the view removes the class). */
@keyframes ems-abaxx-connection-lost-flash {
    0%, 100% { background-color: transparent; }
    50% { background-color: rgba(255, 168, 0, 0.30); }
}

.abaxx-connection-lost {
    animation: ems-abaxx-connection-lost-flash 1.2s ease-in-out infinite;
    border-radius: var(--emsurge-reduced-margin);
}

/* On the dedicated Abaxx price grid every cell flashes rather than styling each value individually. */
.abaxx-connection-lost-grid td {
    animation: ems-abaxx-connection-lost-flash 1.2s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .abaxx-connection-lost,
    .abaxx-connection-lost-grid td {
        animation: none;
        background-color: rgba(255, 168, 0, 0.30);
    }
}

/* Spinner shown in a project-grid cell while the open-project navigation is in progress (#4166). */
.ems-open-project-spin {
    display: inline-flex;
    animation: ems-open-project-spin 0.8s linear infinite;
}

@keyframes ems-open-project-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* While a team.core DataGrid is expanded to full screen it adds tcc-grid-fs-lock to <html> and renders its own close (X). Hide the marketplace dialog's own close button in that state so only the grid's close is shown. */
html.tcc-grid-fs-lock .marketplace-dialog-close-button {
    display: none;
}

/* The "?" that carries a field's or section's explanation in its native title tooltip (FieldHelpIcon). Sized in em so it tracks whatever label it sits beside. */
.emsurge-help-icon {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 1.25em;
    height: 1.25em;
    border: 1.4px solid currentColor;
    border-radius: 50%;
    color: var(--emsurge-dim-font-color);
    font-size: 0.85em;
    font-weight: 700;
    line-height: 1;
    cursor: default;
}

.emsurge-help-icon:hover {
    color: var(--emsurge-golden-bright-color);
}

/* A rule between stacked input sections of a step, drawn only where one separated section directly follows another - so it never opens or closes the step, and a section hidden by its own condition takes its rule with it. One full-width line in the same colour the recap ledger rules its rows with, so a step and the recap it produces separate their sections the same way. */
.step-subsection--separated + .step-subsection--separated {
    padding-top: var(--emsurge-standard-padding);
    border-top: 1px solid var(--emsurge-palette-lines-default);
}
