/* ============================================================================
   SmartForwarder — "Industry" theme layer
   ----------------------------------------------------------------------------
   The design (Claude Design, "Industry") expressed in the DevExpress way: a
   stylesheet layered OVER the theme the user picks in the Theme Switcher, never
   a forked theme file.

   What it carries: the type system (Barlow Condensed for labels, Barlow for
   everything else), square corners, hairline rules, a compact 28px data row and
   fill/tint/outline status badges.

   What it deliberately does NOT carry: a palette. The accent is whatever the
   Theme Switcher is on (`appsettings.json` →
   DevExpress:ExpressApp:ThemeSwitcher), which now defaults to the design's
   steel `#5980a6` as an ordinary Fluent item — so the app opens on the design's
   colour, and all 11 Fluent accents, the 4 classic themes and the Size Mode
   switcher keep working. Every colour below is read from a `--dxds-*` token, so
   it follows that choice instead of overriding it.

   DATA KEEPS ITS OWN CASE. The design sets values in caps ("ACME EXPORT CO.,
   LTD"); here only labels the application model owns are uppercased — captions,
   column headers, tab and action names. A customer, vessel, port or status
   reads exactly as it is stored.

   DevExpress documents `--dxds-*` as the public styling API, `--dxbl-*` as
   internal, and the theme files as off-limits — which is why this layers rather
   than forks and why it should survive a 25.2.x upgrade. Rules that must name a
   component class (`.dxbl-grid-*` and friends) are grouped so an upgrade has
   one place to check.

   Loaded from Pages/_Host.cshtml AFTER the theme link and `css/site.css`.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1. The fonts. Self-hosted (wwwroot/fonts) rather than pulled from Google
   Fonts: the app is served on an intranet and must not depend on an outbound
   request at first paint. Barlow is SIL Open Font License 1.1.

   The Vietnamese subset is not optional here — customer and port names carry
   diacritics, and without it the browser falls back mid-word.
   --------------------------------------------------------------------------- */
@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/barlow-400-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/barlow-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/barlow-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/barlow-500-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/barlow-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/barlow-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/barlow-600-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/barlow-600-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/barlow-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/barlow-700-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/barlow-700-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/barlow-700-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/barlow-condensed-400-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/barlow-condensed-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/barlow-condensed-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/barlow-condensed-500-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/barlow-condensed-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/barlow-condensed-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/barlow-condensed-600-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/barlow-condensed-600-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/barlow-condensed-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/barlow-condensed-700-vietnamese.woff2') format('woff2');
    unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/barlow-condensed-700-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/barlow-condensed-700-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ---------------------------------------------------------------------------
   2. The knobs. Everything below reads from these, so the whole look is tuned
   from one place — and setting `--sf-font-chrome`/`--sf-font-body` back to
   `inherit` disables the typography half without deleting it.

   Chrome sizes run slightly larger than the theme's: Barlow Condensed is a
   narrow face and sets visually smaller than Segoe UI at the same pixel size.
   --------------------------------------------------------------------------- */
:root {
    --sf-font-chrome: 'Barlow Condensed', 'Segoe UI', system-ui, -apple-system, sans-serif;
    --sf-font-body: 'Barlow', 'Segoe UI', system-ui, -apple-system, sans-serif;

    /* Tracking. Condensed uppercase needs air or it reads as a block. */
    --sf-tracking-label: .14em; /* group captions, section labels */
    --sf-tracking-nav: .10em; /* ribbon tabs, action captions */
    --sf-tracking-title: .04em; /* view caption, document tabs */
    --sf-tracking-column: .10em; /* tighter than a section label: a column
                                    header has to fit inside its column. At
                                    .14em "PORT OF LOADING" wrapped to two
                                    lines and cost a row of grid height. */

    --sf-size-nav-group: .8125rem; /* 13px  — navigation group header */
    --sf-size-nav-item: .9375rem; /* 15px  — navigation leaf item */
    --sf-size-action: .9375rem; /* 15px  — ribbon / toolbar action caption */
    --sf-size-ribbon-tab: .9375rem; /* 15px  — Home / View */
    --sf-size-doc-tab: .9375rem; /* 15px  — MDI document tab */
    --sf-size-view-caption: 1.25rem; /* 20px  — view caption in the header */
    --sf-size-column: .75rem; /* 12px  — grid column header */

    /* Density. The design's "compact": a 28px data row and a 12.5px cell. */
    --sf-row-height: 28px;
    --sf-size-cell: .78125rem; /* 12.5px */
}

/* The Size Mode switcher (ThemeSwitcher → ShowSizeModeSwitcher) puts
   `xaf-size-s|m|l` on <body>. Keep our own sizes in step with it instead of
   fighting it: Small tightens further, Large relaxes back to a roomy row. */
.dxbl-theme-fluent.xaf-size-s {
    --sf-size-view-caption: 1.0625rem;
    --sf-row-height: 24px;
    --sf-size-cell: .75rem;
}

.dxbl-theme-fluent.xaf-size-l {
    --sf-size-view-caption: 1.375rem;
    --sf-row-height: 38px;
    --sf-size-cell: .875rem;
}

/* ---------------------------------------------------------------------------
   3. The body font. `--dxds-font-family-sans-serif` is the documented public
   token every Fluent component reads, so one line moves the whole application
   onto Barlow. The `body` rule covers the classic themes (Blazing Berry and
   friends), which predate the token and declare a font stack of their own.

   Data KEEPS ITS OWN CASE. Nothing here uppercases a value: only labels the
   model owns (captions, column headers, action names) are transformed, and a
   customer name, a vessel or a port reads exactly as it was typed.
   --------------------------------------------------------------------------- */
:root {
    --dxds-font-family-sans-serif: var(--sf-font-body);
}

body,
.dxbl-app,
.dxbl-btn,
.dxbl-text-edit-input,
input,
select,
textarea {
    font-family: var(--sf-font-body);
}

/* Tabular figures across the board — dates, container counts and booking
   numbers line up column-wise instead of wobbling. Barlow has proper tabular
   figures, which is half the reason the design picked it for a logistics grid. */
.dxbl-grid,
.dxbl-text-edit-input {
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   4. Square corners. `--dxds-border-radius-*` is the documented base scale that
   every Fluent component reads, so zeroing the scale squares the whole suite in
   one block — no per-component chasing.

   `--dxds-border-radius-full` is deliberately left alone: it is what makes
   radio buttons, avatars and badge dots round, and squaring those would be a
   bug, not a style.
   --------------------------------------------------------------------------- */
:root {
    --dxds-border-radius-10: 0;
    --dxds-border-radius-20: 0;
    --dxds-border-radius-30: 0;
    --dxds-border-radius-40: 0;
    --dxds-border-radius-50: 0;
    --dxds-border-radius-60: 0;
    --dxds-border-radius-80: 0;
    --dxds-border-radius-100: 0;
    --dxds-border-radius-120: 0;
    --dxds-border-radius-160: 0;
}

/* The classic themes are Bootstrap-based and round through Bootstrap's own
   variables, which the token scale above does not reach. */
body {
    --bs-border-radius: 0;
    --bs-border-radius-sm: 0;
    --bs-border-radius-lg: 0;
    --bs-border-radius-xl: 0;
    --bs-border-radius-2xl: 0;
}

/* The public pages (sign-up, forgot/reset password) draw their own card in
   site.css with a hard-coded radius, which predates this layer. Squared here
   rather than there so every "the design says no rounded corners" decision
   stays in one file. The success tick stays a circle — it is an icon. */
.sf-register-card,
.sf-register-error {
    border-radius: 0;
}

/* ---------------------------------------------------------------------------
   5. XAF chrome — XAF's own `xaf-*` classes, stable across the 25.x line.
   --------------------------------------------------------------------------- */

/* View caption — the screen's title in the top bar. The three `.xaf-size-*`
   selectors are not decoration: XAF sizes this element through
   `.dxbl-theme-fluent.xaf-size-m .xaf-view-caption-lg`, so a bare
   `.xaf-view-caption-lg` rule loses on specificity and only the font-family
   would land. Matching that specificity and loading later is what wins.

   `line-height` is load-bearing here, not tidiness. XAF gives this element
   `xaf-ellipsis` (`overflow: hidden`) and lets its height come from an
   inherited 20px line box sized for the theme's 14px caption. Raising the font
   to 20px without raising the line box leaves the glyphs taller than the box
   that clips them, and the descenders are cut off — "nguyen" lost the tails of
   its g and y while "Admin", which has none, looked perfect. */
.dxbl-theme-fluent.xaf-size-s .xaf-view-caption-lg,
.dxbl-theme-fluent.xaf-size-m .xaf-view-caption-lg,
.dxbl-theme-fluent.xaf-size-l .xaf-view-caption-lg,
.xaf-view-caption-lg {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-view-caption);
    line-height: 1.35;
    font-weight: 600;
    letter-spacing: var(--sf-tracking-title);
    text-transform: uppercase;
}

/* The record's own name on a Detail View gets the same size and face but NOT
   `text-transform` — a booking number is already upper case in the data, and a
   record whose name is mixed case ("Ho Chi Minh City (Cat Lai)") must keep it.
   This is the one place where the design and "data keeps its case" disagree,
   and the data wins. */
.dxbl-theme-fluent.xaf-size-s .xaf-object-caption,
.dxbl-theme-fluent.xaf-size-m .xaf-object-caption,
.dxbl-theme-fluent.xaf-size-l .xaf-object-caption,
.xaf-object-caption {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-view-caption);
    line-height: 1.35; /* same descender clipping as the caption above — a user
                          named "nguyen" was losing the tails of its g and y */
    font-weight: 600;
    letter-spacing: var(--sf-tracking-title);
}

/* A Detail View captions in two parts — `xaf-view-caption-sm` is the class name
   ("Booking") over `xaf-object-caption`, the record itself ("STASGN260700001"),
   styled as the title above. The class name is the design's section label:
   small, tracked, uppercase.

   The record's own text is NOT uppercased by a rule — a booking number is
   already upper case in the data, and a record whose name is mixed case must
   keep it. */
.dxbl-theme-fluent.xaf-size-s .xaf-view-caption-sm,
.dxbl-theme-fluent.xaf-size-m .xaf-view-caption-sm,
.dxbl-theme-fluent.xaf-size-l .xaf-view-caption-sm,
.xaf-view-caption-sm {
    font-family: var(--sf-font-chrome);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: var(--sf-tracking-label);
    text-transform: uppercase;
}

/* Navigation group ("Bookings", "Schedules", "Catalogs"): the design's section
   label — small, heavy, widely tracked, uppercase, and set on a tinted band so
   the groups read as dividers rather than as bigger items.

   The tint is the accent's lightest step and the text its darkest, both from
   `--dxds-primary-*`, so the band follows whatever accent the Theme Switcher is
   on — the same pair the tint status badge uses. `--bs-*` fallbacks cover the
   classic themes, which have no `--dxds-*` scale.

   `:has(.xaf-nav-link)` is load-bearing, not tidiness: XAF renders the panel's
   Filter box inside a `.dxbl-accordion-group-header` of its own, so the bare
   class tints the search box as well. A real group is the one that carries a
   nav link. */
.xaf-navmenu .dxbl-accordion-group-header:has(.xaf-nav-link) {
    padding-block: 0;
    background: var(--dxds-primary-10, var(--bs-primary-bg-subtle, #eef6ff));
    border-top: 1px solid var(--dxds-color-border-neutral-subtle-rest, var(--bs-border-color, rgba(0, 0, 0, .12)));
    border-bottom: 1px solid var(--dxds-color-border-neutral-subtle-rest, var(--bs-border-color, rgba(0, 0, 0, .12)));
}

.xaf-navmenu .xaf-nav-item.has-children > .dxbl-accordion-group-header .xaf-nav-link,
.xaf-navmenu .dxbl-accordion-group-header .xaf-nav-link {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-nav-group);
    font-weight: 700;
    letter-spacing: var(--sf-tracking-label);
    text-transform: uppercase;
    color: var(--dxds-primary-160, var(--bs-primary-text-emphasis, #1d2d3d));
}

/* Navigation leaf ("Vessel Schedule", "Booking"): condensed but NOT uppercase —
   these are names, and all-caps Vietnamese reads badly at this size. */
.xaf-navmenu .xaf-nav-link {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-nav-item);
    letter-spacing: .01em;
}

/* No underlines in the navigation panel. XAF underlines every leaf through
   `.clickable-xaf-nav-item > div > a .xaf-nav-link` (0,3,2), so the override has to name the
   same shape — a plain `.xaf-nav-link` rule loses. Both of XAF's selector forms are covered
   because the anchor is sometimes a direct child and sometimes wrapped in a div.

   The panel is a list of destinations, not prose with links in it: the row highlight and the
   accent rule on the selected item already say what is clickable and where you are. */
.xaf-navmenu .clickable-xaf-nav-item > a .xaf-nav-link,
.xaf-navmenu .clickable-xaf-nav-item > div > a .xaf-nav-link {
    text-decoration: none;
}

/* The selected navigation item is filled in the accent and carries a 3px accent
   rule down its left edge — the design's marker. The document tab strip already
   says "you are here" in the accent colour (a 3px `::after` on
   `.dxbl-tabs-item.dxbl-active`, painted from `--dxds-primary-100`), so the
   theme's neutral grey selection in the navigation panel was the odd one out.

   The fill goes on the OUTER `.xaf-nav-item`, and the anchor inside it is forced
   transparent — not the other way round, which is the arrangement that survives
   both theme families. Fluent paints the anchor `#e9e9e8` and lets it be
   overridden; the classic themes win that particular contest (`background-color`
   and `color` set on the anchor were both beaten there, while `box-shadow` went
   through — the give-away that the rule matched and only those two declarations
   lost). The outer element has no theme rule on it at all, so painting there
   lands everywhere, and the anchor covers it exactly (measured: both 269×32 at
   the same origin), so an inset shadow on the parent needs that anchor to be
   see-through or it is simply painted over.

   `--dxds-primary-20` is two steps up the tint scale from the `-10` the group
   header band uses, so a selected leaf reads as stronger than the band above it
   while staying in the same accent, whichever accent the Theme Switcher is on;
   the text moves to `-130` for contrast on it. The classic themes have no
   `--dxds-*` scale at all and answer with `--bs-*`; their fill is mixed from
   `--bs-primary` rather than taken from `--bs-primary-bg-subtle`, because that
   is the same token the group header band falls back to and the selected row
   would come out the identical tint — verified on Blazing Berry, where both
   resolved to `#dfd7e8`. */
.xaf-navmenu .xaf-nav-item.dxbl-active {
    background-color: var(--dxds-primary-20, color-mix(in srgb, var(--bs-primary, #5980a6) 30%, #fff));
    box-shadow: inset 3px 0 0 var(--dxds-primary-100, var(--bs-primary, currentColor));
}

.xaf-navmenu .xaf-nav-item.dxbl-active > .dxbl-accordion-item-content.dxbl-active {
    background-color: transparent;
    color: var(--dxds-primary-130, var(--bs-primary, inherit));
}

.xaf-navmenu .xaf-nav-item.dxbl-active .xaf-nav-link {
    font-weight: 600;
}

/* No icons in the navigation panel. The design's nav is text only: the icons XAF
   generates are generic stand-ins (BO_Sale, BO_Contact…) that repeat down the
   list and carry no information the label does not already give, and dropping
   them lets the group headers do the structural work.

   Hidden here rather than by clearing ImageName on every navigation item,
   because a new business object with [NavigationItem] would arrive with an icon
   again and nobody would remember. Icons elsewhere — the view caption, the
   document tabs, the ribbon — are untouched. */
.xaf-navmenu .xaf-nav-menu-item-icon {
    display: none;
}

/* The about block at the foot of the navigation panel. Two lines: the product name carrying
   the application's identity, then version and description together in a quiet second line.
   The markup comes from the model's AboutInfoString (Model.xafml) — without those spans this
   is four bare text nodes separated by <br> and nothing here could reach them. */
.about-info {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    /* Full-bleed hairline above the block, matching the rules that bracket the navigation
       group headers. The side margins are cancelled so the rule can reach both edges of the
       panel, and given back as padding so the text stays exactly where it was. */
    margin-inline: 0;
    padding-inline: 1rem;
    padding-top: .625rem;
    border-top: 1px solid var(--dxds-color-border-neutral-subtle-rest, var(--bs-border-color, rgba(0, 0, 0, .12)));
    /* XAF leaves 24px here against a 16px side inset, which reads as a dangling block.
       One value, so the corner is square. */
    margin-bottom: 1rem;
}

.sf-about-name {
    font-family: var(--sf-font-chrome);
    font-size: .875rem;
    font-weight: 700;
    letter-spacing: var(--sf-tracking-label);
    text-transform: uppercase;
    color: var(--dxds-color-content-neutral-default-rest, var(--bs-body-color, inherit));
}

/* Deliberately quiet: the version is reference information someone goes looking for when
   reporting a problem, not something to read every day. */
.sf-about-meta {
    font-size: .75rem;
    opacity: .65;
}

/* Navigation filter box, so the panel is consistent top to bottom. */
.xaf-sidebar .dxbl-navigation-filter input {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-nav-item);
}

/* Document (MDI) tab headers. */
.xaf-tabbed-mdi .xaf-tab-header-template {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-doc-tab);
    font-weight: 600;
    letter-spacing: var(--sf-tracking-title);
    text-transform: uppercase;
}

/* Action captions — every XAF Action rendered as a button, plus the ordinary
   buttons on the public pages (sign-in, sign-up, password reset), so a screen
   drawn before the XAF frame exists still belongs to the same system.

   Set on the BUTTON, not on a caption span: a ribbon action renders its text as
   a bare `<span>` with no class of its own (`.dxbl-btn-caption` exists only on
   some button flavours), so the button is the only reliable hook. The icon is a
   sibling `<img>`/`<svg>` and is unaffected by font rules. Editors that sit in
   the same toolbar (the full-text search box) are NOT buttons and keep the body
   font, which is right — they hold typed text, not a label. */
.dxbl-btn,
.dxbl-btn-caption,
.dxbl-toolbar-adaptive-item-text,
.xaf-btn.xaf-action {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-action);
    font-weight: 600;
    letter-spacing: var(--sf-tracking-nav);
    text-transform: uppercase;
}

/* Tab strips — the ribbon's ("Home", "View") and a Detail View's own
   ("General", "Parties", "Equipment Details", …). Deliberately NOT scoped to
   the ribbon: both are the same component and both are navigation, so scoping
   would leave the form tabs in the body font next to a condensed ribbon two
   rows above them. Tab labels come from the model, never from data. */
.dxbl-tabs-item .dxbl-tabs-text-container,
.dxbl-tabs-item {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-ribbon-tab);
    font-weight: 600;
    letter-spacing: var(--sf-tracking-nav);
    text-transform: uppercase;
}

/* The colour swatches in the Theme Switcher. Each row is a flex line of swatch + name, and
   the swatch is a plain flex item — `flex-shrink: 1`, `min-width: auto` — so a caption wider
   than its column squeezes the 18px square down to a sliver. That is what "SmartForwarder
   Steel" did to its own swatch; the short "Collyer Steel" fits, but the next long name would
   do it again, so pin the square instead of relying on the caption staying short. */
.themes-menu .nav-link .image {
    flex: none;
}

/* ---------------------------------------------------------------------------
   6. The grid. Column headers are labels and get the full treatment; the rows
   below are data and get only the density and the body font.
   `.dxbl-grid-*` are internal DevExpress classes — if an upgrade renames them,
   this is the block to check.
   --------------------------------------------------------------------------- */
.dxbl-grid-header-content {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-column);
    font-weight: 600;
    letter-spacing: var(--sf-tracking-column);
    text-transform: uppercase;
}

/* Compact rows. Three things are needed together and the row stays tall if any
   one is missing:
     - `padding-block: 0`, or the cell's own vertical padding outvotes the height;
     - `white-space: nowrap` + ellipsis, or a long value ("KOTA ANGGUN V.0320S
       SGN→SIN 21/03/2026") wraps to three lines and drags the row with it —
       this is the one that actually decides the row height in this grid;
     - the extra `.dxbl-grid` in the selector, because DevExpress sizes the cell
       through a three-class selector of its own and a bare `td` rule loses.
   Cells keep their own case and the body font; only the size changes.

   Truncation is affordable here precisely because GridColumnSizingController
   already gives every column a MinWidth and the grid a horizontal scrollbar, so
   a clipped value is one drag away rather than lost. */
.dxbl-grid .dxbl-grid-table > tbody > tr > td {
    height: var(--sf-row-height);
    padding-block: 0;
    font-size: var(--sf-size-cell);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* …except while the cell is being edited. The catalog List Views run Batch
   inline edit (WinForms parity), which puts a real editor inside the cell: the
   clipping and the 28px floor above would cut its border and its buttons off.
   A cell that contains an editor opts out of both. */
.dxbl-grid .dxbl-grid-table > tbody > tr > td:has(.dxbl-edit),
.dxbl-grid .dxbl-grid-table > tbody > tr > td:has(input),
.dxbl-grid .dxbl-grid-table > tbody > tr > td:has(.dxbl-text-edit) {
    height: auto;
    padding-block: revert;
    overflow: visible;
    white-space: normal;
}

/* A reference cell does not hold its text directly — XAF wraps it in a
   `<xaf-navigation-click-helper>` block, and the ellipsis has to go on whatever
   element actually contains the text. Without this the value is clipped mid-word
   with no "…" to say so, which reads like a data error rather than truncation. */
.dxbl-grid .dxbl-grid-table > tbody > tr > td > xaf-navigation-click-helper,
.dxbl-grid .dxbl-grid-table > tbody > tr > td > .xaf-wrap-ellipsis {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A reference cell renders as a link. Underline only on hover, so a column of foreign keys
   stops reading as a wall of blue.

   Weight stays at the row's: the design puts links at 500, but in a grid only SOME columns
   are references, so a heavier link weight singles out Terminal Type / Country / City and
   makes them look emphasised against the plain text columns beside them. Data should not
   change weight because of how it happens to be stored. */
.dxbl-grid-table a {
    text-decoration: none;
}

.dxbl-grid-table a:hover {
    text-decoration: underline;
}

/* The filter row sits directly under the headers and is an input, not a
   label — condensed, but left in sentence case and untracked so typed filter
   text still looks like typed text. */
.dxbl-grid-filter-row-cell input,
.dxbl-grid-filter-row-cell input::placeholder {
    font-family: var(--sf-font-chrome);
    font-size: var(--sf-size-cell);
    letter-spacing: .01em;
}

/* ---------------------------------------------------------------------------
   7. Form Layout group captions — the design's "Section label". These are the
   headers over a group of editors ("Company details" on the sign-up page, a
   captioned group in a Detail View).

   Field captions (`.dxbl-fl-cpt` — "Booking No.", "Sailing Date") are
   deliberately NOT included: a field caption belongs to the value beside it and
   reads as one unit with it, so it keeps the body font.
   --------------------------------------------------------------------------- */
.dxbl-fl-group .dxbl-group-header {
    font-family: var(--sf-font-chrome);
    font-weight: 600;
    letter-spacing: var(--sf-tracking-label);
    text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
   8. Status badges. Rendered by Controllers/StatusBadgeColumnController.cs into
   any enum column whose name ends in "Status"; the class here decides how each
   one reads.

   The design's rule: status is carried by FILL vs TINT vs OUTLINE vs NEUTRAL,
   not by hue, so the palette stays whatever accent the Theme Switcher is on and
   the one genuinely red thing on the screen is a cancellation. All colours come
   from `--dxds-*` tokens, with Bootstrap fallbacks for the classic themes.

   The label keeps the enum's own casing — no `text-transform` here, unlike the
   design, because a status is data.
   --------------------------------------------------------------------------- */
.sf-badge {
    display: inline-flex;
    align-items: center;
    height: 19px;
    padding: 0 8px;
    border: 1px solid currentColor;
    font-family: var(--sf-font-chrome);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .06em;
    line-height: 1;
    white-space: nowrap;
}

/* Done and gone: the one solid object in the column. */
.sf-badge--solid {
    background: var(--dxds-primary-100, var(--bs-primary, #5980a6));
    border-color: var(--dxds-primary-100, var(--bs-primary, #5980a6));
    color: #fff;
}

/* Committed. */
.sf-badge--tint {
    background: var(--dxds-primary-20, var(--bs-primary-bg-subtle, #eef6ff));
    border-color: transparent;
    color: var(--dxds-primary-140, var(--bs-primary-text-emphasis, #2c455d));
}

/* In progress — outline only. */
.sf-badge--outline {
    background: transparent;
    color: var(--dxds-primary-120, var(--bs-primary, #416180));
}

/* Not started / not submitted — reads as absent. */
.sf-badge--neutral {
    background: color-mix(in srgb, currentColor 7%, transparent);
    border-color: transparent;
    opacity: .7;
}

/* Cancelled, declined, rejected, failed — the single exception to the mono
   palette, and deliberately outline rather than solid so a dead record does not
   shout louder than a live one. */
.sf-badge--alert {
    background: transparent;
    color: var(--dxds-color-content-danger-default-rest, var(--bs-danger, #8f3b36));
}
