/*
    Modern.css - visual refresh layer for the Schedule app.

    This file is PURELY ADDITIVE. Scheduler.css and Colours.css are untouched;
    everything here is an override applied on top. To revert the whole refresh,
    remove the single <link> tag for this file from index.html.

    IMPORTANT - load order: this stylesheet must be the LAST one in index.html's
    <head>, after fullcalendar / jquery-ui / scheduler.min.css. Scheduler.css is
    loaded *before* those libraries, which is why it needs ~100 !important rules
    to win. Loading last means this file wins on source order alone, so
    !important is only used here where the rule it replaces already had one.

    Covers (original 10-item quick-wins list):
      1. Typography          5. Motion / hover states
      3. Dialog elevation    6. Focus rings (accessibility)
      4. Modal overlays      8. Scrollbars
                             9. Date quick-links strip

    Corner radius (originally item 2) was reverted - square corners throughout.

    Also covers (from the later "executive polish" recommendations list, a
    different numbering to the above - see the section headers below for
    which is which):
      3. Type scale             7. Icon rendering quality (CSS-only part;
      4. Consolidate greys         the icon SET/library replacement itself
      6. Tables & badges           needs a asset decision - see that section)
      8. Highlighted-job state preserves the underlying status colour

    Also covers a Job Details pane (#Details) redesign - its own list,
    unrelated to either numbering above:
      1. Invert label/value hierarchy   4. Two-column rows for short fields
      2. Flat surface, hairline rows    6. Status as a coloured pill
      3. Reclaim the wasted right margin
    (5, 7, 8 - a sticky identity header, hiding empty fields, and grouping
    fields into sections - were tried and reverted; 6 was reapplied on its
    own afterwards, which is why the numbering here has a gap.)
*/

:root {
    /* Inter first (self-hosted - see Libraries/Inter/inter.css), falling back
       to the system stack if that file fails to load for any reason. */
    --totm-font: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

    --totm-brand: #1976D2;
    --totm-brand-ink: #0C447C;
    --totm-brand-tint: #E8F1FB;

    --totm-shadow-card: 0 1px 3px rgba(15, 23, 42, 0.12);
    --totm-shadow-hover: 0 3px 10px rgba(15, 23, 42, 0.20);
    --totm-shadow-dialog: 0 12px 32px rgba(15, 23, 42, 0.22), 0 2px 8px rgba(15, 23, 42, 0.12);
    --totm-shadow-panel: -8px 0 24px rgba(15, 23, 42, 0.25);

    --totm-scrim: rgba(15, 23, 42, 0.45);
    --totm-scrollbar: #C3C9D4;
    --totm-scrollbar-hover: #99A3B4;

    --totm-motion: 0.15s ease;

    /* Type scale. Base stays 14px (unchanged) - the calendar rows, booking bars
       and job cards all have hard pixel heights that would overflow if it grew.
       Everything else in the app is normalised onto these steps. */
    --totm-fs-2xs: 11px;
    --totm-fs-xs:  12px;
    --totm-fs-sm:  13px;
    --totm-fs-lg:  16px;
    --totm-fs-xl:  18px;

    /* Neutral greys, reused from the Mobile app's Tokens.css (--border /
       --border-strong) so the two apps read as one product rather than two
       separately-themed ones. */
    --totm-border: #E3E5E9;
    --totm-border-strong: #C9CCD1;

    /* Text tones - --totm-text matches Mobile Tokens.css's --text exactly.
       --totm-text-muted was previously a one-off literal (#5F6368) on the
       table header cells; tokenised here so the Job Details pane below can
       reuse the same muted tone rather than a second, slightly-different
       grey. */
    --totm-text: #1A1A1A;
    --totm-text-muted: #5F6368;
}


/* ---------------------------------------------------------------------------
   1. Typography

   Replaces Arial (body) and Century Gothic (buttons, hamburger menu) with
   Inter (self-hosted, Libraries/Inter/inter.css), falling back to the OS
   system font stack - Segoe UI on Windows, San Francisco on macOS - if that
   file doesn't load.

   Base font-size deliberately stays at 14px: the calendar rows, booking bars
   and job cards all have hard pixel heights (.fc-timeline-event is
   height:28px/line-height:15px) that would overflow if the base grew.
   line-height is raised only inside dialogs and the two text-heavy panes,
   where nothing is height-constrained.
   --------------------------------------------------------------------------- */

html, body,
button:not(.fa), input:not(.fa), select, option, textarea,
.HamburgerMenuItem,
.JobDetailsAttachmentButton,
.ui-dropdownchecklist-item,
.ui-dropdownchecklist-text {
    font-family: var(--totm-font) !important;
}

/* Several screens (Batch, Recurring Jobs, Users) render icon-only buttons as
   <button class="fa fa-xxx"> - the Font Awesome classes go directly on the
   button rather than on a nested <i>. The button/input rule above would
   otherwise stomp the icon glyph font on that exact element (icons render
   blank), so those elements are excluded above and get their icon font
   restored here instead. */
.fa {
    font-family: FontAwesome !important;
}

.ModalDialog,
#JobInformationArea,
#SettingsDialogContent,
#SwitchTenantContent {
    line-height: 1.45;
}

/* Segoe UI's default line boxes are taller than Arial's at the same font-size,
   which pushed these two out of their fixed-height parents (#SchedulerHeader is
   40px; #DateQuickLinks is 43px with overflow:auto, so a 1px overrun produced a
   scrollbar). Pinning line-height reproduces the original Arial heights exactly
   and makes them font-independent from here on. */
#HeaderBar_CompanyName {
    line-height: 24px;
}

.DateQuickLinkDayName {
    line-height: 16px;
}

.DateQuickLinkDateNumber {
    line-height: 21px;
}

/* Dates and quantities line up in columns instead of jittering. */
.DateQuickLinkDateNumber,
.UserTable td,
.BatchTable td {
    font-variant-numeric: tabular-nums;
}


/* ---------------------------------------------------------------------------
   2. Corner radius - REMOVED

   Buttons, inputs, dialogs, job cards and tags deliberately keep their original
   square corners. Scheduler.css's `border-radius: 0 !important` on buttons is
   left to stand rather than being overridden.

   What remains below is not corner radius: the job card's resting shadow (which
   pairs with the hover lift in section 5) and the header button treatment.
   Those buttons share the exact background colour of the blue bar behind them
   and were previously legible only because of a white bottom border; a
   translucent white fill reads more clearly as a button.

   .HamburgerMenuButton is deliberately NOT included - it keeps its original
   Scheduler.css appearance (solid #1976D2 fill, white bottom-border divider,
   and its own rgba(240,240,240,0.15) hover).
   --------------------------------------------------------------------------- */

.UnassignedJob {
    box-shadow: var(--totm-shadow-card);
    /* Without this, a fast mousedown-and-move onto the calendar can register as a text
       selection instead of (or as well as) a jQuery UI drag start, especially since the job
       number/customer name text inside is otherwise perfectly normal selectable text. Inherits
       onto .JobStatusIndicator/.JobListItemDetailArea/.JobHeadingJobNo/.JobHeadingCustomerName
       below it, so nothing inside the card is selectable either. */
    -webkit-user-select: none;
    user-select: none;
}


#SchedulerHeader button,
#SchedulerHeader input[type=button],
#HeaderMiddlePanel button,
#SettingsDialogHeaderButtonContainer button {
    background-color: rgba(255, 255, 255, 0.14) !important;
    border-bottom: none;
}

    #SchedulerHeader button:hover,
    #SchedulerHeader input[type=button]:hover {
        background-color: rgba(255, 255, 255, 0.26) !important;
    }


/* ---------------------------------------------------------------------------
   3. Dialog elevation

   All 14 modals carry .ModalDialog, so one rule covers the lot. The hard
   1px #ababab border is removed per-id, because each dialog sets its own
   `border` at id specificity which a class rule cannot beat. The shadow
   is what separates the dialog from the page now.

   Corners stay square (see section 2), so the .SectionHeading titlebar needs
   no matching radius.
   --------------------------------------------------------------------------- */

.ModalDialog {
    box-shadow: var(--totm-shadow-dialog);
}

#LoginScreen,
#NewJobScreen,
#AlterAllocationDurationScreen,
#CreateBookingScreen,
#CreateMemoScreen,
#TextEntryDialog,
#BookingTimePickerDialog,
#DoubleTextEntryDialog,
#TextReminderDialog,
#ConfirmActionScreen,
#NewCustomerScreen,
#SettingWrapperDialog,
#SwitchTenantDialog,
#SetupWizardScreen {
    border: none;
}

/* Edge-anchored slide-in panel: shadow only, no radius. */
#HamburgerMenu {
    box-shadow: var(--totm-shadow-panel);
}


/* ---------------------------------------------------------------------------
   4. Modal overlays

   Both scrims were a light grey at 50% opacity, which washed the page out
   rather than pushing it back. opacity must be reset to 1 because the colour
   now carries its own alpha.
   --------------------------------------------------------------------------- */

#GreyOut,
#HamburgerScreen {
    background-color: var(--totm-scrim);
    opacity: 1;
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}


/* ---------------------------------------------------------------------------
   5. Motion / hover states

   Scheduler.css contained exactly one transition. Deliberately limited to
   colour and shadow - no transform, because .UnassignedJob is a FullCalendar
   external draggable and a transform would offset the drag helper.
   --------------------------------------------------------------------------- */

button,
input[type=button],
.JobDetailsAttachmentButton,
.UnassignedJob,
.TenantOption,
.TenantOptionLabel,
.SelectableStaffMember,
.DateQuickLinkButton,
.HamburgerMenuItem,
.NewCustomerTypeOption,
.JobDetailsAllocationItem {
    transition: background-color var(--totm-motion),
                color var(--totm-motion),
                box-shadow var(--totm-motion),
                border-color var(--totm-motion);
}

/* Fading a card out on hover reads as "disabled". Lift it instead. */
.UnassignedJob:hover {
    opacity: 1;
    box-shadow: var(--totm-shadow-hover);
}

.UnassignedJob:focus {
    opacity: 1;
}


/* ---------------------------------------------------------------------------
   6. Focus rings

   Scheduler.css line 16 has `*:focus { outline: 0 }`, which removes every
   keyboard focus indicator in the app. :focus-visible restores a ring for
   keyboard users only - mouse clicks stay clean.

   Same specificity as *:focus (0,1,0), so this wins on source order.
   --------------------------------------------------------------------------- */

:focus-visible {
    outline: 2px solid var(--totm-brand);
    outline-offset: 2px;
}

/* A blue ring is invisible against the blue chrome. */
#SchedulerHeader :focus-visible,
#HamburgerMenu :focus-visible,
.SectionHeading :focus-visible,
.fc-toolbar :focus-visible {
    outline-color: #fff;
}


/* ---------------------------------------------------------------------------
   8. Scrollbars

   Six near-identical webkit blocks in Scheduler.css shared a dark inset track
   shadow and a solid blue thumb. Consolidated into one rounded neutral thumb.

   The 8px track width is deliberately unchanged: FullCalendar v3 measures
   scrollbar width to align the timeline header against the body, so widening
   .fc-scroller risks column misalignment. The visible thumb is inset to 4px
   via a transparent border + background-clip.
   --------------------------------------------------------------------------- */

.fc-scroller,
#TheJobs,
#JobInformationArea,
#SettingsDialogContent,
#SwitchTenantContent,
.ui-dropdownchecklist-dropcontainer,
.ui-autocomplete {
    scrollbar-width: thin;
    scrollbar-color: var(--totm-scrollbar) transparent;
}

    .fc-scroller::-webkit-scrollbar,
    #TheJobs::-webkit-scrollbar,
    #JobInformationArea::-webkit-scrollbar,
    #SettingsDialogContent::-webkit-scrollbar,
    #SwitchTenantContent::-webkit-scrollbar,
    .ui-dropdownchecklist-dropcontainer::-webkit-scrollbar,
    .ui-autocomplete::-webkit-scrollbar {
        width: 8px;
        height: 8px;
        background-color: transparent;
    }

    .fc-scroller::-webkit-scrollbar-track,
    #TheJobs::-webkit-scrollbar-track,
    #JobInformationArea::-webkit-scrollbar-track,
    #SettingsDialogContent::-webkit-scrollbar-track,
    #SwitchTenantContent::-webkit-scrollbar-track,
    .ui-dropdownchecklist-dropcontainer::-webkit-scrollbar-track,
    .ui-autocomplete::-webkit-scrollbar-track {
        background-color: transparent;
        -webkit-box-shadow: none;
        box-shadow: none;
    }

    .fc-scroller::-webkit-scrollbar-thumb,
    #TheJobs::-webkit-scrollbar-thumb,
    #JobInformationArea::-webkit-scrollbar-thumb,
    #SettingsDialogContent::-webkit-scrollbar-thumb,
    #SwitchTenantContent::-webkit-scrollbar-thumb,
    .ui-dropdownchecklist-dropcontainer::-webkit-scrollbar-thumb,
    .ui-autocomplete::-webkit-scrollbar-thumb {
        background-color: var(--totm-scrollbar);
        border: 2px solid transparent;
        background-clip: padding-box;
        border-radius: 8px;
        -webkit-box-shadow: none;
        box-shadow: none;
    }

        .fc-scroller::-webkit-scrollbar-thumb:hover,
        #TheJobs::-webkit-scrollbar-thumb:hover,
        #JobInformationArea::-webkit-scrollbar-thumb:hover,
        #SettingsDialogContent::-webkit-scrollbar-thumb:hover,
        #SwitchTenantContent::-webkit-scrollbar-thumb:hover,
        .ui-dropdownchecklist-dropcontainer::-webkit-scrollbar-thumb:hover,
        .ui-autocomplete::-webkit-scrollbar-thumb:hover {
            background-color: var(--totm-scrollbar-hover);
        }


/* ---------------------------------------------------------------------------
   9. Date quick-links strip

   28 equal columns separated by hard 1px rules become spaced segments. Corners
   stay square, matching the rest of the app.

   The gap comes from transparent LEFT/RIGHT borders only, never top or bottom:
   #DateQuickLinks is a fixed 43px tall with overflow:auto, and adding vertical
   borders would push the buttons past that and trigger a scrollbar. Vertical
   size is therefore identical to before.
   --------------------------------------------------------------------------- */

.DateQuickLinkButton {
    border: 0;
    border-left: 2px solid transparent;
    border-right: 2px solid transparent;
    background-clip: padding-box;
}

/* Scheduler.css uses `#DateQuickLinks :hover`, a descendant selector that also
   matches the two inner <label>s - so each label paints its own square blue
   block inside the pill. These rules keep the fill on the pill itself. */
#DateQuickLinks .DateQuickLinkButton:hover {
    background-color: var(--totm-brand-tint);
    color: var(--totm-brand-ink);
}

    #DateQuickLinks .DateQuickLinkButton:hover .DateQuickLinkDayName,
    #DateQuickLinks .DateQuickLinkButton:hover .DateQuickLinkDateNumber,
    #DateQuickLinks .DateQuickLinkButtonSelected:hover .DateQuickLinkDayName,
    #DateQuickLinks .DateQuickLinkButtonSelected:hover .DateQuickLinkDateNumber {
        background-color: transparent !important;
        color: inherit !important;
    }

.DateQuickLinkButtonSelected {
    box-shadow: 0 1px 4px rgba(25, 118, 210, 0.45);
}

.DateQuickLinkDayName {
    opacity: 0.75;
    letter-spacing: 0.02em;
}

/* Restores the "has allocations" underline that the `border: 0` reset above
   clears. Must stay after .DateQuickLinkButton - same specificity, so source
   order decides. */
.DateQuickLinkButtonHasAllocations {
    border-bottom: 2px solid #8B1A1A;
}


/* =============================================================================
   The sections below are from a separate, later "executive polish" list with
   its own 1-8 numbering (1 neutral chrome / 2 one blue - both live in
   Chrome-Neutral.css - 3 type scale, 4 consolidate greys, 5 status palette -
   not requested, 6 tables, 7 icon set, 8 highlight state). Numbers below refer
   to THAT list, not the 1-10 list at the top of this file.
   ============================================================================= */


/* ---------------------------------------------------------------------------
   3. Type scale

   Scheduler.css has 14 distinct font-size values, several arriving via pt
   (10pt/14pt/16pt/18pt) rather than px, which round to odd fractional pixel
   sizes (10pt = 13.33px) that don't line up with anything else on screen.
   Most already land close to the scale above and are left alone; only the
   genuinely mismatched ones are normalised here.

   The other half of this item is the dialog/section titlebars: .SectionHeading
   never sets its own font-size (the `font-size: 1.6em` at Scheduler.css:143 is
   commented out and was never live), so its <h2>/<h3> render at the browser's
   default h2 size (~21px bold). Large bold titlebars read as loud rather than
   considered; shrinking to a small uppercase label - the same pattern used for
   the table headers below - is the highest-value change in this section.

   .SectionHeading's 40px height/line-height (Scheduler.css) is unaffected:
   line-height is inherited by the heading unless overridden, and nothing here
   sets it, so vertical centring is untouched.
   --------------------------------------------------------------------------- */

.SectionHeading h2,
.SectionHeading h3 {
    font-size: var(--totm-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.92;
}

/* #HeaderBar_CompanyName is also an <h2>, but it's the app's brand/company
   name in the main header bar, not a section titlebar - deliberately not
   included above (it lives outside .SectionHeading, so the selectors above
   don't match it anyway; called out so that stays a deliberate choice rather
   than an oversight). */

.JobMemo {
    font-size: var(--totm-fs-sm); /* was 10pt (13.33px) */
}

.FetchingNewJobsHeading {
    font-size: var(--totm-fs-lg); /* was 16pt (~21.3px) */
}

.SetupWizardTaskRow .fa-check-circle {
    font-size: 24px; /* was 18pt - this literally is 24px, just spelled oddly */
}

.SetupWizardTaskRow .fa-circle-o {
    font-size: var(--totm-fs-xl); /* was 14pt (~18.7px) */
}


/* ---------------------------------------------------------------------------
   4. Consolidate greys

   Borders across the app use nine different greys for the same job: #ababab,
   #dcdcdc, #ddd, #eee/#EEE, #ABADB3 (dead - commented out), #999 (dead -
   commented out), #888, #777. Reduced to two - a hairline and a stronger
   divider - reusing the exact values from the Mobile app's Tokens.css
   (--border / --border-strong) so both apps share one grey vocabulary.

   Scoped to LIGHT surfaces only (dialogs, tables, cards on a white
   background). Dividers that sit on dark chrome - .HamburgerMenuItem's
   border-bottom, the #fff dividers on header/hamburger buttons - are
   deliberately left alone: swapping them for a bluish-grey token would lose
   contrast against a dark background, the opposite of the goal here.
   #ababab is not listed below because the dialog-elevation section earlier in
   this file already replaces it with `border: none`.
   --------------------------------------------------------------------------- */

.JobInfoElementTitle,
.JobDetailsAllocationItem,
.SetupWizardTaskRow,
.UserTable td,
.BatchTable td {
    border-color: var(--totm-border);
}

.CreateBookingSearchBox,
.WebHookItemDiv {
    border-color: var(--totm-border-strong);
}

.fc-timeline-event {
    border-color: var(--totm-border-strong) !important; /* Scheduler.css's own #888 border is !important */
}

/* .ui-state-hover sets border-bottom to black separately from its other three
   sides (a deliberate active-state accent) - only the non-accent sides are
   touched, via longhand properties, so that accent survives. */
.ui-state-hover {
    border-top-color: var(--totm-border) !important;
    border-left-color: var(--totm-border) !important;
    border-right-color: var(--totm-border) !important;
}


/* ---------------------------------------------------------------------------
   6. Tables & badges

   Solid-blue-filled table headers become a plain surface with a small
   uppercase label and a single strong rule beneath - the same language as the
   .SectionHeading titlebars above, so table headers and dialog titles now
   read as one design language instead of two.

   Both tables render <td> (not <th>) inside their <thead> - confirmed against
   View.Users.js/View.Batch.js, this app never uses <th> - so the header cell
   selectors below target thead td, not thead th.

   Sticky headers: both tables render inside #SettingsDialogContent, a fixed
   max-height (720px) scrolling pane (Scheduler.css), so position:sticky is
   contained and safe - it cannot escape that scroller. The header cells need
   their own opaque background (not just the thead's) for sticky to paint
   correctly over scrolled-under rows.
   --------------------------------------------------------------------------- */

.UserTable thead,
.BatchTable thead {
    background-color: #fff;
    color: #333;
}

    .UserTable thead td,
    .BatchTable thead td {
        position: sticky;
        top: 0;
        z-index: 2;
        background-color: #fff;
        border-bottom: 2px solid var(--totm-border-strong);
        font-size: var(--totm-fs-2xs);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--totm-text-muted);
    }

/* Retire the Bootstrap-3-era solid badge fills (and their 3px radius - square
   corners throughout, matching the rest of the app) for tinted labels that
   read as status text rather than loud blocks. */
.CompletedFormsDraftBadge {
    background-color: rgba(249, 168, 37, 0.18);
    color: #8A5A00;
    border-radius: 0;
}

.CompletedFormsCompleteBadge {
    background-color: rgba(46, 125, 50, 0.14);
    color: #1B5E20;
    border-radius: 0;
}


/* ---------------------------------------------------------------------------
   7. Icon rendering quality - CSS-only part

   The real fix for "chunky, inconsistent stroke weight" icons is a new icon
   asset - a newer Font Awesome release, or an SVG set like Lucide/Phosphor -
   which means new font/SVG files added to the project. That's a bigger call
   than a CSS pass (licensing, ~57 call sites across ~15 files using two
   different markup patterns - see the .fa rule in the typography section
   above for one of them). Flagged to the user separately rather than done
   silently here.

   What IS safely fixable without new assets: several icon-only utility
   buttons (Batch line actions, and the Recurring Job/User row actions that
   share .UserTable's markup pattern) never had an explicit font-size, so they
   inherited the body text size (14px), while the visually-equivalent
   SetupWizard/header icon buttons are 18px. Normalising closes that
   inconsistency without touching the icon font itself.
   --------------------------------------------------------------------------- */

.batchLineButton,
.UserTable button.fa {
    font-size: var(--totm-fs-xl);
}


/* ---------------------------------------------------------------------------
   8. Highlighted-job state preserves the underlying status colour

   .HighlightedJob (Scheduler.css) sets a flat !important background-color,
   which has two problems rather than one:

     - For jobs using a Colours.css status class (DarkBlue/LightGreen/etc,
       the palette dispatchers actually rely on) it has NO effect at all:
       Colours.css loads after Scheduler.css, so its !important status colour
       already wins over .HighlightedJob's !important - confirmed empirically
       against the live page, not assumed. Highlighting is therefore already
       invisible today for any job with a status colour.
     - For jobs using a Scheduler.css-internal class (plain/.OnHoldUnassignedJob/
       .CompletedJob, all defined earlier in the same file) .HighlightedJob DOES
       win, and wipes out that status colour while highlighted.

   Fixed by moving the highlight indicator off background-color entirely, onto
   a box-shadow ring, so status colour survives in every case rather than a
   different case in each direction. The ring uses a white-then-brand double
   layer specifically because a single colour cannot have reliable contrast
   against all ~14 Colours.css palette values, which range from near-white
   (Yellow, FluroGreen) to near-black (Black, DarkRed) - this is the same
   double-ring technique selection outlines use for exactly this reason.

   CSS cannot "un-apply" a property from another rule, only replace it outright
   - so every status colour's background needs restoring explicitly (with
   !important, matching what it's overriding). This can't be left as a single
   generic fallback rule either: an early version of this fix used just
   `.UnassignedJob.HighlightedJob { background-color: #777 !important }` to
   restore the plain-job default, but that selector's specificity (0,2,0) with
   !important beats every Colours.css class's own !important rule (0,1,0)
   regardless of which one is also present - verified against the live page,
   this actually forced EVERY highlighted job to flat grey, the opposite of
   the goal. Each status combination below is listed explicitly so its
   specificity (0,3,0) only wins for jobs that actually carry that class,
   correctly losing to nothing else and correctly not firing for any other
   status. The bare .UnassignedJob.HighlightedJob rule is still needed as the
   plain-job (no status class) case - it's fine at (0,2,0) precisely because
   every rule below it outranks it when a status class is also present. Every
   colour value below is copied verbatim from Colours.css/Scheduler.css. */

.UnassignedJob.HighlightedJob {
    background-color: #777 !important; /* restores .UnassignedJob's own default (no status class) */
}

.UnassignedJob.OnHoldUnassignedJob.HighlightedJob {
    background-color: #B77 !important; /* restores .OnHoldUnassignedJob (Scheduler.css) */
}

.UnassignedJob.CompletedJob.HighlightedJob {
    background-color: #55a955 !important; /* restores .CompletedJob (Scheduler.css) */
}

.UnassignedJob.DarkBlue.HighlightedJob    { background-color: #183B8C !important; }
.UnassignedJob.GreenBlue.HighlightedJob   { background-color: #00A8A8 !important; }
.UnassignedJob.DarkGreen.HighlightedJob   { background-color: #008040 !important; }
.UnassignedJob.LightGreen.HighlightedJob  { background-color: #79BE50 !important; }
.UnassignedJob.DarkRed.HighlightedJob     { background-color: #AC042B !important; }
.UnassignedJob.LightRed.HighlightedJob    { background-color: #EE3224 !important; }
.UnassignedJob.Gray.HighlightedJob        { background-color: #6D7587 !important; }
.UnassignedJob.Purple.HighlightedJob      { background-color: #9A459A !important; }
.UnassignedJob.Pink.HighlightedJob        { background-color: #E90169 !important; }
.UnassignedJob.Black.HighlightedJob       { background-color: #000 !important; }

/* These four also set color:#000 in Colours.css (dark text needed on a light
   fill) - restoring only background-color would leave the highlighted card
   with a dark fill but whatever text colour some other rule happens to
   supply, so color is restored alongside it. */
.UnassignedJob.LightBlue.HighlightedJob   { background-color: rgba(187, 221, 255, 0.85) !important; color: #000 !important; }
.UnassignedJob.FluroGreen.HighlightedJob  { background-color: rgba(124, 255, 76, 0.85) !important; color: #000 !important; }
.UnassignedJob.Yellow.HighlightedJob      { background-color: #FFE633 !important; color: #000 !important; }
.UnassignedJob.Orange.HighlightedJob      { background-color: #FA9205 !important; color: #000 !important; }

.UnassignedJob.HighlightedJob,
.UnassignedJob.HighlightedJob:hover {
    box-shadow: 0 0 0 2px #fff, 0 0 0 5px var(--totm-brand);
}


/* =============================================================================
   Job Details pane (#Details) redesign - own 1-4 list, unrelated to either
   numbering above. Measured against the live pane before writing this: at a
   300px pane width, .JobInfoElement's `width: 84%` (Scheduler.css) wastes
   76px of 370px usable width, and the label (14px/700/#444) and value
   (14px/400/#000) are close enough in size/weight that neither reads as more
   important than the other - every field looks like a disabled form input on
   a grey page rather than a data summary.
   ============================================================================= */

/* ---------------------------------------------------------------------------
   1. Invert label/value hierarchy

   .JobInfoElementTitle was a bordered, boxed 14px bold label - visually
   louder than the data it's labelling. Shrunk to the same small-uppercase
   treatment already used for table headers and section titlebars elsewhere
   in this file, so the pane reads as one consistent language rather than
   inventing a fourth. Values get their own deliberate weight (500) and the
   shared --totm-text tone instead of inheriting whatever black Scheduler.css
   happened to set.
   --------------------------------------------------------------------------- */

#JobInformationArea .JobInfoElementTitle {
    border: none;
    padding: 0;
    margin: 0 0 4px 0;
    font-size: var(--totm-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--totm-text-muted);
}

/* Scoped under #JobInformationArea because Scheduler.css's own rule here -
   `.JobInfoElement label, textarea` - is a comma-selector bug that styles
   EVERY textarea on the page, not just ones inside .JobInfoElement. Scoping
   to the pane's container avoids repeating that mistake. */
#JobInformationArea .JobInfoElement label,
#JobInformationArea .JobInfoElement textarea {
    background-color: transparent;
    border: none;
    padding: 0;
    font-size: 14px;
    font-weight: 500;
    color: var(--totm-text);
}

    /* #JobInfo_Description is a real <textarea readonly> - it's read-only so a
       resize handle and form-control chrome would be misleading; letting it
       read as a plain wrapped text block matches the flat surface below. */
    #JobInformationArea .JobInfoElement textarea {
        resize: none;
    }


/* ---------------------------------------------------------------------------
   2. Flat surface, hairline rows

   #Details was solid #eee, with every value sitting in its own #FFF box on
   top - the "stack of disabled inputs" look. Flattened to one white surface
   with a single hairline under each row instead of fifteen separate boxes.
   --------------------------------------------------------------------------- */

#Details {
    background-color: #fff;
}

#JobInformationArea .JobInfoElement {
    margin: 0;
    padding: 12px 0;
    border-bottom: 1px solid var(--totm-border);
}

    #JobInformationArea .JobInfoElement:last-child {
        border-bottom: none;
    }


/* ---------------------------------------------------------------------------
   3. Reclaim the wasted right margin

   `.JobInfoElement { width: 84% }` (Scheduler.css) left roughly a fifth of
   the pane's width empty on the right of every field - measured at 76px of
   370px usable width on a 300px-wide pane. box-sizing:border-box also fixes
   the label/value elements measuring wider than their own parent (306px/
   304px inside a 294px .JobInfoElement), which is why they visually
   overflowed their row by a few pixels.
   --------------------------------------------------------------------------- */

#JobInformationArea .JobInfoElement {
    width: 100%;
    box-sizing: border-box;
}

/* Scheduler.css only pads the left side (padding-left:20px) - content on the
   right ran flush against the scroll track with zero breathing room.
   Measured: row right edge sat exactly on #JobInformationArea's own
   clientWidth boundary, i.e. right up against the scrollbar.

   Scheduler.css sizes this element as content-box with width:calc(100% - 20px)
   - a manual trick to cancel out padding-left:20px so the total rendered box
   still comes to exactly 100% of its parent. Simply adding padding-right here
   without box-sizing:border-box broke that cancellation: content-box adds
   padding ON TOP of the specified width rather than absorbing it, so the
   element silently overflowed its parent (#Details) by exactly 16px - masked
   at the time by #Details' own overflow-x:hidden quietly clipping it, and by
   every row being a single full-width column with nothing distinctive at the
   clipped edge to notice. It only became visible once the Attachments grid
   below put two items on one row, letting that clipped 16px visibly eat into
   the second column. box-sizing:border-box + width:100% makes both paddings
   absorbed within the box instead of added beyond it, matching how every
   other width/padding pairing in this file already works. */
#JobInformationArea {
    box-sizing: border-box;
    width: 100%;
    padding-right: 16px;
}


/* ---------------------------------------------------------------------------
   4. Two-column rows for short fields

   Job Number, Status, and both dates are short values that don't need a
   label-above/value-below stack - putting the value on the same line as its
   label roughly halves the vertical space these four rows take. Everything
   else (Customer, Site, Description, ...) stays stacked, since those values
   are genuinely multi-line or too long to sit next to an 11px label.

   Matched by :has() on the known field id rather than adding a class in
   index.html, so this stays a pure CSS change. :has() has been supported in
   every evergreen browser since 2022/2023 - fine for an internal desktop
   tool - but if that ever becomes a constraint, these selectors are the
   place to swap for a markup-driven class instead.

   Status gets its own rule rather than joining the shared one: it has a
   third child, #JobInfoStatusRapidFireDiv (quick-status buttons, rendered by
   View.JobDetailsPane.js), which needs to wrap to its own line below the
   label/value pair rather than becoming a third column.
   --------------------------------------------------------------------------- */

#JobInformationArea .JobInfoElement:has(> #JobInfo_Code),
#JobInformationArea .JobInfoElement:has(> #JobInfo_DateEntered),
#JobInformationArea .JobInfoElement:has(> #JobInfo_DateRequired),
#JobInformationArea .JobInfoElement:has(> #JobInfo_Status) {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 12px;
}

    #JobInformationArea .JobInfoElement:has(> #JobInfo_Code) > .JobInfoElementTitle,
    #JobInformationArea .JobInfoElement:has(> #JobInfo_DateEntered) > .JobInfoElementTitle,
    #JobInformationArea .JobInfoElement:has(> #JobInfo_DateRequired) > .JobInfoElementTitle,
    #JobInformationArea .JobInfoElement:has(> #JobInfo_Status) > .JobInfoElementTitle {
        width: auto;
        flex: 0 0 auto;
        margin: 0;
    }

    #JobInformationArea .JobInfoElement:has(> #JobInfo_Code) > label,
    #JobInformationArea .JobInfoElement:has(> #JobInfo_DateEntered) > label,
    #JobInformationArea .JobInfoElement:has(> #JobInfo_DateRequired) > label {
        width: auto;
        text-align: right;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    #JobInformationArea .JobInfoElement:has(> #JobInfo_Status) > label#JobInfo_Status {
        width: auto;
        text-align: right;
    }

    /* Forces the rapid-fire status buttons onto their own row below the
       label/value pair, rather than becoming a cramped third flex column. */
    #JobInformationArea #JobInfoStatusRapidFireDiv {
        flex-basis: 100%;
        width: 100%;
    }


/* ---------------------------------------------------------------------------
   6. Status as a coloured pill

   Was plain text. View.JobDetailsPane.js sets background-color/color inline
   on #JobInfo_Status, reusing the exact same
   Util.ColourMapping.getColourForStatus()/getTextColourForStatus() calls the
   job list and calendar already use - so a job's status pill here always
   matches its colour everywhere else in the app. This file only supplies the
   shape: padding, uppercase, no radius (square corners, matching the rest of
   the app).

   View.JobDetailsPane.js clears both the text AND the inline colours
   together when there's no status, so :empty is enough to hide the pill's
   padding/shape rather than it rendering as a stray colourless box.
   --------------------------------------------------------------------------- */

#JobInfo_Status {
    display: inline-block;
    padding: 3px 10px;
    font-size: var(--totm-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

    #JobInfo_Status:empty {
        display: none;
    }


/* ---------------------------------------------------------------------------
   Bug fix: attached photos effectively invisible in the Attachments list

   .JobDetailsAttachmentButton img (Scheduler.css) only sets max-width:320px -
   no height constraint at all. A job with 3 attached photos was rendering
   each one at close to its native resolution (measured: 320x427, 320x240,
   320x569 for a real job's 3 attachments) stacked in the ~155-300px-wide
   #Details sidebar. That pushed #JobDetailsAttachments 1028px down the
   pane's content (measured) and made the combined list 1355px tall - so the
   attachments were genuinely in the DOM and correctly loaded, just requiring
   far more scrolling than anyone would reasonably do to find them.

   This class is ONLY used for the sidebar thumbnail list - the full-size
   image viewer (opened by clicking a thumbnail) is a separate element,
   #JobDetailsImageGalleryImage, styled elsewhere in this file and unaffected
   by this change.

   #JobDetailsAttachments is also laid out as a 2-column grid (below) rather
   than one attachment per row, so the image cap here is just height/
   object-fit - width is left to fill whatever the grid column gives it
   rather than an independent max-width, so it doesn't fight the column and
   leave an odd gap on wider panes.

   Every tile's total height is now the SUM of two independently fixed
   pieces - the 70px image/icon below, and .JobDetailsAttachmentName's fixed
   28px (2-line-clamped) filename below that - rather than being driven by
   however much room the filename text happens to need. That's what makes
   every tile in the grid come out identically tall regardless of file type
   or how long its filename is, not just roughly similar. Both were sized
   down from their original 100px/40px so a 2-line filename still fits
   comfortably within a compact overall tile.
   --------------------------------------------------------------------------- */

.JobDetailsAttachmentButton img {
    display: block;
    width: 100%;
    height: 70px;
    object-fit: cover;
    margin-top: 4px;
}

/* Same height/margin-top as the image thumbnail above, so a document tile
   (job.OtherAttachments - anything that isn't an image) and a photo tile
   occupy the same footprint in the 2-column grid below. line-height centres
   the glyph vertically within that height; .JobDetailsAttachmentButton's own
   text-align:center (below) centres it horizontally, and its color:#fff is
   inherited by the icon the same way it already is by the filename text. */
.JobDetailsAttachmentIcon {
    display: block;
    height: 70px;
    line-height: 70px;
    margin-top: 4px;
    font-size: 28px;
}

/* Filename sits in its own element (View.JobDetailsPane.js) specifically so
   it can be clamped independently of the image/icon beside it. height (not
   max-height) always reserves exactly 2 lines' worth of space, whether the
   filename needs one line or two, so a short name ("a.jpg") and a long one
   ("Altered - 1.jpg") produce the same tile height - line-clamp only
   controls what happens to text that doesn't fit, not how much space is
   reserved for text that does. word-break lets filenames with no natural
   break points (no spaces) still wrap instead of overflowing sideways. */
.JobDetailsAttachmentName {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    height: 28px;
    font-size: 11px;
    line-height: 14px;
    word-break: break-word;
}

/* Fixed 2 columns (not auto-fill) - a single attachment occupies one cell
   rather than stretching across the row, and a third occupies its own new
   row rather than the grid trying to fit 3-across on a wide pane. */
/* width:100% is required, not decorative - #JobDetailsAttachments sits inside
   .JobInfoElement, which Scheduler.css floats (float:left). A block-level
   grid container's width:auto does not reliably fill a floated ancestor's
   content box the way an ordinary block element's would: verified live that
   without an explicit width the container computed to width:0 while its
   1fr tracks still sized off their content's min-content width, so the grid
   silently overflowed its own (nominally zero-width) box to the right rather
   than laying out within the row. */
#JobDetailsAttachments {
    display: grid;
    width: 100%;
    box-sizing: border-box;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}

    #JobDetailsAttachments li {
        list-style: none;
        margin: 0;
    }

    /* Stretches to fill its grid cell (grid's default justify-items:stretch)
       instead of Scheduler.css's own display:inline-block width-to-content,
       so image and text-only (non-image, job.OtherAttachments) chips both
       line up to the same column width. Background/border/text-colour soften
       Scheduler.css's own solid #1976D2 fill + white text into a thin border
       and a faint tint - a whole grid of solid blue tiles reads as loud, and
       a bordered/tinted tile still clearly reads as "a thing you can click"
       without competing with the actual photo thumbnails for attention. */
    #JobDetailsAttachments .JobDetailsAttachmentButton {
        display: block;
        box-sizing: border-box;
        text-align: center;
        background-color: var(--totm-brand-tint);
        color: var(--totm-text);
        border: 1px solid var(--totm-border);
    }

        #JobDetailsAttachments .JobDetailsAttachmentButton:hover {
            background-color: #fff;
            border-color: var(--totm-border-strong);
            color: var(--totm-text);
        }


/* ---------------------------------------------------------------------------
   Upload panel under Attachments (drag-and-drop + browse button)

   Behaviour is wired up in View.JobDetailsPane.js (setupAttachmentUpload) -
   this is just the drop zone's shape. Square corners throughout, matching
   the rest of the app; .JobDetailsAttachmentDropZoneActive is added/removed
   on dragover/dragleave/drop to give feedback that a drop will land here.
   --------------------------------------------------------------------------- */

.JobDetailsAttachmentDropZone {
    margin-top: 12px;
    padding: 20px 12px;
    text-align: center;
    box-sizing: border-box;
    border: 2px dashed var(--totm-border-strong);
    color: var(--totm-text-muted);
    transition: border-color var(--totm-motion), background-color var(--totm-motion), color var(--totm-motion);
}

    .JobDetailsAttachmentDropZone > .fa {
        display: block;
        font-size: 28px;
        margin-bottom: 6px;
    }

    .JobDetailsAttachmentDropZoneText {
        font-size: var(--totm-fs-sm);
        margin-bottom: 10px;
    }

.JobDetailsAttachmentDropZoneActive {
    border-color: var(--totm-brand);
    background-color: var(--totm-brand-tint);
    color: var(--totm-brand-ink);
}

#JobDetailsAttachmentBrowseButton {
    margin-right: 0;
}


/* ---------------------------------------------------------------------------
   Let the 3 main panels (#external-events, #CalendarWrapper, #Details)
   rescale on smaller screens

   #wrap's own width:100% is fine - the bug is min-width:1400px underneath it.
   #external-events and #Details are position:fixed with percentage `right`
   offsets, which resolve against the real viewport regardless of #wrap - but
   #CalendarWrapper is a plain float:left, percentage-of-#wrap element, so its
   pixel width was floored at 1400px's worth of "59%" no matter how narrow the
   viewport actually was. Below ~1400px those two different reference frames
   diverged: the two fixed side panels correctly shrank with the real
   viewport while the calendar stayed pinned to its 1400px-relative width,
   and the gap between them shrank until the calendar started rendering
   UNDERNEATH the Jobs List panel.

   Measured on the real page (min-width overridden live to confirm): at
   1280px wide, #CalendarWrapper's right edge sat 55px past #external-events'
   left edge - a genuine visible overlap, not just a "things feel cramped"
   complaint. Removing the floor fixes this because #wrap can then actually
   shrink to the real viewport width, so #CalendarWrapper's percentage
   resolves against the same width the fixed side panels are already using.
   Re-verified no overlap at 1366/1280/1024/900px, all with a clean double-
   digit-pixel gap between the calendar and Jobs List panel.
   --------------------------------------------------------------------------- */

#wrap {
    min-width: 0;
}


/* ---------------------------------------------------------------------------
   Pending/Progress/Admin toggle wraps to 2 lines at narrower panel widths

   #JobsToDisplayToggle label (Scheduler.css) is width:32% content-box, with a
   1px border each side from jQuery UI's own .ui-button theme class - so each
   label's actual rendered width is "32% + 2px", not 32%. Three of those sum
   to "96% + 6px". At wide containers that fixed 6px is negligible inside the
   remaining 4% of headroom; at the narrower panel widths reachable now that
   #wrap can shrink (above), that same fixed 6px eventually exceeds the 4%
   headroom, and since these are inline-block (not flex), overflow wraps the
   3rd label to a new line rather than shrinking to fit. Measured live at
   1280px wide: container content box 211px, three labels summing to exactly
   210px - a 1px margin that sub-pixel/rounding differences alone are enough
   to tip over.

   Switched the container to flex with flex:1 labels instead of width:32% -
   flex distributes the container's actual available width directly, so
   there's no percentage-plus-fixed-border math left to overflow.
   --------------------------------------------------------------------------- */

#JobsToDisplayToggle {
    display: flex;
}

    #JobsToDisplayToggle label {
        /* flex-basis:auto (the 3rd value here, not 0) sizes each label to its
           own content first, THEN flex-grow:1 shares out whatever room is
           left - giving the original width:32% "fill the row, roughly equal
           thirds" look whenever there's enough space, which is the common
           case. Deliberately not flex-basis:0 + min-width:0 (forces truly
           equal widths, tried first): that forces every label to the same
           width regardless of content, which at the narrowest panel widths
           this toggle can now reach shrank "Progress" below what its own
           text needs and clipped it - confirmed live at 1024px wide. With
           flex-basis:auto, min-width stays at its flexbox default (auto),
           which refuses to shrink a label below its own content's min-content
           width - so at those same narrow widths the row instead overflows
           its own flex-basis slightly rather than clipping any label, and
           confirmed there's still room in #external-events for that at
           1024px and 900px alike (no wrap, no clipping, nothing extends past
           the panel's own edge). */
        flex: 1 1 auto;
        width: auto;
        box-sizing: border-box;
    }
