/* ==========================================================================
   Contractor, the Daveng Contractor App
   Brand theme, copied from RADAR and trimmed to what this app uses. Palette
   sampled from the Daveng logo artwork and daveng.co.za.

   Linked by _Layout.cshtml and _LoginLayout.cshtml before site.css.
   Never hard-code a colour, font or spacing value in a view. Use these
   variables and the dv- utility classes.

   Look and feel follows the Daveng public site: white and light, bright blue
   for action, navy reserved for the sidebar and for type, green only for
   positive outcomes. Soft diffuse shadows rather than hard borders.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Self-hosted Montserrat. No CDN.
   -------------------------------------------------------------------------- */
@font-face {
    font-family: 'Montserrat';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../lib/fonts/montserrat-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: 'Montserrat';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../lib/fonts/montserrat-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;
}

:root {
    /* --- Primary brand, sampled from the logo --- */
    --dv-navy:          #1A1348;
    --dv-navy-deep:     #120C36;
    --dv-navy-soft:     #2A2260;
    --dv-blue:          #0071A8;
    --dv-blue-bright:   #0089CC;
    --dv-blue-light:    #2B7BB9;
    --dv-blue-deep:     #114675;
    --dv-green:         #7EC245;
    --dv-green-deep:    #5E9B2C;
    --dv-grey:          #808285;

    /* --- Chrome gradient ------------------------------------------------
       Drawn from the statistics band on daveng.co.za, which runs indigo to
       blue. Deepened from the band itself: a full height sidebar carries far
       more area than a small stat tile, so the same values read washed out.
       Used for the sidebar and the other large coloured surfaces so they
       read as one family. Both ends clear AA against white text by a wide
       margin - 12.1:1 at the top, 8.2:1 at the bottom. */
    --dv-chrome-from:   #222A6A;
    --dv-chrome-mid:    #1B3B77;
    --dv-chrome-to:     #134A72;

    /* --- Neutrals --- */
    --dv-text:          #2B2F3A;
    --dv-text-muted:    #6B7280;
    --dv-line:          #C9D2E2;
    --dv-line-soft:     #E6EAF3;
    --dv-surface:       #FFFFFF;
    --dv-canvas:        #F5F7FC;

    /* --- Tints, used for icon chips and soft fills --- */
    --dv-tint-blue:     #E6F2FA;
    --dv-tint-navy:     #ECEAF5;
    --dv-tint-green:    #EDF7E2;
    --dv-tint-amber:    #FEF4E2;
    --dv-tint-red:      #FDECEC;

    /* --- States --- */
    --dv-success:       #7EC245;
    --dv-warning:       #E8930C;
    --dv-danger:        #DC2626;
    --dv-info:          #0EA5E9;

    /* --- Structure ---

       Leon, 17 September 2026: "The look and feel is very subtle. I can hardly
       see the lines of the textboxes." The portal runs on a tablet, so every
       box now has a definite edge, every card is a framed panel with a light
       shadow, and the controls are big enough to hit with a thumb. */
    --dv-radius:        12px;
    --dv-radius-sm:     10px;
    --dv-radius-pill:   999px;
    --dv-shadow:        0 1px 2px rgba(26, 19, 72, 0.04), 0 4px 16px rgba(26, 19, 72, 0.06);
    --dv-shadow-hover:  0 2px 4px rgba(26, 19, 72, 0.05), 0 12px 28px rgba(26, 19, 72, 0.12);
    --dv-shadow-lg:     0 16px 48px rgba(26, 19, 72, 0.18);
    --dv-shadow-bar:    0 1px 3px rgba(26, 19, 72, 0.07);

    --dv-sidebar-w:     236px;
    --dv-rail-w:        66px;
    --dv-appbar-h:      60px;

    /* --- Spacing scale --- */
    --dv-space-1:       4px;
    --dv-space-2:       8px;
    --dv-space-3:       12px;
    --dv-space-4:       16px;
    --dv-space-5:       24px;
    --dv-space-6:       32px;

    /* --- Field use --- */
    --dv-tap:           48px;

    /* The edge of anything a person types into or picks from, and the edge of
       a card. Darker than the old --dv-line, which was almost invisible on a
       tablet in daylight. */
    --dv-field-line:    #C6CFDF;
    --dv-field-hover:   #A5B2C9;
    --dv-card-line:     #D5DDEB;

    /* --- Type --- */
    --dv-font-head:     'Montserrat', 'Segoe UI', Helvetica, Arial, sans-serif;
    --dv-font-body:     'Segoe UI', Helvetica, Arial, sans-serif;
    --dv-font-pdf:      Calibri, sans-serif;
}

/* --------------------------------------------------------------------------
   Bootstrap 5 variable overrides
   -------------------------------------------------------------------------- */
:root {
    --bs-primary:       #0071A8;
    --bs-primary-rgb:   0, 113, 168;
    --bs-secondary:     #808285;
    --bs-success:       #7EC245;
    --bs-danger:        #DC2626;
    --bs-warning:       #E8930C;
    --bs-info:          #0EA5E9;
    --bs-body-color:    #2B2F3A;
    --bs-body-bg:       #F5F7FC;
    --bs-border-color:  #E7EAF2;
    --bs-link-color:    #0071A8;
    --bs-link-hover-color: #114675;
    --bs-border-radius: 10px;
    --bs-font-sans-serif: 'Segoe UI', Helvetica, Arial, sans-serif;
}

html {
    font-size: 14px;
}

@media (min-width: 768px) {
    html {
        font-size: 15px;
    }
}

body {
    font-family: var(--dv-font-body);
    color: var(--dv-text);
    background: var(--dv-canvas);
    margin-bottom: 0;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6,
.dv-kpi-value,
.navbar-brand {
    font-family: var(--dv-font-head);
    color: var(--dv-navy);
    font-weight: 700;
}

h4 {
    font-size: 1.3rem;
    letter-spacing: -0.3px;
    margin-bottom: 0;
}

a {
    color: var(--dv-blue);
    text-decoration: none;
}

a:hover {
    color: var(--dv-blue-deep);
    text-decoration: underline;
}

hr {
    border-color: var(--dv-line);
    opacity: 1;
}

/* ==========================================================================
   APPLICATION SHELL
   ========================================================================== */

.dv-shell {
    display: flex;
    min-height: 100vh;
    align-items: stretch;
}

/* --------------------------------------------------------------------------
   Sidebar
   -------------------------------------------------------------------------- */
.dv-sidebar {
    width: var(--dv-sidebar-w);
    flex: 0 0 var(--dv-sidebar-w);
    background: linear-gradient(165deg, var(--dv-chrome-from) 0%, var(--dv-chrome-mid) 52%, var(--dv-chrome-to) 100%);
    color: rgba(255, 255, 255, 0.82);
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1040;
    /* Visible, not hidden: the Configure and user menus open upward out of the
       sidebar foot and must not be clipped by it. Scrolling is handled by
       .dv-nav alone. */
    overflow: visible;
    transition: width 0.2s ease, flex-basis 0.2s ease;
}

/* A soft edge, echoing the logo gradient. */
.dv-sidebar::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 1px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.28), rgba(126, 194, 69, 0.4) 60%, transparent);
}

/* --- Brand row --- */
.dv-brand-row {
    display: flex;
    align-items: center;
    gap: var(--dv-space-1);
    padding: var(--dv-space-3) var(--dv-space-3) var(--dv-space-3) 14px;
    flex-shrink: 0;
    position: relative;
}

.dv-brand-row::after {
    content: '';
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 0;
    height: 1px;
    background: linear-gradient(90deg, var(--dv-blue-bright), rgba(126, 194, 69, 0.6) 60%, transparent);
    opacity: 0.7;
}

.dv-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    min-width: 0;
    flex: 1;
}

.dv-brand:hover {
    text-decoration: none;
}

.dv-brand-mark {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border-radius: var(--dv-radius-sm);
    background: var(--dv-surface);
    padding: 3px;
    object-fit: contain;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}

.dv-brand-text {
    line-height: 1.15;
    min-width: 0;
    overflow: hidden;
}

.dv-brand-name {
    display: block;
    font-family: var(--dv-font-head);
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: 3px;
    color: #FFFFFF;
    white-space: nowrap;
}

/* The signed in user's contractor, under the word Contractor. A long name is
   cut short with an ellipsis and read in full on hover. */
.dv-brand-sub {
    display: block;
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.72);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 2px;
}

/* --- Collapse to rail --- */
.dv-rail-toggle {
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: var(--dv-radius-sm);
    background: rgba(255, 255, 255, 0.14);
    color: rgba(255, 255, 255, 0.8);
    transition: background 0.15s, color 0.15s, transform 0.2s;
}

.dv-rail-toggle svg {
    width: 15px;
    height: 15px;
}

.dv-rail-toggle:hover {
    background: rgba(255, 255, 255, 0.16);
    color: #FFFFFF;
}

/* --- Navigation --- */
.dv-nav {
    flex: 1 1 auto;
    padding: var(--dv-space-3) 10px var(--dv-space-4);
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}

.dv-nav::-webkit-scrollbar {
    width: 5px;
}

.dv-nav::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.16);
    border-radius: var(--dv-radius-pill);
}

.dv-nav-group-label {
    font-size: 0.58rem;
    font-weight: 800;
    letter-spacing: 1.1px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.58);
    padding: var(--dv-space-4) 10px var(--dv-space-1);
    white-space: nowrap;
    overflow: hidden;
}

.dv-nav-item {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    padding: 9px 10px;
    margin-bottom: 2px;
    border: none;
    border-radius: var(--dv-radius-sm);
    background: transparent;
    color: rgba(255, 255, 255, 0.88);
    font-size: 0.82rem;
    font-weight: 600;
    text-align: left;
    text-decoration: none;
    white-space: nowrap;
    position: relative;
    transition: background 0.15s ease, color 0.15s ease;
}

.dv-nav-item:hover {
    background: rgba(255, 255, 255, 0.14);
    color: #FFFFFF;
    text-decoration: none;
}

/* The sidebar is now blue, so the selected item inverts to white rather than
   trying to be a brighter blue against blue. */
.dv-nav-item.active {
    background: var(--dv-surface);
    color: var(--dv-navy);
    font-weight: 700;
    box-shadow: 0 2px 10px rgba(9, 24, 62, 0.24);
}

.dv-nav-item.active:hover {
    background: var(--dv-surface);
    color: var(--dv-navy);
}

.dv-nav-item.active .dv-nav-icon {
    opacity: 1;
    color: var(--dv-blue);
}

.dv-nav-item-sub {
    font-size: 0.78rem;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.76);
    padding-left: 18px;
}

.dv-nav-item-sub.active {
    font-weight: 700;
    color: var(--dv-navy);
}

.dv-nav-item-sub .dv-nav-icon {
    width: 15px;
    height: 15px;
}

/* A module that sits underneath another, Documents under Reviews, used to be
   drawn one step in with a short rule beside it. Leon, 5 September 2026: it
   should look like every other item, so the class is no longer applied and the
   rules that drew it are gone rather than left here unused.

   The relationship is carried by the ORDER of the menu, which is where the rest
   of the grouping lives too. */

.dv-nav-icon {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    opacity: 0.82;
}

.dv-nav-label {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* A menu item that is not built yet. It is shown so people can see what is
   coming, greyed and not a link, and says "Not available yet" on hover. */
.dv-nav-item.dv-nav-disabled {
    opacity: 0.45;
    cursor: default;
}

.dv-nav-item.dv-nav-disabled:hover {
    background: transparent;
    color: rgba(255, 255, 255, 0.88);
}

.dv-nav-caret {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    margin-left: auto;
    opacity: 0.55;
    transition: transform 0.18s ease;
}

[aria-expanded="true"] > .dv-nav-caret {
    transform: rotate(180deg);
}

/* --- Sidebar foot: Configure and the signed in user --- */
.dv-sidebar-foot {
    flex-shrink: 0;
    padding: var(--dv-space-2) 10px var(--dv-space-3);
}

.dv-nav-configure {
    margin-bottom: var(--dv-space-2);
}

.dv-sidebar-user {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 8px;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 0;
    background: transparent;
    text-align: left;
    white-space: nowrap;
    transition: background 0.15s ease;
}

.dv-sidebar-user:hover {
    background: rgba(255, 255, 255, 0.12);
}

.dv-avatar {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--dv-blue-bright), var(--dv-green));
    color: #FFFFFF;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--dv-font-head);
    font-size: 0.7rem;
    font-weight: 800;
}

.dv-sidebar-user-text {
    flex: 1;
    min-width: 0;
    overflow: hidden;
}

.dv-sidebar-user-name {
    display: block;
    font-size: 0.78rem;
    font-weight: 700;
    color: #FFFFFF;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dv-sidebar-user-role {
    display: block;
    font-size: 0.65rem;
    color: rgba(255, 255, 255, 0.72);
}

/* Menus that open upward out of the sidebar foot. */
.dv-foot-menu {
    min-width: 220px;
    border: none;
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow-lg);
    padding: var(--dv-space-2);
    margin-bottom: var(--dv-space-2) !important;
}

.dv-foot-menu-head {
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    color: var(--dv-text-muted);
    padding: var(--dv-space-1) var(--dv-space-2) var(--dv-space-2);
}

.dv-foot-menu .dropdown-item {
    border-radius: var(--dv-radius-sm);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 8px 10px;
}

.dv-foot-menu .dropdown-item:hover {
    background: var(--dv-tint-blue);
    color: var(--dv-blue-deep);
}

/* Switch user, for testing. The list can be long, so the menu scrolls rather
   than running off the top of the window. */
.dv-foot-menu {
    max-height: calc(100vh - 96px);
    overflow-y: auto;
}

.dv-switch-group {
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--dv-navy);
    padding: var(--dv-space-2) var(--dv-space-2) 2px;
}

.dv-foot-menu .dv-switch-item {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    padding-top: 6px;
    padding-bottom: 6px;
}

.dv-switch-note {
    font-size: 0.72rem;
    font-weight: 400;
    color: var(--dv-text-muted);
}

.dv-foot-menu .dv-switch-item.active,
.dv-foot-menu .dv-switch-item:disabled {
    background: var(--dv-tint-blue);
    color: var(--dv-blue-deep);
    opacity: 1;
}

/* --------------------------------------------------------------------------
   Collapsed rail
   -------------------------------------------------------------------------- */
.dv-shell.dv-rail .dv-sidebar {
    width: var(--dv-rail-w);
    flex-basis: var(--dv-rail-w);
}

.dv-shell.dv-rail .dv-main {
    margin-left: var(--dv-rail-w);
}

.dv-shell.dv-rail .dv-brand-text,
.dv-shell.dv-rail .dv-nav-label,
.dv-shell.dv-rail .dv-nav-caret,
.dv-shell.dv-rail .dv-sidebar-user-text {
    display: none;
}

.dv-shell.dv-rail .dv-brand-row {
    flex-direction: column;
    gap: var(--dv-space-2);
    padding-left: var(--dv-space-2);
    padding-right: var(--dv-space-2);
}

.dv-shell.dv-rail .dv-brand {
    justify-content: center;
}

.dv-shell.dv-rail .dv-rail-toggle svg {
    transform: rotate(180deg);
}

.dv-shell.dv-rail .dv-nav,
.dv-shell.dv-rail .dv-sidebar-foot {
    padding-left: var(--dv-space-2);
    padding-right: var(--dv-space-2);
}

.dv-shell.dv-rail .dv-nav-item,
.dv-shell.dv-rail .dv-sidebar-user {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
    gap: 0;
}

.dv-shell.dv-rail .dv-nav-group-label {
    height: 1px;
    padding: 0;
    margin: var(--dv-space-3) auto var(--dv-space-2);
    width: 22px;
    background: rgba(255, 255, 255, 0.14);
    color: transparent;
    overflow: hidden;
}

/* Name the icon on hover when the labels are gone. The nav scrolls, so a
   tooltip drawn inside it would be clipped - site.js positions this one
   against the viewport instead. */
.dv-rail-tip {
    position: fixed;
    background: var(--dv-navy);
    color: #FFFFFF;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 6px 11px;
    border-radius: var(--dv-radius-sm);
    box-shadow: var(--dv-shadow-lg);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.12s ease;
    z-index: 1200;
}

.dv-rail-tip.show {
    opacity: 1;
}

/* Applied by the inline script before first paint so the rail never flashes. */
.dv-pre-collapsed .dv-sidebar {
    width: var(--dv-rail-w);
    flex-basis: var(--dv-rail-w);
}

.dv-pre-collapsed .dv-main {
    margin-left: var(--dv-rail-w);
}

/* --------------------------------------------------------------------------
   Main column and app bar
   -------------------------------------------------------------------------- */
.dv-main {
    flex: 1 1 auto;
    min-width: 0;
    margin-left: var(--dv-sidebar-w);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    transition: margin-left 0.2s ease;
}

/* Light app bar, echoing the white header band on the Daveng website. */
.dv-appbar {
    height: var(--dv-appbar-h);
    background: var(--dv-surface);
    border-bottom: 1px solid var(--dv-line);
    box-shadow: var(--dv-shadow-bar);
    display: flex;
    align-items: center;
    gap: var(--dv-space-3);
    padding: 0 var(--dv-space-5);
    position: sticky;
    top: 0;
    z-index: 1030;
}

.dv-appbar-title {
    font-family: var(--dv-font-head);
    font-size: 1rem;
    font-weight: 700;
    color: var(--dv-navy);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: -0.2px;
}

/* The scope note that used to sit under the page heading. */
.dv-appbar-subtitle {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--dv-blue-deep);
    background: var(--dv-tint-blue);
    border-radius: var(--dv-radius-pill);
    padding: 4px 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 340px;
    flex-shrink: 1;
}

.dv-appbar-centre {
    flex: 1 1 auto;
    display: flex;
    justify-content: flex-end;
    min-width: 0;
}

/* With the heading in the app bar the content can start straight in. */
.dv-content > .dv-toolbar:first-child,
.dv-content > .row:first-child,
.dv-content > .dv-card:first-child,
.dv-content > form:first-child {
    margin-top: 0;
}

@media (max-width: 991.98px) {
    .dv-appbar-subtitle {
        display: none;
    }
}

.dv-hamburger {
    display: none;
    background: transparent;
    border: 1px solid var(--dv-line);
    border-radius: var(--dv-radius-sm);
    color: var(--dv-navy);
    width: 38px;
    height: 34px;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.dv-hamburger svg {
    width: 18px;
    height: 18px;
}

.dv-content {
    flex: 1 1 auto;
    padding: var(--dv-space-5) var(--dv-space-5) var(--dv-space-6);
    min-width: 0;
}

.dv-footer {
    padding: var(--dv-space-3) var(--dv-space-5);
    border-top: 1px solid var(--dv-line);
    background: var(--dv-surface);
    color: var(--dv-text-muted);
    font-size: 0.73rem;
}

/* --- Slide-over drawer below 992px --- */
.dv-scrim {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(18, 12, 54, 0.5);
    z-index: 1035;
}

@media (max-width: 991.98px) {
    .dv-sidebar,
    .dv-shell.dv-rail .dv-sidebar,
    .dv-pre-collapsed .dv-sidebar {
        width: var(--dv-sidebar-w);
        flex-basis: var(--dv-sidebar-w);
        transform: translateX(-100%);
        transition: transform 0.22s ease-in-out;
        box-shadow: var(--dv-shadow-lg);
    }

    .dv-shell.dv-drawer-open .dv-sidebar {
        transform: translateX(0);
    }

    .dv-shell.dv-drawer-open .dv-scrim {
        display: block;
    }

    /* The rail is a desktop idea. On a tablet the drawer is always full width. */
    .dv-shell.dv-rail .dv-brand-text,
    .dv-shell.dv-rail .dv-nav-label,
        .dv-shell.dv-rail .dv-nav-caret,
    .dv-shell.dv-rail .dv-sidebar-user-text {
        display: block;
    }

    .dv-shell.dv-rail .dv-nav-item,
    .dv-shell.dv-rail .dv-sidebar-user {
        justify-content: flex-start;
        gap: 11px;
        padding-left: 10px;
    }

    .dv-shell.dv-rail .dv-brand-row {
        flex-direction: row;
    }

    .dv-shell.dv-rail .dv-nav-group-label {
        height: auto;
        width: auto;
        background: none;
        color: rgba(255, 255, 255, 0.32);
        padding: var(--dv-space-4) 10px var(--dv-space-1);
        margin: 0;
    }

    .dv-rail-toggle {
        display: none;
    }

    .dv-main,
    .dv-shell.dv-rail .dv-main,
    .dv-pre-collapsed .dv-main {
        margin-left: 0;
    }

    .dv-hamburger {
        display: inline-flex;
    }

    .dv-appbar,
    .dv-content {
        padding-left: var(--dv-space-3);
        padding-right: var(--dv-space-3);
    }
}

/* ==========================================================================
   BUTTONS
   ========================================================================== */

.btn {
    border-radius: var(--dv-radius-sm);
    font-weight: 600;
    transition: all 0.18s ease;
    /* A thumb on a tablet, not a mouse pointer. */
    min-height: 42px;
}

.btn-sm {
    font-size: 0.8rem;
    padding: 7px 15px;
    min-height: 38px;
}

/* A link dressed as a button, in a table row or beside a heading, keeps its
   own size. */
.btn-link.table-action-link,
.btn-link.p-0 {
    min-height: 0;
}

/* Blue is action, per the brand guide. */
.btn-primary {
    background: linear-gradient(135deg, var(--dv-blue-bright), var(--dv-blue));
    border: none;
    color: #FFFFFF;
    box-shadow: 0 2px 8px rgba(0, 113, 168, 0.28);
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
    background: linear-gradient(135deg, var(--dv-blue), var(--dv-blue-deep));
    color: #FFFFFF;
    box-shadow: 0 4px 14px rgba(0, 113, 168, 0.36);
    transform: translateY(-1px);
}

.btn-secondary {
    background: var(--dv-surface);
    border: 1px solid var(--dv-line);
    color: var(--dv-text);
}

.btn-secondary:hover,
.btn-secondary:focus,
.btn-secondary:active {
    background: var(--dv-tint-blue);
    border-color: rgba(0, 113, 168, 0.35);
    color: var(--dv-blue-deep);
}

.btn-danger {
    background: var(--dv-danger);
    border-color: var(--dv-danger);
}

.btn-danger:hover,
.btn-danger:focus {
    background: #B91C1C;
    border-color: #B91C1C;
}

.btn:focus-visible {
    box-shadow: 0 0 0 0.2rem rgba(0, 113, 168, 0.3);
    outline: none;
}

/* ==========================================================================
   FORMS
   ========================================================================== */

.form-control,
.form-select {
    border: 1px solid var(--dv-field-line);
    border-radius: var(--dv-radius-sm);
    font-size: 0.92rem;
    color: var(--dv-text);
    background-color: var(--dv-surface);
    min-height: var(--dv-tap);
    padding: 0.55rem 0.8rem;
}

/* A box inside a table row or a toolbar stays compact, and keeps the same
   edge so it still reads as a box. */
.form-control-sm,
.form-select-sm {
    border: 1px solid var(--dv-field-line);
    border-radius: var(--dv-radius-sm);
    min-height: 40px;
}

.form-control:hover,
.form-select:hover,
.form-control-sm:hover,
.form-select-sm:hover {
    border-color: var(--dv-field-hover);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--dv-blue);
    box-shadow: 0 0 0 0.2rem rgba(0, 113, 168, 0.2);
}

.form-control::placeholder {
    color: #98A2B3;
}

/* The unit beside a box, such as the m on an instructed quantity, carries the
   same edge and height as the box itself. */
.input-group-text {
    border: 1px solid var(--dv-field-line);
    background: var(--dv-canvas);
    color: var(--dv-text);
    font-weight: 600;
}

.input-group > .form-control,
.input-group > .form-select {
    min-height: var(--dv-tap);
}

textarea.form-control {
    min-height: 140px;
}

.col-form-label,
.form-label {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--dv-navy);
}

/* Leon, 17 September 2026: no up and down arrows on a quantity. They are a
   mouse control, they sit under a thumb on a tablet, and a quantity is typed
   rather than nudged one at a time. */
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

/* A tick box carries the same soft corner as the boxes around it. A radio
   stays round. */
.form-check-input {
    width: 1.3rem;
    height: 1.3rem;
    border: 1px solid #B4BFD3;
}

.form-check-input[type="checkbox"] {
    border-radius: 5px;
}

.form-check-label {
    font-size: 0.9rem;
}

.form-check-input:checked {
    background-color: var(--dv-blue);
    border-color: var(--dv-blue);
}

.form-text {
    color: var(--dv-text-muted);
    font-size: 0.78rem;
}

.text-danger {
    color: var(--dv-danger) !important;
    font-size: 0.8rem;
}

/* ==========================================================================
   TABLES
   ========================================================================== */

.table-wrapper {
    background: var(--dv-surface);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    overflow: hidden;
    overflow-x: auto;
}

.table {
    margin-bottom: 0;
    border-collapse: collapse;
}

/* Table headers use the same chrome family as the sidebar, so the whole
   portal reads as one colour scheme. */
.table > thead th,
.table thead th {
    background: linear-gradient(90deg, var(--dv-chrome-from), var(--dv-chrome-mid));
    color: #FFFFFF;
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.72rem;
    letter-spacing: 0.6px;
    padding: 11px 12px;
    border-bottom: none;
    border-top: none;
    vertical-align: middle;
    white-space: nowrap;
}

.table > tbody td,
.table tbody td {
    font-size: 0.85rem;
    padding: 10px 12px;
    border-top: 1px solid var(--dv-line);
    border-bottom: none;
    border-color: var(--dv-line);
    vertical-align: middle;
    color: var(--dv-text);
}

.table > tbody > tr:first-child > td {
    border-top: none;
}

.table-hover > tbody > tr:hover > * {
    background-color: var(--dv-tint-blue);
    color: var(--dv-navy);
}

.table-striped > tbody > tr:nth-of-type(odd) > *,
.table-striped > tbody > tr:nth-of-type(even) > * {
    background-color: var(--dv-surface);
}

.table-action-link {
    color: var(--dv-blue);
    font-weight: 600;
    font-size: 0.8rem;
    text-decoration: none;
    white-space: nowrap;
}

.table-action-link:hover {
    color: var(--dv-blue-deep);
    text-decoration: underline;
}

/* SNAG S4. A delete is a POST now, so the control beside Edit and View is a
   submit button rather than a link. It has to read as the same thing, so the
   browser's own button chrome comes off and .table-action-link does the rest.
   The tap target rule still applies: nothing here changes its size. */
.dv-link-button {
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    line-height: inherit;
    cursor: pointer;
    vertical-align: baseline;
}

.dv-link-button:focus-visible {
    outline: 2px solid var(--dv-blue);
    outline-offset: 2px;
}

/* SNAG S11. A message can be a paragraph of SQL Server's own words, so it
   wraps rather than pushing the table sideways, and the stack trace keeps its
   line breaks and scrolls inside its own box. */
.dv-error-message {
    max-width: 40rem;
    word-break: break-word;
}

.dv-error-detail {
    font-size: 0.72rem;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 22rem;
    overflow: auto;
}

.table-action-sep {
    color: var(--dv-line);
    margin: 0 3px;
}

/* --- Sortable --- */
.sortable th {
    cursor: pointer;
    position: relative;
    user-select: none;
    padding-right: 24px;
}

.sortable th:hover {
    background: linear-gradient(90deg, var(--dv-chrome-mid), var(--dv-chrome-to));
}

.sortable th::after {
    content: '\2195';
    position: absolute;
    right: 9px;
    opacity: 0.4;
    font-size: 0.7rem;
}

.sortable th.sort-asc::after {
    content: '\2191';
    opacity: 1;
}

.sortable th.sort-desc::after {
    content: '\2193';
    opacity: 1;
}

.sortable th.no-sort {
    cursor: default;
    padding-right: 12px;
}

.sortable th.no-sort::after {
    content: '';
}

.sortable th.no-sort:hover {
    background: linear-gradient(90deg, var(--dv-chrome-from), var(--dv-chrome-mid));
}

/* ==========================================================================
   CARDS, PAGE HEADER, KPI TILES
   ========================================================================== */

.dv-page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--dv-space-3);
    margin-bottom: var(--dv-space-2);
}

.dv-page-head h4 {
    margin: 0;
}

.dv-page-sub {
    font-size: 0.8rem;
    color: var(--dv-text-muted);
}

.dv-card,
.card {
    background: var(--dv-surface);
    border: 1px solid var(--dv-card-line);
    border-radius: var(--dv-radius);
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.06);
}

.dv-card {
    padding: var(--dv-space-5);
    margin-bottom: var(--dv-space-4);
}

/* The card's own heading sits on a tinted strip across the top of the panel,
   whether it stands alone or shares its row with a button. Leon, 18 September
   2026: the round's Route Position panel is an ordinary card now, so it takes
   the strip with the rest of them. */
.dv-card > .dv-card-heading,
.dv-card > div:first-child:has(> .dv-card-heading) {
    background: linear-gradient(180deg, #F7F9FE, #F1F5FC);
    border-bottom: 1px solid #DFE5F1;
    margin: calc(var(--dv-space-5) * -1) calc(var(--dv-space-5) * -1) var(--dv-space-5);
    padding: var(--dv-space-4) var(--dv-space-5);
    border-radius: calc(var(--dv-radius) - 1px) calc(var(--dv-radius) - 1px) 0 0;
}

.dv-card > div:first-child:has(> .dv-card-heading) > .dv-card-heading {
    margin: 0;
    padding: 0;
    background: none;
    border-bottom: none;
}

.dv-card-heading {
    font-family: var(--dv-font-head);
    font-size: 0.72rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.9px;
    color: var(--dv-navy);
    margin-bottom: var(--dv-space-4);
    padding-bottom: var(--dv-space-3);
    border-bottom: 1px solid var(--dv-line);
    display: flex;
    align-items: center;
    gap: var(--dv-space-2);
}

.dv-card-heading::before {
    content: '';
    width: 3px;
    height: 14px;
    background: linear-gradient(180deg, var(--dv-blue-bright), var(--dv-green));
    border-radius: var(--dv-radius-pill);
    flex-shrink: 0;
}

/* --- KPI tiles --- */
.dv-kpi {
    display: block;
    background: var(--dv-surface);
    border: none;
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    /* Tightened: these sit above the content on every register and were
       costing about a third of the fold before anything useful appeared. */
    padding: var(--dv-space-3) var(--dv-space-4);
    height: 100%;
    text-decoration: none;
    position: relative;
    overflow: hidden;
    transition: box-shadow 0.2s ease, transform 0.2s ease;
}

/* A colour bar down the leading edge rather than a heavy underline. */
.dv-kpi::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: var(--dv-blue);
}

a.dv-kpi:hover {
    box-shadow: var(--dv-shadow-hover);
    transform: translateY(-3px);
    text-decoration: none;
}

.dv-kpi-navy::before  { background: linear-gradient(180deg, var(--dv-navy), var(--dv-navy-soft)); }
.dv-kpi-blue::before  { background: linear-gradient(180deg, var(--dv-blue-bright), var(--dv-blue)); }
.dv-kpi-green::before { background: linear-gradient(180deg, var(--dv-green), var(--dv-green-deep)); }
.dv-kpi-grey::before  { background: linear-gradient(180deg, #A2A5AC, var(--dv-grey)); }

.dv-kpi-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--dv-space-3);
}

/* Circular icon chip, echoing the round icons on the Daveng website. */
.dv-kpi-icon {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--dv-tint-blue);
    color: var(--dv-blue);
}

.dv-kpi-icon svg {
    width: 16px;
    height: 16px;
}

.dv-kpi-navy  .dv-kpi-icon { background: var(--dv-tint-navy);  color: var(--dv-navy); }
.dv-kpi-blue  .dv-kpi-icon { background: var(--dv-tint-blue);  color: var(--dv-blue); }
.dv-kpi-green .dv-kpi-icon { background: var(--dv-tint-green); color: var(--dv-green-deep); }
.dv-kpi-grey  .dv-kpi-icon { background: var(--dv-line-soft);  color: var(--dv-grey); }

.dv-kpi-value {
    font-family: var(--dv-font-head);
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--dv-navy);
    line-height: 1.1;
    letter-spacing: -0.5px;
}

.dv-kpi-label {
    font-size: 0.62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--dv-text-muted);
    margin-top: 2px;
}

.dv-kpi-hint {
    font-size: 0.72rem;
    color: var(--dv-text-muted);
    margin-top: var(--dv-space-2);
    padding-top: var(--dv-space-2);
    border-top: 1px solid var(--dv-line);
}

.dv-kpi-placeholder {
    background: transparent;
    border: 1px dashed var(--dv-line);
    box-shadow: none;
    opacity: 0.8;
}

.dv-kpi-placeholder::before {
    display: none;
}

.dv-kpi-placeholder .dv-kpi-value,
.dv-kpi-placeholder .dv-kpi-label {
    color: var(--dv-grey);
}

.dv-kpi-placeholder .dv-kpi-icon {
    background: var(--dv-line-soft);
    color: var(--dv-line);
}

/* ==========================================================================
   STATUS BADGES
   ========================================================================== */

.dv-badge {
    display: inline-block;
    font-family: var(--dv-font-head);
    font-size: 0.65rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 4px 10px;
    border-radius: var(--dv-radius-pill);
    white-space: nowrap;
    line-height: 1.5;
}

.dv-badge-good    { background: var(--dv-tint-green); color: var(--dv-green-deep); }
.dv-badge-fair    { background: var(--dv-tint-amber); color: #B4700A; }
.dv-badge-poor    { background: var(--dv-tint-red);   color: #B91C1C; }
.dv-badge-info    { background: var(--dv-tint-blue);  color: var(--dv-blue-deep); }
.dv-badge-neutral { background: var(--dv-line-soft);  color: var(--dv-text-muted); }

/* ==========================================================================
   LIST TOOLBAR
   ========================================================================== */

.dv-toolbar {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: var(--dv-space-2);
    margin-bottom: var(--dv-space-4);
}

.dv-toolbar-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--dv-space-2);
}

.dv-search {
    width: 260px;
}

.dv-filter-select {
    width: 180px;
}

.dv-actions-col {
    width: 220px;
}

.dv-tick-col {
    width: 80px;
}

.dv-icon-btn {
    padding: 6px 8px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
}

.dv-icon-btn img {
    width: 20px;
    height: 20px;
    display: block;
}

.dv-viewswitch {
    display: inline-flex;
    border: 1px solid var(--dv-line);
    border-radius: var(--dv-radius-sm);
    overflow: hidden;
    background: var(--dv-surface);
}

.dv-viewswitch a {
    padding: 7px 14px;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--dv-text-muted);
    text-decoration: none;
    border-right: 1px solid var(--dv-line);
}

.dv-viewswitch a:last-child {
    border-right: none;
}

.dv-viewswitch a.active {
    background: var(--dv-blue);
    color: #FFFFFF;
}

.dv-viewswitch a:hover:not(.active) {
    background: var(--dv-tint-blue);
    color: var(--dv-blue-deep);
    text-decoration: none;
}

/* ==========================================================================
   EMPTY STATE
   ========================================================================== */

.dv-empty {
    background: var(--dv-surface);
    border: 1px dashed var(--dv-line);
    border-radius: var(--dv-radius);
    padding: var(--dv-space-6) var(--dv-space-5);
    text-align: center;
}

.dv-empty-title {
    font-family: var(--dv-font-head);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--dv-navy);
    margin-bottom: var(--dv-space-2);
}

.dv-empty-text {
    font-size: 0.87rem;
    color: var(--dv-text-muted);
    margin-bottom: var(--dv-space-4);
    max-width: 560px;
    margin-left: auto;
    margin-right: auto;
}

/* ==========================================================================
   DETAIL PATTERN
   ========================================================================== */

.dv-detail-head {
    background: linear-gradient(125deg, var(--dv-chrome-from) 0%, var(--dv-chrome-mid) 55%, var(--dv-chrome-to) 100%);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    padding: var(--dv-space-5);
    margin-bottom: var(--dv-space-4);
    color: rgba(255, 255, 255, 0.85);
    position: relative;
    overflow: hidden;
}

.dv-detail-head::after {
    content: '';
    position: absolute;
    right: -60px;
    top: -80px;
    width: 260px;
    height: 260px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(0, 137, 204, 0.28), transparent 70%);
    pointer-events: none;
}

.dv-detail-head-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--dv-space-3);
    margin-bottom: var(--dv-space-4);
    position: relative;
}

.dv-detail-number {
    font-family: var(--dv-font-head);
    font-size: 1.5rem;
    font-weight: 800;
    color: #FFFFFF;
    letter-spacing: -0.4px;
    line-height: 1.1;
}

.dv-detail-name {
    font-size: 0.9rem;
    color: rgba(255, 255, 255, 0.72);
    margin-top: 3px;
}

.dv-detail-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-5);
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.6);
    position: relative;
}

.dv-detail-meta strong {
    color: #FFFFFF;
    font-weight: 600;
}

.dv-detail-actions {
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-2);
    align-items: center;
}

.dv-tabs {
    display: flex;
    gap: 4px;
    background: var(--dv-surface);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    padding: 5px;
    margin-bottom: var(--dv-space-4);
    overflow-x: auto;
}

.dv-tab {
    padding: 9px 18px;
    font-family: var(--dv-font-head);
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--dv-text-muted);
    text-decoration: none;
    border-radius: var(--dv-radius-sm);
    white-space: nowrap;
    transition: all 0.15s ease;
}

.dv-tab:hover {
    color: var(--dv-navy);
    background: var(--dv-line-soft);
    text-decoration: none;
}

.dv-tab.active {
    color: #FFFFFF;
    background: linear-gradient(135deg, var(--dv-blue-bright), var(--dv-blue));
    box-shadow: 0 2px 8px rgba(0, 113, 168, 0.3);
}

.dv-tab.disabled {
    color: #C3C8D4;
    pointer-events: none;
}

/* A count carried on a tab, for example the number of assets on a project. */
.dv-tab-count {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: var(--dv-radius-pill);
    background: var(--dv-line-soft);
    color: var(--dv-text-muted);
    font-size: 0.68rem;
    font-weight: 800;
}

.dv-tab.active .dv-tab-count {
    background: rgba(255, 255, 255, 0.24);
    color: #FFFFFF;
}

/* ==========================================================================
   LABEL / VALUE ROWS
   ========================================================================== */

.dv-rows {
    display: block;
}

.dv-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--dv-space-3);
    padding: 9px 0;
    border-bottom: 1px solid var(--dv-line-soft);
    font-size: 0.85rem;
}

.dv-row:last-child {
    border-bottom: none;
}

.dv-row-label {
    color: var(--dv-text-muted);
    font-size: 0.8rem;
    /* Short labels hold their width; a long one - the recent activity list
       carries whole sentences - wraps rather than pushing the page sideways. */
    flex: 0 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.dv-row-value {
    font-weight: 600;
    color: var(--dv-text);
    text-align: right;
}

.dv-row-time {
    font-size: 0.73rem;
    color: var(--dv-text-muted);
    white-space: nowrap;
    flex-shrink: 0;
}

/* ==========================================================================
   TEAM COLUMNS AND CHECKLIST
   ========================================================================== */

.dv-team-col {
    background: var(--dv-surface);
    border: none;
    border-top: 3px solid var(--dv-line);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    padding: var(--dv-space-4);
    height: 100%;
}

.dv-team-col.client      { border-top-color: var(--dv-blue-bright); }
.dv-team-col.consultant  { border-top-color: var(--dv-navy); }
.dv-team-col.contractor  { border-top-color: var(--dv-green); }

.dv-team-col-head {
    font-size: 0.6rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--dv-text-muted);
    margin-bottom: var(--dv-space-3);
}

.dv-team-member {
    padding: var(--dv-space-3) 0;
    border-bottom: 1px solid var(--dv-line-soft);
}

.dv-team-member:last-child {
    border-bottom: none;
}

.dv-team-name {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--dv-navy);
}

.dv-team-role {
    font-size: 0.76rem;
    color: var(--dv-blue);
    font-weight: 600;
}

.dv-team-contact {
    font-size: 0.75rem;
    color: var(--dv-text-muted);
}

.dv-check {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 10px 0;
    border-bottom: 1px solid var(--dv-line-soft);
    font-size: 0.85rem;
}

.dv-check:last-of-type {
    border-bottom: none;
}

.dv-check-mark {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 800;
    color: #FFFFFF;
    background: var(--dv-line);
    margin-top: 1px;
}

.dv-check.done .dv-check-mark {
    background: linear-gradient(135deg, var(--dv-green), var(--dv-green-deep));
}

.dv-check.done .dv-check-text {
    color: var(--dv-text-muted);
}

.dv-check-text {
    color: var(--dv-text);
}

/* ==========================================================================
   GROUPED CARD CAPTURE
   The second capture pattern: long forms broken into cards with the label
   stacked above its control, rather than the horizontal row layout used for
   short forms. See Build/ScreenPatterns.md.
   ========================================================================== */

.dv-field {
    margin-bottom: var(--dv-space-4);
}

.dv-field > .form-label {
    margin-bottom: 5px;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--dv-navy);
}

.dv-field .form-text {
    margin-top: 5px;
}

/* A value the portal owns and the user cannot type over. */
.dv-readonly {
    background: var(--dv-line-soft);
    font-family: var(--dv-font-head);
    font-weight: 700;
    color: var(--dv-navy);
}

.dv-readonly:focus {
    background: var(--dv-line-soft);
    box-shadow: none;
}

/* Action bar under a grouped card form. */
.dv-form-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: var(--dv-space-3);
    margin-top: var(--dv-space-4);
    padding: var(--dv-space-4);
    background: var(--dv-surface);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
}

/* Condition segmented control. Built from radio inputs so it posts without
   script, and coloured from the same status palette used everywhere else. */
.dv-cond-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-2);
}

.dv-cond-btn {
    flex: 1 1 0;
    min-width: 90px;
    text-align: center;
    padding: 10px var(--dv-space-3);
    border-radius: var(--dv-radius-sm);
    border: 1px solid transparent;
    font-family: var(--dv-font-head);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    cursor: pointer;
    transition: all 0.15s ease;
}

.dv-cond-btn:hover {
    filter: brightness(0.96);
}

/* Unselected: the soft status tint. Selected: the full status colour. */
.dv-cond-btn.dv-badge-good    { background: var(--dv-tint-green); color: var(--dv-green-deep); }
.dv-cond-btn.dv-badge-fair    { background: var(--dv-tint-amber); color: #B4700A; }
.dv-cond-btn.dv-badge-poor    { background: var(--dv-tint-red);   color: #B91C1C; }
.dv-cond-btn.dv-badge-info    { background: var(--dv-tint-blue);  color: var(--dv-blue-deep); }
.dv-cond-btn.dv-badge-neutral { background: var(--dv-line-soft);  color: var(--dv-text-muted); }

.btn-check:checked + .dv-cond-btn.dv-badge-good {
    background: var(--dv-green-deep);
    color: #FFFFFF;
    box-shadow: 0 2px 10px rgba(94, 155, 44, 0.35);
}

.btn-check:checked + .dv-cond-btn.dv-badge-fair {
    background: var(--dv-warning);
    color: #FFFFFF;
    box-shadow: 0 2px 10px rgba(232, 147, 12, 0.35);
}

.btn-check:checked + .dv-cond-btn.dv-badge-poor {
    background: var(--dv-danger);
    color: #FFFFFF;
    box-shadow: 0 2px 10px rgba(220, 38, 38, 0.35);
}

.btn-check:checked + .dv-cond-btn.dv-badge-info {
    background: var(--dv-blue);
    color: #FFFFFF;
}

.btn-check:checked + .dv-cond-btn.dv-badge-neutral {
    background: var(--dv-grey);
    color: #FFFFFF;
}

.btn-check:focus-visible + .dv-cond-btn {
    border-color: var(--dv-blue);
    box-shadow: 0 0 0 0.2rem rgba(0, 113, 168, 0.25);
}

/* Extent, Task 7. A 1 to 5 scale with no words behind it, so it must not
   borrow the condition palette: green on a "1" would read as good news when
   it only means a small area. Neutral until chosen, blue when chosen, the
   same treatment the app already gives a plain selection. */
.dv-cond-btn.dv-extent-btn {
    background: var(--dv-line-soft);
    color: var(--dv-text-muted);
    min-width: 3rem;
    font-variant-numeric: tabular-nums;
}

.btn-check:checked + .dv-cond-btn.dv-extent-btn {
    background: var(--dv-blue);
    color: #FFFFFF;
    box-shadow: 0 2px 10px rgba(0, 113, 168, 0.3);
}

/* Degree and Extent on a defect read as a pair, "D4 / E3", so the two badges
   sit tight together with the separator between them. */
.dv-scale-pair {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    white-space: nowrap;
}

.dv-scale-pair .dv-scale-sep {
    color: var(--dv-text-muted);
    font-size: 0.75rem;
}

/* A capability that arrives in a later release, shown so the shape of the
   screen is clear without pretending it works. */
.dv-photo-placeholder {
    border: 1px dashed var(--dv-line);
    border-radius: var(--dv-radius-sm);
    padding: var(--dv-space-4);
    text-align: center;
    font-size: 0.8rem;
    color: var(--dv-text-muted);
    background: var(--dv-canvas);
}

/* ==========================================================================
   LOGIN
   ========================================================================== */

.dv-login-canvas {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--dv-space-5) var(--dv-space-3);
    background:
        radial-gradient(1200px 520px at 12% -12%, rgba(0, 137, 204, 0.14), transparent 62%),
        radial-gradient(900px 440px at 108% 112%, rgba(126, 194, 69, 0.14), transparent 62%),
        var(--dv-canvas);
}

.dv-login-card {
    width: 100%;
    max-width: 410px;
    background: var(--dv-surface);
    border: none;
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow-lg);
    padding: var(--dv-space-6) var(--dv-space-5) var(--dv-space-5);
    position: relative;
    overflow: hidden;
}

.dv-login-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(90deg, var(--dv-navy), var(--dv-blue-bright) 55%, var(--dv-green));
}

.dv-login-logo {
    display: block;
    max-width: 220px;
    width: 100%;
    height: auto;
    margin: 0 auto var(--dv-space-5);
}

.dv-login-product {
    text-align: center;
    margin-bottom: var(--dv-space-5);
    padding-top: var(--dv-space-4);
    position: relative;
}

.dv-login-product::before {
    content: '';
    position: absolute;
    top: 0;
    left: 15%;
    right: 15%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--dv-blue-bright), var(--dv-green), transparent);
}

.dv-login-product-name {
    display: block;
    font-family: var(--dv-font-head);
    font-size: 1.6rem;
    font-weight: 800;
    letter-spacing: 6px;
    color: var(--dv-navy);
    text-indent: 6px;
    line-height: 1.1;
}

.dv-login-product-expansion {
    display: block;
    font-size: 0.64rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    color: var(--dv-text-muted);
    margin-top: var(--dv-space-1);
}

.dv-login-title {
    font-family: var(--dv-font-head);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.4px;
    color: var(--dv-text-muted);
    text-align: center;
    margin-bottom: var(--dv-space-5);
}

.dv-login-footnote {
    text-align: center;
    font-size: 0.7rem;
    color: var(--dv-text-muted);
    margin-top: var(--dv-space-4);
}

/* ==========================================================================
   ALERTS, TOASTS, MODALS
   ========================================================================== */

.alert {
    font-size: 0.875rem;
    border-radius: var(--dv-radius);
    border-width: 1px;
}

.alert-danger {
    background: var(--dv-tint-red);
    border-color: #F6BDBD;
    color: #991B1B;
}

.dv-toast-host {
    position: fixed;
    top: calc(var(--dv-appbar-h) + var(--dv-space-4));
    left: 50%;
    transform: translateX(-50%);
    z-index: 1100;
}

.toast.bg-success {
    background: var(--dv-navy) !important;
    border-left: 4px solid var(--dv-green);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow-lg);
}

.modal-content {
    border: none;
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow-lg);
    overflow: hidden;
}

.modal-header {
    background: linear-gradient(120deg, var(--dv-chrome-from), var(--dv-chrome-to));
    color: #FFFFFF;
    border-bottom: none;
    padding: var(--dv-space-4) var(--dv-space-5);
}

.modal-title {
    font-family: var(--dv-font-head);
    font-size: 0.88rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: #FFFFFF;
}

.modal-header .btn-close {
    filter: invert(1) grayscale(1) brightness(2);
}

.modal-body {
    padding: var(--dv-space-5);
}

.modal-footer {
    border-top: 1px solid var(--dv-line);
    padding: var(--dv-space-3) var(--dv-space-5);
}

/* PDF preview. The viewer needs real height, so the body is sized against the
   viewport rather than growing with its content. */
.dv-pdf-modal {
    height: 88vh;
}

.dv-pdf-body {
    padding: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.dv-pdf-frame {
    flex: 1 1 auto;
    width: 100%;
    border: none;
    background: var(--dv-line-soft);
}

.dv-pdf-status {
    padding: var(--dv-space-6);
    text-align: center;
    margin: auto;
}

.dropdown-menu {
    border: none;
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow-lg);
    padding: var(--dv-space-2);
}

.dropdown-item {
    border-radius: var(--dv-radius-sm);
    font-size: 0.85rem;
    padding: 8px 10px;
}

.dropdown-item:hover {
    background: var(--dv-tint-blue);
    color: var(--dv-blue-deep);
}

/* ==========================================================================
   UTILITY
   ========================================================================== */

.dv-muted {
    color: var(--dv-text-muted);
    font-size: 0.82rem;
}

.dv-scope-note {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--dv-blue-deep);
    background: var(--dv-tint-blue);
    border-radius: var(--dv-radius-pill);
    padding: 4px 12px;
    display: inline-block;
}

.dv-warn-text {
    color: var(--dv-warning);
    font-weight: 600;
}

/* ==========================================================================
   FIELD USE - tablet friendly tap targets, high contrast
   ========================================================================== */

@media (max-width: 992px) {
    .btn,
    .form-control,
    .form-select {
        min-height: var(--dv-tap);
    }

    .dv-icon-btn {
        min-width: var(--dv-tap);
        justify-content: center;
    }

    .table > tbody td,
    .table tbody td {
        padding: 12px;
        font-size: 0.9rem;
    }

    .table-action-link {
        font-size: 0.85rem;
        display: inline-block;
        padding: 4px 0;
    }

    .dv-search,
    .dv-filter-select {
        width: 100%;
    }

    .dv-toolbar-group {
        width: 100%;
    }

    .dv-nav-item,
    .dv-sidebar-user {
        min-height: var(--dv-tap);
    }
}

@media print {
    .dv-sidebar,
    .dv-appbar,
    .dv-footer,
    .dv-toolbar {
        display: none !important;
    }

    .dv-main {
        margin-left: 0;
    }
}


/* ==========================================================================
   RELEASE 2

   Everything below belongs to the Release 2 modules: attachments, the
   notification bell, roads, the Master List, inspections, defects and
   instructions. It follows the same rules as the rest of this file - no
   literal colours, no literal spacing, tap targets at least --dv-tap on
   touch, and every wide table scrolls inside its own box rather than
   pushing the page sideways.
   ========================================================================== */


/* --------------------------------------------------------------------------
   SHARED UTILITIES
   -------------------------------------------------------------------------- */

/* Present to a screen reader, invisible on screen. */
.dv-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Money and quantities line up on the decimal, so they are read down a column
   rather than across a row. */
.dv-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Leon, 18 September 2026: a figure in a table never breaks across two lines.
   R 2 205.00 was reading as "R 2" over "205.00" in a squeezed total. */
.table td.dv-num,
.table th.dv-num {
    white-space: nowrap;
}

.dv-num-input {
    text-align: right;
    font-variant-numeric: tabular-nums;
    max-width: 7rem;
}

/* A rate or a total must never be shortened with an ellipsis - a truncated
   amount is worse than no amount. */
/* Leon, 18 September 2026: dv-no-truncate also says "never wrap", which is
   right for a figure or a reference and wrong for a sentence: a description
   then held its column open and pushed the columns after it off the edge.
   Add dv-wrap beside it for text that should keep every word but may run onto
   a second line. */
.dv-no-truncate.dv-wrap {
    white-space: normal;
}

.dv-no-truncate {
    max-width: none;
    overflow: visible;
    text-overflow: clip;
    white-space: nowrap;
}

/* The capture form wrapper. Gives every long form the same bottom room so the
   sticky action bar never covers the last field. */
.dv-capture {
    padding-bottom: var(--dv-space-6);
}

.dv-appbar-end {
    display: flex;
    align-items: center;
    gap: var(--dv-space-2);
    margin-left: auto;
}

/* A single line of reason text sitting next to the button that needs it. */
.dv-reason {
    min-width: 16rem;
    flex: 1 1 16rem;
}

/* Why something was reopened, cancelled or closed. Stated, not hidden. */
.dv-reopen-note {
    padding: var(--dv-space-2) var(--dv-space-3);
    border-left: 3px solid var(--dv-warning);
    border-radius: var(--dv-radius-sm);
    background: var(--dv-tint-amber);
    font-size: 0.82rem;
    color: var(--dv-text);
}

.dv-section-heading {
    font-family: var(--dv-font-head);
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--dv-text-muted);
    margin: var(--dv-space-5) 0 var(--dv-space-3) 0;
}

/* Controls that belong on one line above a table. */
.dv-rows-inline {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--dv-space-2);
}

.dv-checkgroup {
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-2) var(--dv-space-5);
}

/* Good / Fair / Poor as three large targets, not a dropdown. An inspector is
   using this one-handed on a tablet at the roadside. The buttons themselves
   are .dv-cond-btn, styled further up; this only lays them out and guarantees
   the tap height, which .dv-cond-btn's padding alone does not. */
.dv-cond-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-2);
}

.dv-cond-row .dv-cond-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--dv-tap);
    margin: 0;
}

.dv-cond-row .btn-check:focus-visible + .dv-cond-btn {
    outline: 2px solid var(--dv-blue);
    outline-offset: 2px;
}

.dv-total-row {
    background: var(--dv-canvas);
    font-weight: 700;
}

.dv-avatar-sm {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--dv-tint-navy);
    color: var(--dv-navy);
    font-size: 0.66rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.dv-edit-item {
    white-space: nowrap;
}

/* The CPA formula, shown as the client writes it. */
.dv-formula {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 0.78rem;
    background: var(--dv-canvas);
    border-radius: var(--dv-radius-sm);
    padding: var(--dv-space-2) var(--dv-space-3);
    color: var(--dv-text);
    overflow-x: auto;
}

/* A second row of tabs inside a tab. */
.dv-tabs-inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-1);
    margin-bottom: var(--dv-space-4);
    border-bottom: 1px solid var(--dv-line);
}

.dv-tabs-inner .dv-tab {
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.8rem;
    padding: 7px 14px;
}


/* --------------------------------------------------------------------------
   KPI VARIANTS AND FACT STRIPS
   -------------------------------------------------------------------------- */

.dv-kpi-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: var(--dv-space-3);
    margin-bottom: var(--dv-space-3);
}

.dv-kpi-note {
    font-size: 0.7rem;
    color: var(--dv-text-muted);
    margin-top: var(--dv-space-1);
}

.dv-kpi-red::before   { background: linear-gradient(180deg, var(--dv-danger), #B91C1C); }
.dv-kpi-amber::before { background: linear-gradient(180deg, var(--dv-warning), #B4700A); }

.dv-kpi-red .dv-kpi-icon   { background: var(--dv-tint-red);   color: #B91C1C; }
.dv-kpi-amber .dv-kpi-icon { background: var(--dv-tint-amber); color: #B4700A; }

/* One figure on a line, for use inside a card rather than across the top. */
.dv-kpi-inline {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--dv-space-2);
    padding: var(--dv-space-2) 0;
    border-bottom: 1px solid var(--dv-line-soft);
}

.dv-kpi-inline:last-child { border-bottom: none; }

.dv-kpi-inline-label {
    font-size: 0.78rem;
    color: var(--dv-text-muted);
}

.dv-kpi-inline-value {
    font-family: var(--dv-font-head);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--dv-navy);
    font-variant-numeric: tabular-nums;
}

/* The facts that sit under a heading: label above, value below. */
/* The fact strip always sits INSIDE a card, so it carries no surface of its
   own. It used to be a white panel with its own shadow on a white card, which
   read as a box inside a box and put every value in 1rem heading bold. It now
   follows the asset register: a quiet grid of tinted cells, the label small and
   the value readable rather than shouted. Keep these two in step. */
.dv-fact-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--dv-space-2);
    margin-bottom: var(--dv-space-3);
}

.dv-fact {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    background: var(--dv-canvas);
    border-radius: var(--dv-radius-sm);
    padding: 8px 10px;
}

.dv-fact-label {
    font-size: 0.58rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--dv-text-muted);
    margin-bottom: 2px;
}

/* Unlike the asset card this wraps rather than truncating. A priority reading
   "Immediate - 0 to 2 days" or a contractor's full name is the reason the fact
   is on the card at all, so it is not worth clipping to keep the rows even. */
.dv-fact-value {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--dv-navy);
    min-width: 0;
    overflow-wrap: anywhere;
}


/* --------------------------------------------------------------------------
   ITEM CARDS
   The card half of the cards-versus-list pattern, used by the inspection,
   defect and instruction registers.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   CARD GRID
   Every register that shows records as cards rather than as a table.

   C54. This was defined twice, here and 1300 lines earlier as two fixed
   columns with a media query of its own. Same specificity, so this one won at
   every width and the other was dead, along with its comment promising two
   cards across. One definition now, and it says what happens.

   A card is 310px at its narrowest and as many fit as the row allows, so a
   card is the same width on every register. auto-fill rather than auto-fit on
   purpose: with auto-fit a single record would stretch its card across the
   whole page. The last row carries the remainder, which is what a grid of
   cards is meant to look like.
   ========================================================================== */

.dv-card-grid {
    display: grid;
    /* Leon, 18 September 2026: 310 was too tight once a status badge ran to
       three words. */
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
    gap: var(--dv-space-4);
    align-items: stretch;   /* footers line up across a row */
}

/* See .dv-conduct: a grid item's automatic minimum lets wide content push the
   page sideways rather than being contained. */
.dv-card-grid > *,
.dv-kpi-row > *,
.dv-fact-strip > *,
.dv-sub-grid > *,
.dv-gallery-strip > *,
.dv-assign-strip > * {
    min-width: 0;
}

.dv-item-card {
    display: flex;
    flex-direction: column;
    background: var(--dv-surface);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    overflow: hidden;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.dv-item-card:hover {
    box-shadow: var(--dv-shadow-hover);
    transform: translateY(-1px);
}

/* A card or a row that opens when you click it. Leon, 5 September 2026.

   The class is added by initClickableRows to whatever actually has somewhere to
   go, so a card with nothing to open still looks inert. The name inside it is
   coloured like a link because that is the part a person aims at, and the whole
   surface responds so they do not have to. */
.dv-item-card.dv-clickable,
table.sortable tbody tr.dv-clickable {
    cursor: pointer;
}

.dv-item-card.dv-clickable .dv-item-card-number,
table.sortable tbody tr.dv-clickable td:first-child {
    color: var(--dv-blue);
}

.dv-item-card.dv-clickable:hover .dv-item-card-number,
table.sortable tbody tr.dv-clickable:hover td:first-child {
    text-decoration: underline;
}

table.sortable tbody tr.dv-clickable:hover {
    background: var(--dv-tint-blue);
}

/* The Open link stays. It is what a keyboard reaches, and on a touch screen it
   is a target that does not depend on hitting the card between its own
   controls. */

/* Leon, 18 September 2026: a long status, such as Completed - Awaiting
   Inspection, would not shrink, so it squeezed the record number until
   RP-0006 broke over two lines. The head wraps instead: the number and its
   sub line keep their room and a badge that does not fit drops under them. */
.dv-item-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--dv-space-2);
    padding: var(--dv-space-4) var(--dv-space-4) var(--dv-space-2) var(--dv-space-4);
}

.dv-item-card-head > div:first-child {
    flex: 1 1 11rem;
    min-width: 0;
}

.dv-item-card-head > .dv-badge {
    flex: 0 0 auto;
}

/* The record number and any badge that qualifies it - Urgent, VO, a defect
   count - sit on one line together.

   Without this the badge is an inline-block, so its bottom edge lands on the
   number's text baseline and it hangs low, while the status badge beside it is
   a flex child of the head and aligns to the top. Two alignment models on one
   line, which is why Urgent and Draft never lined up. */
.dv-item-card-number {
    font-family: var(--dv-font-head);
    font-size: 1rem;
    font-weight: 800;
    color: var(--dv-navy);
    letter-spacing: -0.2px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--dv-space-2);
    /* The number itself never breaks mid reference. */
    white-space: nowrap;
    /* The row is pinned to the badge's own height: 0.65rem text at line-height
       1.5, plus its 4px padding top and bottom. That keeps the line the same
       height whatever the heading font's metrics are, so the status badge
       sitting at the head's flex-start lands on exactly the same line as the
       badges inside this one. Without it the taller of the two drives the row
       and the other drifts by a few pixels. */
    line-height: calc((0.65rem * 1.5) + 8px);
}

.dv-item-card-sub {
    font-size: 0.74rem;
    color: var(--dv-text-muted);
    margin-top: 2px;
}

.dv-item-card-body {
    flex: 1 1 auto;
    padding: 0 var(--dv-space-4) var(--dv-space-3) var(--dv-space-4);
    font-size: 0.8rem;
}

.dv-item-card-body dl,
.dv-item-card-body .dv-item-card-line {
    display: flex;
    justify-content: space-between;
    gap: var(--dv-space-2);
    margin: 0 0 var(--dv-space-1) 0;
}

.dv-item-card-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--dv-space-3);
    padding: var(--dv-space-3) var(--dv-space-4);
    border-top: 1px solid var(--dv-line-soft);
    background: var(--dv-canvas);
    font-size: 0.75rem;
    color: var(--dv-text-muted);
}

.dv-item-card-open {
    margin-left: auto;
    font-weight: 700;
    font-size: 0.75rem;
    text-decoration: none;
    white-space: nowrap;
}

.dv-item-card-open::after {
    content: " \2192";
}


/* --------------------------------------------------------------------------
   WIDE TABLES

   .table-wrapper has been on every table in the portal since Release 1 but
   never had a rule behind it, so a wide table pushed the whole page sideways
   on a phone. The table scrolls inside its own box instead; the page never
   does. -webkit-overflow-scrolling keeps the momentum scroll on iPad, which
   is the device the Consultant actually reviews on.
   -------------------------------------------------------------------------- */

.table-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
}

@media (max-width: 767.98px) {
    /* A table that has to scroll should not also squeeze itself to nothing. */
    .table-wrapper > .table {
        min-width: 34rem;
    }

    .table-wrapper > .table th,
    .table-wrapper > .table td {
        white-space: nowrap;
    }
}


/* --------------------------------------------------------------------------
   TABLET
   -------------------------------------------------------------------------- */

@media (max-width: 991.98px) {
    .dv-detail-split {
        grid-template-columns: 1fr;
    }

    /* The timeline moves above the detail on a narrow screen, because what
       happened to a defect is the first question asked about it. */
    .dv-detail-side {
        order: -1;
    }

    .dv-conduct {
        grid-template-columns: 1fr;
    }

    .dv-picker-list {
        max-height: 20rem;
    }

    .dv-classswitch {
        width: 100%;
    }

    .dv-classswitch a {
        flex: 1 1 auto;
        text-align: center;
    }
}


/* --------------------------------------------------------------------------
   PHONE
   -------------------------------------------------------------------------- */

@media (max-width: 767.98px) {
    /* One asset at a time. The picker shows until an asset is chosen, then the
       panel takes the screen and a back link returns to the list. Driven by
       .has-open on the wrapper, which the view sets server side from whether an
       asset is selected, so it works with JavaScript off. */
    .dv-conduct:not(.has-open) .dv-conduct-panel { display: none; }
    .dv-conduct.has-open .dv-conduct-picker { display: none; }
    .dv-conduct.has-open .dv-conduct-back { display: flex; }

    .dv-conduct-panel {
        padding: var(--dv-space-4);
    }

    .dv-conduct-actions .btn {
        flex: 1 1 100%;
    }

    .dv-fact-strip {
        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
        padding: var(--dv-space-3);
        gap: var(--dv-space-3);
    }

    .dv-card-grid,
    .dv-kpi-row {
        grid-template-columns: 1fr;
    }

    .dv-gallery-strip {
        grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    }

    .dv-bell-menu {
        position: fixed;
        left: var(--dv-space-2);
        right: var(--dv-space-2);
        width: auto;
    }

    .dv-convert-bar {
        position: fixed;
        left: var(--dv-space-2);
        right: var(--dv-space-2);
        bottom: var(--dv-space-2);
        top: auto;
        margin: 0;
        z-index: 1030;
    }

    .dv-num-input {
        max-width: none;
    }

    .dv-reason {
        min-width: 0;
        flex: 1 1 100%;
    }
}


/* --------------------------------------------------------------------------
   Task 5, MT-8. The collapsing detail header.

   Leon, in the review: "you seeing all that information is not needed all the
   time ... the top bit of a project like this, like, we don't, this is not
   relevant. We can have like a little hide and expand." Dewlann made the same
   point about density.

   One implementation, applied by a class, rather than four copies across
   Project, Instruction, Repair and Defect.

   The record number and the status badge stay visible when collapsed. Those
   two are the reason anybody looks at the header at all, so hiding them would
   defeat the point of having one.
   ===================================================================== */
.dv-detail-meta.is-collapsed > span:not(.dv-keep) {
    display: none;
}

.dv-meta-toggle {
    background: none;
    border: 0;
    padding: 0 0.35rem;
    color: var(--dv-text-muted);
    font-size: 0.8rem;
    cursor: pointer;
    line-height: 1;
}

.dv-meta-toggle:hover {
    color: var(--dv-blue);
}

/* A list of external references, e.g. the Stats SA releases on the CPA tab. */
.dv-link-list {
    list-style: none;
    padding: 0;
    margin: 0.25rem 0 0 0;
}

.dv-link-list li {
    padding: 0.15rem 0;
    font-size: 0.85rem;
}

.dv-link-list strong {
    display: inline-block;
    min-width: 5.5rem;
}

.dv-link-list .dv-muted {
    font-size: 0.8rem;
}

/* =====================================================================
   Task 36, MT-5. Field mode.

   Dewlann, in the review: "the moment we're on site, we need bigger icons, we
   need legacy options. We just need to focus on getting the data on the sheet."

   The reviewer of the Inspector login confirmed the responsive work is already
   sound, so this is not a responsiveness problem. It is a DENSITY problem: the
   same screen, correctly laid out for a tablet, still shows more than somebody
   standing on a road needs.

   So it is a class on <body> and nothing else. No parallel views: two copies of
   the conduct screen would diverge within a month.

   What it never does is hide something that cannot be reached another way, or
   change what a save does. It is the same system, quieter.
   ===================================================================== */
body.dv-field-mode {
    /* The theme routes every touch target through --dv-tap, and the FIELD USE
       block above already applies it below 992px. So field mode raises the
       variable rather than restating a list of selectors, which would fall out
       of date the first time a new control is added.

       42px to 54px. Measured, not guessed: at 42px the buttons were already
       reachable and field mode changed almost nothing, which is worse than not
       having it. */
    --dv-tap: 54px;
    font-size: 1.1rem;
}

/* And it has to hold above 992px as well. A tablet in landscape is 1024 wide
   and is still somebody standing next to a road. */
body.dv-field-mode .btn,
body.dv-field-mode .form-control,
body.dv-field-mode .form-select,
body.dv-field-mode .dv-nav-item,
body.dv-field-mode .dv-sidebar-user {
    min-height: var(--dv-tap);
}

body.dv-field-mode .btn,
body.dv-field-mode .form-control,
body.dv-field-mode .form-select {
    font-size: 1.05rem;
}

body.dv-field-mode .dv-icon-btn {
    min-width: var(--dv-tap);
}

body.dv-field-mode .dv-cond-btn {
    min-height: var(--dv-tap);
    min-width: 4.5rem;
    font-size: 1.1rem;
    padding: 0.6rem 1rem;
}

/* A tick box a gloved thumb can actually hit. */
body.dv-field-mode .form-check-input {
    width: 1.75rem;
    height: 1.75rem;
}

/* The KPI strip is a management view. On a road it is noise. */
body.dv-field-mode .dv-kpi,
body.dv-field-mode .dv-tab-count {
    display: none;
}

/* The detail header collapses to the number and the status. */
body.dv-field-mode .dv-detail-meta > span:not(.dv-keep) {
    display: none;
}

/* A table on a tablet becomes a stack of cards, because a horizontal scroll
   with one hand on a steering wheel is not a table. */
@media (max-width: 991.98px) {
    body.dv-field-mode .table-wrapper table thead {
        display: none;
    }

    body.dv-field-mode .table-wrapper table,
    body.dv-field-mode .table-wrapper tbody,
    body.dv-field-mode .table-wrapper tr,
    body.dv-field-mode .table-wrapper td {
        display: block;
        width: 100%;
    }

    /* Leon, 20 September 2026, on a phone: the stacked cards were wider than
       the screen, so the values sat off the right edge and a card of six
       figures looked empty. A table that has to scroll sideways keeps its
       34rem, but a table that has become a stack of cards is not scrolling any
       more and must fit the screen it is on. */
    body.dv-field-mode .table-wrapper > .table {
        min-width: 0;
    }

    body.dv-field-mode .table-wrapper tr {
        border: 1px solid var(--dv-line);
        border-radius: 0.5rem;
        margin-bottom: 0.6rem;
        padding: 0.5rem 0.75rem;
    }

    body.dv-field-mode .table-wrapper td {
        border: 0;
        padding: 0.25rem 0;
    }

    /* A stacked card with no labels is a column of orphan values: "Inspection",
       "RP-0002", "N9", "2026-08-20" tells a reader nothing. The heading the
       cell belongs under is carried on data-label by the field mode script and
       printed here, because the thead itself is hidden above. */
    body.dv-field-mode .table-wrapper td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: 0.72rem;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--dv-text-muted);
        margin-bottom: 0.1rem;
    }

    /* An empty cell would otherwise show its label with nothing under it. */
    body.dv-field-mode .table-wrapper td:empty {
        display: none;
    }
}

/* The toggle itself, in the app bar. */
.dv-field-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    color: var(--dv-text-muted);
    white-space: nowrap;
}

/* Folded to icons, the menu shows the tick box alone. Its words would spill
   out of the strip. */
.dv-shell.dv-rail .dv-field-toggle {
    justify-content: center;
    width: 100%;
}

.dv-shell.dv-rail .dv-field-toggle span {
    display: none;
}


/* =====================================================================
   LEON, 20 SEPTEMBER 2026. THE MENU AND THE TOOLBARS ON A PHONE
   --------------------------------------------------------------------------- */

/* Help and Support, the Asset Map and Asset Approvals used to be anchored at
   the foot with Configure, which left a short scrolling list above them and
   made the menu awkward to move under a thumb. They are the last group of the
   scrolling list now, under a hairline so the grouping still reads. */
.dv-nav-extra {
    margin-top: var(--dv-space-3);
    padding-top: var(--dv-space-3);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.dv-shell.dv-rail .dv-nav-extra {
    margin-top: var(--dv-space-2);
    padding-top: var(--dv-space-2);
}

/* A row of buttons at the top of a screen: where to go and what to do. It
   wraps on its own down to a tablet, which reads well. On a phone it used to
   break into a ragged stack of pills of different widths, so there the two
   halves become their own full width rows: the months as one segmented strip,
   the actions two to a row, each a full sized target. */
.dv-page-tools {
    display: flex;
    flex-wrap: wrap;
    gap: var(--dv-space-2);
    align-items: center;
}

.dv-page-tools .dv-page-tools-spacer {
    margin-left: auto;
}

@media (max-width: 575.98px) {
    .dv-page-tools {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--dv-space-2);
    }

    .dv-page-tools .dv-page-tools-spacer {
        display: none;
    }

    /* The months read as one control across the top. */
    .dv-page-tools .dv-tools-period {
        grid-column: 1 / -1;
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 0;
    }

    .dv-page-tools .dv-tools-period > .btn {
        border-radius: 0;
        border-right-width: 0;
    }

    .dv-page-tools .dv-tools-period > .btn:first-child {
        border-top-left-radius: var(--dv-radius-sm);
        border-bottom-left-radius: var(--dv-radius-sm);
    }

    .dv-page-tools .dv-tools-period > .btn:last-child {
        border-top-right-radius: var(--dv-radius-sm);
        border-bottom-right-radius: var(--dv-radius-sm);
        border-right-width: 1px;
    }

    /* Every action is the same size, side by side, two to a row. */
    .dv-page-tools > .btn,
    .dv-page-tools > form,
    .dv-page-tools > .btn-group,
    .dv-page-tools .dv-tools-period > .btn {
        width: 100%;
        min-height: var(--dv-tap);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        white-space: nowrap;
    }

    /* A set of buttons that belong together, such as the months, takes the
       whole row and splits it evenly rather than spilling out of half of it. */
    .dv-page-tools > .btn-group {
        grid-column: 1 / -1;
    }

    .dv-page-tools > .btn-group > .btn {
        flex: 1 1 0;
        min-width: 0;
        min-height: var(--dv-tap);
    }

    /* Something that must not be cut in half, such as a project picker, takes
       the whole row. */
    .dv-page-tools > .dv-tools-wide,
    .dv-page-tools > form.dv-tools-wide {
        grid-column: 1 / -1;
    }

    .dv-page-tools > form.dv-tools-wide .form-select {
        width: 100%;
        min-height: var(--dv-tap);
    }
}




/* =====================================================================
   SPRINT 1 REGRESSION, 4 OCTOBER 2026

   The snag list from Leon's full regression of Sprint 1. Each rule says
   which snag it closes. Kept together so the fix round reads as one piece.
   ===================================================================== */

/* Sort arrows sat on the heading text in narrow columns. .table thead th set
   the padding after .sortable th did, so the room for the arrow was lost. */
.table.sortable > thead th {
    padding-right: 26px;
}

.table.sortable > thead th.no-sort {
    padding-right: 12px;
}

/* An Actions column holds one or two short links. A fixed 220 pixels left
   it half empty while dates and numbers broke over two lines beside it. */
.dv-actions-col {
    width: 1%;
    white-space: nowrap;
}

.table tbody td:has(> .table-action-link) {
    white-space: nowrap;
}

/* A reference, a date or an amount in a table never breaks over two lines.
   It keeps every character and is not shortened with an ellipsis. */
.table td.dv-nowrap,
.table th.dv-nowrap {
    white-space: nowrap;
}

/* A column that can go when the screen is narrow, on a tablet or a small
   laptop, so the table fits without scrolling sideways. Its value is still on
   the card view and on the record itself, and on a phone, where each row is a
   card, it comes back. */
@media (min-width: 576px) and (max-width: 1199.98px) {
    .table .dv-hide-narrow {
        display: none;
    }
}

/* A name column that wrapped over three lines while Email had room. */
.table .dv-col-name {
    min-width: 13rem;
}

/* --- Short add and edit forms sit on a card --------------------------------
   They floated on the grey page and their rows ran 11 pixels past it, because
   a Bootstrap row has negative side margins and nothing gave them room. The
   card's padding takes those margins, and each label lines up with the middle
   of the box beside it. */
.dv-form-card {
    background: var(--dv-surface);
    border-radius: var(--dv-radius);
    box-shadow: var(--dv-shadow);
    padding: var(--dv-space-5) var(--dv-space-5) var(--dv-space-3);
    max-width: 62rem;
}

.dv-form-card + .dv-form-card {
    margin-top: var(--dv-space-4);
}

.dv-form-card-title {
    font-family: var(--dv-font-head);
    font-size: 0.85rem;
    font-weight: 800;
    color: var(--dv-navy);
    margin-bottom: var(--dv-space-3);
}

/* Every box is the tap height, so the label takes that height too and sits
   at the top of its row, level with the box rather than with the help text
   under it. */
@media (min-width: 576px) {
    .dv-form-card .col-form-label {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        align-self: flex-start;
        min-height: var(--dv-tap);
        padding-top: 0;
        padding-bottom: 0;
    }
}

@media (max-width: 575.98px) {
    .dv-form-card {
        padding: var(--dv-space-4) var(--dv-space-3) var(--dv-space-2);
    }
}

/* --- The side menu ----------------------------------------------------------
   The menu under your name, with Switch user in it, ran up over the brand at
   the top. It now stops below the brand row and scrolls. */
.dv-foot-menu {
    max-height: calc(100vh - 170px);
}

/* Who is signed in, at the head of that menu, in normal case on two lines,
   rather than one upper case line that wrapped. */
.dv-foot-menu-who {
    padding: var(--dv-space-1) var(--dv-space-2) var(--dv-space-2);
    line-height: 1.3;
}

.dv-foot-menu-who strong {
    display: block;
    font-size: 0.82rem;
    color: var(--dv-navy);
}

.dv-foot-menu-who span {
    display: block;
    font-size: 0.72rem;
    color: var(--dv-text-muted);
}

/* A small heading over a group in the main menu, used when the Configure
   screens are the only menu a person has, as for a Daveng Administrator. */
.dv-nav-heading {
    font-size: 0.62rem;
    font-weight: 800;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    padding: var(--dv-space-1) 10px var(--dv-space-2);
}

.dv-shell.dv-rail .dv-nav-heading {
    display: none;
}

/* Field mode's label was grey on navy and hard to read. */
.dv-sidebar .dv-field-toggle {
    color: rgba(255, 255, 255, 0.85);
    padding: 0 8px var(--dv-space-2);
}

/* The drawer's close button, on a phone or tablet only. */
.dv-drawer-close {
    display: none;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: var(--dv-radius-sm);
    background: rgba(255, 255, 255, 0.14);
    color: #FFFFFF;
}

.dv-drawer-close svg {
    width: 18px;
    height: 18px;
}

@media (max-width: 991.98px) {
    .dv-drawer-close {
        display: inline-flex;
    }

    /* The drawer's shadow showed as a grey strip down the left of every page
       while it was closed. It only casts a shadow when it is open. */
    .dv-sidebar,
    .dv-shell.dv-rail .dv-sidebar,
    .dv-pre-collapsed .dv-sidebar {
        box-shadow: none;
    }

    .dv-shell.dv-drawer-open .dv-sidebar {
        box-shadow: var(--dv-shadow-lg);
    }
}

/* --- The app bar ------------------------------------------------------------
   While switched, the "Testing as" badge pushed the page title out and made
   every page scroll sideways on a phone. The title keeps its room, the badge
   gives way first, and on a phone it shortens to "Testing". */
.dv-appbar-title {
    flex: 0 1 auto;
    min-width: 4rem;
}

.dv-appbar-end {
    min-width: 0;
    flex: 0 1 auto;
}

.dv-appbar-end .dv-badge {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dv-testing-short {
    display: none;
}

@media (max-width: 575.98px) {
    .dv-testing-full {
        display: none;
    }

    .dv-testing-short {
        display: inline;
    }
}

/* --- List toolbars ----------------------------------------------------------
   On a tablet and a phone the toolbar stacked into four rows, one control to
   a row, and pushed the list below the first screen. Now the search and its
   filters share a row, and the exports, the view switch and Add share the
   next. On a phone the search takes a row of its own. Button text sits in the
   middle of the button, where it sat at the top on a phone. */
.dv-toolbar .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 991.98px) {
    .dv-toolbar-group {
        width: 100%;
    }

    .dv-toolbar-group .dv-search {
        flex: 1 1 12rem;
        width: auto;
        min-width: 0;
    }

    .dv-toolbar-group .dv-filter-select {
        flex: 1 1 9rem;
        width: auto;
        min-width: 0;
    }

    .dv-toolbar-group > .btn-primary {
        margin-left: auto;
    }
}

@media (max-width: 575.98px) {
    .dv-toolbar-group .dv-search {
        flex-basis: 100%;
    }

    /* With no dropdown beside it, the search keeps Filter on its own line. */
    .dv-toolbar-group:not(:has(.dv-filter-select)) .dv-search {
        flex-basis: 0;
    }

    .dv-toolbar-group .dv-filter-select {
        flex-basis: 0;
    }
}

/* Tiles two to a row on a phone, not one, so the list is still in sight. */
@media (max-width: 767.98px) {
    .dv-kpi-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .dv-kpi {
        padding: var(--dv-space-2) var(--dv-space-3);
    }
}

/* --- Tables on a phone ------------------------------------------------------
   A table no longer scrolls sideways on a phone. Each row becomes a small
   card with each value under its heading, the way field mode already stacks
   a table. site.js copies each heading onto its cells. */
@media (max-width: 575.98px) {
    .table-wrapper > .table {
        min-width: 0;
    }

    .table-wrapper table thead {
        display: none;
    }

    .table-wrapper table,
    .table-wrapper tbody,
    .table-wrapper tr,
    .table-wrapper td {
        display: block;
        width: 100%;
    }

    .table-wrapper {
        background: transparent;
        box-shadow: none;
        border-radius: 0;
        overflow: visible;
    }

    .table-wrapper tr {
        background: var(--dv-surface);
        border-radius: var(--dv-radius);
        box-shadow: var(--dv-shadow);
        margin-bottom: var(--dv-space-2);
        padding: var(--dv-space-2) var(--dv-space-3);
    }

    .table-wrapper > .table > tbody td {
        border: 0;
        padding: 3px 0;
        white-space: normal;
        text-align: left;
        background: transparent;
        box-shadow: none;
    }

    .table-wrapper td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: 0.66rem;
        font-weight: 700;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--dv-text-muted);
    }

    .table-wrapper td:empty {
        display: none;
    }

    /* The Actions heading says nothing its links do not. */
    .table-wrapper td[data-label="Actions"]::before {
        display: none;
    }
}

/* --- Item cards ------------------------------------------------------------
   A long company name was cut off under its type badge. A name wraps; a
   record number still never breaks. */
/* A card whose top line is only the record number and its status. The
   status stays on that line however long it is, and the name sits on a full
   width line of its own underneath. */
.dv-item-card-head-split {
    flex-wrap: nowrap;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 2px;
}

.dv-item-card-head-split > .dv-item-card-number {
    flex: 0 1 auto;
    min-width: 0;
}

.dv-item-card-subrow {
    font-size: 0.74rem;
    color: var(--dv-text-muted);
    padding: 0 var(--dv-space-4) var(--dv-space-2);
}

.dv-item-card-number.dv-wrap-name {
    white-space: normal;
    line-height: 1.3;
}

/* --- Field mode -------------------------------------------------------------
   The Dashboard's tiles are the Dashboard. Field mode hides the tiles on the
   lists, where they are noise on site, but never on the Dashboard. */
body.dv-field-mode .dv-dashboard .dv-kpi {
    display: block;
}

/* --- Task 1.14. The contractor's logo -------------------------------------- */
.dv-logo-preview {
    display: inline-block;
    padding: var(--dv-space-2) var(--dv-space-3);
    border: 1px solid var(--dv-line);
    border-radius: var(--dv-radius-sm);
    background: var(--dv-surface);
}

.dv-logo-preview img {
    display: block;
    max-height: 48px;
    max-width: 240px;
}

.table td.dv-logo-cell img {
    display: block;
    max-height: 24px;
    max-width: 96px;
}

/* A dropdown that holds a company name, such as the contractor on Users. The
   standard filter width cut "Karoo Road Works (Pty) Ltd" short. */
.dv-filter-select.dv-filter-select-wide {
    width: 17rem;
}

@media (max-width: 991.98px) {
    .dv-toolbar-group .dv-filter-select.dv-filter-select-wide {
        flex: 1 1 14rem;
        width: auto;
    }
}

/* The Dashboard's tiles are its content, so their figures are a size larger
   than the tiles above a list. */
.dv-kpi-dash .dv-kpi-value {
    font-size: 1.8rem;
}

.dv-kpi-dash .dv-kpi-icon {
    width: 40px;
    height: 40px;
}

.dv-kpi-dash .dv-kpi-icon svg {
    width: 20px;
    height: 20px;
}

/* A button that is a link, such as Cancel, Back or Users, centres its word as
   a real button does. On a phone and a tablet every button is the tap height,
   and a link drew its word near the top. Third regression, 4 October 2026. */
a.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* On a phone, a list with a wide dropdown, such as the contractor on a Daveng
   Administrator's Users, gives the dropdown its own row and keeps Filter on
   the search's row, rather than alone on a third. */
@media (max-width: 575.98px) {
    .dv-toolbar-group .dv-filter-select.dv-filter-select-wide {
        flex-basis: 100%;
    }

    .dv-toolbar-group:has(.dv-filter-select-wide) .dv-search {
        flex-basis: 0;
    }
}

/* --- One width for every form ---------------------------------------------
   Second regression: the short forms stopped at 62rem while Add Project and
   the General Definitions list ran the full width. They now share it. */
.dv-page-narrow {
    max-width: 62rem;
}

.dv-page-narrow .dv-form-card {
    max-width: none;
}

/* --- A record someone may read but not change ------------------------------
   Second regression, 4 October 2026. A Manager's record was a greyed out copy
   of the edit form, with help text meant for someone editing. Read only, each
   box shows its value as plain text on the card, the dropdown arrows and the
   help go, and nothing looks like something to click. */
fieldset.dv-read-only .form-control,
fieldset.dv-read-only .form-select,
fieldset.dv-read-only .dv-readonly {
    border-color: transparent;
    background: transparent;
    background-image: none;
    box-shadow: none;
    color: var(--dv-text);
    font-family: inherit;
    font-weight: 600;
    padding-left: 0;
    opacity: 1;
    resize: none;
    -webkit-appearance: none;
    appearance: none;
}

fieldset.dv-read-only .input-group-text {
    background: transparent;
    border-color: transparent;
    padding-left: var(--dv-space-1);
    color: var(--dv-text-muted);
}

fieldset.dv-read-only .form-text {
    display: none;
}

fieldset.dv-read-only .form-control::placeholder {
    color: var(--dv-text);
    opacity: 1;
}

fieldset.dv-read-only textarea.form-control {
    min-height: 0;
    overflow: hidden;
}

fieldset.dv-read-only .form-check-input:disabled,
fieldset.dv-read-only .form-check-input:disabled ~ .form-check-label {
    opacity: 1;
}

fieldset.dv-read-only #dvTeamMembers {
    box-shadow: none;
    border: 0;
    padding: 0;
    background: transparent;
}

/* --- A page that is not there ------------------------------------------- */
.dv-notfound {
    max-width: 34rem;
    margin: var(--dv-space-6) auto;
    text-align: center;
}
