/* JDOC Holiday Rota — site styles */

html {
    font-size: 14px;
    position: relative;
    min-height: 100%;
}

@media (min-width: 768px) {
    html {
        font-size: 16px;
    }
}

body {
    margin-bottom: 0;
}

/* ── Navbar ─────────────────────────────────────────────────────────────────── */
.navbar-brand img {
    border-radius: 4px;
}

/* ── Lists ───────────────────────────────────────────────────────────────────── */
/*  Every list is a .table (with table-sm), set at one compact size (UAT 1: the Users list's), so more rows fit on     */
/*  screen. Only the rota's phone cards set their own, larger, size.                                                    */
.table {
    font-size: .8125rem;
}

.table .badge {
    font-size: .7rem;
}

/* A list's text buttons (the rota's Claim, Transfer and so on) at the list's size, so they don't make rows taller */
.table .btn-sm {
    --bs-btn-font-size: .8125rem;
}

/* ── Shift table ─────────────────────────────────────────────────────────────── */
.shift-table th {
    white-space: nowrap;
    font-weight: 600;
}

.shift-table td {
    vertical-align: middle;
    white-space: nowrap;
}

.shift-amount {
    font-variant-numeric: tabular-nums;
}

/* Star before a holiday shift's name */
.holiday-icon {
    color: #d63384;
    vertical-align: -2px;
}

/* Icon-only Edit and Delete buttons in the Actions column (2.7) */
.btn-icon {
    padding: .15rem .4rem;
    line-height: 1;
}

/* The floating "back to the top" button on lists that load more as they scroll (UAT 1, Shared/_BackToTop) */
.back-to-top {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1030;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border-radius: 50%;
    box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .25);
}

.back-to-top svg {
    width: 1.25rem;
    height: 1.25rem;
}

/* A pair's time (2.11): its title holds the halves' own times */
.pair-time {
    text-decoration: underline dotted var(--bs-secondary-color, #6c757d);
    text-underline-offset: 3px;
    cursor: help;
}

/* 4.3: a split half's icon (the other half in its title) and a split second half's "paid with" note. */
.split-icon {
    color: var(--bs-secondary-color, #6c757d);
    cursor: help;
}

.fee-note {
    font-size: .8rem;
    color: var(--bs-secondary-color, #6c757d);
}

/* Draft shifts (2.7): hatched, in every layout, over the alternating group background */
.shift-table tr.shift-draft > td,
.shift-table tr.shift-draft {
    background-image: repeating-linear-gradient(135deg, rgba(253, 126, 20, .08) 0 6px, transparent 6px 12px);
}

/* ── Shift table — tablet layout (576px – 991px) ────────────────────────────── */
/*  Each row becomes a named-area grid:                                          */
/*    date | dayname  / amount   | actions                                       */
/*    date | shiftname / assigned | actions                                      */
/*    date | time      / surgery  | actions                                      */
@media (min-width: 576px) and (max-width: 991.98px) {
    .shift-table-wrapper { overflow-x: visible; }

    .shift-table,
    .shift-table tbody { display: block; }

    .shift-table thead { display: none; }

    .shift-table tr {
        display: grid;
        grid-template-areas:
            "date dayname   amount   actions"
            "date shiftname assigned actions"
            "date time      surgery  actions";
        grid-template-columns: max-content 1fr auto auto;
        column-gap: 0.75rem;
        row-gap: 0.1rem;
        padding: 0.4rem 0.25rem;
        border-bottom: 1px solid var(--bs-border-color, #dee2e6);
    }

    .shift-table td {
        border: none;
        padding: 0;
        white-space: normal;
    }

    .shift-table td[data-cell="date"] {
        grid-area: date;
        align-self: center;
        white-space: nowrap;
    }

    /* Non-first-row date cells are visually empty at tablet but still occupy the date grid-area */
    .shift-table td.shift-date-rest {
        grid-area: date;
        visibility: hidden;
    }

    .shift-table td[data-cell="dayname"] {
        grid-area: dayname;
        color: var(--bs-secondary-color, #6c757d);
        align-self: end;
    }

    .shift-table td[data-cell="shiftname"] {
        grid-area: shiftname;
        font-weight: 500;
        align-self: start;
    }

    .shift-table td[data-cell="time"] {
        grid-area: time;
        align-self: start;
    }

    .shift-table td[data-cell="surgery"] {
        grid-area: surgery;
        text-align: right;
        align-self: start;
    }

    .shift-table td[data-cell="amount"] {
        grid-area: amount;
        text-align: right;
        align-self: end;
    }

    .shift-table td[data-cell="assigned-to"] {
        grid-area: assigned;
        text-align: right;
        align-self: start;
    }

    .shift-table td[data-cell="actions"] {
        grid-area: actions;
        align-self: center;
    }

    /* Alternating group background for tablet card rows */
    .shift-table tr.shift-group-alt > td {
        background-color: rgba(0, 0, 0, .04);
    }
}

/* ── Shift table — mobile card layout (<576px) ──────────────────────────────── */
/*  Each row becomes a rounded card of label / value pairs, two to a line        */
/*  (UAT 1: one pair per line made the cards too tall):                          */
/*    Date    | Day                                                              */
/*    Shift   | Time                                                             */
/*    Surgery | Fee      (Surgery alone, full width, when there's no Fee column) */
/*    Assigned to        (full width: names are long)                            */
/*    actions                                                                    */
@media (max-width: 575.98px) {
    .shift-table-wrapper { overflow-x: visible; }

    .shift-table,
    .shift-table tbody { display: block; }

    .shift-table thead { display: none; }

    .shift-table tr {
        display: grid;
        /* Fixed shares, so the columns line up from card to card; sized so "Wed 30 Dec" and "23:00–08:00" fit at 360px */
        grid-template-columns: minmax(0, 54fr) minmax(0, 46fr);
        column-gap: 0.5rem;
        border: 1px solid var(--bs-border-color, #dee2e6);
        border-radius: 0.375rem;
        padding: 0.6rem 0.6rem;
        margin-bottom: 0.6rem;
        background-color: #fff;
    }

    .shift-table tr.shift-group-alt {
        background-color: rgba(0, 0, 0, .04);
    }

    .shift-table td {
        display: flex;
        align-items: baseline;
        min-width: 0;
        padding: 0.15rem 0;
        border: none;
        white-space: normal;
        text-align: left;
        font-size: 1.05rem;
    }

    /* No year on phones, so the date fits beside its label (as on Home) */
    .shift-table .rota-year { display: none; }

    /* A long value (a day name beside a Draft badge) wraps beside its label rather than overflowing */
    .shift-table td > * { min-width: 0; }

    /* The card (tr) carries the group, draft and highlight backgrounds; cell backgrounds would show as blocks */
    .shift-table tr > td,
    .shift-table tr.shift-group-alt > td,
    .shift-table tr.shift-draft > td {
        background: none;
        box-shadow: none;
    }

    /* !important only to beat Bootstrap's .text-end on the Fee cell, which is right-aligned in the table */
    .shift-table td[data-cell="amount"] { text-align: left !important; }

    /* Likewise Bootstrap's .text-nowrap on Time: an overnight "+1" goes onto a second line rather than overflowing */
    .shift-table td[data-cell="time"] { white-space: normal !important; }

    /* Label shown before each cell's value, a little smaller than it; the min-width lines the values up in each column */
    .shift-table td::before {
        content: attr(data-label);
        font-size: 0.95rem;
        font-weight: 600;
        color: #495057;
        flex-shrink: 0;
        min-width: 3.5rem;
        margin-right: 0.5rem;
    }

    .shift-table td[data-cell="dayname"]::before,
    .shift-table td[data-cell="time"]::before,
    .shift-table td[data-cell="amount"]::before { min-width: 2.25rem; }

    /* Fee after Surgery; Assigned to and the actions last */
    .shift-table td[data-cell="amount"] { order: 1; }

    .shift-table td[data-cell="assigned-to"],
    .shift-table td[data-cell="actions"] {
        order: 2;
        grid-column: 1 / -1;
    }

    .shift-table tr:not(:has(> td[data-cell="amount"])) > td[data-cell="surgery"] {
        grid-column: 1 / -1;
    }

    /* Actions cell: no label; separator line above; buttons right-aligned */
    .shift-table td[data-cell="actions"] {
        justify-content: flex-end;
        padding-top: 0.4rem;
        margin-top: 0.25rem;
        border-top: 1px solid var(--bs-border-color, #dee2e6);
    }

    .shift-table td[data-cell="actions"]::before { content: ""; }

    .shift-table .btn {
        font-size: 0.95rem;
        padding: 0.25rem 0.6rem;
    }
}

/* Row highlight when updated by SignalR */
@keyframes rowHighlight {
    0%   { background-color: #fff3cd; }
    100% { background-color: transparent; }
}

.row-updated {
    animation: rowHighlight 1.5s ease-out;
}

/* ── Date-group alternating rows (desktop table view) ────────────────────────── */
.shift-group-alt > td {
    background-color: rgba(0, 0, 0, .04);
}

/* At desktop, hide the repeated date cell used for tablet/mobile layouts */
@media (min-width: 992px) {
    .shift-date-rest {
        display: none;
    }
}

/* ── Transfer history icon button ─────────────────────────────────────────────── */
.btn-shift-history {
    background: none;
    border: none;
    padding: 0;
    color: var(--bs-secondary-color, #6c757d);
    cursor: pointer;
    line-height: 1;
    vertical-align: middle;
}
.btn-shift-history:hover,
.btn-shift-history:focus {
    color: var(--bs-body-color, #212529);
    outline: none;
}

/* Shift history popover (stopwatch): scrolls past about eight entries */
.shift-history-popover {
    max-width: 22rem;
}
.shift-history-popover .popover-body {
    max-height: 18rem;
    overflow-y: auto;
}
.shift-history-entry + .shift-history-entry {
    border-top: 1px solid var(--bs-border-color, #dee2e6);
    margin-top: .4rem;
    padding-top: .4rem;
}
.shift-history-meta {
    font-size: .8em;
    color: var(--bs-secondary-color, #6c757d);
}

/* ── Date input placeholder text ────────────────────────────────────────────── */
/* The browser renders dd/mm/yyyy hint text as black by default; make it grey    */
input[type="date"]:not(:valid) {
    color: #adb5bd;
}

/* ── Auth forms ──────────────────────────────────────────────────────────────── */
.auth-card {
    max-width: 440px;
    margin: 0 auto;
}

/* Every sign-in button (each OAuth provider and "Sign in with email") looks the  */
/* same; only the text and logo differ. Set through Bootstrap's button variables  */
/* so the hover and pressed states follow.                                        */
.btn-signin {
    --bs-btn-bg: #fff;
    --bs-btn-color: #3c4043;
    --bs-btn-border-color: #dadce0;
    --bs-btn-hover-bg: #f8f9fa;
    --bs-btn-hover-color: #202124;
    --bs-btn-hover-border-color: #c6c9cc;
    --bs-btn-active-bg: #f1f3f4;
    --bs-btn-active-color: #202124;
    --bs-btn-active-border-color: #c6c9cc;
    --bs-btn-font-weight: 500;
}

/* ── Admin tables ────────────────────────────────────────────────────────────── */
.admin-table td {
    vertical-align: middle;
}

/* Ended surgeries are greyed; text-muted on a row loses to the table cell colour */
.admin-table tr.surgery-ended {
    --bs-table-color: var(--bs-secondary-color);
}

/* Surgery change history: scrolls rather than stretching the page */
.surgery-history {
    max-height: 420px;
    overflow-y: auto;
}

/* Invitations list: capped at 70vh, scrolling inside its card under a sticky column header */
.invites-list-card {
    display: flex;
    flex-direction: column;
    max-height: 70vh;
}

.invites-list-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}

.invites-list-scroll thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    white-space: nowrap;
}

/* Line the table's edges up with the card header's padding */
.invites-list-scroll :is(th, td):first-child {
    padding-left: 1rem;
}

.invites-list-scroll :is(th, td):last-child {
    padding-right: 1rem;
}

/* Manage users: long email addresses are cut short (the full one is the tooltip) */
.users-table thead th {
    white-space: nowrap;
    vertical-align: bottom;
}

.users-table .user-email {
    max-width: 14rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.users-table .btn-icon {
    padding: .2rem .4rem;
    line-height: 1;
}

/* The column header sticks under the navbar as the page scrolls. As on the rota, only at desktop widths:
   .table-responsive's overflow-x breaks position: sticky, and narrower screens need it to scroll sideways. */
@media (min-width: 992px) {
    .users-table-wrapper {
        overflow-x: visible;
    }

    .users-table thead th {
        position: sticky;
        top: var(--navbar-height, 0px);
        z-index: 2;
        /* box-shadow replaces the bottom border, which stops rendering on sticky cells */
        box-shadow: inset 0 -1px 0 #dee2e6;
    }
}

/* Scrollable, infinite-loading log file list */
.logs-table-wrapper {
    max-height: 60vh;
    overflow-y: auto;
}

/* ── Sticky shift-table header ───────────────────────────────────────────────── */
/*  Only applied at desktop widths (≥992 px) where thead is actually visible.    */
/*  At smaller breakpoints the table switches to grid/card layouts that hide      */
/*  thead entirely, so sticky has no effect there.                                */
/*  overflow-x: auto on .table-responsive breaks position: sticky, so we         */
/*  revert it here — the columns fit comfortably at this width.                   */
@media (min-width: 992px) {
    .shift-table-wrapper {
        overflow-x: visible;
    }

    .shift-table thead th {
        position: sticky;
        top: var(--navbar-height, 0px);
        z-index: 2;
        /* Repeat Bootstrap table-light background so scrolled rows don't show through */
        background-color: #f8f9fa;
        /* box-shadow replaces the bottom border, which stops rendering on sticky cells */
        box-shadow: inset 0 -1px 0 #dee2e6;
    }
}

/* ── Transfer confirmation pages ─────────────────────────────────────────────── */
.transfer-confirmation {
    max-width: 560px;
    margin: 0 auto;
    text-align: center;
}

/* ── Disabled "Claim this shift" button (not live yet / at shift limit) ──────── */
.claim-shift-btn:disabled {
    background-color: #e9ecef;
    border-color: #ced4da;
    color: #6c757d;
    opacity: 1;
}

/* Why Claim is disabled ("Opens …", "Limit reached"), beside its icon (UAT 1); nothing when it's enabled */
.claim-block:empty {
    display: none;
}

/* ── Responsive action button wrapping ───────────────────────────────────────── */
.action-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

/* ── PIN verification input ──────────────────────────────────────────────────── */
.pin-input {
    letter-spacing: 0.4em;
    font-size: 2rem;
}

.pin-input::placeholder {
    color: #ccc;
    opacity: 1;   /* Firefox reduces opacity by default */
}

/* ── Focus styles ────────────────────────────────────────────────────────────── */
.btn:focus, .btn:active:focus,
.form-control:focus, .form-check-input:focus,
.form-select:focus {
    box-shadow: 0 0 0 0.15rem rgba(13, 110, 253, 0.4);
}

/* ── Dashboard (Home) ────────────────────────────────────────────────────────── */
/* Each card shows its header plus 6 rows, then scrolls inside the card under a sticky header. Rows never wrap,
   so every row is the same height and the cap is exact. On phones the table scrolls sideways in the card too. */
.dashboard-card {
    --dashboard-row-height: 2.25rem;
}

.dashboard-scroll {
    max-height: calc(7 * var(--dashboard-row-height) + 1px);
    overflow: auto;
}

.dashboard-scroll :is(th, td) {
    height: var(--dashboard-row-height);
    white-space: nowrap;
    vertical-align: middle;
}

.dashboard-scroll thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    /* box-shadow replaces the bottom border, which stops rendering on sticky cells */
    border-bottom: 0;
    box-shadow: inset 0 -1px 0 var(--bs-border-color, #dee2e6);
}

.dashboard-scroll :is(th, td):first-child {
    padding-left: 1rem;
}

.dashboard-scroll :is(th, td):last-child {
    padding-right: 1rem;
}

.dashboard-underway > td {
    --bs-table-bg-state: var(--bs-primary-bg-subtle, #cfe2ff);
}

.dashboard-line-break,
.dashboard-scroll .dashboard-phone-only {
    display: none;
}

/* Phones: each row is two lines, so Doctor and Mobile are never off-screen. Line 1: date (no year), start–end, shift
   (holiday as just the star, cut short with an ellipsis rather than wrapping); line 2: doctor, mobile or surgery, the
   Underway badge, icons. The header is hidden visually but kept for screen readers, and the 6-row cap uses the taller
   row. Backgrounds move from the cells to the row, so a short line isn't striped. */
@media (max-width: 575.98px) {
    .dashboard-card {
        --dashboard-row-height: 3.9rem;
    }

    .dashboard-scroll {
        max-height: calc(6 * var(--dashboard-row-height) + 1px);
        overflow-x: hidden;
    }

    .dashboard-scroll table,
    .dashboard-scroll tbody {
        display: block;
    }

    .dashboard-scroll thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }

    .dashboard-scroll tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        min-height: var(--dashboard-row-height);
        padding: .4rem 1rem;
        column-gap: 0;
        border-bottom: var(--bs-border-width, 1px) solid var(--bs-border-color, #dee2e6);
    }

    .dashboard-scroll tbody tr.dashboard-underway {
        background-color: var(--bs-primary-bg-subtle, #cfe2ff);
    }

    .dashboard-scroll tbody td,
    .dashboard-scroll tbody td:first-child,
    .dashboard-scroll tbody td:last-child {
        display: block;
        height: auto;
        padding: 0;
        border: 0;
        background: transparent;
        box-shadow: none;
    }

    .dashboard-desktop-only {
        display: none;
    }

    .dashboard-scroll tbody td {
        margin-right: .5rem;
    }

    .dashboard-scroll tbody td[data-cell="start"] {
        margin-right: 0;
    }

    .dashboard-scroll td[data-cell="date"] {
        font-weight: 500;
    }

    .dashboard-scroll td[data-cell="end"]::before {
        content: "–";
    }

    .dashboard-scroll td[data-cell="shift"] {
        order: 1;
        white-space: nowrap;
        flex: 1 1 0;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .dashboard-scroll tbody td.dashboard-line-break {
        display: block;
        order: 2;
        flex-basis: 100%;
        margin-right: 0;
    }

    .dashboard-scroll td[data-cell="doctor"],
    .dashboard-scroll td[data-cell="mobile"],
    .dashboard-scroll td[data-cell="surgery"] {
        order: 3;
    }

    .dashboard-scroll td[data-cell="surgery"] {
        flex: 1 1 0;
        white-space: nowrap;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        color: var(--bs-secondary-color, #6c757d);
    }

    .dashboard-scroll tbody td.dashboard-phone-only {
        display: block;
        order: 4;
    }

    .dashboard-scroll td[data-cell="icons"] {
        order: 5;
        margin-left: auto;
        margin-right: 0;
    }
}

/* Locum terms popover (dashboard): free text, so it wraps and scrolls */
.locum-popover {
    max-width: 22rem;
}
.locum-popover .popover-body {
    max-height: 18rem;
    overflow-y: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
.locum-popover .locum-for {
    font-size: .8em;
    color: var(--bs-secondary-color, #6c757d);
    margin-bottom: .25rem;
}

/* Admin → Messages (2.9): scrolls inside its card under a sticky header, loading more near the bottom */
.messages-scroll {
    max-height: 60vh;
    overflow-y: auto;
}

.messages-scroll thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    white-space: nowrap;
}

.messages-scroll .message-preview {
    max-width: 18rem;
}

/* An email's body in the detail dialog: a sandboxed frame, so nothing in it can run */
.message-body-frame {
    width: 100%;
    height: 24rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: .375rem;
}

.message-body-text {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    padding: 1rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: .375rem;
    background-color: var(--bs-tertiary-bg, #f8f9fa);
}

/* The rota's "loading more" row (2.11): a plain line under the last block, not a card or grid, in every layout */
@media (max-width: 991.98px) {
    .shift-table tr.rota-more {
        display: block;
        border: 0;
        background: none;
        padding: 0.5rem 0;
        margin: 0;
    }

    .shift-table tr.rota-more > td {
        display: block;
        border: 0;
    }
}

/* The rota's "Shifts" filter (3.5): the surgery list scrolls rather than running off the page. */
.rota-shifts-menu {
    max-height: 20rem;
    overflow-y: auto;
}

/* A very long surgery name in the button would otherwise widen the filter bar. */
#shiftsButton {
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Sent items (4.5): a stored email fills its own tab */
.sent-item-frame {
    height: calc(100vh - 14rem);
    min-height: 24rem;
}
