/* Lustro token set for the admin UI.

   Taken from the reference implementation, AF.CreditReportParser.Web,
   wwwroot/css/app.css. The values are lifted rather than re-derived: Lustro is the reference
   implementation and where the two differ, Lustro is right.

   This file is the single source of truth for the theme. It must load AFTER the Radzen theme
   stylesheet, because the --rz-* block below overrides custom properties Radzen declares on
   :root and equal specificity means the later declaration wins. index.html links it last for
   that reason. */

@font-face {
    font-family: "Inter";
    src: url('../fonts/Inter_18pt-Regular.ttf');
    font-style: normal;
}

@font-face {
    font-family: "InterSemiBold";
    src: url('../fonts/Inter_18pt-SemiBold.ttf');
    font-style: normal;
}

:root {
    /* Shell (darkest navy) */
    --shell-900: #060b18;
    --shell-800: #0a1220;
    --shell-700: #0d1a2f;
    /* Raised content surfaces (data sits on these, lighter than the shell) */
    --surface: #101c30;
    --surface-raised: #13203a;
    --surface-hover: #16264a;
    /* Gold accent */
    --gold: #e8b84b;
    --gold-bright: #f5c542;
    /* Structural hairline */
    --hairline: rgba(90, 140, 180, 0.18);
    /* A firmer edge for input borders and chips, which a hairline alone leaves looking unbounded */
    --hairline-strong: rgba(90, 140, 180, 0.34);
    /* Status */
    --status-success: #4ade80;
    --status-danger: #f0677d;
    --status-warning: #e8b84b;
    --status-info: #5aa0d0;
    /* Text.
       --ink and --ink-muted clear 4.5:1 against every surface above and so carry body text.
       --ink-faint clears 3:1 but not 4.5:1 on the lighter surfaces, so it is for large text and
       non-text marks only, never body copy. ThemeTokenTests holds both of those to account. */
    --ink: #f4f7fb;
    --ink-muted: #9fb0c3;
    /* 4.54:1 on --surface-hover, which is the lightest surface in the set, and higher on all the others. Lustro carries #6b7d92, which measures 4.04:1 and therefore fails
       WCAG 2.2 AA (1.4.3) wherever it is used for text, which here is the token UID, input
       placeholders and the login note. Lifted on the same hue to the first value that clears the
       bar, so the palette keeps its character and the text becomes readable. */
    --ink-faint: #7b90a8;
    /* Shell gradient */
    --shell-gradient: radial-gradient(140% 120% at 15% 0%, #0d1a2f 0%, #060b18 60%);
    /* Capability names, route paths, methods and claims. Nothing is downloaded: JetBrains Mono is used only where it is already installed */
    --font-mono: "JetBrains Mono", ui-monospace, Consolas, monospace;

    /* Accent aliases kept for existing rules */
    --brand-primary: var(--gold);
    --brand-primary-hover: var(--gold-bright);

    /* ── Align Radzen to the Lustro navy + gold palette ──────────────────────
       app.css loads after the Radzen theme, so overriding these Radzen custom properties on
       :root re-themes every Radzen dialog, grid, notification, menu and spinner the admin UI
       already renders, from one place, instead of the stock accent on grey. No Radzen component
       is styled individually and none needs to be.

       The admin UI loads the dark Radzen theme for this to land as intended. In the dark theme
       --rz-base-900 is the body background and --rz-base-800 the panel surface, which is what
       the navy scale below is written against. On a light theme the same names mean text
       colours, so the remapping would read as grey panels with navy text rather than the Lustro
       chrome. */
    --rz-primary: var(--gold);
    --rz-primary-light: var(--gold-bright);
    --rz-primary-lighter: rgba(232, 184, 75, 0.14);
    --rz-primary-dark: #d3a63e;
    --rz-primary-darker: #b98f33;
    /* Dark text sits on the gold primary (light) surface */
    --rz-text-contrast-color: var(--shell-900);
    /* Remap the neutral base surfaces to the navy scale */
    --rz-base-900: #060b18;
    --rz-base-800: #101c30;
    --rz-base-700: #13203a;
    --rz-base-600: #16264a;
    --rz-series-1: var(--gold);

    /* The selected grid row.

       Radzen's own dark theme leaves --rz-grid-selected-color at #060b18, a near black meant to
       sit on the pale blue band its light theme paints behind a selected row. On this palette the
       band is dark, so selecting a row rendered its own text at 1.32:1 and made the row you had
       just chosen the one row you could not read. Measured on the tenant grid.

       Same shape of fault as the Bootstrap utilities: a light theme's value surviving into a dark
       one because nothing re-pointed it. The band is set to the quiet amber wash used everywhere
       else for a current state, and the text stays --ink. */
    --rz-grid-selected-background-color: rgba(232, 184, 75, 0.14);
    --rz-grid-selected-color: var(--ink);

    /* Beyond the reference. Lustro sets the font on html and body only, which leaves Radzen
       components on the theme's own face. Inter is required throughout here, and this is the
       one variable that reaches every Radzen component without styling any of them. */
    --rz-text-font-family: "Inter", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;

    /* ── Controls: inputs, buttons and dialogs ───────────────────────────────
       The reference styles bare <input>, <button> and a hand rolled .dialog. The admin UI
       renders Radzen equivalents, and Radzen builds every one of them from the custom
       properties below. Setting them here applies the reference's treatment to every text box,
       dropdown, numeric, date picker, dialog and confirmation at once, which is the same
       mechanism as the palette block above and for the same reason: no Radzen component gets
       styled individually.

       Measurements are the reference's: a 1px hairline border on the raised surface, 8px
       corners on fields and 10px on buttons, 9px by 12px padding. */
    --rz-input-background-color: var(--surface-raised);
    --rz-input-value-color: var(--ink);
    --rz-input-placeholder-color: var(--ink-faint);
    --rz-input-border: 1px solid var(--hairline);
    --rz-input-hover-border: 1px solid var(--hairline);
    --rz-input-focus-border: 1px solid var(--gold);
    --rz-input-border-radius: 8px;
    --rz-input-height: 2.5rem;
    --rz-input-padding: 0.5625rem 0.75rem;
    --rz-input-font-size: 0.875rem;
    /* Radzen sinks every field with an inset shadow. The reference uses a flat fill and lets the
       border carry the edge, which is what keeps a form of eight fields from looking quilted. */
    --rz-input-shadow: none;
    --rz-input-hover-shadow: none;
    --rz-input-focus-shadow: none;
    --rz-input-disabled-shadow: none;
    /* A disabled field still has to be readable: an administrator reads the email address on a
       readonly step up prompt to check they are signed in as the right person. --ink-muted on
       --surface clears 4.5:1, which --rz-text-disabled-color does not (WCAG 2.2, 1.4.3). */
    --rz-input-disabled-background-color: var(--surface);
    --rz-input-disabled-color: var(--ink-muted);
    --rz-input-disabled-placeholder-color: var(--ink-muted);
    --rz-input-disabled-border: 1px solid var(--hairline);
    --rz-input-disabled-opacity: 1;

    --rz-button-border-radius: 10px;
    /* Radzen ships --rz-button-disabled-opacity: 0.2, which fades a disabled button to roughly
       1.3:1 against the surface behind it: unreadable, and a state an administrator has to be
       able to tell apart from a busy one. Opacity is pinned at 1 and the disabled appearance is
       set explicitly below in colours that clear 4.5:1. */
    --rz-button-disabled-opacity: 1;
    --rz-button-shadow: none;
    --rz-button-hover-shadow: none;
    --rz-button-active-shadow: none;
    --rz-button-hover-gradient: none;
    --rz-button-active-gradient: none;
    /* Radzen ships "none", so a Radzen button is invisible to a keyboard user. Nothing in the
       admin UI can be operated by keyboard without this (WCAG 2.2, 2.4.7 and 2.4.11). */
    --rz-button-focus-outline: 2px solid var(--gold-bright);

    /* Dialog chrome, from the reference's .dialog and .dialog-backdrop: the content surface a
       step above the shell, a hairline edge, 10px corners and a 60% black backdrop. */
    --rz-dialog-background-color: var(--surface);
    --rz-dialog-title-background-color: var(--surface);
    --rz-dialog-title-color: var(--ink);
    --rz-dialog-title-border: 1px solid var(--hairline);
    --rz-dialog-title-font-size: 1rem;
    --rz-dialog-title-font-weight: 600;
    --rz-dialog-title-letter-spacing: 0;
    --rz-dialog-close-color: var(--ink-muted);
    --rz-dialog-close-hover-color: var(--ink);
    --rz-dialog-mask-background-color: rgba(0, 0, 0, 0.6);
    --rz-dialog-border-radius: 10px;
    --rz-dialog-shadow: 0 22px 64px 0 rgba(0, 0, 0, 0.55);
}

/* ── Bootstrap and sb-admin-2 text utilities, remapped for a dark theme ──────────────────────
   sb-admin-2 is a LIGHT theme and its text colours were chosen for a white page. They are still
   applied, because the dialogs use .text-muted and .form-text, and .text-muted carries
   "!important" so nothing short of an equally weighted rule displaces it.

   Measured on --surface #101c30:

       .text-muted   #858796   4.80:1   scrapes AA, and reads muddy because it is a warm grey
       .form-text    #6c757d   3.64:1   FAILS AA for body text (WCAG 2.2, 1.4.3)
       --ink-muted   #9fb0c3   7.70:1   AAA, and already the palette's colour for secondary text

   So the application was rendering secondary text in a colour chosen for a white background,
   at roughly half the contrast of the token that exists for exactly this purpose. That is what
   made the dialog copy hard to read.

   These are the utilities the screens actually use. Anything else from sb-admin-2 that turns up
   in a dark context should be added here rather than worked around at the call site. */
.text-muted {
    color: var(--ink-muted) !important;
}

/* ── sb-admin-2's bare element selectors ─────────────────────────────────────────────────────
   The utilities above were the visible half of this problem. The other half is that sb-admin-2
   also styles bare elements, and a rule on the element beats inheritance outright, whatever the
   colour set on the container. So every container colour in this file simply never reached a
   paragraph:

       p { font-family:"Lato",sans-serif; letter-spacing:1px; font-size:14px; color:#333 }

   Measured against the dialog surface, this is what was leaking through:

       p         #333      1.35:1   reported as unreadable on the tenant classification dialog
       pre       #3a3b45   1.54:1
       a         #4e73df   3.93:1   and a second accent colour, Bootstrap blue
       code      #e83e8c   4.47:1
       caption   #858796   4.80:1   scrapes AA, reads muddy, same warm grey as .text-muted

   Only body had ever been reset. Fixing the paragraph alone would have left the other four to
   be found one at a time, which is how this theme has been repaired three times already, so the
   whole set is taken together here.

   Paragraphs inherit rather than take a colour of their own, because every container in this
   file already sets the right one and the only reason they were not getting it was this rule.
   The font and the letter spacing go with it: Lato is not loaded, so paragraphs were rendering
   in the fallback sans serif with 1px of tracking while everything around them was Inter.
   Font size is deliberately left alone, because screens have been laid out against it. */
p {
    color: inherit;
    font-family: inherit;
    letter-spacing: normal;
}

caption {
    color: var(--ink-muted);
}

code,
pre {
    color: var(--ink);
}

/* A link in prose, which sb-admin-2 leaves as Bootstrap blue. Anything with a class of its own,
   the sidebar items and the launcher cards among them, sets its own colour and is unaffected. */
a {
    color: var(--gold);
}

/* ── Bootstrap alerts ────────────────────────────────────────────────────────────────────────
   Measured in the running application, .alert-info was 1.12:1 and .alert-secondary 1.28:1.
   sb-admin-2 sets a near black colour on these for a pale panel, and on this theme the panel is
   dark, so the copy was invisible rather than merely dim.

   Each variant keeps its meaning through a tinted wash and a left rule in its own status
   colour, which is how the rest of this theme signals state, and the copy itself is --ink so it
   is read at 17:1 rather than at whatever the tint allows. The heading inherits, so a variant
   used for a block of explanation reads as prose rather than as a warning. */
.alert {
    border: 1px solid var(--hairline);
    border-left-width: 3px;
    border-radius: 10px;
    padding: 12px 16px;
    color: var(--ink);
    background: var(--surface-raised);
}

.alert p,
.alert li,
.alert .mb-0 {
    color: var(--ink);
}

.alert a {
    color: var(--gold);
}

.alert-secondary {
    border-left-color: var(--ink-faint);
    background: var(--surface-raised);
}

.alert-info {
    border-left-color: var(--status-info);
    background: rgba(90, 160, 208, 0.10);
}

.alert-success {
    border-left-color: var(--status-success);
    background: rgba(74, 222, 128, 0.10);
}

.alert-warning {
    border-left-color: var(--status-warning);
    background: rgba(232, 184, 75, 0.10);
}

.alert-danger {
    border-left-color: var(--status-danger);
    background: rgba(240, 103, 125, 0.12);
}

/* Hint text, and only hint text. A line that explains a field is secondary to the field, and
   --ink-muted is 7.70:1 on the dialog surface, well above the 4.5:1 floor.

   .form-check-label used to be in this list and is deliberately not any more. The label on a
   radio is the choice itself, not a note about it. */
.form-text,
.invalid-feedback ~ .form-text {
    color: var(--ink-muted);
}

/* Dialog body text.

   This rule used to set --ink-muted and then lift headings, legends and labels back to --ink.
   The intent was to catch Bootstrap's body colour leaking into a dialog, and it overshot: every
   paragraph in every dialog came out as secondary text, including the ones carrying the point.

   On the tenant classification dialog that meant the sentence explaining what the decision
   actually does, and the four lines saying what the tenant is classified as today, were all set
   in the muted grey while the headings beside them were near white. Each one measured above the
   AA floor, which is why a contrast sweep passed it and a person looking at it did not. Passing
   4.5:1 and reading as disabled are different things, and reported as washed out.

   So the default is --ink and muting is applied deliberately, to hints, rather than applied to
   everything and then taken back. The whitelist that lifted headings and labels is gone with it,
   because they now inherit the right colour. */
.modal-body,
.rz-dialog-content {
    color: var(--ink);
}

html, body {
    height: 100%;
    font-family: "Inter", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    font-size: 16px;
    background: var(--shell-900);
    color: var(--ink);
}

body {
    background: var(--shell-gradient);
    background-attachment: fixed;
    color: var(--ink);
}

h5 {
    font-family: "InterSemiBold", "Inter", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    font-size: 18px;
}

/* ── The icon set ─────────────────────────────────────────────────────────────

   One set, drawn by Shared/Icons/AppIcon.razor in the Presentation project. Before this the
   admin UI carried five: Font Awesome from a CDN kit, Radzen's Material ligatures, MudBlazor's
   Material set, open-iconic from the Blazor template, and hand written inline SVG in the shell.

   No rule here sets an icon's colour. Every icon is stroked in currentColor, so it takes the
   colour of whatever it sits inside: --ink-faint in a resting nav item, --gold in an active one,
   --shell-900 on a filled amber button, --status-danger on an outlined danger button. An icon
   that carried its own colour would have to be told about each of those, and would be wrong the
   first time a token moved. The two modifiers below set a colour only where the icon stands on
   its own with no control around it to inherit from. */

.app-icon {
    flex-shrink: 0;
    /* Sits on the text baseline rather than below it, which is what an inline SVG does by
       default and what put a 3px kink in every button that pairs an icon with a word. */
    vertical-align: -0.15em;
}

/* An icon alone on a loading screen has nothing to inherit from, so it is named here. */
.app-icon--gold {
    color: var(--gold);
}

.app-icon--spin {
    animation: app-icon-spin 0.9s linear infinite;
    transform-origin: 50% 50%;
}

/* The part of the ring that is not the moving head. Opacity rather than a second colour, so the
   spinner still inherits and still works on any surface. */
.app-icon__spinner-track {
    opacity: 0.25;
}

@keyframes app-icon-spin {
    to {
        transform: rotate(360deg);
    }
}

/* Respecting a reduced motion preference is not optional for something that turns continuously
   (WCAG 2.2, 2.3.3). The spinner stops and reads as a static ring; the live region beside every
   one of them is what actually announces that work is in progress. */
@media (prefers-reduced-motion: reduce) {
    .app-icon--spin {
        animation: none;
    }
}

/* A Radzen button lays its child content out inline, so an icon and its label need the gap the
   Radzen icon span used to bring with it. */
.rz-button .app-icon + .rz-button-text {
    margin-left: 8px;
}

/* Back, above a detail page. Was an sb-admin-2 split button with the icon in its own coloured
   block; it is a ghost button with an icon and a word, spaced like every other. */
.admin-back-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

/* ── App shell: left sidebar + slim top bar ───────────────────────────────────

   Lifted from the reference implementation, AF.CreditReportParser.Web, wwwroot/css/app.css,
   ".app-shell" section. Structure and measurements are the reference's, unchanged. Only the
   three divergences called out below are the admin UI's own, and each has a reason.

   The markup that uses this is AppShell.razor in AF.Main.Admin.UI.Presentation. It carries the
   admin UI's own wording; nothing here names a Lustro screen. */

/* #wrapper is where the Blazor root component mounts (Program.cs), and sb-admin-2.min.css
   declares "#wrapper { display: flex }". Every layout therefore renders as a FLEX ITEM, and a
   flex item sizes to its content rather than filling its parent.

   This is stated once, here, for every layout. It was previously stated only on .app-shell, so
   .login-shell and .logout-shell sized to their card and left the rest of the viewport bare.
   A layout added later would have inherited the same trap and the same hour of confusion.

   Remove this only when sb-admin-2 goes, and check every layout when you do. */
#wrapper > * {
    flex: 1 1 auto;
    min-width: 0;
}

.app-shell {
    display: flex;
    min-height: 100vh;
    /* DIVERGENCE 1. The reference renders into a plain div. The admin UI renders into #wrapper,
       which sb-admin-2 declares "display: flex", so the shell is a flex item and would otherwise
       size to its content and leave the rest of the viewport bare. Growing to fill is what the
       reference gets for free from a block parent. */
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
}

.app-sidebar {
    width: 240px;
    flex-shrink: 0;
    background: var(--shell-900);
    border-right: 1px solid var(--hairline);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

.app-sidebar__brand {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 64px;
    padding: 0 20px;
    border-bottom: 1px solid var(--hairline);
    text-decoration: none;
}

.app-sidebar__brand-mark {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    /* White fill matches the Allegiant logo's own background so the mark reads as one piece */
    border: 1px solid #ffffff;
    background: #ffffff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
}

.app-sidebar__brand-mark img {
    width: 22px;
    height: 22px;
    object-fit: contain;
}

.app-sidebar__brand-words {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.app-sidebar__brand-sub {
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-muted);
}

.app-sidebar__brand-name {
    font-family: InterSemiBold;
    font-size: 15px;
    /* Lustro carries 0.16em, chosen for LUSTRO: one word, six letters. The wordmark here is
       "Platform Admin", fourteen characters, and the brand block has 154px to work in once the
       240px sidebar gives up its padding, the 34px mark and the 12px gap. At the reference
       tracking that measures wider than the box and the mark wraps or clips. Reduced to match
       the tracking on --brand-sub directly above, so the two lines of the wordmark are set
       consistently rather than one of them being tuned to a word we no longer use. */
    letter-spacing: 0.08em;
    color: var(--ink);
}

.app-sidebar__nav {
    flex: 1;
    padding: 18px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.app-nav-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 8px;
    color: var(--ink-muted);
    text-decoration: none;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.app-nav-item:hover {
    background: var(--surface-hover);
    color: var(--ink);
    text-decoration: none;
}

.app-nav-item.active {
    background: var(--surface);
    color: var(--ink);
}

/* The active marker is a bar, not a tint. Shape and position carry the state, so it survives
   greyscale, high contrast and colour blindness, which a change of colour alone would not
   (WCAG 2.2, 1.4.1 Use of Colour). aria-current="page" in the markup carries the same fact to
   assistive technology, which cannot see the bar at all. */
.app-nav-item.active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 20px;
    background: var(--gold);
    border-radius: 0 3px 3px 0;
}

.app-nav-item .app-nav-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--ink-faint);
}

.app-nav-item:hover .app-nav-icon,
.app-nav-item.active .app-nav-icon {
    color: var(--gold);
}

/* DIVERGENCE 2. The reference leaves focus to the browser default, which is a thin dark ring and
   is all but invisible on this navy. Every shell control is reachable by keyboard, so every one
   of them needs a focus state that can actually be seen (WCAG 2.2, 2.4.7 and 2.4.11).
   :focus-visible rather than :focus, so a pointer click does not leave a ring behind. */
.app-nav-item:focus-visible,
.app-sidebar__brand:focus-visible {
    outline: 2px solid var(--gold-bright);
    outline-offset: 2px;
    color: var(--ink);
}

.app-sidebar__footer {
    padding: 16px 12px;
    border-top: 1px solid var(--hairline);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.app-user-chip {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--hairline);
    border-radius: 10px;
    background: var(--surface);
}

.app-user-chip__avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--surface-hover);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ink);
    flex-shrink: 0;
}

.app-user-chip__words {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    /* The chip shows what is known and nothing else, so the words box can be empty or hold one
       line rather than two. min-width: 0 keeps a long name from pushing the chip wider than the
       sidebar. */
    min-width: 0;
    overflow: hidden;
}

.app-user-chip__name {
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-user-chip__role {
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-muted);
}

.app-main {
    flex: 1;
    /* min-width: 0 is what keeps a wide grid inside the main column instead of pushing the page
       sideways. Without it a flex item floors at its content width and the whole page scrolls
       horizontally. The 1280px guarantee rests on this line. */
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.app-topbar {
    height: 56px;
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 0 24px;
    border-bottom: 1px solid var(--hairline);
    background: rgba(6, 11, 24, 0.65);
    backdrop-filter: blur(8px);
}

.app-topbar__title {
    font-family: InterSemiBold;
    font-size: 14px;
    color: var(--ink);
}

.app-content {
    flex: 1;
    padding: 24px;
    min-width: 0;
    /* DIVERGENCE 3. The screens inside still carry sb-admin-2 markup, and .container on a wide
       viewport pins content to a fixed centred width. Overriding it here lets the content column
       use the width the shell gives it. The grids themselves are a later story; this only stops
       the shell being undone by the page it wraps. */
    overflow-x: auto;
}

.app-content > .container,
.app-content .container-fluid {
    width: 100%;
    max-width: none;
    padding-left: 0;
    padding-right: 0;
}

/* ── Grids ────────────────────────────────────────────────────────────────────

   The reference styles a plain <table> (AF.CreditReportParser.Web, wwwroot/css/app.css, the
   "table" section). The admin UI renders Radzen grids, so the same treatment is mapped onto
   Radzen's own classes once here rather than restated on every page. The measurements are the
   reference's, unchanged: 13px Inter, a raised header row in muted 12px semibold, hairline
   rules, 6px by 12px cells, and a surface-hover row highlight. */

.rz-data-grid,
.rz-datatable {
    width: 100%;
    background: transparent;
    border: 0;
}

/* Full width and automatic layout.

   This is the whole of the "no horizontal scrollbar at 1280px" guarantee. A table laid out
   automatically at width 100% divides the width it is given between its columns and sizes each
   to its content, so it cannot exceed its container at any viewport. Radzen switches to
   table-layout: fixed through .rz-grid-table-fixed as soon as a column carries an explicit
   width, and a fixed layout honours those widths whatever the container measures. The tenants
   and tokens grids between them declared about 2,400px of fixed columns against the 922px the
   shell leaves at 1280px, which is what produced the scrollbar. Those pixel widths are gone
   from the pages; overriding the class as well stops a later column reintroducing the problem
   for every grid at once. */
.rz-data-grid .rz-grid-table,
.rz-data-grid .rz-grid-table-fixed {
    width: 100%;
    table-layout: auto;
    border-collapse: collapse;
    font: 13px/1.4 "Inter", "Segoe UI", -apple-system, sans-serif;
    color: var(--ink);
}

.rz-data-grid .rz-grid-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface-raised);
    padding: 8px 12px;
    text-align: left;
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-muted);
    border: 0;
    border-bottom: 1px solid var(--hairline);
    white-space: nowrap;
    text-transform: none;
    letter-spacing: 0;
}

/* Radzen sets its own size and colour on the title span inside the header cell, so the cell's
   own treatment has to be handed down or the raised row keeps Radzen's typography. */
.rz-data-grid .rz-grid-table thead th .rz-column-title,
.rz-data-grid .rz-grid-table thead th .rz-column-title-content {
    font: inherit;
    color: inherit;
}

.rz-data-grid .rz-grid-table td,
.rz-data-grid .rz-grid-table tbody > tr > td {
    padding: 6px 12px;
    border: 0;
    border-bottom: 1px solid var(--hairline);
    vertical-align: middle;
    /* Cell content wraps rather than widening its column. A capability list or a drift summary
       reads perfectly well over two lines, and neither is worth a horizontal scrollbar. */
    white-space: normal;
    overflow-wrap: anywhere;
}

.rz-data-grid .rz-grid-table tbody > tr:hover > td {
    background: var(--surface-hover);
}

/* The selected row.

   Selection is a current state, so it is marked in the one accent, in the same way the navigation
   marks the page you are on. It used to be declared page by page in a copied <style> block as
   #1E88E5 with white text, which was a second accent colour and a second palette.

   The tint is deliberately quiet and the text stays --ink rather than flipping to --shell-900 on
   a full amber fill, because --ink on a 14% amber wash over --surface stays above 4.5:1 where a
   row of solid amber behind body text does not (WCAG 2.2, 1.4.3). The left edge carries the state
   as well as the tint, so selection does not rest on colour alone (1.4.1). */
/* Two classes, because there are two ways a row here becomes the selected one. Radzen marks its
   own selection with rz-state-highlight; the e-signature templates grid marks its own with a
   plain .selected from RowRender. Both must look the same, and both must be readable. */
.rz-data-grid .rz-grid-table tbody > tr.selected > td,
tbody > tr.selected > td,
tr.selected > td,
.rz-data-grid .rz-grid-table tbody > tr.rz-state-highlight > td,
.rz-selectable tbody tr.rz-data-row.rz-state-highlight > td {
    background: rgba(232, 184, 75, 0.14);
    color: var(--ink);
}

/* Radzen paints the selected row's text on the inner span rather than the cell, so a colour set
   on the td alone is overridden by its own rule and the row stays unreadable. */
.rz-selectable tbody tr.rz-data-row.rz-state-highlight .rz-cell-data,
tr.selected > td .rz-cell-data {
    color: var(--ink);
}

tr.selected > td:first-child,
tr.rz-state-highlight > td:first-child {
    box-shadow: inset 3px 0 0 0 var(--gold);
}

/* The empty state.

   The reference centres a line that says what to do next rather than reporting that there is
   nothing there: "Use the search filter above to find contacts." Radzen's own default reads
   "No records to display", which tells an administrator nothing they cannot already see. Every
   grid supplies an EmptyTemplate built on this class, so the default is never reached. */
/* A line of orientation under a card heading, for a screen whose first step is not the obvious
   one. --ink-muted rather than --ink-faint, because this is text to be read rather than a label
   beside something else. */
.card-lead {
    margin: 0 0 16px;
    max-width: 68ch;
    color: var(--ink-muted);
    font-size: 13px;
    line-height: 1.5;
}

.admin-grid-empty {
    padding: 28px 12px;
    text-align: center;
    color: var(--ink-muted);
    font-size: 13px;
}

.admin-grid-empty__title {
    display: block;
    margin-bottom: 4px;
    color: var(--ink);
    font-family: "InterSemiBold", "Inter", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}

/* Row actions share a single column. Three buttons in three columns spent roughly 340px of a
   922px grid on chrome alone, and an unbroken run of buttons is the one thing a narrower
   window cannot absorb. Wrapping hands that width back to the data. */
.admin-grid-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: flex-start;
}

/* The reference's treatment for an identifier column (table td.id): monospace, faint, and
   ellipsised rather than left to set the column width. A GUID is 36 characters that nobody
   reads left to right, and it should not cost a quarter of the grid. The field stays a
   readonly input so it can still be selected and copied. */
.admin-grid-id {
    width: 100%;
    min-width: 0;
    max-width: 180px;
    background: transparent;
    border: 0;
    padding: 0;
    font-family: ui-monospace, Consolas, monospace;
    font-size: 12px;
    color: var(--ink-faint);
    text-overflow: ellipsis;
}

/* ── Forms, buttons and dialogs ───────────────────────────────────────────────

   From the reference implementation, AF.CreditReportParser.Web, wwwroot/css/app.css: the
   "label", ".form-control", "button", "button.alt", "button.danger", ".dialog" and
   ".search-bar" rules. The admin UI renders Radzen controls and leftover Bootstrap classes
   rather than the reference's bare elements, so the treatment is mapped onto both here, once,
   instead of being restated on every page.

   One accent. Amber marks a primary action and the current state, and nothing else. Everything
   secondary is a ghost: no fill, a hairline border, ink text. That single restriction is most
   of why the reference reads as calm, and it is why ButtonStyle.Success and ButtonStyle.Warning
   no longer appear anywhere in the markup. ButtonStyle.Warning was the worse of the two:
   --status-warning is #e8b84b, the same value as --gold, so a warning button was literally the
   primary accent spent on a secondary action.

   Radzen's own accent styles are deliberately not remapped to the ghost here. Doing so would
   let ButtonStyle.Success keep working and quietly reappear on the next page somebody adds. The
   guard is in the markup instead: ControlStylingTests fails the build if either style returns. */

/* Labels sit above their field, never beside it, and the field below fills the row. The
   reference does this everywhere and the reason is scanning rather than taste: a column of
   label-then-field can be read straight down, where a label beside its field makes the eye
   track sideways on every row. */
/* A field's label names the thing being asked for, so it is --ink rather than the muted grey it
   used to carry. Its hint underneath stays muted, which is what carries the hierarchy; doing it
   with colour on the label as well left the question quieter than the note about it. */
.form-label,
.rz-label,
.admin-field > label {
    display: block;
    margin-bottom: 4px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink);
}

.admin-field {
    margin-bottom: 12px;
}

/* Help text below a field, pointed at by aria-describedby so it is announced with the control
   rather than stranded after it. --ink-muted is 7.3:1 on every surface in the set, so this is
   quieter than the field's own text without dropping below 4.5:1 (WCAG 2.2, 1.4.3). */
.admin-field__hint {
    margin-top: 4px;
    font-size: 12px;
    line-height: 1.5;
    color: var(--ink-muted);
}

/* The name of a value that a page has produced rather than asked for, such as a generated signing
   link. It is not a <label>, because there is no control for it to label; it reads like one so
   that a result panel scans the same way as the form above it. */
.admin-result__label {
    display: block;
    margin-bottom: 4px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-muted);
}

/* A row of fields with the action at the end of it, not below it. The reference's .search-bar.
   Each field grows to share the row; the trailing action is capped so it stays button sized. */
.admin-form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-end;
    margin-bottom: 16px;
}

.admin-form-row > * {
    flex: 1 1 180px;
    min-width: 0;
    margin-bottom: 0;
}

.admin-form-row > *:last-child {
    flex: 0 0 auto;
    max-width: 200px;
}

/* The action row above a grid. Wraps, so a narrow window stacks the buttons rather than
   pushing the page sideways. */
.admin-action-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    margin-bottom: 16px;
}

/* Actions at the foot of a dialog, ranged right with the primary last, which is the reference's
   order and matches the platform convention on Windows. */
/* The row of actions above a grid. One place for the primary action on a screen, so that
   "Add capability" sits where "Add Tenant" and "Create new admin" already sit and nobody has to
   look for it. */
.admin-grid-toolbar {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-bottom: 14px;
}

.admin-dialog-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
    margin-top: 20px;
}

/* Fields. The Radzen controls take these from the --rz-input-* block on :root; these rules are
   for the plain <input class="form-control"> and <select> that the hand written dialogs and the
   step up prompt still render. Full width and 40px tall, a quiet hairline border on the raised
   fill, as the reference has it. */
.form-control,
.admin-field input,
.admin-field select,
.admin-field textarea {
    width: 100%;
    min-height: 40px;
    padding: 9px 12px;
    background: var(--surface-raised);
    border: 1px solid var(--hairline);
    border-radius: 8px;
    color: var(--ink);
    font: 14px/1.4 "Inter", "Segoe UI", -apple-system, sans-serif;
}

.form-control::placeholder {
    color: var(--ink-faint);
}

.form-control:disabled,
.form-control[readonly] {
    background: var(--surface);
    /* The reference fades a disabled field to --ink-muted, which clears 4.5:1 on every surface
       in the set. A readonly field here is not decoration: the step up prompt shows the signed
       in email in one, and it has to be read to be checked. */
    color: var(--ink-muted);
}

/* A native <select> renders its list with the operating system's own colours unless the options
   are given the surface explicitly, which on a dark theme means black on white mid form. */
select.form-control option {
    background: var(--surface-raised);
    color: var(--ink);
}

/* Help text below a field. Bootstrap's .form-text is #6c757d, which is about 4:1 on --surface and
   so fails as body copy; the classify tenant dialog states what each classification means in it,
   which is the text an administrator most needs to read (WCAG 2.2, 1.4.3). --ink-muted is 7.3:1.
   Same value as .admin-field__hint, because they are the same thing under two class names: one is
   Bootstrap's, the other is ours, and the dialogs were written against the first. */
.form-text {
    margin-top: 4px;
    font-size: 12px;
    line-height: 1.5;
    color: var(--ink-muted);
}

/* Radios and checkboxes. Bootstrap paints an unchecked control white with a black hairline, which
   is the one light mark on a navy dialog, and a checked one #0d6efd: a second accent, and exactly
   the kind of stray blue this story exists to remove. A checked radio is a current state, so it
   takes the one accent. */
.form-check-input {
    background-color: var(--surface-raised);
    border: 1px solid var(--hairline);
}

.form-check-input:checked {
    background-color: var(--gold);
    border-color: var(--gold);
}

/* The tick and the dot are drawn as a background image whose fill Bootstrap hardcodes to white,
   which all but vanishes on amber. --shell-900, as on a primary button. */
.form-check-input:checked[type="checkbox"] {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23060b18' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}

.form-check-input:checked[type="radio"] {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23060b18'/%3e%3c/svg%3e");
}

.form-check-input:focus {
    border-color: var(--gold);
    box-shadow: none;
}

.form-check-input:focus-visible {
    outline: 2px solid var(--gold-bright);
    outline-offset: 2px;
}

.form-check-input:disabled {
    opacity: 1;
    background-color: var(--surface);
    border-color: var(--hairline);
}

.form-check-label {
    color: var(--ink);
}

/* A grouped set of controls. The classify tenant dialog groups its two radios in a fieldset, whose
   legend is the question the radios answer, so it has to read as a heading rather than as the
   browser's default black text on the border. */
fieldset > legend {
    float: none;
    width: auto;
    padding: 0;
    margin-bottom: 8px;
    font-size: 14px;
    color: var(--ink);
}

/* Chrome paints an autofilled field a fixed pale yellow, which puts near black text on the one
   light surface in the whole application. A large inset shadow is the only way to repaint it. */
.form-control:-webkit-autofill,
.form-control:-webkit-autofill:hover,
.form-control:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 1000px var(--surface-raised) inset;
    -webkit-text-fill-color: var(--ink);
}

/* Focus.

   Divergence from the reference, and the one place in this section that does not lift its rule.
   The reference marks focus with box-shadow: 0 0 0 2px rgba(232, 184, 75, 0.25). A quarter
   opacity gold over --surface-raised composites to about #48463e, which is roughly 1.4:1
   against the field it is meant to be marking: well under the 3:1 that a focus indicator needs
   as a non-text mark (WCAG 2.2, 1.4.11, and 2.4.11 Focus Appearance). A solid --gold-bright
   outline at 2px clears 3:1 against every surface in the set, and the offset keeps it clear of
   the field's own border so the two do not read as one thick edge. This is the same treatment
   login.css already uses, so focus looks the same before and after signing in. */
.form-control:focus,
.admin-field input:focus,
.admin-field select:focus,
.admin-field textarea:focus {
    background: var(--surface-raised);
    color: var(--ink);
    border-color: var(--gold);
    outline: none;
}

.form-control:focus-visible,
.rz-button:focus-visible,
.rz-textbox:focus-visible,
.rz-textarea:focus-visible,
.btn:focus-visible,
.admin-field input:focus-visible,
.admin-field select:focus-visible,
.admin-field textarea:focus-visible {
    outline: 2px solid var(--gold-bright);
    outline-offset: 2px;
}

/* Radzen sets the outline on :focus rather than :focus-visible, so the offset has to be given
   the same way or a clicked button draws its ring flush against its own edge. */
.rz-button:focus {
    outline-offset: 2px;
}

/* Primary actions. Amber fill, near black text, and the same 1px transparent border the
   reference gives every button so a filled and a ghost button on one row share a box height and
   sit on the same baseline. */
.rz-button.rz-primary,
.btn-primary,
.rz-dialog-confirm-buttons .rz-button.rz-primary {
    background: var(--gold);
    background-image: none;
    color: var(--shell-900);
    border: 1px solid transparent;
    border-radius: 10px;
    padding: 7px 14px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
    vertical-align: middle;
}

.rz-button.rz-primary:not(.rz-state-disabled):hover,
.rz-button.rz-primary:not(.rz-state-disabled):active,
.btn-primary:not(:disabled):hover,
.btn-primary:not(:disabled):active {
    background: var(--gold-bright);
    background-image: none;
    color: var(--shell-900);
}

/* Secondary actions are ghosts. Transparent fill, hairline border, ink text: present but not
   competing with the one amber action on the screen. ButtonStyle.Secondary with
   Variant.Outlined is the pairing the markup uses; .rz-light and .rz-base are here so that a
   Radzen internal control, a paginator or a grid's own button, matches rather than reverting to
   the theme's grey. */
.rz-button.rz-secondary,
.rz-button.rz-light,
.rz-button.rz-base,
.btn-secondary,
.btn-light,
.rz-dialog-confirm-buttons .rz-button.rz-secondary,
.rz-dialog-confirm-buttons .rz-button.rz-light,
.rz-dialog-confirm-buttons .rz-button.rz-base {
    background: transparent;
    background-image: none;
    color: var(--ink);
    border: 1px solid var(--hairline);
    border-radius: 10px;
    padding: 7px 14px;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    vertical-align: middle;
}

.rz-button.rz-secondary:not(.rz-state-disabled):hover,
.rz-button.rz-light:not(.rz-state-disabled):hover,
.rz-button.rz-base:not(.rz-state-disabled):hover,
.btn-secondary:not(:disabled):hover,
.btn-light:not(:disabled):hover {
    background: var(--surface-hover);
    background-image: none;
    color: var(--ink);
    border-color: var(--hairline);
}

/* Destructive actions. Not amber, and not a ghost either: the reference gives its danger button
   a fill of its own, because an action that cannot be undone should not look like the action
   next to it. Revoking is a filled danger button and regenerating an outlined one, so the two
   are told apart by weight as well as by their labels. */
.rz-button.rz-danger,
.btn-danger {
    background: var(--status-danger);
    background-image: none;
    color: var(--shell-900);
    border: 1px solid transparent;
    border-radius: 10px;
    padding: 7px 14px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
    vertical-align: middle;
}

.rz-button.rz-danger:not(.rz-state-disabled):hover,
.btn-danger:not(:disabled):hover {
    background: #f3899a;
    background-image: none;
    color: var(--shell-900);
}

/* An outlined danger button carries the colour as text and border rather than as a fill.
   --status-danger on --surface is 5.6:1 and on --surface-hover 4.9:1, so the label stays
   readable on the row highlight as well as off it (WCAG 2.2, 1.4.3). */
.rz-button.rz-danger.rz-variant-outlined,
.rz-button.rz-danger.rz-variant-text {
    background: transparent;
    background-image: none;
    color: var(--status-danger);
    border: 1px solid var(--status-danger);
}

.rz-button.rz-danger.rz-variant-outlined:not(.rz-state-disabled):hover,
.rz-button.rz-danger.rz-variant-text:not(.rz-state-disabled):hover {
    background: var(--surface-hover);
    background-image: none;
    color: var(--status-danger);
}

/* Disabled.

   Divergence from the reference, for the same reason as focus. The reference disables a primary
   button with rgba(232, 184, 75, 0.25) behind rgba(6, 11, 24, 0.6), which composites to roughly
   1.5:1 and is legible only because you already know what it says. Radzen is worse again: it
   ships --rz-button-disabled-opacity: 0.2 and fades the whole control. Every disabled button
   here instead takes the raised surface with --ink-muted text, which is 7.3:1, and keeps its
   hairline border so it still reads as a control rather than as a caption. The state is not
   carried by contrast alone in any case: the disabled attribute reaches assistive technology,
   and the cursor stops changing (WCAG 2.2, 1.4.3 and 1.4.1). */
.rz-button.rz-state-disabled,
.rz-button:disabled,
.btn:disabled,
.btn.disabled {
    background: var(--surface-raised);
    background-image: none;
    color: var(--ink-muted);
    border: 1px solid var(--hairline);
    opacity: 1;
}

/* An icon inside a button takes the button's colour, or Radzen keeps its own and an amber
   primary ends up with a pale icon on a pale fill. */
.rz-button .rz-button-icon-left,
.rz-button .rz-button-icon-right,
.rz-button .rzi,
.btn .rzi {
    color: inherit;
}

/* Dialog chrome. The --rz-dialog-* block on :root does the work for every Radzen dialog and
   confirmation; these two rules cover the parts Radzen does not expose as a variable. */
.rz-dialog {
    border: 1px solid var(--hairline);
    color: var(--ink);
}

.rz-dialog-content {
    color: var(--ink);
}

/* The hand written dialogs, the step up password prompt and the token reveal, render their own
   container rather than going through Radzen. Same chrome, one class. */
.admin-dialog {
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: 10px;
    color: var(--ink);
    padding: 20px;
}

/* Alerts. Bootstrap's own alert colours are near black text on pastel, which is the one light
   block on an otherwise navy page. These keep Bootstrap's class names, since the markup already
   uses them, and restate them as a tinted panel with an ink label and a coloured edge, so the
   status is carried by the border and the wording rather than by the fill alone (WCAG 2.2,
   1.4.1). */
.alert {
    border-radius: 8px;
    border: 1px solid var(--hairline);
    background: var(--surface-raised);
    color: var(--ink);
}

.alert-danger {
    border-color: var(--status-danger);
    background: rgba(240, 103, 125, 0.12);
    color: var(--ink);
}

.alert-warning {
    border-color: var(--status-warning);
    background: rgba(232, 184, 75, 0.12);
    color: var(--ink);
}

.alert-info {
    border-color: var(--status-info);
    background: rgba(90, 160, 208, 0.12);
    color: var(--ink);
}

.alert-success {
    border-color: var(--status-success);
    background: rgba(74, 222, 128, 0.12);
    color: var(--ink);
}

/* Validation text. --status-danger on the surfaces in this set clears 4.5:1, and the message is
   always adjacent to the field it belongs to rather than colour coded from a distance. */
.validation-message,
.text-danger {
    color: var(--status-danger);
}

/* Bootstrap's remaining text colour helpers, which the dialogs already use. Left alone they are
   Bootstrap's own palette rather than this one: .text-muted is #6c757d, about 4:1 on --surface and
   so below the threshold for body text, and .text-warning is #ffc107, a second yellow sitting a
   few degrees from the accent and read as a mistake rather than as a distinction. Each is mapped
   onto the status token it means. None of these is ever the only carrier of its meaning: the
   wording says what the state is, and a panel that needs weight uses .alert with its border
   (WCAG 2.2, 1.4.1 and 1.4.3). */
.text-muted,
.text-secondary {
    color: var(--ink-muted);
}

.text-warning {
    color: var(--status-warning);
}

.text-success {
    color: var(--status-success);
}

.text-info {
    color: var(--status-info);
}

/* Cards. The admin UI's screens are still wrapped in sb-admin-2 cards, whose default is a white
   panel with a grey header. Left alone they punch a light rectangle through every page. */
.card {
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: 10px;
    color: var(--ink);
}

.card-header {
    background: transparent;
    border-bottom: 1px solid var(--hairline);
    color: var(--ink);
    font-family: "InterSemiBold", "Inter", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    font-size: 16px;
    padding: 14px 20px;
}

.card-body {
    background: transparent;
    color: var(--ink);
}

/* Scrollbars to match the dark theme. From the same section of the reference: without them a
   scrollbar renders as a light strip against the navy on every screen that has one. */
*::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

*::-webkit-scrollbar-track {
    background: transparent;
}

*::-webkit-scrollbar-thumb {
    background: rgba(90, 140, 180, 0.22);
    border-radius: 8px;
}

*::-webkit-scrollbar-thumb:hover {
    background: rgba(90, 140, 180, 0.35);
}

/* The sidebar stacks below 720px, as the reference does. The 1280px guarantee is unaffected:
   above this breakpoint the sidebar is a fixed 240px and .app-main takes the rest. */
@media (max-width: 720px) {
    .app-shell {
        flex-direction: column;
    }

    .app-sidebar {
        width: 100%;
        height: auto;
        position: static;
        flex-direction: row;
        align-items: center;
        overflow-x: auto;
    }

    .app-sidebar__nav {
        flex-direction: row;
        padding: 8px;
    }

    .app-sidebar__footer {
        border-top: none;
        border-left: 1px solid var(--hairline);
    }
}
