/* Jennings brand skin over DashLite - same approach as the proven Esper skin:
   pure CSS overlay, no template edits. Palette from the Jennings shield:
   orange #F26A21, charcoal #33383e. Kills the stock DashLite purple. */

:root {
    --jn-orange: #F26A21;
    --jn-orange-dark: #d4551a;
    --jn-orange-light: #fdf0e8;
    --jn-charcoal: #33383e;
    --jn-charcoal-dark: #24282d;
}

/* Buttons */
.btn-primary { background-color: var(--jn-orange); border-color: var(--jn-orange); }
.btn-primary:hover, .btn-primary:focus, .btn-primary:active,
.btn-primary:not(:disabled):not(.disabled):active { background-color: var(--jn-orange-dark); border-color: var(--jn-orange-dark); }
.btn-outline-primary { color: var(--jn-orange); border-color: var(--jn-orange); }
.btn-outline-primary:hover { background-color: var(--jn-orange); border-color: var(--jn-orange); color: #fff; }
.btn-charcoal { background-color: var(--jn-charcoal); border-color: var(--jn-charcoal); color: #fff; }
.btn-charcoal:hover { background-color: var(--jn-charcoal-dark); border-color: var(--jn-charcoal-dark); color: #fff; }

/* Links + accents */
a { color: var(--jn-orange-dark); }
a:hover { color: var(--jn-orange); }
.text-primary { color: var(--jn-orange) !important; }
.bg-primary { background-color: var(--jn-orange) !important; }
.bg-primary-dim { background-color: var(--jn-orange-light) !important; }
.badge.bg-primary { background-color: var(--jn-orange) !important; }
.badge.bg-outline-primary { color: var(--jn-charcoal); border-color: #d8dce2 !important; }

/* Light sidebar (Tom's chosen default) - charcoal text, orange active state */
.nk-sidebar.is-light .nk-menu-heading .overline-title { color: var(--jn-orange) !important; }
.nk-sidebar.is-light .nk-menu-item.active > .nk-menu-link,
.nk-sidebar.is-light .nk-menu-item.current-page > .nk-menu-link { color: var(--jn-orange); background: var(--jn-orange-light); }
.nk-sidebar.is-light .nk-menu-item.active > .nk-menu-link .nk-menu-icon { color: var(--jn-orange); }
.nk-sidebar.is-light .nk-menu-link:hover { color: var(--jn-orange); }
.nk-sidebar.is-light .nk-menu-link:hover .nk-menu-icon { color: var(--jn-orange); }

/* Dark + brand sidebar variants get the charcoal treatment */
.nk-sidebar.is-dark, .nk-sidebar.is-theme { background: var(--jn-charcoal); }
.nk-sidebar.is-dark .nk-sidebar-head, .nk-sidebar.is-theme .nk-sidebar-head { background: var(--jn-charcoal-dark); }
.nk-sidebar.is-dark .nk-menu-heading .overline-title,
.nk-sidebar.is-theme .nk-menu-heading .overline-title { color: var(--jn-orange) !important; }
.nk-sidebar.is-dark .nk-menu-item.active > .nk-menu-link,
.nk-sidebar.is-theme .nk-menu-item.active > .nk-menu-link { color: #fff; background: rgba(255, 255, 255, 0.06); }
.nk-sidebar.is-dark .nk-menu-item.active > .nk-menu-link .nk-menu-icon,
.nk-sidebar.is-theme .nk-menu-item.active > .nk-menu-link .nk-menu-icon,
.nk-sidebar.is-dark .nk-menu-link:hover .nk-menu-icon,
.nk-sidebar.is-theme .nk-menu-link:hover .nk-menu-icon { color: var(--jn-orange); }

/* Tabs + focus states - no more DashLite purple */
.nav-tabs .nav-link { color: #5b6470; }
.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { color: var(--jn-charcoal); }
.nav-tabs .nav-link.active { color: var(--jn-charcoal); border-bottom: 2px solid var(--jn-orange); font-weight: 600; }
.form-control:focus, .form-select:focus { border-color: var(--jn-orange); box-shadow: 0 0 0 3px rgba(242, 106, 33, 0.12); }
.form-check-input:checked { background-color: var(--jn-orange); border-color: var(--jn-orange); }
.form-switch .form-check-input:checked { background-color: var(--jn-orange); border-color: var(--jn-orange); }
.custom-control-input:checked ~ .custom-control-label::before { background-color: var(--jn-orange); border-color: var(--jn-orange); }

/* Cards + tables */
.card-bordered { border-color: #e2e6ec; }
.nk-tb-item:hover { background: #fdf8f5; }
.page-title { color: var(--jn-charcoal); }

/* Header quick-action buttons */
.nk-header .btn-success { background-color: var(--jn-orange); border-color: var(--jn-orange); }
.nk-header .btn-success:hover { background-color: var(--jn-orange-dark); border-color: var(--jn-orange-dark); }

/* Workspace tab strip - active tab underline already inline, match hover */
.jn-tab-strip a:hover { color: var(--jn-orange) !important; }

/* Pagination + dropdown accents */
.page-link { color: var(--jn-orange-dark); }
.page-item.active .page-link { background-color: var(--jn-orange); border-color: var(--jn-orange); }
.dropdown-menu .link-list a:hover { color: var(--jn-orange); }

/* Small buttons sit flush with small inputs in inline forms (25-Jul fix) */
.btn-sm { padding-top: 0.4375rem; padding-bottom: 0.4375rem; line-height: 1.25; }
.btn-xs { padding: 0.15rem 0.5rem; font-size: 0.75rem; line-height: 1.3; }
.input-group-sm > .btn { padding-top: 0.25rem; padding-bottom: 0.25rem; }

/* List items with identity (26-Jul): icon chip + strong title + soft meta */
.jn-item { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-bottom: 1px solid #eceff3; }
.jn-item:last-child { border-bottom: 0; }
.jn-item .jn-ico { flex: 0 0 38px; height: 38px; border-radius: 8px; background: var(--jn-orange-light); color: var(--jn-orange); display: flex; align-items: center; justify-content: center; font-size: 1.05rem; }
.jn-item .jn-ico.charcoal { background: #eef0f3; color: var(--jn-charcoal); }
.jn-item .jn-body { flex: 1; min-width: 0; }
.jn-item .jn-title { font-weight: 600; color: var(--jn-charcoal); }
.jn-item .jn-meta { font-size: .8rem; color: #8a93a2; margin-top: 1px; }
.jn-item .jn-text { margin-top: 4px; color: #3f4652; }
.jn-item .jn-side { flex: 0 0 auto; text-align: right; }
.jn-empty { text-align: center; color: #9aa2b1; padding: 18px 0; }
.jn-empty .icon { font-size: 1.8rem; display: block; margin-bottom: 6px; color: #c9cfd9; }

/* Job summary stat band (26-Jul) */
.jn-stats { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.jn-stat { flex: 1 1 120px; background: #f7f8fa; border: 1px solid #e4e7ec; border-radius: 8px; padding: 10px 12px; }
.jn-stat .k { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; color: #8a93a2; font-weight: 600; }
.jn-stat .v { font-size: 1.05rem; font-weight: 700; color: var(--jn-charcoal); margin-top: 2px; }
.jn-stat.orange { background: var(--jn-orange-light); border-color: #f5c9ad; }
.jn-stat.orange .v { color: var(--jn-orange-dark); }

/* Day dispatch board (Gantt) */
.jn-gantt { min-width: 1900px; }   /* 24 hours at a readable width; the board scrolls */
.jn-gantt .row-eng { display: flex; align-items: stretch; border-bottom: 1px solid #eceff3; }
.jn-gantt .eng-name { flex: 0 0 150px; padding: 10px 12px; font-weight: 600; color: var(--jn-charcoal); border-right: 1px solid #eceff3; font-size: .85rem; }
/* Hour lines, plus a lighter line every 15 minutes so the snap points are
   visible (Tom, 03-Sep). 24 hours across, so an hour is 100%/24 and a quarter
   is 100%/96. The faint layer is painted first, the hour lines over it. */
.jn-gantt .eng-track { flex: 1; position: relative; min-height: 46px;
    background:
      repeating-linear-gradient(to right, transparent, transparent calc(100%/24 - 1px), #eceff3 calc(100%/24 - 1px), #eceff3 calc(100%/24)),
      repeating-linear-gradient(to right, transparent, transparent calc(100%/96 - 1px), #f6f8fa calc(100%/96 - 1px), #f6f8fa calc(100%/96)); }
.jn-gantt .blk { position: absolute; top: 6px; bottom: 6px; border-radius: 6px; background: var(--jn-orange-light); border: 1px solid var(--jn-orange); color: var(--jn-charcoal); font-size: .72rem; padding: 3px 6px; overflow: hidden; white-space: nowrap; text-decoration: none; }
.jn-gantt .blk.done { background: #e8f7ef; border-color: #14804a; }
.jn-gantt .blk.onsite { background: #fff6e0; border-color: #d9a400; }
.jn-gantt .hours { display: flex; margin-left: 150px; color: #8a93a2; font-size: .72rem; }
.jn-gantt .hours span { flex: 1; padding: 4px 0 4px 4px; border-left: 1px solid #eceff3; }

/* ---- Mobile pass (27-Jul, from Tom's phone screenshots) ---- */
@media (max-width: 767.98px) {
    /* Tab rows scroll sideways instead of wrapping into a mess */
    .nav-tabs { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .nav-tabs::-webkit-scrollbar { display: none; }
    .nav-tabs .nav-link { white-space: nowrap; }
    /* Wide tables scroll inside their card instead of blowing the page out */
    .card-inner { overflow-x: auto; }
    /* Summary stat chips: two tidy columns */
    .jn-stats .jn-stat { flex: 1 1 calc(50% - 10px); }
    /* Page-head action buttons get room */
    .nk-block-head-content .btn { margin-bottom: 6px; }
    /* List items: tuck the side badge under on narrow screens */
    .jn-item .jn-side { max-width: 40%; }
    /* Workspace tab strip chips slightly tighter */
    .jn-tab-strip a { max-width: 150px !important; }
}

/* Mobile round 2 (27-Jul): page heads stack, control clusters wrap */
@media (max-width: 767.98px) {
    .nk-block-between { flex-wrap: wrap; row-gap: 8px; }
    .nk-block-between > .nk-block-head-content { flex: 1 1 100%; }
    .nk-block-head .btn-group { flex-wrap: wrap; }
    .nk-block-des p { margin-bottom: 0; }
    /* forms laid out as .row g-2/g-3: let sm cols breathe */
    .card-inner .row.g-2 > [class*="col-"], .card-inner .row.g-1 > [class*="col-"] { min-width: 0; }
    /* input groups with long URLs (pay links) never overflow */
    .input-group { flex-wrap: nowrap; }
    .input-group .form-control { min-width: 0; }
    /* jn-item: allow wrapping of side content under body */
    .jn-item { flex-wrap: wrap; }
    .jn-item .jn-body { flex: 1 1 60%; }
    /* modal-ish cards padding tighter */
    .card-inner { padding: 1rem; }
    /* page titles a notch smaller */
    .nk-block-title.page-title { font-size: 1.35rem; }
}
@media (max-width: 767.98px) {
    .jn-gantt .eng-name { flex: 0 0 96px; font-size: .75rem; padding: 8px; }
    .jn-gantt .hours { margin-left: 96px; }
    /* schedule needs-booking chips: keep readable */
    .card-inner .badge { white-space: normal; text-align: left; }
}

/* Attachment drop zone + uniform 32px control height (26-Jul) */
.jn-drop { border: 2px dashed #d5dae2; border-radius: 10px; padding: 26px 16px; text-align: center; cursor: pointer; transition: border-color .15s, background .15s; }
.jn-drop:hover, .jn-drop.over { border-color: var(--jn-orange); background: var(--jn-orange-light); }
.jn-drop .icon { font-size: 1.9rem; color: var(--jn-orange); display: block; margin-bottom: 6px; }
.jn-drop-label { font-weight: 600; color: var(--jn-charcoal); }
.jn-h32, input.jn-h32, select.jn-h32, button.jn-h32 { height: 32px !important; min-height: 32px; padding-top: 0; padding-bottom: 0; line-height: 30px; }
select.jn-h32 { line-height: normal; }
/* buttons with an icon + span label: give the label breathing room */
.btn .icon + span { margin-left: 6px; }
.jn-key { display:inline-block; width:11px; height:11px; border-radius:2px; border:1px solid; vertical-align:-1px; margin-right:2px; }

/* Day + week Gantt boards (26-Jul, rebuilt) */
.jn-board-scroll { max-height: 78vh; overflow: auto; position: relative; }
.jn-gantt .blk { overflow: hidden; bottom: auto; }   /* height is set per block, not stretched */
.jn-gantt .hours { position: sticky; top: 0; z-index: 5; background: #fff; }
.jn-gantt .row-eng .eng-name { position: sticky; left: 0; z-index: 3; background: #fff; }

/* Week board - nested, full-width flexible grid (rebuilt 26-Jul) */
.jn-wk { width: 100%; }
.jn-wk-namecol { flex: 0 0 150px; box-sizing: border-box; padding: 8px 12px; }
.jn-wk-cols { flex: 1 1 auto; display: grid; grid-template-columns: repeat(7, 1fr); }
.jn-wk-head { display: flex; position: sticky; top: 0; z-index: 5; background: #f7f8fa; border-bottom: 1px solid #e4e7ec; font-weight: 600; font-size: .78rem; color: var(--jn-charcoal); }
.jn-wk-head .jn-wk-namecol { padding: 9px 12px; }
.jn-wk-dayh { padding: 9px 10px; border-left: 1px solid #eceff3; box-sizing: border-box; }
.jn-wk-dayh.today { background: #fdf8f5; }
.jn-wk-eng { display: flex; border-bottom: 1px solid #e4e7ec; }
.jn-wk-eng .name { font-weight: 600; font-size: .84rem; color: var(--jn-charcoal); display: flex; align-items: center; border-right: 1px solid #eceff3; }
.jn-wk-grid { flex: 1 1 auto; display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; padding: 4px; position: relative; }
.jn-wk-todaycol { background: #fdf8f5; border-radius: 4px; z-index: 0; }
.jn-wk-job { z-index: 1; display: flex; flex-direction: column; gap: 1px; background: var(--jn-orange-light); border: 1px solid var(--jn-orange); border-left: 3px solid var(--jn-orange); border-radius: 6px; padding: 4px 8px; text-decoration: none; color: var(--jn-charcoal); overflow: hidden; min-width: 0; }
.jn-wk-job:hover { filter: brightness(0.97); }
.jn-wk-job.done { background: #e8f7ef; border-color: #14804a; border-left-color: #14804a; }
.jn-wk-job.onsite { background: #fff6e0; border-color: #d9a400; border-left-color: #d9a400; }
.jn-wk-job .t { font-weight: 700; font-size: .74rem; }
.jn-wk-job .j { font-size: .74rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jn-wk-job .pc { font-size: .68rem; color: #6a7180; }
.jn-h40, input.jn-h40, select.jn-h40, button.jn-h40 { height: 40px !important; min-height: 40px; }

/* ============ Engineer mobile app (rebuilt 27-Jul) ============ */
.jn-eng { background: #f4f5f7; }
.jn-eng-top { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 10px; padding: 12px 14px; background: #fff; border-bottom: 1px solid #e7e9ee; }
.jn-eng-back, .jn-eng-out { flex: 0 0 auto; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; border-radius: 8px; background: #f4f5f7; color: var(--jn-charcoal); font-size: 1.1rem; text-decoration: none; }
.jn-eng-title { flex: 1; min-width: 0; font-weight: 600; color: var(--jn-charcoal); font-size: 1.02rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jn-eng-wrap { max-width: 640px; margin: 0 auto; padding: 12px 12px calc(96px + env(safe-area-inset-bottom)); }
.jn-eng .form-control, .jn-eng .form-select { min-height: 44px; border-radius: 10px; font-size: .92rem; }
.jn-eng textarea.form-control { min-height: 60px; }
.jn-eng .btn { border-radius: 10px; }
.jn-eng .btn-sm { min-height: 38px; }
.jn-eng .card-inner { padding: 14px; }
.jn-eng .card.card-bordered { border-radius: 12px; }
.jn-eng-hello { font-size: .9rem; color: #6a7180; margin-bottom: 12px; }
.jn-eng-section { font-weight: 700; color: var(--jn-charcoal); font-size: .82rem; text-transform: uppercase; letter-spacing: .04em; margin: 20px 2px 8px; }
.jn-eng-seeall { font-size: .78rem; font-weight: 500; text-transform: none; letter-spacing: 0; }
.jn-eng-day { font-weight: 600; color: var(--jn-charcoal); font-size: .86rem; margin: 16px 2px 6px; }
.jn-eng-day.today { color: var(--jn-orange); }
.jn-eng-empty { text-align: center; color: #9aa2b1; padding: 22px 0; background: #fff; border: 1px solid #e7e9ee; border-radius: 12px; }
.jn-eng-empty.sm { padding: 12px 0; font-size: .8rem; }
.jn-eng-empty .icon { display: block; font-size: 1.6rem; margin-bottom: 6px; color: #c9cfd9; }

/* Hero: on-now / next-up */
.jn-hero { display: block; border-radius: 14px; padding: 16px; margin-bottom: 12px; text-decoration: none; color: #fff; }
.jn-hero.on-now { background: linear-gradient(135deg, #14804a, #0c633a); }
.jn-hero.next-up { background: linear-gradient(135deg, #F26A21, #d2551a); }
.jn-hero.none { background: #fff; color: #6a7180; border: 1px solid #e7e9ee; }
.jn-hero-tag { font-size: .76rem; font-weight: 600; opacity: .92; margin-bottom: 6px; }
.jn-hero-title { font-size: 1.12rem; font-weight: 700; }
.jn-hero-sub { font-size: .84rem; opacity: .9; margin-top: 2px; }
.jn-hero-cta { margin-top: 10px; font-weight: 600; font-size: .84rem; display: inline-flex; align-items: center; gap: 4px; }

.jn-eng-alert { display: flex; justify-content: space-between; align-items: center; background: #fff3e9; border: 1px solid #f9c9a6; color: #b0480f; border-radius: 12px; padding: 12px 14px; text-decoration: none; font-weight: 600; font-size: .88rem; margin-bottom: 4px; }

/* Job cards on lists */
.jn-jobcard { display: flex; align-items: center; gap: 12px; background: #fff; border: 1px solid #e7e9ee; border-radius: 12px; padding: 12px 14px; margin-bottom: 8px; text-decoration: none; color: var(--jn-charcoal); }
.jn-jobcard.sm { padding: 10px 12px; }
.jn-jobcard.done { opacity: .6; }
.jn-jobcard-time { flex: 0 0 46px; font-weight: 700; color: var(--jn-orange); font-size: .9rem; text-align: center; line-height: 1.1; }
.jn-jobcard-time .to { display: block; font-weight: 400; font-size: .68rem; color: #9aa2b1; }
.jn-jobcard.done .jn-jobcard-time { color: #14804a; }
.jn-jobcard-body { flex: 1; min-width: 0; }
.jn-jobcard-title { font-weight: 600; font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jn-jobcard-sub { font-size: .78rem; color: #8a93a2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jn-jobcard-arrow { flex: 0 0 auto; color: #c4cad4; }

/* Job detail */
.jn-eng-jobhead { background: #fff; border: 1px solid #e7e9ee; border-radius: 12px; padding: 14px; margin-bottom: 12px; }
.jn-eng-jobname { font-weight: 700; font-size: 1.08rem; color: var(--jn-charcoal); }
.jn-eng-jobaddr { font-size: .86rem; color: #6a7180; margin: 4px 0 10px; }
.jn-eng-actions { display: flex; gap: 8px; }
.jn-eng-actions .btn { flex: 1; }
.jn-eng-enroute { display: flex; gap: 8px; margin-bottom: 12px; }
.jn-eng-rich p:last-child { margin-bottom: 0; }
.jn-eng-cta { margin-top: 4px; }

/* Quick-actions grid (engineer job page) */
.jn-qgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 2px 0 14px; }
.jn-qtile { display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 5px; background: #fff; border: 1px solid #e7e9ee; border-radius: 12px; padding: 12px 6px;
    text-decoration: none; color: var(--jn-charcoal); font-size: .76rem; font-weight: 600;
    text-align: center; line-height: 1.15; min-height: 74px; transition: border-color .12s, box-shadow .12s; cursor: pointer; }
.jn-qtile:active { box-shadow: inset 0 0 0 2px var(--jn-orange, #F26A21); }
.jn-qtile .ni { font-size: 1.38rem; color: var(--jn-orange, #F26A21); }
.jn-qtile.is-done { border-color: #9fe1cb; background: #f1faf5; }
.jn-qtile.is-done .ni { color: #0c9f5f; }
.jn-qtile .jn-qbadge { position: absolute; }
.jn-qtile-wrap { position: relative; }
.jn-qtile-wrap .badge { position: absolute; top: 5px; right: 5px; }

/* Section cards on the engineer job sub-pages - each is its own screen now
   (hub-and-spoke), so the card is always fully open; the old chevron is hidden. */
.jn-acc > .card-inner > .jn-acc-head { cursor: default; display: flex; align-items: center;
    justify-content: space-between; margin: 0 0 12px; }
.jn-acc > .card-inner > .jn-acc-head .jn-acc-chev { display: none; }
.jn-acc > .card-inner > .jn-acc-body { display: block; }
.jn-acc .jn-acc-sub { font-size: .76rem; color: #8094ae; font-weight: 500; }

/* Timesheet - pay view */
.jn-ts-summary { display: flex; gap: 10px; margin-bottom: 10px; }
.jn-ts-summary > div { flex: 1; background: var(--jn-charcoal); color: #fff; border-radius: 12px; padding: 12px 14px; }
.jn-ts-summary .k { font-size: .74rem; opacity: .82; }
.jn-ts-summary .v { font-size: 1.3rem; font-weight: 700; }
.jn-ts-deadline { background: #fff3e9; border: 1px solid #f9c9a6; color: #b0480f; border-radius: 10px; padding: 10px 12px; font-size: .84rem; font-weight: 500; margin-bottom: 12px; }
.jn-ts-deadline.done { background: #e8f7ef; border-color: #9fe1cb; color: #0c633a; }
.jn-ts-job { display: block; background: #fff; border: 1px solid #e7e9ee; border-radius: 11px; padding: 11px 13px; margin-bottom: 7px; text-decoration: none; color: var(--jn-charcoal); }
.jn-ts-job-head { display: flex; justify-content: space-between; align-items: center; }
.jn-ts-pay { font-weight: 700; color: #14804a; }
.jn-ts-job-meta { font-size: .76rem; color: #8a93a2; margin-top: 2px; }

.jn-eng-weeknav {
 display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; font-weight: 600; color: var(--jn-charcoal); }

/* Bottom tab bar */
.jn-eng-nav { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; display: flex; background: #fff; border-top: 1px solid #e7e9ee; padding-bottom: env(safe-area-inset-bottom); }
.jn-eng-nav a { flex: 1; text-align: center; padding: 9px 0 8px; color: #9aa2b1; text-decoration: none; font-size: .68rem; }
.jn-eng-nav a .icon { display: block; font-size: 1.25rem; margin-bottom: 1px; }
.jn-eng-nav a.on { color: var(--jn-orange); }

/* Engineer pay/cost breakdown box on the job Engineers tab (27-Jul) */
.jn-costbox { background: #f7f8fa; border: 1px solid #eceff3; border-radius: 10px; padding: 12px; }

/* ============================================================
   ENGINEER-APP BUTTON/INPUT ROWS - the ONE convention (27-Jul).
   This block is the permanent fix for the recurring "buttons
   overflow / squish" bug. Rules, not one-offs:
     - Input + button  -> wrap in .input-group (Bootstrap owns it).
     - Two+ buttons     -> .d-flex.gap-2 (or .jn-eng-enroute); the
                           rule below makes them EQUAL width and
                           never overflow, whatever w-50/flex-fill
                           classes are on them.
     - Single button    -> .w-100.
   Never hand-roll .d-flex with a button + auto/percent widths.
   ============================================================ */
.jn-eng .btn { max-width: 100%; }
.jn-eng .d-flex.gap-2 > .btn,
.jn-eng-enroute > .btn { flex: 1 1 0; min-width: 0; }
.jn-eng .input-group > .form-control { min-width: 0; }

/* Editable weekly timesheet table (27-Jul) */
.jn-ts-table { background: #fff; border: 1px solid #e7e9ee; border-radius: 12px; overflow: hidden; }
.jn-ts-thead, .jn-ts-line, .jn-ts-tfoot { display: grid; grid-template-columns: 1fr 78px 92px; gap: 8px; align-items: center; padding: 8px 12px; }
.jn-ts-thead { background: #f7f8fa; font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: #6a7180; }
.jn-ts-thead .c-hrs, .jn-ts-thead .c-pay, .jn-ts-line .c-hrs, .jn-ts-line .c-pay, .jn-ts-tfoot .c-hrs, .jn-ts-tfoot .c-pay { text-align: center; }
.jn-ts-line { border-top: 1px solid #eceff3; }
.jn-ts-line .c-job, .jn-ts-thead .c-job, .jn-ts-tfoot .c-job { min-width: 0; }
.jn-ts-line .c-job .fw-medium { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jn-ts-line .form-control { text-align: center; padding: 6px 4px; }
.jn-ts-tfoot { border-top: 2px solid #e4e7ec; background: #fafbfc; }

/* weeknav chevrons visible on the grey page bg; forms inside button rows behave like buttons */
.jn-eng-weeknav .btn { background: #fff; border: 1px solid #e0e3e9; color: var(--jn-charcoal); }
.jn-eng .d-flex.gap-2 > form { flex: 1 1 0; min-width: 0; }
.jn-eng .d-flex.gap-2 > form > .btn { width: 100%; }

/* ============================================================
   GLOBAL CONTROL-HEIGHT EQUALISER (12-Aug). Tom has flagged
   mismatched input/select/button heights repeatedly. This pins
   every size tier to ONE height so mixed rows can never mismatch:
   default tier 38px, -sm tier 32px, -lg tier 46px. Do NOT add
   per-page height hacks - this rule is the single source.
   ============================================================ */
.form-control:not(.form-control-sm):not(.form-control-lg),
.form-select:not(.form-select-sm):not(.form-select-lg),
.btn:not(.btn-sm):not(.btn-lg):not(.btn-xs) {
    min-height: 38px;
}
.form-control-sm, .form-select-sm, .btn-sm, .input-group-sm > .form-control,
.input-group-sm > .form-select, .input-group-sm > .btn, .input-group-sm > .input-group-text {
    min-height: 32px;
    padding-top: .25rem;
    padding-bottom: .25rem;
}
.form-control-lg, .form-select-lg, .btn-lg { min-height: 46px; }
textarea.form-control { height: auto; }
.btn { display: inline-flex; align-items: center; justify-content: center; }

/* ============================================================
   DASHLITE .gap-N CLASH FIX (18-Aug). DashLite ships .gap-1..5
   as fixed-HEIGHT spacer utilities (.gap-2 {height:.75rem}), not
   Bootstrap 5 flex gaps. Any .d-flex.gap-N row therefore collapsed
   to ~12px tall and its buttons overlaid the content below (Tom's
   screenshot, job Money tab). Restore real flex-gap semantics when
   gap-N sits on a flex container; standalone DashLite spacers are
   untouched.
   ============================================================ */
.d-flex.gap-1, .d-inline-flex.gap-1 { height: auto; gap: .25rem; }
.d-flex.gap-2, .d-inline-flex.gap-2 { height: auto; gap: .5rem; }
.d-flex.gap-3, .d-inline-flex.gap-3 { height: auto; gap: 1rem; }
.d-flex.gap-4, .d-inline-flex.gap-4 { height: auto; gap: 1.5rem; }
.d-flex.gap-5, .d-inline-flex.gap-5 { height: auto; gap: 3rem; }

/* ============================================================
   ORG SWITCHER (Stage 1, polished 19-Aug per Tom): clean pill
   button in the header + left-aligned rounded dropdown.
   ============================================================ */
.jn-org-btn { display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px; border: 1px solid #e0e3e9;
    border-radius: 10px; background: #fff; color: var(--jn-charcoal, #33383e); font-size: .85rem; font-weight: 600; }
.jn-org-btn:hover, .jn-org-btn:focus { border-color: var(--jn-orange, #F26A21); color: var(--jn-orange, #F26A21); }
.jn-org-btn .icon { font-size: 1rem; }
.jn-org-menu { min-width: 280px; padding: 8px; border-radius: 12px; border: 1px solid #e4e7ec;
    box-shadow: 0 10px 30px rgba(20, 25, 38, .12); }
.jn-org-head { font-size: .68rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: #8a93a2; padding: 4px 10px 8px; }
.jn-org-item { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; border: 0;
    background: transparent; padding: 9px 10px; border-radius: 8px; font-size: .88rem; color: var(--jn-charcoal, #33383e); }
.jn-org-item:hover { background: #f6f7f9; }
.jn-org-item.active { background: #fdf3ec; color: var(--jn-orange, #F26A21); font-weight: 700; }
.jn-org-item .icon { font-size: 1.05rem; color: inherit; }

/* ============================================================
   WEEK (HOURS) DISPATCH TIMELINE (19-Aug): engineers pinned left,
   one horizontal band of days x hours, scrolled to today.
   ============================================================ */
.jn-tl { display: flex; align-items: stretch; }
.jn-tl-names { flex: 0 0 150px; border-right: 2px solid #e4e7ec; background: #fff; z-index: 6; }
.jn-tl-corner { height: 54px; display: flex; align-items: flex-end; padding: 6px 12px; font-size: .68rem;
    font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: #8a93a2; border-bottom: 1px solid #e4e7ec; }
.jn-tl-name { display: flex; align-items: center; padding: 0 12px; font-size: .82rem; font-weight: 600;
    color: var(--jn-charcoal, #33383e); border-bottom: 1px solid #eceff3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jn-tl-scroll { overflow-x: auto; flex: 1 1 auto; }
.jn-tl-canvas { position: relative; }
.jn-tl-days { display: flex; height: 26px; }
.jn-tl-day { flex: 0 0 auto; font-size: .72rem; font-weight: 700; color: #6a7180; padding: 5px 8px;
    border-left: 2px solid #d7dbe2; border-bottom: 1px solid #eceff3; background: #f7f8fa; position: sticky; }
.jn-tl-day.today { color: var(--jn-orange, #F26A21); background: #fdf3ec; }
.jn-tl-day.wkend { background: #f1f2f5; }
.jn-tl-hours { display: flex; height: 28px; border-bottom: 1px solid #e4e7ec; }
.jn-tl-hour { flex: 0 0 auto; font-size: .62rem; color: #9aa2af; padding: 8px 0 0 4px; border-left: 1px solid #eef0f3; }
.jn-tl-hour.daystart { border-left: 2px solid #d7dbe2; }
.jn-tl-row { position: relative; border-bottom: 1px solid #eceff3; cursor: copy; }
.jn-tl-daybg { position: absolute; top: 0; bottom: 0; border-left: 2px solid #d7dbe2; pointer-events: none; }
.jn-tl-daybg.today { background: rgba(242, 106, 33, .045); }
.jn-tl-daybg.wkend { background: rgba(20, 25, 38, .03); }
.jn-tl-row .blk { position: absolute; font-size: .64rem; line-height: 1.15; display: flex; flex-direction: column;
    justify-content: center; align-items: flex-start; gap: 1px;
    padding: 3px 6px; border-radius: 6px; border: 1px solid var(--jn-orange, #F26A21); background: var(--jn-orange-light, #fdf0e8);
    color: #7a4a24; text-decoration: none; overflow: hidden; white-space: nowrap; }
.jn-tl-row .blk.onsite { background: #fff6e0; border-color: #d9a400; }
.jn-tl-row .blk.done { background: #e8f7ef; border-color: #14804a; color: #14804a; }
/* match the Gantt cards: name + address stacked under the time/job-number line,
   each clipped to its block width so a long address can't blow the card out */
.jn-tl-row .blk .blk-l2, .jn-tl-row .blk .blk-l3 { display: block; max-width: 100%;
    font-size: .62rem; font-weight: 400; opacity: .9; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jn-tl-row .blk .blk-l3 { opacity: .72; }

/* Schedule hover card (Tom 01-Oct): blocks overlap and get cramped, so hovering
   a job shows the full detail without clicking in. One floating card, fed from a
   <template> inside each block; shared by every schedule view. pointer-events are
   off so moving the mouse never lands on the card and flickers it. */
.jn-schpop-pop { position: fixed; z-index: 1095; width: 268px; max-width: 90vw; pointer-events: none;
    background: #fff; border: 1px solid #e4e7ec; border-radius: 10px; box-shadow: 0 12px 34px rgba(20, 25, 38, .18);
    padding: 11px 13px; font-size: .78rem; color: #2b3038; line-height: 1.35; opacity: 0;
    transform: translateY(3px); transition: opacity .1s ease, transform .1s ease; }
.jn-schpop-pop.show { opacity: 1; transform: translateY(0); }
.jn-schpop-h { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; }
.jn-schpop-ref { font-weight: 700; font-size: .86rem; color: #1b1f26; }
.jn-schpop-org { font-size: .64rem; font-weight: 600; text-transform: uppercase; letter-spacing: .02em;
    color: #8a5a2a; background: #fdf0e8; border: 1px solid #f3cdae; border-radius: 10px; padding: 1px 7px; }
.jn-schpop-st { margin-left: auto; font-size: .64rem; font-weight: 700; border-radius: 10px; padding: 1px 8px; }
.jn-schpop-name { font-weight: 600; font-size: .82rem; color: #1b1f26; margin-bottom: 6px; }
.jn-schpop-rows > div { display: flex; align-items: flex-start; gap: 7px; margin: 3px 0; }
.jn-schpop-rows .icon { flex: 0 0 auto; width: 14px; margin-top: 1px; color: #9aa0ab; font-size: .82rem; }
.jn-schpop-rows span { min-width: 0; }
.jn-schpop-desc { margin-top: 7px; padding-top: 7px; border-top: 1px dashed #eceff3; color: #5a616c; }
.jn-schpop-foot { margin-top: 8px; font-size: .68rem; color: #9aa0ab; }

/* Pinned card (Tom 06-Oct): a clicked card stays put and takes clicks, so the
   office can open or unbook the job straight from the board. The hover card
   stays pointer-events:none so it never flickers; only the pinned one is live. */
.jn-schpop-pop.pinned { pointer-events: auto; padding-top: 13px;
    box-shadow: 0 16px 42px rgba(20, 25, 38, .26); border-color: #d4d9e1; }
.jn-schpop-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px;
    padding-top: 9px; border-top: 1px solid #eceff3; }
.jn-schpop-acts .btn { flex: 1 1 auto; display: inline-flex; align-items: center;
    justify-content: center; gap: 5px; font-size: .74rem; padding: 5px 9px; white-space: nowrap; }
.jn-schpop-acts .btn .icon { font-size: .86rem; }
.jn-schpop-x { position: absolute; top: 5px; right: 6px; width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center; padding: 0;
    border: 0; background: transparent; color: #9aa0ab; border-radius: 6px; cursor: pointer; }
.jn-schpop-x:hover { background: #f1f3f6; color: #4a5160; }

/* Unsaved-changes bar (#13, Siân 06-Oct): the old pill was easy to miss. Make it a
   prominent fixed bar with a one-click "Save now", and flash green to confirm the
   save landed. */
.jn-unsaved-bar {
    position: fixed; z-index: 1055; left: 50%; bottom: 20px; transform: translateX(-50%);
    max-width: 94vw; display: none; align-items: center; gap: 14px;
    background: #f4bd19; color: #26221b; padding: 11px 14px 11px 18px; border-radius: 12px;
    box-shadow: 0 8px 26px rgba(20, 25, 38, .28); font-size: .92rem; font-weight: 600;
    border: 1.5px solid #e0a800;
}
.jn-unsaved-bar .jn-unsaved-msg { display: flex; align-items: center; }
.jn-unsaved-bar .jn-unsaved-msg::before {
    content: ""; flex: 0 0 auto; width: 9px; height: 9px; margin-right: 9px; border-radius: 50%;
    background: #c0392b; box-shadow: 0 0 0 3px rgba(192, 57, 43, .22); animation: jnUnsavedPulse 1.4s ease-in-out infinite;
}
.jn-unsaved-bar .jn-unsaved-save {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    background: #26221b; color: #fff; border: 0; border-radius: 8px; padding: 7px 14px;
    font-size: .88rem; font-weight: 600; white-space: nowrap;
}
.jn-unsaved-bar .jn-unsaved-save:hover { background: #000; }
.jn-unsaved-bar.is-saved { background: #e8f7ef; color: #14804a; border-color: #8fd9b0; }
.jn-unsaved-bar.is-saved .jn-unsaved-msg::before { display: none; }
@keyframes jnUnsavedPulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }
@media (max-width: 560px) { .jn-unsaved-bar { left: 12px; right: 12px; transform: none; max-width: none; } }

/* Settings "Save Settings" saved-confirmation flash (#13): the button goes green
   "Saved" briefly so the office sees the save landed, not just a passing toast. */
.btn.jn-saved-ok, .btn.jn-saved-ok:hover { background: #14804a !important; border-color: #14804a !important; color: #fff !important; }

/* Bill grid one-line fix (#5, Tom 06-Oct): the 10-column bill table squeezed its
   cells onto two lines on a normal-width screen once the cost/financials columns
   were added. Keep every row on a single line; the .table-responsive wrapper lets
   it scroll sideways only if it genuinely runs out of width. */
.jn-billgrid { white-space: nowrap; }
.jn-billgrid th, .jn-billgrid td { vertical-align: middle; }
.jn-billgrid td .badge { vertical-align: baseline; }

/* Costing grid (Stage 2): internal (non-billable) lines sit in the same table
   but read as "our side only" - muted, so the customer-facing rows stand out */
.jn-line-internal td { background: #f7f8fa; color: #8a919e; }
.jn-line-internal td .badge { opacity: .85; }

/* ---- Report requirement picker (Stage 4) --------------------------------
   Big, obvious tick cards instead of a run of small checkboxes - Tom, 26-Aug:
   the list "got lost in the motion". The native input stays in the DOM for
   form submission but is visually hidden; the label is the control. */
.jn-tplgrid { display: flex; flex-wrap: wrap; gap: 10px; }
.jn-tpl-cb { position: absolute; opacity: 0; width: 0; height: 0; }
.jn-tpl {
    display: flex; align-items: center; gap: 12px; cursor: pointer;
    min-width: 240px; padding: 12px 16px 12px 12px;
    border: 1.5px solid #e3e7ee; border-radius: 10px; background: #fff;
    transition: border-color .12s, background .12s, box-shadow .12s;
}
.jn-tpl:hover { border-color: var(--jn-orange); background: #fffaf7; }
.jn-tpl-tick {
    flex: 0 0 32px; height: 32px; border-radius: 8px;
    border: 1.5px solid #dfe4ec; background: #f6f8fa; color: transparent;
    display: flex; align-items: center; justify-content: center; font-size: 1rem;
    transition: background .12s, border-color .12s, color .12s;
}
.jn-tpl-txt { display: flex; flex-direction: column; line-height: 1.25; }
.jn-tpl-name { font-weight: 600; color: #33383e; }
.jn-tpl-sub { font-size: .78rem; color: #8a94a6; }
.jn-tpl-cb:checked + .jn-tpl { border-color: var(--jn-orange); background: var(--jn-orange-light); box-shadow: 0 1px 4px rgba(242,106,33,.16); }
.jn-tpl-cb:checked + .jn-tpl .jn-tpl-tick { background: var(--jn-orange); border-color: var(--jn-orange); color: #fff; }
.jn-tpl-cb:checked + .jn-tpl .jn-tpl-sub { color: #b4643c; }
.jn-tpl-cb:focus-visible + .jn-tpl { outline: 2px solid var(--jn-orange); outline-offset: 2px; }

/* ---- Attachment sharing control ---------------------------------------- */
.jn-share { display: flex; align-items: center; gap: 8px; }
.jn-share form { margin: 0; }

/* ---- Taller notification dropdown (Tom, 26-Aug) -------------------------
   Dashlite caps .dropdown-menu at 416px AND .nk-notification at 239px, so an
   inline max-height on the body did nothing. Both have to be lifted, scoped to
   the bell menu so other dropdowns keep the theme's sizing. */
.dropdown-menu.jn-notif-menu { max-height: none; overflow: visible; }
.dropdown-menu.jn-notif-menu .nk-notification { max-height: none; overflow: visible; }
.dropdown-menu.jn-notif-menu .dropdown-body.jn-notif-body { max-height: min(70vh, 640px); overflow-y: auto; }

/* ---- Job lifecycle strip (Stage 4) -------------------------------------- */
.jn-lifecycle { display: flex; align-items: center; gap: 0; flex-wrap: wrap; }
.jn-lc-step { display: flex; align-items: center; gap: 8px; padding: 4px 18px 4px 0; margin-right: 18px; position: relative; color: #97a1b0; }
.jn-lc-step:not(:last-child)::after {
    content: ''; position: absolute; right: 0; top: 50%; width: 18px; height: 2px;
    background: #e3e7ee; transform: translateY(-50%);
}
.jn-lc-step.is-done:not(:last-child)::after { background: var(--jn-orange); }
.jn-lc-dot {
    flex: 0 0 26px; height: 26px; border-radius: 50%; background: #f1f3f7; color: #97a1b0;
    display: flex; align-items: center; justify-content: center; font-size: .78rem; font-weight: 600;
}
.jn-lc-step.is-done .jn-lc-dot { background: var(--jn-orange); color: #fff; }
.jn-lc-step.is-done { color: #33383e; }
.jn-lc-step.is-now .jn-lc-label { font-weight: 600; }
.jn-lc-step.is-now .jn-lc-dot { box-shadow: 0 0 0 3px rgba(242,106,33,.18); }
.jn-lc-label { font-size: .84rem; }

/* ---- Coordinator "My work" buckets (Stage 4) ---------------------------- */
.jn-bucket { border: 1px solid #e5e9f0; border-radius: 10px; padding: 12px 14px; height: 100%; background: #fff; }
.jn-bucket-head { display: flex; align-items: center; gap: 8px; }
.jn-bucket-head .icon { font-size: 1.05rem; }
.jn-bucket-title { font-weight: 600; font-size: .88rem; color: #33383e; flex: 1; }
.jn-bucket-note { font-size: .74rem; color: #97a1b0; margin: 2px 0 8px; line-height: 1.35; }
.jn-bucket-row {
    display: flex; justify-content: space-between; gap: 8px; padding: 5px 0;
    border-top: 1px solid #f1f3f7; font-size: .82rem; text-decoration: none; color: #33383e;
}
.jn-bucket-row:hover { color: var(--jn-orange); }
.jn-bucket-more { font-size: .74rem; color: #97a1b0; padding-top: 5px; }

/* ---- Dashboard tiles + aged receivables (Stage 4, two dashboards) -------- */
.jn-tile { text-decoration: none; color: inherit; border-top: 3px solid #e5e9f0 !important; transition: box-shadow .12s, transform .12s; }
.jn-tile:hover { box-shadow: 0 3px 14px rgba(51,56,62,.09); transform: translateY(-1px); color: inherit; }
.jn-tile-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.jn-tile-val { font-size: 1.9rem; font-weight: 700; line-height: 1.05; color: #33383e; }
.jn-tile-label { font-size: .84rem; color: #5c6672; font-weight: 500; margin-top: 2px; }
.jn-tile-note { font-size: .74rem; color: #97a1b0; margin-top: 8px; line-height: 1.35; }
.jn-tile-ico { width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center; font-size: 1rem; flex: 0 0 34px; }
.jn-tile-danger  { border-top-color: #e85347 !important; } .jn-tile-danger  .jn-tile-ico { background: #fdeceb; color: #e85347; }
.jn-tile-warning { border-top-color: #f4bd0e !important; } .jn-tile-warning .jn-tile-ico { background: #fdf6e0; color: #c99a06; }
.jn-tile-success { border-top-color: #1ee0ac !important; } .jn-tile-success .jn-tile-ico { background: #e4faf3; color: #12a97f; }
.jn-tile-primary { border-top-color: var(--jn-orange) !important; } .jn-tile-primary .jn-tile-ico { background: var(--jn-orange-light); color: var(--jn-orange); }
.jn-tile-info    { border-top-color: #559bfb !important; } .jn-tile-info    .jn-tile-ico { background: #e9f2fe; color: #2f7fe0; }

.jn-mini { display: block; border: 1px solid #eceff3; border-radius: 8px; padding: 8px 10px; text-decoration: none; }
.jn-mini:hover { border-color: var(--jn-orange); }
.jn-mini-val { display: block; font-size: 1.15rem; font-weight: 700; color: #33383e; line-height: 1.1; }
.jn-mini-lbl { display: block; font-size: .72rem; color: #8a94a6; }

.jn-aged { display: flex; align-items: flex-end; gap: 14px; height: 210px; padding-top: 6px; }
.jn-aged-col { flex: 1; display: flex; flex-direction: column; align-items: center; height: 100%; }
.jn-aged-amt { font-size: .76rem; font-weight: 600; color: #5c6672; margin-bottom: 4px; }
.jn-aged-track { flex: 1; width: 100%; display: flex; align-items: flex-end; background: linear-gradient(#f7f9fb, #f7f9fb) no-repeat; border-radius: 5px; }
.jn-aged-bar { width: 100%; border-radius: 5px 5px 0 0; min-height: 3px; }
.jn-aged-lbl { font-size: .74rem; color: #8a94a6; margin-top: 6px; text-align: center; }
.jn-aged-notyetdue { background: #559bfb; }
.jn-aged-0-30      { background: #f4bd0e; }
.jn-aged-31-60     { background: #f2884b; }
.jn-aged-61-90     { background: #e85347; }
.jn-aged-91plus    { background: #a1232b; }

/* ---- Schedule toolbar (Tom, 26-Aug: the nav/view buttons "looked a bit messy")
   One row, three tidy groups - date nav, view switcher, filters - with the
   action pushed to the right. Wraps sensibly rather than fragmenting. */
.jn-sched-toolbar {
    background: #fff; border: 1px solid #e5e9f0; border-radius: 10px;
    padding: 10px 12px; margin-bottom: 16px;
}
.jn-sched-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-start; }
.jn-sched-bar .jn-sched-sep { width: 1px; align-self: stretch; background: #e9edf3; margin: 0 2px; }
.jn-sched-bar .btn-group .btn { display: inline-flex; align-items: center; gap: 4px; }
.jn-sched-filters { display: flex; gap: 6px; margin: 0; }
.jn-sched-filters .form-select { min-width: 148px; }
.jn-sched-action { margin-left: auto; }
@media (max-width: 991px) {
    .jn-sched-action { margin-left: 0; }
    .jn-sched-filters .form-select { min-width: 130px; }
}
/* Phone: the view switcher (Gantt / Week / Month / Office) is wider than the
   screen as one connected pill, so "Office" fell off the edge. Let it wrap into
   its own chips, fully reachable (Tom, 01-Oct mobile pass). */
@media (max-width: 575.98px) {
    .jn-sched-bar .btn-group[aria-label="Choose a view"] { flex-wrap: wrap; gap: 6px; }
    .jn-sched-bar .btn-group[aria-label="Choose a view"] .btn { margin-left: 0; border-radius: 6px; }
    .jn-sched-filters, .jn-sched-filters .form-select { width: 100%; }
}
/* Mobile header (Tom, 01-Oct mobile pass): the wordmark logo was wide enough to
   push the notification bell and the user menu off the right edge - the user
   menu became unreachable and the bell sat flush to the edge. Cap the mobile
   logo so the header tools always sit comfortably inside the screen. */
@media (max-width: 767.98px) {
    .nk-header-brand.d-xl-none .logo-img { max-height: 26px; width: auto; }
    .nk-header .nk-header-wrap { column-gap: 6px; }
    .nk-header-tools { margin-left: auto; }
    .nk-quick-nav > li { padding-left: 2px; padding-right: 2px; }
}
/* Narrow phones (≤575): a little tighter still so the user menu + bell never
   reach the edge even on an iPhone SE-width screen. */
@media (max-width: 575.98px) {
    .nk-header-brand.d-xl-none .logo-img { max-height: 22px; }
    .jn-org-btn { gap: 4px; padding: 6px 9px; }
}
/* Tablet portrait (md, 768-991): here the quick-action button LABELS and the
   full company name both switch on, but an iPad-portrait viewport is still too
   narrow for all of it, so the bell + user menu were pushed off the right edge.
   Keep the logo small and the header actions icon-only through this range; the
   full labels come back at lg (Tom, 01-Oct iPad check). */
@media (min-width: 768px) and (max-width: 991.98px) {
    .nk-header-brand.d-xl-none .logo-img { max-height: 26px; width: auto; }
    .nk-header-news .btn span { display: none !important; }
    .nk-header-news .btn { padding-left: .55rem; padding-right: .55rem; }
    .jn-org-btn span.d-md-inline { display: none !important; }
}

/* Inactive view buttons were washing out against the white page and reading as
   disabled (Tom couldn't find the Gantt button at all). Give them a real border
   and readable text so the whole switcher looks clickable. */
.jn-sched-bar .btn-outline-light { border-color: #dbe0e8; color: #4a5361; background: #fff; }
.jn-sched-bar .btn-outline-light:hover { border-color: var(--jn-orange); color: var(--jn-orange); background: #fffaf7; }

/* ---- Job map (dashboard) ------------------------------------------------ */
.jn-jobmap { height: 380px; border-radius: 8px; border: 1px solid #e5e9f0; z-index: 0; }
.jn-maplegend { display: flex; gap: 16px; margin-top: 8px; font-size: .76rem; color: #8a94a6; }
.jn-maplegend i { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 5px; vertical-align: middle; }
.leaflet-popup-content { font-size: .82rem; line-height: 1.45; }

/* Dashlite sets a global `svg { height:100%; max-width:100% }`. Leaflet's overlay
   pane has no height of its own, so that collapsed the marker SVG to 0px and
   every pin vanished while the tiles rendered fine (Tom, 26-Aug: "the map isn't
   showing the plots, it's just a map"). Let the SVG use its own width/height
   attributes inside a map. */
.leaflet-container svg,
.leaflet-container img { height: auto; max-width: none; }

/* ---- Email attachment picker (Stage 5) ---------------------------------- */
.jn-attachbox { border: 1px solid #e5e9f0; border-radius: 8px; padding: 10px 12px; background: #fbfcfd; }
.jn-attachbox-head { display: flex; justify-content: space-between; align-items: center; font-size: .8rem; font-weight: 600; color: #4a5361; margin-bottom: 4px; }
.jn-attachrow { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: .84rem; cursor: pointer; }
.jn-attachrow input { margin: 0; }
.jn-attachname { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jn-attachsize { color: #98a1b0; font-size: .74rem; white-space: nowrap; }
.jn-attachnote { font-size: .74rem; color: #8a94a6; margin-top: 6px; line-height: 1.4; }
.jn-attachnote.over { color: #b5761f; background: #fdf6e0; border-radius: 6px; padding: 6px 8px; }

/* ---- Row actions on editable line tables --------------------------------
   The edit and remove buttons were stacking (the delete sat in its own form,
   which breaks out of the inline flow) and looked like two unrelated controls.
   One flex pair, matched squares, quiet until you hover the row. */
.jn-rowact { display: flex; gap: 4px; justify-content: flex-end; align-items: center; }
.jn-rowact form { margin: 0; display: flex; }
.jn-rowact-btn {
    width: 26px; height: 26px; padding: 0; border-radius: 6px; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid #e3e7ee; background: #fff; color: #8a94a6; font-size: .82rem;
    transition: color .12s, border-color .12s, background .12s;
}
.jn-rowact-btn:hover { color: var(--jn-orange); border-color: var(--jn-orange); background: #fffaf7; }
.jn-rowact-btn.danger:hover { color: #e85347; border-color: #e85347; background: #fdeceb; }
tr:hover > td > .jn-rowact .jn-rowact-btn { border-color: #d6dce6; }

/* ---- Fleet renewals: "coming up" chips ---------------------------------- */
.jn-duewrap { display: flex; flex-wrap: wrap; gap: 8px; }
.jn-duechip {
    display: inline-flex; align-items: baseline; gap: 6px; text-decoration: none;
    border: 1px solid #f0d9b8; background: #fdf6e0; color: #7a5a12;
    border-radius: 20px; padding: 5px 12px; font-size: .78rem;
}
.jn-duechip strong { color: #33383e; font-weight: 600; }
.jn-duechip span { color: #b5761f; }
.jn-duechip:hover { border-color: var(--jn-orange); }
.jn-duechip.late { background: #fdeceb; border-color: #f3c7c3; color: #a33228; }
.jn-duechip.late span { color: #c0392b; font-weight: 600; }
.jn-item .jn-ico.danger { background: #fdeceb; color: #e85347; }

/* ---- Contact type-ahead (tasks, global search) -------------------------- */
.jn-cs-results { position: absolute; z-index: 1050; left: 8px; right: 8px; top: 100%; background: #fff;
    border: 1px solid #e3e7ee; border-radius: 8px; box-shadow: 0 8px 24px rgba(20,25,38,.14); overflow: hidden; }
.jn-cs-item { display: block; width: 100%; text-align: left; border: 0; background: #fff; padding: 8px 12px; cursor: pointer; }
.jn-cs-item:hover { background: #fffaf7; }
.jn-cs-item strong { display: block; font-size: .84rem; color: #33383e; }
.jn-cs-item span { display: block; font-size: .74rem; color: #98a1b0; }

/* ---- Global search (Stage 9) -------------------------------------------- */
.jn-gs-results { position: absolute; z-index: 1060; left: 0; right: 0; top: calc(100% + 6px); background: #fff;
    border: 1px solid #e3e7ee; border-radius: 10px; box-shadow: 0 12px 32px rgba(20,25,38,.16);
    max-height: min(70vh, 520px); overflow-y: auto; padding: 4px 0; }
.jn-gs-group { font-size: .68rem; letter-spacing: 1px; text-transform: uppercase; color: #98a1b0;
    padding: 8px 14px 3px; font-weight: 700; }
.jn-gs-row { display: block; padding: 6px 14px; text-decoration: none; }
.jn-gs-row:hover { background: #fffaf7; }
.jn-gs-row strong { display: block; font-size: .84rem; color: #33383e; font-weight: 600; }
.jn-gs-row span { display: block; font-size: .74rem; color: #98a1b0; }

/* ---- Address lookup control -------------------------------------------- */
.jn-addr-wrap { margin-top: 6px; }
.jn-addr-find { white-space: nowrap; }

/* ---------------------------------------------------------------------------
   Style guard - even spacing, nothing clipped.
   TinyMCE replaces the textarea with its own wrapper, so the mb-2 sitting on
   the textarea never applied and the Save button ended up flush against the
   editor (Internal notes, Scope of works, job report answers).
   --------------------------------------------------------------------------- */
.tox-tinymce { margin-bottom: 0.75rem; }

/* A form action button never touches the control above it. Scoped to buttons
   that actually FOLLOW an input - "any last button in a form" was too broad and
   was knocking icon buttons out of line with their neighbours. */
.tox-tinymce + .btn,
textarea + .btn,
select + .btn { margin-top: 0.25rem; }

/* Selects must fit their longest option - "Labour", not "Lab". */
table .form-select-sm { min-width: 7.5rem; }

/* Money inputs must show the whole figure, not "350" for 3500.00. */
table .input-group-sm > .form-control[inputmode="decimal"] { min-width: 5.5rem; }

/* A form that wraps a single button inside a flex row: without this the form is
   the flex item, not the button, and its own box height knocks the button a few
   pixels out of line with its neighbours. display:contents makes the button a
   direct sibling of the others, so icon buttons always sit level. */
.jn-contents { display: contents; }

/* ---------------------------------------------------------------------------
   Schedule day board - resource rows, hour columns, jump strip.
   --------------------------------------------------------------------------- */
.jn-daystrip { display: flex; align-items: stretch; gap: 2px; padding: 8px 10px;
    border-bottom: 1px solid #eceff3; flex-wrap: wrap; }
.jn-daystrip > .ms-auto { flex: 0 0 auto; }
.jn-daystrip .ds { flex: 1 1 0; min-width: 44px; text-align: center; padding: 4px 0 5px; border-radius: 6px;
    text-decoration: none; color: var(--jn-charcoal); border: 1px solid transparent; position: relative; }
.jn-daystrip .ds:hover { background: #f4f6f9; }
.jn-daystrip .ds.wknd { color: #9aa2af; }
.jn-daystrip .ds.sel { background: var(--jn-orange); border-color: var(--jn-orange); color: #fff; }
.jn-daystrip .ds .dow { display: block; font-size: .62rem; letter-spacing: .5px; text-transform: uppercase; }
.jn-daystrip .ds .dom { display: block; font-size: .95rem; font-weight: 600; line-height: 1.1; }
.jn-daystrip .ds .dot { position: absolute; left: 50%; bottom: 2px; transform: translateX(-50%);
    width: 4px; height: 4px; border-radius: 50%; background: var(--jn-orange); }
.jn-daystrip .ds.sel .dot { background: #fff; }

/* Left column carries the day's load, so a dispatcher can see who has room. */
.jn-gantt .eng-name { display: flex; flex-direction: column; justify-content: center; gap: 2px; }
.jn-gantt .eng-meta { font-size: .68rem; font-weight: 400; color: #6a7080; display: flex; gap: 8px; }
.jn-gantt .eng-meta .icon { font-size: .7rem; }

/* Taller blocks earn a second and third line rather than truncating. */
.jn-gantt .blk .blk-l2, .jn-gantt .blk .blk-l3 { display: block; font-size: .66rem; opacity: .85;
    line-height: 1.25; overflow: hidden; text-overflow: ellipsis; }
.jn-gantt-h2 .blk, .jn-gantt-h3 .blk,
.jn-gantt-h4 .blk, .jn-gantt-h5 .blk { white-space: normal; }

/* ---------------------------------------------------------------------------
   Searchable dropdown - shows everything on click, filters as you type.
   The native <select> stays in the DOM (and keeps posting) but is hidden once
   the combo takes over, so the form works with or without JS.
   --------------------------------------------------------------------------- */
.jn-combo { position: relative; }
.jn-combo .jn-combo-native { position: absolute; opacity: 0; pointer-events: none; height: 0; width: 0; }
.jn-combo-list { position: absolute; z-index: 1000; left: 0; right: 0; top: calc(100% + 2px);
    max-height: 260px; overflow-y: auto; background: #fff; border: 1px solid #dbdfea;
    border-radius: 4px; box-shadow: 0 6px 18px rgba(43,55,72,.14); padding: 4px; }
.jn-combo-item { display: block; width: 100%; text-align: left; border: 0; background: none;
    padding: 7px 10px; border-radius: 4px; font-size: .875rem; color: var(--jn-charcoal); }
.jn-combo-item:hover { background: #f4f6f9; }
.jn-combo-item.is-on { background: var(--jn-orange-light); font-weight: 500; }
.jn-combo-empty { padding: 10px; color: #8a93a2; font-size: .8125rem; }

/* Dragging a booked job onto another engineer or time. */
.jn-gantt .blk.jn-drag { cursor: grab; }
.jn-gantt .blk.jn-drag:active { cursor: grabbing; }
/* While dragging: the row is only faintly marked (that tells you WHO), and the
   ghost shows exactly WHERE and at what time it will land (Tom, 03-Sep). */
.jn-gantt .eng-track.is-drop { box-shadow: inset 3px 0 0 var(--jn-orange); }
.jn-gantt .jn-drop-ghost { position: absolute; top: 3px; bottom: 3px; z-index: 40;
    background: rgba(242, 106, 33, .18); border: 2px solid var(--jn-orange); border-radius: 6px;
    pointer-events: none; }
/* The time sits in a solid pill above the slot, clear of whatever is underneath. */
.jn-gantt .jn-drop-time { position: absolute; left: 0; top: -20px; z-index: 41;
    background: var(--jn-orange); color: #fff; font-size: .68rem; font-weight: 700;
    padding: 2px 7px; border-radius: 4px; white-space: nowrap; line-height: 1.4;
    box-shadow: 0 2px 6px rgba(20, 25, 38, .25); }
/* Week (hours) timeline: same drop ghost + time pill, positioned in pixels. */
.jn-tl-track .jn-drop-ghost { position: absolute; top: 2px; height: 26px; z-index: 40;
    background: rgba(242, 106, 33, .18); border: 2px solid var(--jn-orange); border-radius: 6px;
    pointer-events: none; }
.jn-tl-track .jn-drop-time { position: absolute; left: 0; top: -20px; z-index: 41;
    background: var(--jn-orange); color: #fff; font-size: .68rem; font-weight: 700;
    padding: 2px 7px; border-radius: 4px; white-space: nowrap; line-height: 1.4;
    box-shadow: 0 2px 6px rgba(20, 25, 38, .25); }
.jn-tl-track.is-drop { outline: 2px dashed var(--jn-orange); outline-offset: -2px; }

/* A block too narrow to read an address in keeps just the time and job number. */
.jn-gantt .blk.is-narrow .blk-l2,
.jn-gantt .blk.is-narrow .blk-l3 { display: none; }
.jn-gantt .blk.is-narrow { white-space: nowrap; }

/* Applied-filter chips (Tom, 05-Sep: "it looks too messy - we should have a
   toggle button like more filters then it shows the rest"). The panel now stays
   shut until you ask for it, so these say what is narrowing the list while it is
   closed. Each one clicks off. */
.jn-chips { display: flex; flex-wrap: wrap; align-items: center; gap: .375rem; margin-top: .75rem; }
.jn-chips-label { font-size: .75rem; color: #8a93a2; margin-right: .125rem; }
.jn-chip { display: inline-flex; align-items: center; gap: .5rem; padding: .1875rem .375rem .1875rem .625rem;
    border: 1px solid #e5e9f2; border-radius: 999px; background: #f5f6fa; font-size: .75rem; color: #526484; }
.jn-chip b { font-weight: 500; color: #364a63; }
.jn-chip a { display: inline-flex; width: 16px; height: 16px; align-items: center; justify-content: center;
    border-radius: 50%; color: #8a93a2; font-size: .8125rem; line-height: 1; text-decoration: none; }
.jn-chip a:hover { background: var(--jn-orange); color: #fff; }
.jn-chips .jn-chip-clear { font-size: .75rem; color: #8a93a2; text-decoration: underline; margin-left: .25rem; }
.jn-chips .jn-chip-clear:hover { color: var(--jn-orange); }
.jn-chips[hidden] { display: none; }

/* Global search box (Tom, 07-Sep: "needs a border on this search box you can't
   see it"). The Dashlite theme strips the border and background off it - that
   works on their dark header, but ours is white, so the field was invisible
   until you clicked in it. Give it the same edge as every other input. */
.nk-header-search .form-control {
    background-color: #fff;
    border: 1px solid #dbdfea;
    border-radius: 4px;
}
.nk-header-search .form-control:focus {
    border-color: var(--jn-orange);
    box-shadow: 0 0 0 3px rgba(242, 106, 33, .12);
}
/* The theme paints the magnifier white for a dark header - invisible on ours. */
.nk-header-search .form-icon .icon { color: #8091a7; }

/* Push-notifications enable banner - thin bar across the top of the engineer app. */
.jn-push-bar { position: fixed; top: 0; left: 0; right: 0; z-index: 1200;
    display: flex; align-items: center; gap: 10px; padding: 9px 12px;
    background: #33383e; color: #fff; font-size: .82rem; line-height: 1.35;
    box-shadow: 0 2px 10px rgba(20,25,38,.25); }
.jn-push-bar span { flex: 1 1 auto; }
.jn-push-bar .jn-push-enable { flex: 0 0 auto; background: var(--jn-orange,#F26A21); color: #fff;
    border: 0; border-radius: 6px; font-weight: 700; font-size: .8rem; padding: 6px 14px; cursor: pointer; }
.jn-push-bar .jn-push-x { flex: 0 0 auto; background: transparent; color: #fff; border: 0;
    font-size: 1.3rem; line-height: 1; padding: 0 4px; cursor: pointer; opacity: .8; }

/* ===== Engineer app - cleaner job page (Linda, 02-Oct meeting) ========== */
/* Expandable work description: clamp to 3 lines with a Read more toggle. */
.jn-eng-desc-body { overflow: hidden; }
.jn-eng-desc:not(.open) .jn-eng-desc-body {
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.jn-eng-desc-more { display: inline-block; margin-top: 6px; color: var(--jn-orange, #F26A21);
    font-weight: 600; font-size: .82rem; cursor: pointer; }
.jn-eng-desc.open .jn-eng-desc-more .more-lbl::after { content: 'Show less'; }
.jn-eng-desc:not(.open) .jn-eng-desc-more .more-lbl::after { content: 'Read more'; }

/* Job contacts popup (all contacts - site, customer, job, PM) */
.jn-cbtn { display: inline-flex; align-items: center; gap: 7px; }
.jn-cmodal { position: fixed; inset: 0; z-index: 1200; background: rgba(20,25,38,.45);
    display: none; align-items: flex-end; }
.jn-cmodal.open { display: flex; }
.jn-cmodal-card { background: #fff; width: 100%; max-height: 86vh; overflow-y: auto;
    border-radius: 16px 16px 0 0; padding: 16px 18px calc(24px + env(safe-area-inset-bottom)); }
.jn-cmodal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.jn-cmodal-head h6 { margin: 0; }
.jn-cmodal-x { border: 0; background: #f2f4f7; width: 30px; height: 30px; border-radius: 50%; font-size: 1rem; color: #5a6270; }
.jn-crow { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 12px 0; border-bottom: 1px solid #f0f3f7; }
.jn-crow:last-child { border-bottom: 0; }
.jn-crole { font-size: .66rem; text-transform: uppercase; color: #9aa3b2; letter-spacing: .03em; }
.jn-cname { font-weight: 600; color: #1b1f26; }
.jn-cacts { display: flex; flex: 0 0 auto; }
.jn-cacts a { display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
    margin-left: 16px; color: var(--jn-orange, #F26A21); font-size: .62rem; text-decoration: none; }
.jn-cacts a .icon { font-size: 1.2rem; }

/* Work history at this site */
.jn-hist-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
    padding: 10px 0; border-bottom: 1px solid #f0f3f7; }
.jn-hist-row:last-child { border-bottom: 0; }
.jn-hist-main { min-width: 0; }
.jn-hist-main .t { font-weight: 600; font-size: .86rem; color: #1b1f26; }
.jn-hist-main .d { color: #8a94a6; font-size: .74rem; }
.jn-hist-badge { flex: 0 0 auto; font-size: .64rem; }

/* Signature pad (engineer sign-off) */
.jn-sigwrap { border: 1.5px dashed #cfd6e0; border-radius: 10px; background: #fcfdff; }
.jn-sigpad { display: block; width: 100%; height: 150px; touch-action: none; border-radius: 10px; }

/* Entity tab strips (job page etc) stay on ONE line and scroll sideways rather than
   wrapping to two rows on narrower screens (Tom, 06-Oct). */
.jn-tabs-1line { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.jn-tabs-1line::-webkit-scrollbar { height: 4px; }
.jn-tabs-1line::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, .18); border-radius: 4px; }
.jn-tabs-1line .nav-item { flex: 0 0 auto; }
.jn-tabs-1line .nav-link { white-space: nowrap; }
