﻿/* Landscape orientation blocker — phones only */
#landscape-blocker {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 999999;
    background-color: white;
    color: #333;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    padding: 20px;
}

#landscape-blocker .landscape-logo {
    max-height: 50px;
    margin-bottom: 30px;
}

#landscape-blocker .rotate-icon {
    font-size: 64px;
    margin-bottom: 25px;
    color: #349ad8;
    animation: rotatePortrait 2s ease-in-out infinite alternate;
}

#landscape-blocker h2 {
    margin: 0 0 12px;
    font-size: 24px;
    color: #1d69a6;
    font-weight: 600;
}

#landscape-blocker p {
    margin: 0 0 25px;
    font-size: 16px;
    color: #666;
}

#landscape-blocker .landscape-support {
    font-size: 14px;
    color: #999;
}

#landscape-blocker .landscape-support a {
    color: #349ad8;
    text-decoration: none;
}

@keyframes rotatePortrait {
    from { transform: rotate(90deg); }
    to { transform: rotate(0deg); }
}

@media (orientation: landscape) and (max-height: 500px) {
    #landscape-blocker {
        display: flex;
    }

    #divIncludesHeaderNavigationBody {
        display: none;
    }

    /* Allow pages to opt out */
    .allow-landscape #landscape-blocker {
        display: none;
    }

    .allow-landscape #divIncludesHeaderNavigationBody {
        display: flex;
    }
}


/**** Mobile Form Tabs ****/
#mobileFormTabs {
    display: flex;
    align-items: flex-end;
    border-bottom: 3px solid #349ad8;
    padding-left: 10px;
    padding-right: 10px;
    padding-top: 10px;
    background: white;
    flex-shrink: 0;
}

.mobile-tab-item {
    flex: 1;
    text-align: center;
    padding: 10px 4px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    color: #666;
    user-select: none;
}

.mobile-tab-item.active-mobile-tab {
    color: #349ad8;
    font-weight: 600;
    background-color: #f0f0f0;
}

.mobile-tab-item.disabled-tab {
    opacity: 0.4;
    pointer-events: none;
}

.mobile-tab-content {
    display: none;
    padding-top: 10px;
}

.mobile-tab-content.active-mobile-tab-content {
    display: block;
}

@media screen and (min-width: 900px) {
    /***** Mobile Form Tabs - hidden on desktop ******/
    #mobileFormTabs {
        display: none;
    }

    .mobile-tab-content {
        display: block !important;
    }
}


/* Report pages tab layout */
.reports-page {
    padding-bottom: 0 !important;
}

#reportsTabDesktop {
    display: none;
}

#reportsTabMobile {
    display: flex;
    align-items: flex-end;
    border-bottom: 3px solid #349ad8;
    padding-left: 10px;
    padding-right: 10px;
    padding-top: 10px;
    background: white;
    flex-shrink: 0;
}

#reportsTabMobile .mobile-tab-item {
    text-decoration: none;
}

.reports-page > form > ul.tab,
.reports-page > form > #reportsTabDesktop,
.reports-page > form > #reportsTabMobile,
.reports-page > form > .custom-report-sub-tabs {
    flex-shrink: 0;
}

.reports-page > form > .tabcontent {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    -webkit-overflow-scrolling: touch;
    float: none;
}

.reports-page > form > .tabcontent > * {
    float: none;
}

@media (max-width: 900px) {
    .reports-page > form > .tabcontent {
        border-left: none;
        border-right: none;
        border-bottom: none;
    }
}

@media screen and (min-width: 900px) {
    #reportsTabMobile {
        display: none;
    }

    #reportsTabDesktop {
        display: block;
    }

    .reports-page {
        display: flex;
        flex-direction: column;
        overflow: hidden;
        float: none;
        height: calc(100vh - 120px);
    }

    .reports-page > form {
        display: flex;
        flex-direction: column;
        flex: 1;
        overflow: hidden;
        float: none;
        min-height: 0;
    }

    .reports-page > form > .tabcontent {
        flex: 1;
        overflow-y: auto;
        min-height: 0;
        float: none;
    }

    .reports-page {
        height: 100%;
        overflow: hidden;
    }

    .reports-page > form {
        display: flex;
        flex-direction: column;
        height: 100%;
        padding: 10px;
        overflow: hidden;
        box-sizing: border-box;
    }

    .reports-page > form > ul.tab,
    .reports-page > form > #reportsTabDesktop,
    .reports-page > form > #reportsTabMobile {
        flex-shrink: 0;
    }

    .reports-page > form > .tabcontent {
        flex: 1;
        overflow-y: auto;
        min-height: 0;
    }
}


/* Kendo grid overrides */
.k-selected td {
    background-color: #1d69a6 !important;
    color: white;
}

/* A grid whose rows are controls - one click anywhere on a row opens or loads what it stands for. The
   estimate list on the home page is the reference, and every grid that works that way carries this
   class so they all answer the pointer the same: the hand cursor, the light-blue hover, and the site's
   dark-blue .k-selected row (above) once it has been picked. */
.datagrid.clickable-rows tbody tr {
    cursor: pointer;
}

    .datagrid.clickable-rows tbody tr:hover td {
        background-color: #cfe2f0;
    }

    .datagrid.clickable-rows tbody tr.k-selected:hover td {
        background-color: #1d69a6;
    }

/* A grid with one page of rows has no pages to turn, so the whole pager row goes - the count on it as
   well - and the rows take the space it was in. ShowPagingOnlyWhenPaging (MiscScript.js) puts this on
   the pager from the grid's DataBound event. */
.single-page-pager {
    display: none !important;
}

.k-state-hover td {
    background-color: #7ca0bc;
    color: white;
}

/* Grid columns that fold on a phone: .grid-col-wide shows on a wide screen only, .grid-col-narrow - the
   summary column that stands in for them - on a phone only. On a Kendo column, set the class in both
   HeaderHtmlAttributes and HtmlAttributes. Scoped under .k-grid because the Kendo theme, which loads
   after this file, sets display: table-cell on .k-table-th / .k-table-td at the same specificity as a
   bare class, and would otherwise win by order. */
.k-grid .grid-col-narrow {
    display: none;
}

/* A second line under a cell's text, shown on a phone only: what the folded .grid-col-wide columns
   said, summed up under the row's title so a row takes two lines instead of a column it has to
   scroll to. Put it in the column's ClientTemplate. */
.grid-col-stack-line {
    display: none;
}

@media screen and (max-width: 700px) {
    .k-grid .grid-col-wide {
        display: none;
    }

    .k-grid .grid-col-narrow {
        display: table-cell;
    }

    .grid-col-stack-line {
        display: block;
        margin-top: 2px;
        font-size: 13px;
        color: #7a8794;
    }

    .k-state-hover .grid-col-stack-line,
    .k-selected .grid-col-stack-line {
        color: inherit;
    }
}

.k-grid tbody tr {
    height: 30px;
}

.k-grid tbody td {
    padding-top: 8px;
    padding-bottom: 8px;
}

@media screen and (min-width: 900px) {
    .k-grid tbody tr {
        height: auto;
    }

    .k-grid tbody td {
        padding-top: 0;
        padding-bottom: 0;
    }
}

.k-grid .k-cell-inner {
    justify-content: center !important;
}

.k-grid td, .k-grid .k-table-td {
    text-align: center !important;
}

.deleted-row {
    color: lightgray;
    font-style: italic;
}

/* For selected rows in a grid, make the text white. */
.k-selected > td {
    color: white !important;
}

.k-grid a {
    color: white !important;
}

.k-button-text {
    color: black !important;
}

.k-grid td.k-selected, .k-grid .k-table-row.k-selected > td, .k-grid .k-table-td.k-selected, .k-grid .k-table-row.k-selected > .k-table-td {
    background-color: #1d69a6 !important;
    color: white !important;
}

.k-treeview-leaf.k-selected {
    background-color: #1d69a6 !important;
    color: white !important;
}


/* Toggle button on/off */
.switch {
    position: relative;
    display: inline-block;
    width: 60px;
    height: 30px;
}

    .switch input {
        opacity: 0;
        width: 0;
        height: 0;
    }

.slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ccc;
    -webkit-transition: .4s;
    transition: .4s;
}

    .slider:before {
        position: absolute;
        content: "";
        height: 26px;
        width: 26px;
        left: 4px;
        bottom: 2px;
        background-color: white;
        -webkit-transition: .2s;
        transition: .2s;
    }

input:checked + .slider {
    background-color: #007dc1;
}

input:focus + .slider {
    box-shadow: 0 0 1px #007dc1;
}

input:checked + .slider:before {
    -webkit-transform: translateX(26px);
    -ms-transform: translateX(26px);
    transform: translateX(26px);
}

/* Rounded sliders */
.slider.round {
    border-radius: 85px;
}

    .slider.round:before {
        border-radius: 50%;
    }


/* Spinner overlay container */
.spinner-overlay {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 5;
}

/* Spinner animation */
.spinner {
    border: 4px solid #f3f3f3;
    border-top: 4px solid #3498db;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}


/* Grayed-out button style */
a.button.disabled, button.disabled {
    opacity: 0.5;
    pointer-events: none;
    cursor: default;
}

.admonishment {
    font-size: 12px;
    color: red;
    font-weight: bold
}


/*DataGrid Table*/
.datagrid table {
    border-collapse: collapse;
    text-align: center;
    width: 100%;
}

.datagrid {
    font: normal 12px/150% Verdana, Arial, Helvetica, sans-serif;
    background: #fff;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
    text-align: center;
}

    .datagrid table td, .datagrid table th {
        padding: 5px 4px;
    }

    .datagrid table thead th {
        background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );
        background: -moz-linear-gradient( center top, #006699 5%, #00557F 100% );
        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');
        background-color: #006699;
        color: #FFFFFF;
        font-size: 12px;
        font-weight: bold;
        border-left: 1px solid #0070A8;
        text-align: center;
    }

        .datagrid table thead th:first-child {
            border: none;
        }

#smGraphicalGrid tbody td {
    font-size: 10px !important;
}

.datagrid table tbody td {
    color: #000000;
    border-left: 1px solid #E1EEF4;
    font-size: 12px;
    font-weight: normal;
    text-align: center;
}

.datagrid table tbody .alt td {
    background: #E1EEF4;
    color: #000000;
}

.datagrid table tbody td:first-child {
    border-left: none;
}

.datagrid table tbody tr:last-child td {
    border-bottom: none;
}

.datagrid table tfoot td div {
    border-top: 1px solid #006699;
    background: #E1EEf4;
}

.datagrid table tfoot td {
    padding: 0;
    font-size: 12px;
}

    .datagrid table tfoot td div {
        padding: 2px;
    }

    .datagrid table tfoot td ul {
        margin: 0;
        padding: 0;
        list-style: none;
        text-align: right;
    }

.datagrid table tfoot li {
    display: inline;
}

    .datagrid table tfoot li a {
        text-decoration: none;
        display: inline-block;
        padding: 2px 8px;
        margin: 1px;
        color: #FFFFFF;
        border: 1px solid #006699;
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        border-radius: 3px;
        background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );
        background: -moz-linear-gradient( center top, #006699 5%, #00557F 100% );
        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');
        background-color: #006699;
    }

.datagrid table tfoot ul.active, .datagrid table tfoot ul a:hover {
    text-decoration: none;
    border-color: #00557F;
    color: #FFFFFF;
    background: none;
    background-color: #006699;
}

div.dhtmlx_window_active, div.dhx_modal_cover_dv {
    position: fixed !important;
}

.table-button {
    text-decoration: none;
    display: inline-block;
    padding: 2px 8px;
    margin: 1px;
    color: #FFFFFF;
    border: 1px solid #006699;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
    background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );
    background: -moz-linear-gradient( center top, #006699 5%, #00557F 100% );
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');
    background-color: #006699;
}

.center {
    text-align: center;
}


/* Tabs */
ul.tab {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    border: 1px solid #349ad8;
    background-color: #f5f9fb;
}

    ul.tab li {
        float: left;
        padding: 8px;
    }

        ul.tab li a {
            display: inline-block;
            text-align: center;
            text-decoration: none;
            transition: 0.3s;
            color: white;
            height: 30px;
            padding: 4px;
        }

            /* Change background color of links on hover */
            ul.tab li a:hover {
                background-color: #ddd;
            }

            /* Create an active/current tablink class */
            ul.tab li a:focus, .active {
                background-color: #ccc;
            }

@media screen and (min-width:700px) {
    .tabcontent {
        padding: 15px;
    }
}

.tabcontent {
    padding: 5px;
    border: 1px solid #349ad8;
    border-top: none;
}

.tabcontent2 {
    border: none;
    border: 0px;
}

/* A tab row with more tabs than a phone has room for: the same pages again in a <select> inside an
   li.tab-picker at the end of the row. Wide, the picker is hidden and the tabs are the row; narrow,
   the tabs are hidden and the picker is the row. Only rows marked .tab-collapse do this - a row of
   two tabs fits a phone as it is. */
ul.tab li.tab-picker {
    display: none;
}

@media screen and (max-width: 899px) {
    ul.tab.tab-collapse li {
        display: none;
    }

    ul.tab.tab-collapse li.tab-picker {
        display: block;
        float: none;
        padding: 8px;
    }

        ul.tab.tab-collapse li.tab-picker select {
            margin: 0;
        }
}

/* -------------------------------------------------------------------------
   Tabbed page
   The frame of a page with a row of tabs over a bordered content area. The
   home page (Customer Search) is the reference: the tab row at the top, the
   content area under it taking the rest of the window so its bottom edge is
   locked to the foot of the screen, and whatever scrolls scrolling inside the
   content area - a grid, a column of cards - never the page.

   .tab-page          on the page container (#workDesk, with .page-container)
   .tab-page > form   the flex column the tab row and content area stack in
   .tab-page-frame    that column as a div, for a page whose content holds
                      forms of its own and so cannot all sit in one (Billing,
                      with Stripe's card forms): the page's own form, hidden
                      inputs only, goes inside it beside the tab row
   ul.tab             the tab row (Tabs, above)
   .tab-page-body     with .tabcontent on the content area: takes what is
                      left of the height and scrolls if its content is taller
   .tab-page-column   wide screens only: a box between the body and a scroller,
                      passing the height down (see .tab-page-scroll)
   .tab-page-scroll   wide screens only: a box inside the body that scrolls on
                      its own while the rest of the body holds still - the
                      rows of a list under a toolbar and a heading. Every box
                      between it and the body is a .tab-page-column. On a
                      phone neither applies and the whole body scrolls, as
                      there is no room for a box that scrolls inside a box.
                      Add .tab-page-scroll-flush for a scroller that runs out
                      to the frame of the body, its scrollbar against the
                      frame, with the page's capped card stack inside it
   .tab-page-foot-actions
                      on the body: on a phone its .page-actions-divided row
                      moves under the flush scroller, locked to the foot of
                      the screen, and the scroller scrolls above it (see
                      .page-actions-divided)

   What a page puts inside the body is the page's own layout; the shell is
   the frame and says nothing about the content.
   ------------------------------------------------------------------------- */
.page-container.tab-page {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    /* forms.css leaves a gap under every page container for a footer; here the frame is the footer. */
    padding-bottom: 0;
    overflow: hidden;
    float: none;
    box-sizing: border-box;
}

    .page-container.tab-page > form,
    .page-container.tab-page > .tab-page-frame {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
        height: auto;
        width: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
        float: none;
        box-sizing: border-box;
    }

    .page-container.tab-page > form > ul.tab,
    .page-container.tab-page > .tab-page-frame > ul.tab {
        flex: 0 0 auto;
    }

.tab-page .tab-page-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Between the border and what is inside it. Set here rather than left to .tabcontent, whose
       5px/15px pair above is written in the wrong order and comes out as 5px at every width. */
    padding: 10px;
    /* The last resort, for a window too short to hold even the rows that do not scroll. Nothing
       overflows at an ordinary height, so there is no scrollbar to see. overflow-x hidden rather
       than auto: a grid that already scrolls sideways inside its own box must not put a second
       horizontal scrollbar on the page. */
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    float: none;
    box-sizing: border-box;
}

    .tab-page .tab-page-body > * {
        float: none;
    }

@media screen and (min-width: 900px) {
    /* Inset from the edges of the content area on every side; the bottom border of the content area
       sits the same distance above the foot of the screen as the tab row sits below the header. */
    .page-container.tab-page > form,
    .page-container.tab-page > .tab-page-frame {
        padding: 10px;
    }

    /* flex: 0 1 auto and not flex: 1, all the way down: the boxes take no more room than their
       contents need, so a list of three rows ends under the third row rather than leaving its pager
       at the foot of an empty window. Only when there is more than fits does the shrinking start,
       and that is what turns the .tab-page-scroll box into a scroller. Every one of them has to say
       min-height: 0, or a flex item refuses to be shorter than its contents and the whole list
       pushes out the bottom of the page again. */
    .tab-page-column {
        display: flex;
        flex-direction: column;
        flex: 0 1 auto;
        min-height: 0;
    }

    .tab-page-scroll {
        flex: 0 1 auto;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
    }

    /* Flush: the scroller run out over the body's 10px padding to its frame on either side and below,
       and up to the line of a divided button row above it, with the padding put back inside so the
       cards keep their distance from the frame and the scrollbar. Without it the scroller is the
       stack of cards, whose width the page caps, and the scrollbar stands at the cap in the middle of a
       wide screen with the page's padding between it and the frame. The capped stack goes inside this
       box, not on it. */
    .tab-page-scroll-flush {
        margin: 0 -10px -10px;
        padding: 14px 10px 10px;
    }
}

/* On a phone the flush scroller does not scroll, but the gap under the button row is still its. */
@media screen and (max-width: 899px) {
    .tab-page-scroll-flush {
        padding-top: 14px;
    }
}


/* Sortable table */
.sortable-table thead {
    cursor: pointer;
}

    .sortable-table thead tr th {
        font-weight: bold;
        text-align: center;
    }

        .sortable-table thead tr th span {
            padding-right: 20px;
            background-repeat: no-repeat;
            background-position: 100% 100%;
        }

        .sortable-table thead tr th.headerSortUp, .sortable-table thead tr th.headerSortDown {
            background: #acc8dd;
        }

            .sortable-table thead tr th.headerSortUp span {
                background-image: url('../images/UpArrow2.gif');
            }

            .sortable-table thead tr th.headerSortDown span {
                background-image: url('../images/DownArrow2.gif');
            }

.sortable-table tbody tr {
    color: #555;
}

    .sortable-table tbody tr td {
        text-align: center;
        padding: 15px 10px;
    }

        .sortable-table tbody tr td.lalign {
            text-align: left;
        }


.ddContainer {
    float: left;
    width: 100%;
}

@media (min-width: 500px) {
    .ddContainer {
        width: 32%;
        max-width: 200px;
        padding-right: 10px;
    }
}

.ReportHistoryContainer {
    height: 400px;
    overflow-y: auto;
}


/* -------------------------------------------------------------------------
   Mobile popups (jQuery UI dialogs)
   ------------------------------------------------------------------------- */
@media (max-width: 899px) {
    .ui-dialog {
        position: fixed !important;
        top: 0 !important;
        left: 0 !important;
        transform: none !important;
        width: 100% !important;
        max-width: 100% !important;
        height: 100% !important;
        max-height: 100% !important;
        min-width: 0 !important;
        min-height: 0 !important;
        margin: 0 !important;
        border-radius: 0;
        display: flex;
        flex-direction: column;
    }

        .ui-dialog .ui-dialog-titlebar,
        .ui-dialog .ui-dialog-buttonpane {
            flex: 0 0 auto;
        }

        .ui-dialog .ui-dialog-titlebar-close {
            display: none;
        }

        .ui-dialog .ui-dialog-content {
            flex: 1 1 auto;
            min-height: 0;
            width: 100% !important;
            height: auto !important;
            max-height: none !important;
            overflow-y: auto !important;
            overflow-x: hidden;
            -webkit-overflow-scrolling: touch;
            padding: 10px !important;
            box-sizing: border-box;
        }
}

/* Modal-popup backdrop */
.ui-widget-overlay {
    background: #000 !important;
    opacity: 0.4 !important;
    z-index: 100001 !important;
}

body .ui-dialog {
    z-index: 100002 !important;
}

/* Customer search popup – mobile */
@media (max-width: 899px) {
    /* Hide Select button column and its colgroup width */
    .ui-dialog #customer-grid td:last-child,
    .ui-dialog #customer-grid th:last-child {
        display: none !important;
    }

    .ui-dialog #customer-grid colgroup col:last-child {
        width: 0 !important;
    }

    .ui-dialog #customer-grid tbody tr {
        cursor: pointer;
    }

    /* Grid full width */
    .ui-dialog #CustomerSearchContainer,
    .ui-dialog #CustomerSearchContainer .container,
    .ui-dialog #customer-grid-container,
    .ui-dialog #customer-grid {
        width: 100% !important;
        max-width: 100% !important;
        padding: 0;
        margin: 0;
    }

    .ui-dialog #customer-grid .k-grid-header,
    .ui-dialog #customer-grid .k-grid-content {
        width: 100% !important;
    }

    .ui-dialog #customer-grid table {
        width: 100% !important;
    }
}

/* Lock page scroll while a modal dialog is open */
body.we-modal-open {
    overflow: hidden !important;
}

/* -------------------------------------------------------------------------
   Cards, badges and notices
   The shared building blocks for settings-style pages (first used on
   Settings > Contract). Use these instead of inventing a panel per page —
   see "Cards, badges and notices" in Proestimator/CLAUDE.md.

   .card             white panel with a border, radius and soft shadow
   .card-compact     the same card at popup scale: tighter padding, no shadow
   .card-clickable   a card that is one target (cursor + hover); the page
                     wires the click
   .card-highlight   the card picked out in the site's blue: the hero figure,
                     the pitch
   .stat-tiles       a row of .card .stat-tile boxes, each a .stat-label over a
                     big .stat-value (+ .stat-tile-hero for the lead figure)
   .card-table       a plain table inside a card: th.num / td.num right-align,
                     tr.row-link for rows that go somewhere
   .card-header      grey title bar: <h2> (or .card-title) + optional action;
                     .card-header-tools groups a badge and a checkbox at its right
   .card-body        padded content; stack several for divided sections
   .card-heading     title row inside a body: .card-heading-title + a .badge
   .stat-grid        labelled values side by side (.stat-label / .stat-value)
   .card-actions     horizontal row of site buttons and .text-link links;
                     card-actions-end pushes them to the right
   .card-empty       centred empty state: <h2> message + one button
   .section-label    small uppercase label above a group of rows
   .form-grid        two columns of .form-field (label over input); .form-field-check
                     for a checkbox beside its label; .option-list for a column of them
   .form-message     the quiet "Saved" line under a form's buttons (ShowFormMessage)
   .card-outlined    blue frame and darker header: a card to act on or choose
   .card-stack       a column of cards/notices; .card-row cards side by side
                     on a wide screen, stacked on a phone
   .page-actions     the button row for a whole page, above its cards;
                     page-actions-divided closes it with the blue line when
                     the cards scroll up behind it
   .badge            status pill: badge-green / -amber / -blue / -red / -gray
   .notice           callout: notice-info / notice-warn / notice-success /
                     notice-danger; add notice-stack for stacked content
   .text-link        the plain blue underlined text link
   .icon-link        small link with a leading icon (help PDF etc.)
   ------------------------------------------------------------------------- */
.card {
    background: #ffffff;
    border: 1px solid #dfe5ea;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
    margin-bottom: 20px;
}

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 14px 20px;
    border-bottom: 1px solid #e9eef2;
    border-radius: 7px 7px 0 0;
    background: #f7f9fb;
    font-size: 14px;
    color: #2b3743;
}

    .card-header h2,
    .card-header .card-title {
        margin: 0;
        font-size: 1.1em;
        font-weight: 600;
        color: #1f2d3a;
        text-align: left;
    }

    .card-header .text-link,
    .card-header .icon-link {
        font-size: 13px;
    }

    .card-header .button {
        margin-top: 0;
        width: auto;
        min-width: 90px;
    }

.card-body {
    padding: 20px;
    font-size: 14px;
    color: #2b3743;
}

    .card-body + .card-body {
        border-top: 1px solid #e9eef2;
    }

.card-subtitle {
    font-size: 13px;
    color: #7a8794;
}

/* Compact: the card as it sits inside a popup or a dense grid of cards, where the page-scale
   padding and shadow would swallow the content. The container spaces compact cards (grid/flex
   gap), so they carry no margin of their own. */
.card-compact {
    border-radius: 6px;
    box-shadow: none;
    margin-bottom: 0;
}

    .card-compact > .card-header {
        padding: 6px 10px;
        gap: 6px;
        border-radius: 5px 5px 0 0;
        font-size: 13px;
    }

        .card-compact > .card-header h2,
        .card-compact > .card-header .card-title {
            font-size: 13px;
        }

    .card-compact > .card-body {
        padding: 6px 10px;
        font-size: 13px;
    }

/* A whole card as one target. It is a card rather than a link so the rows inside it stay readable
   as a table instead of turning into a wall of underlined blue. */
.card-clickable {
    cursor: pointer;
}

    .card-clickable:hover {
        border-color: #349ad8;
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
    }

/* Picked out in the site's blue: the one card on a page that is the point of it - the hero figure
   on a summary, the Pro Advisor pitch in the estimate popup. */
.card-highlight {
    border-color: #019ad2;
    background-color: #eef7fc;
}

    .card-highlight > .card-header {
        background-color: #e1f1fa;
        border-bottom-color: #b9dff2;
    }

        .card-highlight > .card-header h2,
        .card-highlight > .card-header .card-title {
            color: #0b6fa8;
        }

    .card-highlight.card-clickable:hover {
        border-color: #019ad2;
        background-color: #e1f1fa;
    }

/* Outlined: the card framed in the site's blue like the page strip, with a header darker than the
   plain card's grey, for a card that is a thing to act on or to choose - the cards of the subscription
   flow, and every plan card - so it stands apart from the page and from a card that merely holds
   others. */
.card-outlined,
.plan-card {
    border-color: #349ad8;
}

    .card-outlined > .card-header,
    .plan-card > .card-header {
        background-color: #dce8f1;
        border-bottom-color: #349ad8;
    }

        .card-outlined > .card-header h2,
        .card-outlined > .card-header .card-title,
        .plan-card > .card-header h2 {
            color: #1f2d3a;
        }

/* Stat tiles: a row of cards that each carry one figure. The container spaces them, so they have no
   margin of their own; the first one on a page is usually the hero, twice as wide and highlighted. */
.stat-tiles {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
}

.stat-tile {
    flex: 1 1 180px;
    min-width: 0;
    padding: 14px 16px;
    margin-bottom: 0;
}

.stat-tile-hero {
    flex: 2 1 260px;
}

    .stat-tile .stat-label {
        margin-bottom: 6px;
    }

    .stat-tile .stat-value {
        font-size: 28px;
        line-height: 1.1;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .stat-tile-hero .stat-value {
        font-size: 48px;
    }

    .stat-tile .card-subtitle {
        margin-top: 6px;
    }

/* A table inside a card body: light rules between rows, no outer frame - the card is the frame.
   margin is set because main.css spaces every table for a report standing on its own. */
.card-table {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    font-size: 14px;
}

    .card-table th {
        text-align: left;
        font-weight: 600;
        color: #7a8794;
        font-size: 12px;
        padding: 6px 8px;
        border-bottom: 1px solid #e9eef2;
    }

    .card-table td {
        padding: 6px 8px;
        border-bottom: 1px solid #eef1f4;
    }

    .card-table tr:last-child td {
        border-bottom: none;
    }

    .card-table th.num,
    .card-table td.num {
        text-align: right;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }

    .card-table tbody tr.row-link {
        cursor: pointer;
    }

        .card-table tbody tr.row-link:hover td {
            background-color: #f3f8fc;
        }

.card-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.card-heading-title {
    font-size: 1.35em;
    font-weight: 600;
    color: #1f2d3a;
    margin: 0;
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 16px;
    margin-top: 16px;
}

.stat-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #7a8794;
    margin-bottom: 3px;
}

.stat-value {
    font-size: 15px;
    font-weight: 600;
    color: #1f2d3a;
}

.card-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 18px;
}

    .card-actions .button {
        margin-top: 0;
        width: auto;
        min-width: 140px;
    }

    /* The buttons pushed to the right edge of the card. */
    .card-actions-end {
        justify-content: flex-end;
    }

/* A column of cards and notices, one gap between them: the body of a page whose cards stack. The page's
   own style caps its width. */
.card-stack {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

    .card-stack > .card,
    .card-stack > .notice {
        margin-bottom: 0;
    }

/* Cards side by side on a wide screen, stacked on a phone. Nothing grows to fill the row: the page's own
   style gives each card its flex: 0 1 <max>px cap (the settings recipe). */
.card-row {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

    .card-row > .card {
        margin-bottom: 0;
        min-width: 0;
    }

@media screen and (min-width: 900px) {
    .card-row {
        flex-direction: row;
        align-items: flex-start;
    }
}

/* A Kendo grid as the whole of a card body: a thin margin of card around it, and the grid draws no
   border of its own because the card is the frame. */
.card-body-grid {
    padding: 8px;
}

    .card-body-grid .datagrid {
        margin: 0;
    }

    .card-body-grid .k-grid {
        border-width: 0;
        border-radius: 0;
    }

.card-empty {
    text-align: center;
    padding: 30px 20px;
}

    .card-empty h2 {
        margin: 0 0 16px 0;
        font-size: 1.3em;
        font-weight: 600;
        color: #1f2d3a;
    }

    .card-empty .button {
        margin-top: 0;
        width: auto;
        min-width: 160px;
    }

.section-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #7a8794;
    margin: 12px 0 8px 0;
}

    .section-label:first-child {
        margin-top: 0;
    }

/* Form fields in a card: two columns of label-over-input, capped in width so a name box does not run
   the width of the screen. The inputs are the site's inputs (main.css); this only sizes them to the
   field. Settings > Estimators is the reference. */
.form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px 16px;
    max-width: 560px;
}

.form-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

/* A field across both columns: an email address, a street, a note. */
.form-field-wide {
    grid-column: 1 / -1;
}

/* A form with something in it that wants the room - a rich text editor - runs the width of its card
   instead of stopping at the cap. */
.form-grid-wide {
    max-width: none;
}

.form-field > label {
    display: block;
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    color: #5b6771;
    text-align: left;
}

.form-field input[type="text"],
.form-field input[type="password"],
.form-field input[type="email"],
.form-field input[type="tel"],
.form-field input[type="number"],
.form-field input[type="date"],
.form-field select {
    width: 100%;
    height: 34px;
    margin: 0;
    box-sizing: border-box;
}

.form-field textarea {
    width: 100%;
    margin: 0;
    box-sizing: border-box;
}

/* A checkbox with its label beside it rather than over it. */
/* A field beside its button - a promo code and Apply - bottoms aligned, wrapping on a phone. */
.form-field-action {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

    .form-field-action .form-field {
        flex: 0 1 200px;
    }

    .form-field-action .button {
        margin-top: 0;
        width: auto;
        min-width: 100px;
    }

.form-field-check {
    flex-direction: row;
    align-items: center;
    gap: 8px;
}

    .form-field-check input[type="checkbox"] {
        margin: 0;
    }

    .form-field-check > label {
        font-size: 14px;
        font-weight: normal;
        color: #2b3743;
    }

/* The line under a form's buttons where "Saved" appears (ShowFormMessage, MiscScript.js). It holds
   its height at all times, so the buttons do not jump when it speaks; only its opacity changes. */
.form-message {
    min-height: 18px;
    margin-top: 12px;
    font-size: 13px;
    line-height: 18px;
    color: #1e7e34;
    opacity: 0;
    transition: opacity 0.25s ease;
}

    .form-message.form-message-visible {
        opacity: 1;
    }

    .form-message.form-message-error {
        color: #b42318;
    }

/* A column of checkboxes or radios, each beside its label: the preference lists on Settings > Account
   Preferences. Each row is a form-field form-field-check; the list only spaces them. A row that
   belongs to the row above it (a size box under the option that uses it) is an option-list-indent. */
.option-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

    .option-list .form-field-check > label {
        cursor: pointer;
    }

    .option-list .option-list-indent {
        padding-left: 24px;
    }

    /* main.css gives every select the width of its box; a row of option-list only wants one wide
       enough for what is in it. */
    .option-list select {
        width: auto;
        height: 30px;
        margin: 0;
    }

/* Small controls at the right of a card header - a badge, a "show deleted" checkbox - where a header
   holds more than the one button .card-header allows for. */
.card-header-tools {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

    .card-header-tools .form-field-check > label {
        font-size: 13px;
        cursor: pointer;
    }

/* The row of buttons for a whole page - Save on a settings page that is one form across several
   cards - at the top of a tab body, before the cards. It does not scroll with them when the cards are
   the scroller (tab-page-scroll): the button is there whatever the user is looking at. */
.page-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    flex: 0 0 auto;
    margin-bottom: 14px;
}

    .page-actions .button {
        margin-top: 0;
        width: auto;
        min-width: 140px;
    }

    .page-actions .form-message {
        margin-top: 0;
        flex: 1 1 auto;
    }

    .page-actions .notice {
        flex: 1 1 100%;
    }

/* Divided: the row closed off below by the same blue line as the tab row and the frame of the body,
   run out to the frame's sides, for a page whose cards scroll up behind the row - without it the
   cards slide under the buttons with nothing to show where the row ends and the scroller starts.
   The negative side margins undo the body's 10px padding so the line meets the frame. No margin
   under it: the flush scroller that follows (.tab-page-scroll-flush) carries the gap as padding, so
   the cards scroll up to the line. */
.page-actions-divided {
    margin: 0 -10px 0;
    padding: 0 10px 12px;
    border-bottom: 1px solid #349ad8;
}

/* Foot: on a phone the divided row goes to the foot of the body instead, locked to the foot of the
   screen, and the flush scroller above it does the scrolling - the buttons are under the thumb
   whatever the user is looking at. Put tab-page-foot-actions on the body: the row
   (page-actions-divided) and the scroller (tab-page-scroll-flush) inside it change places, and the
   line moves from under the row to over it. Wide, nothing changes and the row is at the top as above.
   Add-Ons is the reference. */
@media screen and (max-width: 899px) {
    .tab-page .tab-page-body.tab-page-foot-actions {
        overflow: hidden;
    }

    .tab-page-foot-actions > .tab-page-scroll-flush {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
        /* Out to the frame at the sides only. Above and below, the body's padding stays as a band
           between the line and the edge the cards are clipped at: run flush, a card scrolling past
           the edge sits on the line and looks like it overlaps it. */
        margin: 0 -10px;
        padding: 0 10px;
    }

    .tab-page-foot-actions > .page-actions-divided {
        order: 1;
        margin: 10px -10px -10px;
        padding: 10px;
        border-bottom: none;
        border-top: 1px solid #349ad8;
        justify-content: space-between;
    }

        /* The buttons share the row, half each, as a pair of nav-btns does in the estimate header. */
        .tab-page-foot-actions > .page-actions-divided .button {
            flex: 1 1 0;
            min-width: 0;
        }
}

@media screen and (max-width: 599px) {
    .form-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Status pills */
.badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    text-decoration: none;
}

    a.badge:hover {
        text-decoration: underline;
    }

.badge-green {
    background: #e6f4ea;
    color: #1e7e34;
}

.badge-amber {
    background: #fff4e0;
    color: #a35c00;
}

.badge-blue {
    background: #e8f2fb;
    color: #0061a7;
}

.badge-red {
    background: #fdecec;
    color: #b42318;
}

.badge-gray {
    background: #eef1f4;
    color: #5b6771;
}

/* Callouts */
.notice {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-radius: 6px;
    font-size: 14px;
    line-height: 1.5;
}

    .notice p {
        margin: 0;
    }

    .notice .button {
        margin-top: 0;
        width: auto;
        min-width: 140px;
    }

    .card-body > .notice {
        margin-top: 16px;
    }

.notice-stack {
    flex-direction: column;
    align-items: flex-start;
}

.notice-info {
    background: #eef6fc;
    border: 1px solid #c9e0f2;
    color: #1f4f75;
}

.notice-warn {
    background: #fff8e6;
    border: 1px solid #f3dfa3;
    color: #6b4b00;
}

.notice-success {
    background: #e6f4ea;
    border: 1px solid #cde9d4;
    color: #1e7e34;
}

.notice-danger {
    background: #fdecec;
    border: 1px solid #f3c2c2;
    color: #b42318;
}

/* Links */
a.text-link {
    color: #0061a7 !important;
    font-weight: normal;
    text-decoration: underline;
    cursor: pointer;
}

.icon-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: #0061a7;
    text-decoration: none;
}

    .icon-link:hover {
        text-decoration: underline;
    }

    .icon-link img {
        display: inline-block;
        width: 18px;
        height: 18px;
        margin: 0;
    }

@media screen and (max-width: 899px) {
    .card-header {
        padding: 12px 16px;
    }

    .stat-tile-hero .stat-value {
        font-size: 36px;
    }

    .card-body {
        padding: 16px;
    }

    .card-actions {
        flex-direction: column;
        align-items: stretch;
        text-align: center;
    }

        .card-actions .button,
        .notice .button {
            width: 100%;
        }

    .notice p {
        flex: 1 1 100%;
    }
}


/* -------------------------------------------------------------------------
   Flow pages
   A page that is one step of a sequence - the subscription flow: pick the
   contract terms, pick the add-ons, review, pay - has no tab row. In its
   place, at the top of the tab-page shell, sits a .page-strip: the same bar
   as the tab row (ul.tab), holding either the steps of the flow (.flow-steps)
   or a plain heading, so the content area under it is framed the same way
   as every tabbed page. The invoice pages are the reference.

   .page-strip         the bar where the tab row would be; an <h1> in it is
                       the page heading (Due Invoices), and a .card-subtitle
                       beside the heading or the steps is the one-line hint
   .flow-steps         an <ol> of the steps: each li.flow-step (or a.flow-step
                       for one the user can go back to) is a .flow-step-number
                       disc and a .flow-step-label; .flow-step-done for the
                       steps behind the user, .flow-step-current for this one,
                       plain for the ones still to come
   ------------------------------------------------------------------------- */
.page-strip {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px 20px;
    flex-wrap: wrap;
    flex: 0 0 auto;
    margin: 0;
    padding: 10px 16px;
    border: 1px solid #349ad8;
    background-color: #f5f9fb;
    color: #2b3743;
}

    .page-strip h1 {
        margin: 0;
        font-size: 1.15em;
        font-weight: 600;
        color: #1f2d3a;
        text-align: left;
    }

ol.flow-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 0;
}

.flow-step {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 0;
    color: #7a8794;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

    /* The line between one step and the next. */
    .flow-step + .flow-step::before {
        content: "";
        display: block;
        width: 28px;
        height: 1px;
        margin: 0 12px;
        background-color: #c9d3dc;
    }

.flow-step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid #c9d3dc;
    background-color: #ffffff;
    font-size: 12px;
    line-height: 1;
}

.flow-step-current {
    color: #0b6fa8;
}

    .flow-step-current .flow-step-number {
        background-color: #349ad8;
        border-color: #349ad8;
        color: #ffffff;
    }

.flow-step-done {
    color: #2b3743;
}

    .flow-step-done .flow-step-number {
        background-color: #e6f4ea;
        border-color: #a9d5b5;
        color: #1e7e34;
    }

    .flow-step-done a:hover .flow-step-label {
        text-decoration: underline;
    }

/* A step behind the user is a link back to it; the link is the whole step. */
.flow-step a {
    display: flex;
    align-items: center;
    gap: 8px;
    color: inherit;
    text-decoration: none;
}

@media screen and (max-width: 599px) {
    /* A phone shows the discs and only the current step's name. */
    .flow-step-label {
        display: none;
    }

    .flow-step-current .flow-step-label {
        display: inline;
    }

    .flow-step + .flow-step::before {
        width: 12px;
        margin: 0 6px;
    }
}

/* -------------------------------------------------------------------------
   Plan cards
   A row of choices side by side, one per column, of which the user picks
   one - the bundles on the add-ons page. Each is a card: a centred header
   naming the plan (with a .badge under the name for the one to point out),
   the terms to pick from - either .plan-price, a big figure over rows drawn
   like radio buttons, or .plan-terms, a Kendo grid with clickable rows - and
   the list of what the plan includes (.plan-features). The one whose terms
   have been picked is .plan-card-selected; one the user cannot pick just now
   - an add-on the chosen bundle already includes - is .disabled, and shows
   its .plan-included note in place of the price.

   .plan-cards          the row; wraps to two columns and then one as the
                        screen narrows
   .plan-card           on a .card; it is a .card-outlined (blue frame,
                        darker header) without needing the class
   .plan-card-selected  picked out in the site's blue: a solid blue header
   .plan-price          the price summary: .plan-price-summary (the
                        .plan-price-amount, a .plan-price-per unit beside it
                        and a .plan-price-caption under it; .plan-price-empty
                        while nothing is picked) over .plan-term-options, a
                        column of .plan-term rows - a faux radio, the term and
                        its total - of which the picked one is
                        .plan-term-selected. The page swaps the summary's text
                        (FadeSwap) and toggles the rows; clicking the picked
                        row again clears it, which a real radio cannot do
   .plan-terms          the grid of terms inside the body; not scrollable, so
                        the table fills the body edge to edge with no
                        scrollbar gutter (the views set Scrollable false)
   .plan-features       the list of what is in the plan; li.plan-feature, with
                        .plan-feature-excluded for what is not
   .plan-note           a line of small print under the terms (a set-up fee,
                        the term already on the contract)
   .plan-blurb          the sentence about the plan, under the header
   .plan-included       the note that the bundle picked above includes this
                        plan; hidden until the card is .disabled, and then
                        stands where the price was
   ------------------------------------------------------------------------- */
.plan-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 16px;
    align-items: stretch;
}

.plan-card {
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
    min-width: 0;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}

    .plan-card > .card-header {
        flex-direction: column;
        justify-content: center;
        gap: 6px;
        text-align: center;
    }

        .plan-card > .card-header h2 {
            text-align: center;
        }

    .plan-card > .card-body {
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        gap: 14px;
        padding: 16px;
    }

.plan-card-selected {
    border-color: #019ad2;
    box-shadow: 0 0 0 2px rgba(1, 154, 210, 0.2);
}

    .plan-card-selected > .card-header {
        background-color: #349ad8;
        border-bottom-color: #349ad8;
    }

        .plan-card-selected > .card-header h2 {
            color: #ffffff;
        }

        .plan-card-selected > .card-header .card-subtitle {
            color: rgba(255, 255, 255, 0.85);
        }

/* An add-on the picked bundle includes: the price and terms give way to the "included" note. */
.plan-card.disabled .plan-price,
.plan-card.disabled .plan-qty {
    display: none;
}

    .plan-card.disabled .plan-terms {
        pointer-events: none;
    }

.plan-included {
    display: none;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 18px 14px;
    border: 1px solid #b7dfc2;
    border-radius: 6px;
    background-color: #e6f4ea;
    color: #1e7e34;
    font-size: 16px;
    font-weight: 600;
    text-align: center;
}

    .plan-included::before {
        content: "\2713";
        font-size: 20px;
        font-weight: 700;
    }

    .plan-card.disabled .plan-included {
        display: flex;
    }

/* A whole row of plan cards not chosen - the other side of an either/or - is only dimmed; picking
   terms on it is what chooses it. */
.plan-cards.disabled .plan-card {
    opacity: 0.7;
}

.plan-terms {
    margin: 0;
}

    .plan-terms .k-grid {
        border: 1px solid #e9eef2;
        border-radius: 4px;
    }

    .plan-terms .datagrid table thead th {
        font-size: 11px;
    }

    /* The rows are the thing to click, so they get a little more height than a listing grid's. */
    .plan-terms .datagrid table tbody td {
        padding: 6px 6px;
    }

/* The price summary: the figure for the term picked, and under it the terms to pick from. */
.plan-price {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.plan-price-summary {
    padding: 8px 0 2px;
    text-align: center;
}

.plan-price-figure {
    display: flex;
    justify-content: center;
    align-items: baseline;
    gap: 5px;
    line-height: 1.1;
}

.plan-price-amount {
    font-size: 34px;
    font-weight: 700;
    color: #1f2d3a;
    transition: color 0.15s ease;
}

.plan-price-per {
    font-size: 14px;
    color: #7a8794;
}

.plan-price-caption {
    min-height: 18px;
    margin-top: 6px;
    font-size: 13px;
    color: #7a8794;
}

.plan-price-empty .plan-price-amount {
    color: #b6c0c9;
}

.plan-term-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* A term row: drawn like a radio button, but the picked one can be clicked again to clear it. */
.plan-term {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border: 1px solid #d5dde3;
    border-radius: 6px;
    background-color: #ffffff;
    font-size: 13px;
    color: #2b3743;
    text-align: left;
    cursor: pointer;
    user-select: none;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

    .plan-term:hover {
        border-color: #349ad8;
        background-color: #f5f9fb;
    }

    .plan-term:focus-visible {
        outline: 2px solid #349ad8;
        outline-offset: 2px;
    }

.plan-term-radio {
    position: relative;
    flex: 0 0 16px;
    width: 16px;
    height: 16px;
    box-sizing: border-box;
    border: 2px solid #9aa5af;
    border-radius: 50%;
    background-color: #ffffff;
}

.plan-term-label {
    flex: 1 1 auto;
}

.plan-term-total {
    font-weight: 600;
    color: #1f2d3a;
    white-space: nowrap;
}

.plan-term-selected {
    border-color: #019ad2;
    background-color: #e8f2fb;
}

    .plan-term-selected:hover {
        background-color: #e8f2fb;
    }

    .plan-term-selected .plan-term-radio {
        border-color: #019ad2;
    }

        .plan-term-selected .plan-term-radio::after {
            content: "";
            position: absolute;
            top: 2px;
            right: 2px;
            bottom: 2px;
            left: 2px;
            border-radius: 50%;
            background-color: #019ad2;
        }

.plan-card.disabled .plan-term {
    pointer-events: none;
}

.plan-features {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 13px;
    text-align: left;
}

.plan-feature {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

    .plan-feature::before {
        content: "\2713";
        flex: 0 0 16px;
        text-align: center;
        font-weight: 700;
        color: #1e7e34;
    }

.plan-feature-excluded {
    color: #9aa5af;
    text-decoration: line-through;
}

    .plan-feature-excluded::before {
        content: "\2013";
        color: #9aa5af;
    }

.plan-note {
    margin: 0;
    font-size: 12px;
    color: #7a8794;
    text-align: left;
}

.plan-blurb {
    margin: 0;
    font-size: 13px;
    line-height: 1.45;
    color: #5b6771;
    text-align: left;
}

    .plan-note.plan-note-strong {
        color: #2b3743;
        font-weight: 600;
    }

/* A quantity picker inside a plan card: the label beside a short select. */
.plan-qty {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
}

    .plan-qty label {
        margin: 0;
        font-weight: 600;
        color: #5b6771;
    }

    .plan-qty select {
        width: auto;
        height: 30px;
        margin: 0;
    }
