/* ==========================================================================
   devsoftuk ERP — brand theme and application components

   Loaded AFTER lib/bootstrap/css/bootstrap.min.css, which stays untouched so
   it can be swapped for a newer release without losing any customisation.

   Two kinds of override live here:
     1. Bootstrap CSS custom properties. Bootstrap 5.3 drives most of its
        surface from these, so redefining them on :root retints links, subtle
        backgrounds, .text-bg-*, alerts, borders, focus rings and type.
     2. Rules where Bootstrap bakes a literal hex at build time — the button
        variants, form focus states and checked controls. Those cannot be
        reached through :root and are restated explicitly below.

   Brand tokens (Part C1):
     blue #1a76d1   black #000    red #d32f2f   green #2e7d32   amber #b26a00
   Theme: navy #0b1f3a frames the product (sidebar, time panel, login); pages are
   white cards with soft shadows on #f4f7fb, with slate text (#172033 / #475569 / #64748b).
   Red carries exactly one meaning across the product — "act now": overdue,
   over estimate, absent, rejected, expired, low stock. Never decoration.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Brand tokens
   -------------------------------------------------------------------------- */

:root {
  --dsu-blue: #1a76d1;
  --dsu-blue-hover: #1664b2;   /* Bootstrap's 15% shade of the base */
  --dsu-blue-active: #145ea8;  /* 20% shade */
  --dsu-blue-light: #e8f1fb;
  --dsu-blue-tint: #cfe0f5;

  --dsu-black: #000000;

  /* Navy: the frame of the product (sidebar, time panel, login). Deep enough that white
     and pale-blue text on it clear 4.5:1 with room to spare. */
  --dsu-navy: #0b1f3a;
  --dsu-navy-2: #0f2a4d;
  --dsu-navy-3: #16406f;

  /* Slate text scale: softer than pure greys, and every step readable on white. */
  --dsu-ink: #172033;
  --dsu-ink-2: #475569;
  --dsu-ink-3: #64748b;
  --dsu-line: #e2e8f0;
  --dsu-line-strong: #cbd5e1;
  --dsu-bg: #f4f7fb;
  --dsu-surface-2: #f8fafc;

  /* Depth: quiet by default, a little more on hover and for floating menus. */
  --dsu-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05);
  --dsu-shadow: 0 1px 3px rgba(15, 23, 42, 0.06), 0 6px 16px -8px rgba(15, 23, 42, 0.10);
  --dsu-shadow-lg: 0 18px 40px -16px rgba(15, 23, 42, 0.28);

  --dsu-red: #d32f2f;
  --dsu-red-light: #fdecec;

  --dsu-green: #2e7d32;
  --dsu-green-light: #e8f5e9;

  --dsu-amber: #b26a00;
  --dsu-amber-light: #fff4e0;

  --dsu-sidebar-width: 240px;
  --dsu-topbar-height: 58px;
}

/* --------------------------------------------------------------------------
   2. Bootstrap custom properties
   -------------------------------------------------------------------------- */

:root {
  /* Type — IBM Plex Sans for text, Plex Mono for codes, times and amounts. */
  --bs-font-sans-serif: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --bs-font-monospace: "IBM Plex Mono", ui-monospace, "Cascadia Mono", monospace;
  --bs-body-font-family: var(--bs-font-sans-serif);
  --bs-body-font-size: 0.875rem;         /* 14px */
  --bs-body-color: var(--dsu-ink);
  --bs-body-color-rgb: 23, 32, 51;
  --bs-body-bg: var(--dsu-bg);
  --bs-body-bg-rgb: 244, 247, 251;
  --bs-emphasis-color: var(--dsu-ink);
  --bs-heading-color: var(--dsu-ink);

  /* Secondary and tertiary text: slate, and solid rather than Bootstrap's half-transparent
     black, so .text-body-tertiary stays above 4.5:1 on white and on the page. */
  --bs-secondary-color: var(--dsu-ink-2);
  --bs-secondary-color-rgb: 71, 85, 105;
  --bs-tertiary-color: var(--dsu-ink-3);
  --bs-tertiary-color-rgb: 100, 116, 139;
  --bs-secondary-bg: #eef2f7;
  --bs-tertiary-bg: var(--dsu-surface-2);

  /* Shape */
  --bs-border-radius: 8px;
  --bs-border-radius-sm: 6px;
  --bs-border-radius-lg: 12px;
  --bs-border-radius-xl: 16px;
  --bs-border-color: var(--dsu-line);
  --bs-border-color-translucent: var(--dsu-line);
  --bs-box-shadow-sm: var(--dsu-shadow-sm);
  --bs-box-shadow: var(--dsu-shadow);
  --bs-box-shadow-lg: var(--dsu-shadow-lg);

  /* Primary — drives .text-bg-primary, .alert-primary, .bg-primary, borders */
  --bs-primary: var(--dsu-blue);
  --bs-primary-rgb: 26, 118, 209;
  --bs-primary-text-emphasis: var(--dsu-blue-active);
  --bs-primary-bg-subtle: var(--dsu-blue-light);
  --bs-primary-border-subtle: var(--dsu-blue-tint);

  /* Danger — the one "act now" colour */
  --bs-danger: var(--dsu-red);
  --bs-danger-rgb: 211, 47, 47;
  --bs-danger-text-emphasis: #a62525;
  --bs-danger-bg-subtle: var(--dsu-red-light);
  --bs-danger-border-subtle: #f5c2c2;

  --bs-success: var(--dsu-green);
  --bs-success-rgb: 46, 125, 50;
  --bs-success-text-emphasis: #256428;
  --bs-success-bg-subtle: var(--dsu-green-light);
  --bs-success-border-subtle: #c3e6c5;

  --bs-warning: var(--dsu-amber);
  --bs-warning-rgb: 178, 106, 0;
  --bs-warning-text-emphasis: #8e5500;
  --bs-warning-bg-subtle: var(--dsu-amber-light);
  --bs-warning-border-subtle: #f4dcb4;

  /* Links and focus */
  --bs-link-color: var(--dsu-blue);
  --bs-link-color-rgb: 26, 118, 209;
  --bs-link-hover-color: var(--dsu-blue-active);
  --bs-link-hover-color-rgb: 20, 94, 168;
  --bs-focus-ring-color: rgba(26, 118, 209, 0.25);
  --bs-focus-ring-width: 2px;
}

/* --------------------------------------------------------------------------
   3. Components where Bootstrap bakes a literal colour
   -------------------------------------------------------------------------- */

.btn-primary {
  --bs-btn-bg: var(--dsu-blue);
  --bs-btn-border-color: var(--dsu-blue);
  --bs-btn-hover-bg: var(--dsu-blue-hover);
  --bs-btn-hover-border-color: var(--dsu-blue-hover);
  --bs-btn-active-bg: var(--dsu-blue-active);
  --bs-btn-active-border-color: var(--dsu-blue-active);
  --bs-btn-disabled-bg: var(--dsu-blue);
  --bs-btn-disabled-border-color: var(--dsu-blue);
  --bs-btn-focus-shadow-rgb: 26, 118, 209;
}

.btn-outline-primary {
  --bs-btn-color: var(--dsu-blue);
  --bs-btn-border-color: var(--dsu-blue);
  --bs-btn-hover-bg: var(--dsu-blue);
  --bs-btn-hover-border-color: var(--dsu-blue);
  --bs-btn-active-bg: var(--dsu-blue);
  --bs-btn-active-border-color: var(--dsu-blue);
  --bs-btn-disabled-color: var(--dsu-blue);
  --bs-btn-disabled-border-color: var(--dsu-blue);
  --bs-btn-focus-shadow-rgb: 26, 118, 209;
}

.btn-danger {
  --bs-btn-bg: var(--dsu-red);
  --bs-btn-border-color: var(--dsu-red);
  --bs-btn-hover-bg: #b32828;
  --bs-btn-hover-border-color: #b32828;
  --bs-btn-active-bg: #a92626;
  --bs-btn-active-border-color: #a92626;
  --bs-btn-disabled-bg: var(--dsu-red);
  --bs-btn-disabled-border-color: var(--dsu-red);
  --bs-btn-focus-shadow-rgb: 211, 47, 47;
}

.btn-success {
  --bs-btn-bg: var(--dsu-green);
  --bs-btn-border-color: var(--dsu-green);
  --bs-btn-hover-bg: #276a2a;
  --bs-btn-hover-border-color: #276a2a;
  --bs-btn-active-bg: #256428;
  --bs-btn-active-border-color: #256428;
  --bs-btn-disabled-bg: var(--dsu-green);
  --bs-btn-disabled-border-color: var(--dsu-green);
  --bs-btn-focus-shadow-rgb: 46, 125, 50;
}

/* Amber is dark enough to need white text, unlike Bootstrap's yellow. */
.btn-warning {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--dsu-amber);
  --bs-btn-border-color: var(--dsu-amber);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: #975a00;
  --bs-btn-hover-border-color: #975a00;
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: #8e5500;
  --bs-btn-active-border-color: #8e5500;
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--dsu-amber);
  --bs-btn-disabled-border-color: var(--dsu-amber);
  --bs-btn-focus-shadow-rgb: 178, 106, 0;
}

/* "Dark" buttons are navy, the same family as the sidebar, rather than pure black. */
.btn-dark {
  --bs-btn-bg: var(--dsu-navy-2);
  --bs-btn-border-color: var(--dsu-navy-2);
  --bs-btn-hover-bg: var(--dsu-navy-3);
  --bs-btn-hover-border-color: var(--dsu-navy-3);
  --bs-btn-active-bg: var(--dsu-navy);
  --bs-btn-active-border-color: var(--dsu-navy);
  --bs-btn-disabled-bg: var(--dsu-navy-2);
  --bs-btn-disabled-border-color: var(--dsu-navy-2);
  --bs-btn-focus-shadow-rgb: 15, 42, 77;
}

.btn-outline-secondary {
  --bs-btn-color: var(--dsu-ink-2);
  --bs-btn-bg: #fff;
  --bs-btn-border-color: var(--dsu-line-strong);
  --bs-btn-hover-color: var(--dsu-ink);
  --bs-btn-hover-bg: var(--dsu-surface-2);
  --bs-btn-hover-border-color: #94a3b8;
  --bs-btn-active-color: var(--dsu-ink);
  --bs-btn-active-bg: #eef2f7;
  --bs-btn-active-border-color: #94a3b8;
  --bs-btn-focus-shadow-rgb: 100, 116, 139;
}

/* All buttons: slightly rounder, medium weight, and a gentle lift on the solid ones. */
.btn {
  --bs-btn-font-weight: 500;
  --bs-btn-border-radius: var(--bs-border-radius);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease,
              box-shadow 0.15s ease, transform 0.15s ease;
}

.btn-sm {
  --bs-btn-border-radius: var(--bs-border-radius-sm);
}

.btn-primary,
.btn-danger,
.btn-success,
.btn-warning,
.btn-dark {
  box-shadow: var(--dsu-shadow-sm);
}

.btn-primary:hover,
.btn-danger:hover,
.btn-success:hover,
.btn-warning:hover,
.btn-dark:hover {
  box-shadow: 0 4px 12px -4px rgba(15, 23, 42, 0.30);
}

@media (prefers-reduced-motion: no-preference) {
  .btn-primary:hover,
  .btn-danger:hover,
  .btn-success:hover,
  .btn-dark:hover {
    transform: translateY(-1px);
  }
}

/* Form controls: focus border and ring are literal in the dist build. */
.form-control:focus,
.form-select:focus {
  border-color: var(--dsu-blue);
  box-shadow: 0 0 0 0.22rem rgba(26, 118, 209, 0.18);
}

.form-check-input:checked {
  background-color: var(--dsu-blue);
  border-color: var(--dsu-blue);
}

.form-check-input:focus {
  border-color: var(--dsu-blue);
  box-shadow: 0 0 0 0.2rem rgba(26, 118, 209, 0.25);
}

.list-group-item.active {
  background-color: var(--dsu-blue);
  border-color: var(--dsu-blue);
}

.progress-bar {
  background-color: var(--dsu-blue);
}

.form-control,
.form-select {
  border-color: var(--dsu-line-strong);
  border-radius: var(--bs-border-radius);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.form-control:hover:not(:focus):not(:disabled),
.form-select:hover:not(:focus):not(:disabled) {
  border-color: #94a3b8;
}

.form-control-sm,
.form-select-sm {
  border-radius: var(--bs-border-radius-sm);
}

.form-control::placeholder {
  color: #94a3b8;
}

.form-label {
  font-weight: 500;
  color: var(--dsu-ink);
  margin-bottom: 0.35rem;
}

.form-control:disabled,
.form-select:disabled {
  background-color: var(--dsu-surface-2);
  color: var(--dsu-ink-2);
}

/* ---- A recorded value shown where a form control would otherwise sit ----
   For facts the screen reports rather than asks for — the late reason on the attendance
   editor, for one. No border to type into and no white field: the page's own tint with a
   quiet rule down the left reads as information. The height matches .form-control, so a
   value sitting beside a select or an input still lines up with it. */
.form-value {
  display: flex;
  align-items: center;
  min-height: calc(1.5em + 0.75rem + 2px);
  padding: 0.375rem 0.75rem;
  background-color: var(--dsu-surface-2);
  border-left: 3px solid var(--dsu-line-strong);
  border-radius: var(--bs-border-radius-sm);
  color: var(--dsu-ink);
  font-weight: 500;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* Nothing recorded: the em dash should not read as loudly as a real value. */
.form-value.is-empty {
  color: var(--dsu-ink-3);
  font-weight: 400;
}

/* ---- Holidays & week-off (Settings → Calendar) ----
   The seven weekday buttons, the holiday tag and the month preview. */
.weekday-toggle {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.weekday-toggle .btn {
  width: 52px;
  font-weight: 600;
}

.holiday-pill {
  background: #ede7f6;
  color: #5e35b1;
}

.month-preview {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  max-width: 340px;
  font-size: 12.5px;
}

.month-preview > div {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border: 1px solid var(--dsu-line);
  border-radius: var(--bs-border-radius-sm);
  background: #fff;
}

.month-preview-head,
.month-preview-blank {
  border: 0 !important;
  background: none !important;
  aspect-ratio: auto !important;
}

.month-preview-head {
  font-weight: 600;
  color: var(--dsu-ink-3);
}

/* Grey for a day nobody works, purple for a holiday — as in the approved mock-up. The grey is
   a step darker than the card's own tint: at surface-2 a week off was all but indistinguishable
   from a working day. */
.month-preview .is-weekoff {
  background: #e4e9f0;
  border-color: var(--dsu-line-strong);
  color: var(--dsu-ink-3);
}

.month-preview .is-holiday {
  background: #ede7f6;
  border-color: #d3c5ef;
  color: #5e35b1;
  font-weight: 600;
}

.month-preview-key {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 3px;
  vertical-align: middle;
  border: 1px solid var(--dsu-line);
}

.month-preview-key.is-weekoff { background: #e4e9f0; border-color: var(--dsu-line-strong); }
.month-preview-key.is-holiday { background: #ede7f6; border-color: #d3c5ef; }

/* --------------------------------------------------------------------------
   4. Application shell

   Responsive strategy (three tiers, replacing the mock-up's two):
     >= 992px  fixed 240px sidebar beside the content
     <  992px  sidebar becomes a Bootstrap offcanvas behind a hamburger
     <  576px  single column, larger touch targets, tighter padding
   -------------------------------------------------------------------------- */

body {
  min-height: 100vh;
}

.app-shell {
  min-height: 100vh;
}

@media (min-width: 992px) {
  .app-shell {
    display: grid;
    grid-template-columns: var(--dsu-sidebar-width) 1fr;
  }
}

/* ---- Sidebar ---- */

/* Navy, darkening slightly towards the bottom. background-color carries the colour the
   contrast tests read; the gradient is an image on top of it, which Bootstrap's offcanvas
   override (below) does not touch. */
.app-sidebar {
  background-color: var(--dsu-navy);
  background-image:
    radial-gradient(120% 50% at 0% 0%, rgba(26, 118, 209, 0.22) 0%, rgba(26, 118, 209, 0) 60%),
    linear-gradient(180deg, #0e2645 0%, #0a1c35 100%);
  color: #fff;
  width: var(--dsu-sidebar-width);
  border-right: 1px solid rgba(255, 255, 255, 0.04);
}

/* The sidebar is `offcanvas-lg`, and from 992px up Bootstrap forces
   `.offcanvas-lg { background-color: transparent !important }` so the panel can sit
   inline instead of sliding over the page.

   That wins over the rule above, and the result is white brand text and pale grey
   nav labels on the page's light background — invisible on desktop, correct on a
   phone, which is why it survives a quick look.

   An `!important` is the only thing that beats an `!important`, so it needs the
   extra class for specificity. Set on background-color, not the background
   shorthand, because that is the property Bootstrap is overriding. */
.app-sidebar.offcanvas-lg {
  background-color: var(--dsu-navy) !important;
}

@media (min-width: 992px) {
  .app-sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
  }
}

/* The DevSoft logo on a white plate, with the panel ("Admin panel") as a small tag under it. */
.app-sidebar .brand {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 20px 16px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.app-sidebar .brand-logo {
  display: block;
  width: 100%;
  color: #fff;               /* the visually hidden name is read against the navy */
  text-decoration: none;
  border-radius: var(--bs-border-radius);
}

.app-sidebar .brand-logo:focus-visible {
  outline: 2px solid #7cc0ff;
  outline-offset: 3px;
}

.app-sidebar .brand-plate {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 8px 14px;
  background: #fff;
  border-radius: var(--bs-border-radius);
  box-shadow: 0 8px 20px -10px rgba(0, 0, 0, 0.55), inset 0 -1px 0 rgba(15, 23, 42, 0.06);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.app-sidebar .brand-logo:hover .brand-plate {
  box-shadow: 0 10px 24px -10px rgba(61, 155, 255, 0.55), inset 0 -1px 0 rgba(15, 23, 42, 0.06);
}

.app-sidebar .brand-plate img {
  display: block;
  width: auto;
  height: 46px;
  max-width: 100%;
  object-fit: contain;
}

/* Close (phone/tablet only), pinned to the corner beside the logo plate. */
.app-sidebar .brand .btn-close {
  position: absolute;
  top: 10px;
  right: 10px;
}

@media (max-width: 991.98px) {
  .app-sidebar .brand-logo {
    width: calc(100% - 36px);
  }
}

/* Pale steel blue on a solid dark-blue tag: 6.9:1. A solid colour, not a translucent
   white, because translucent tints read as white to the sidebar contrast test. */
.app-sidebar .brand .panel-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  font-size: 11px;
  color: #b7c7dc;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  background: #13305a;
  border: 1px solid #1c406f;
  border-radius: 999px;
}

.app-sidebar .brand .panel-label .bi {
  color: #7cc0ff;
}

/* Group headings are small and uppercase, so they are held to the body-text minimum:
   #8ea3bf on the navy is 6.2:1. */
.app-sidebar .nav-group {
  padding: 18px 20px 6px;
  font-size: 10.5px;
  font-weight: 600;
  color: #8ea3bf;
  letter-spacing: 0.9px;
  text-transform: uppercase;
}

.app-sidebar .nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 2px 10px;
  padding: 9px 12px;
  border-radius: var(--bs-border-radius);
  /* #cbd6e4 on the navy is 12:1. */
  color: #cbd6e4;
  font-size: 13.5px;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.app-sidebar .nav-link .bi {
  font-size: 15px;
  width: 18px;
  text-align: center;
  color: #8ea3bf;
  transition: color 0.15s ease;
}

.app-sidebar .nav-link:hover,
.app-sidebar .nav-link:focus-visible {
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
}

.app-sidebar .nav-link:hover .bi,
.app-sidebar .nav-link:focus-visible .bi {
  color: #fff;
}

/* The current page: brand blue, lit slightly from the top-left. background-color is the
   solid blue the contrast test reads (white on it is 4.6:1); the gradient sits on top. */
.app-sidebar .nav-link.active {
  background-color: var(--dsu-blue);
  background-image: linear-gradient(135deg, #2386e6 0%, #1668bb 100%);
  color: #fff;
  font-weight: 600;
  box-shadow: 0 8px 18px -10px rgba(26, 118, 209, 0.9), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.app-sidebar .nav-link.active .bi {
  color: #fff;
}

.app-sidebar .nav-link .badge {
  margin-left: auto;
}

/* Comfortable thumb targets once the sidebar is an offcanvas. */
@media (max-width: 991.98px) {
  .app-sidebar .nav-link {
    padding: 12px 14px;
    font-size: 15px;
  }
}

/* ---- Top bar ---- */

/* White, slightly translucent over the page as it scrolls underneath. */
.app-topbar {
  height: var(--dsu-topbar-height);
  background: rgba(255, 255, 255, 0.88);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--dsu-line);
  box-shadow: 0 1px 0 rgba(15, 23, 42, 0.02);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  position: sticky;
  top: 0;
  z-index: 1020;
}

/* Search: a soft pill with a magnifier, turning white with the blue ring when focused. */
.app-topbar .global-search .form-control {
  height: 38px;
  padding-left: 38px;
  border-color: transparent;
  border-radius: 999px;
  background-color: #eef2f7;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%2364748b' viewBox='0 0 16 16'%3E%3Cpath d='M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 14px center;
  background-size: 14px 14px;
  font-size: 13.5px;
}

.app-topbar .global-search .form-control:hover {
  background-color: #e8edf4;
  border-color: transparent;
}

.app-topbar .global-search .form-control:focus {
  background-color: #fff;
  border-color: var(--dsu-blue);
}

/* Notification bell and user menu: quiet round hover targets. */
.app-topbar .btn-link {
  border-radius: 999px;
}

.app-topbar .btn-link:hover {
  background: #eef2f7;
}

.app-topbar .dropdown-toggle::after {
  color: var(--dsu-ink-3);
}

@media (min-width: 992px) {
  .app-topbar {
    padding: 0 28px;
  }
}

.app-topbar .global-search {
  max-width: 380px;
  flex: 1 1 auto;
  position: relative;
}

/* ---------------------------------------------------------------- search dropdown
   The panel under the box (docs/SEARCH.md). Fixed 520px on a desktop, as the design asks;
   under 800px it takes the width of the bar instead, so nothing runs off the screen. */

.search-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 520px;
  max-width: calc(100vw - 32px);
  max-height: min(70vh, 30rem);
  overflow-y: auto;
  z-index: 1080;
  background: #fff;
  border: 1px solid var(--dsu-line);
  border-radius: 10px;
  box-shadow: var(--dsu-shadow-lg);
  padding: 4px 0;
}

.search-panel-message {
  padding: 14px 16px;
  font-size: 13px;
  color: var(--dsu-ink-2);
}

.search-group {
  padding: 8px 16px 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--dsu-ink-3);
}

a.search-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 16px;
  color: inherit;
  text-decoration: none;
}

a.search-row.is-active,
a.search-row:hover {
  background: #f1f6fd;
}

.search-row .search-icon {
  margin-top: 2px;
  color: var(--dsu-ink-3);
}

.search-row .search-text {
  flex: 1 1 auto;
  min-width: 0;
}

.search-row .search-title {
  display: block;
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.search-row .search-sub {
  display: block;
  font-size: 12px;
  color: var(--dsu-ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.search-row .search-pill {
  flex: 0 0 auto;
  align-self: center;
  padding: 2px 9px;
  border-radius: 12px;
  background: #eef2f7;
  color: var(--dsu-ink-2);
  font-size: 11px;
  font-weight: 600;
}

.search-row mark {
  padding: 0;
  background: #fff3cd;
  color: inherit;
}

a.search-more {
  font-size: 12px;
  font-weight: 500;
  color: var(--dsu-blue);
}

/* On a phone the box is narrow and the panel is the width of the screen. */
@media (max-width: 799.98px) {
  .app-topbar .global-search {
    max-width: none;
  }

  .search-panel {
    left: 50%;
    transform: translateX(-50%);
    width: calc(100vw - 24px);
  }
}

.app-topbar .avatar-initials {
  width: 34px;
  height: 34px;
  font-size: 13px;
  font-weight: 600;
  background: linear-gradient(135deg, #3d9bff 0%, var(--dsu-blue) 60%, #1459a3 100%) !important;
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--dsu-blue-tint);
}

/* ---- Content well ---- */

.app-content {
  padding: 16px;
  background: var(--dsu-bg);
  min-width: 0;   /* lets grid children shrink so wide tables can scroll */
}

@media (min-width: 768px) {
  .app-content {
    padding: 28px 32px;
  }
}

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 22px;
}

.page-header h1 {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.2px;
  color: var(--dsu-ink);
  margin: 0;
}

.page-header .subtitle {
  font-size: 13.5px;
  color: var(--dsu-ink-3);
  margin: 4px 0 0;
}

.page-header .breadcrumb {
  --bs-breadcrumb-divider-color: var(--dsu-ink-3);
  --bs-breadcrumb-item-active-color: var(--dsu-ink-3);
}

.page-header .actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* --------------------------------------------------------------------------
   5. ERP components
   -------------------------------------------------------------------------- */

.mono {
  font-family: var(--bs-font-monospace);
  font-size: 12.5px;
}

/* ---- Stat card ---- */

/* A white tile with a thin coloured accent along the top and, where the page provides one,
   an icon in a soft tinted square. --stat and --stat-soft carry the tile's meaning colour. */
.stat-card {
  --stat: var(--dsu-blue);
  --stat-soft: var(--dsu-blue-light);

  position: relative;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--dsu-line);
  border-radius: var(--bs-border-radius-lg);
  box-shadow: var(--dsu-shadow);
  padding: 18px 18px 16px;
  height: 100%;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.stat-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--stat) 0%, color-mix(in srgb, var(--stat) 55%, #fff) 100%);
}

.stat-card:hover {
  box-shadow: 0 2px 4px rgba(15, 23, 42, 0.05), 0 14px 28px -14px rgba(15, 23, 42, 0.22);
}

@media (prefers-reduced-motion: no-preference) {
  .stat-card:hover {
    transform: translateY(-2px);
  }
}

.stat-card.stat-danger { --stat: var(--dsu-red); --stat-soft: var(--dsu-red-light); }
.stat-card.stat-success { --stat: var(--dsu-green); --stat-soft: var(--dsu-green-light); }
.stat-card.stat-warning { --stat: var(--dsu-amber); --stat-soft: var(--dsu-amber-light); }
.stat-card.stat-dark { --stat: var(--dsu-navy-3); --stat-soft: #e6ecf5; }

.stat-card .stat-icon {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 18px;
  color: var(--stat);
  background: var(--stat-soft);
}

/* Room for the icon so a long value never runs under it. */
.stat-card:has(.stat-icon) .stat-value,
.stat-card:has(.stat-icon) .stat-label {
  padding-right: 48px;
}

.stat-card .stat-value {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.4px;
  color: var(--dsu-ink);
}

.stat-card .stat-label {
  margin-top: 4px;
  font-size: 13px;
  font-weight: 500;
  color: var(--dsu-ink-2);
}

.stat-card .stat-detail {
  font-size: 12px;
  color: var(--dsu-ink-3);
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px dashed var(--dsu-line);
}

/* ---- The single red rule ----
   A red row means "act now" and nothing else. Always paired with a text
   badge, so the meaning never depends on colour perception alone. */

.table tr.row-attention > * {
  background-color: var(--dsu-red-light);
  box-shadow: inset 3px 0 0 0 var(--dsu-red);
}

.card.card-attention {
  border-left: 3px solid var(--dsu-red);
}

/* ---- Attendance sheet: employees x days ----
   Scrolls horizontally with a pinned employee column at every width, rather
   than collapsing into a different layout on small screens. */

.sheet-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.sheet-scroll .sheet {
  border-collapse: separate;
  border-spacing: 0;
  white-space: nowrap;
}

.sheet-scroll .sheet th,
.sheet-scroll .sheet td {
  border-bottom: 1px solid var(--dsu-line);
  padding: 6px 8px;
  text-align: center;
  font-size: 12px;
}

.sheet-scroll .sheet .sheet-employee {
  position: sticky;
  left: 0;
  z-index: 2;
  background: #fff;
  text-align: left;
  min-width: 190px;
  box-shadow: 1px 0 0 0 var(--dsu-line);
}

.sheet-scroll .sheet thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: #f7f8fa;
}

.sheet-scroll .sheet thead .sheet-employee {
  z-index: 4;
}

.sheet-scroll .sheet .day-weekoff {
  background: #f2f2f2;
  color: var(--dsu-ink-3);
}

.sheet-scroll .sheet .day-today {
  border-bottom: 2px solid var(--dsu-blue);
}

.sheet-scroll .sheet .st-P { background: var(--dsu-green-light); color: var(--dsu-green); font-weight: 600; }
.sheet-scroll .sheet .st-A { background: var(--dsu-red-light); color: var(--dsu-red); font-weight: 600; }
.sheet-scroll .sheet .st-HD { background: var(--dsu-amber-light); color: var(--dsu-amber); font-weight: 600; }
.sheet-scroll .sheet .st-L { background: var(--dsu-blue-light); color: var(--dsu-blue-active); font-weight: 600; }
.sheet-scroll .sheet .st-WFH { background: var(--dsu-blue-light); color: var(--dsu-blue); font-weight: 600; }
.sheet-scroll .sheet .st-H,
.sheet-scroll .sheet .st-WO { background: #f2f2f2; color: var(--dsu-ink-3); }

/* ---- Punch panel ----
   Built mobile-first: this is the screen people open on a phone at 09:28. */

/* Deep navy into the brand blue, with a soft light in the top-right corner: calm enough
   for a screen people look at all day, and clearly the most important thing on the page. */
.punch-panel {
  --punch-ink: #ffffff;
  --punch-ink-2: rgba(255, 255, 255, 0.82);
  --punch-ink-3: rgba(214, 228, 245, 0.72);
  --punch-tile: rgba(255, 255, 255, 0.07);
  --punch-tile-line: rgba(255, 255, 255, 0.12);

  position: relative;
  overflow: hidden;
  isolation: isolate;
  color: var(--punch-ink);
  background:
    radial-gradient(120% 140% at 100% 0%, rgba(26, 118, 209, 0.55) 0%, rgba(26, 118, 209, 0) 55%),
    linear-gradient(135deg, #0a1f3d 0%, #0f2f5c 55%, #134a8c 100%);
  border: 1px solid rgba(26, 118, 209, 0.35);
  border-radius: var(--bs-border-radius-lg);
  box-shadow: 0 10px 30px -12px rgba(10, 31, 61, 0.55);
  padding: 20px 16px;
}

/* A faint grid, masked to fade out: texture without noise. */
.punch-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: linear-gradient(115deg, transparent 20%, #000 75%);
  mask-image: linear-gradient(115deg, transparent 20%, #000 75%);
  pointer-events: none;
}

@media (min-width: 768px) {
  .punch-panel {
    padding: 26px 28px;
  }
}

.punch-panel .punch-clock {
  font-family: var(--bs-font-monospace);
  font-size: 38px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: 0.5px;
  color: var(--punch-ink);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
}

@media (max-width: 575.98px) {
  .punch-panel .punch-clock {
    font-size: 30px;
  }
}

/* Which clock the panel is showing, and the shift it is measured against. Quiet, but
   always present: on a shared screen it is the only thing that says whose day this is. */
.punch-panel .punch-region {
  display: inline-block;
  color: var(--punch-ink-3);
  font-size: 12px;
  letter-spacing: 0.2px;
  margin-top: 8px;
  min-height: 1rem;
}

.punch-panel .punch-region:not(:empty) {
  padding: 2px 10px;
  border: 1px solid var(--punch-tile-line);
  border-radius: 999px;
  background: var(--punch-tile);
}

.punch-panel .punch-status {
  color: var(--punch-ink-2);
  font-size: 13.5px;
  margin-top: 8px;
}

/* Buttons on the blue: primary turns white so it does not melt into the panel. */
.punch-panel .btn-primary {
  --bs-btn-bg: #ffffff;
  --bs-btn-color: var(--dsu-blue-active);
  --bs-btn-border-color: #ffffff;
  --bs-btn-hover-bg: var(--dsu-blue-light);
  --bs-btn-hover-color: var(--dsu-blue-active);
  --bs-btn-hover-border-color: var(--dsu-blue-light);
  --bs-btn-active-bg: var(--dsu-blue-tint);
  --bs-btn-active-color: var(--dsu-blue-active);
  --bs-btn-active-border-color: var(--dsu-blue-tint);
  font-weight: 600;
}

.punch-panel .punch-actions .btn {
  box-shadow: 0 4px 14px -6px rgba(0, 0, 0, 0.45);
}

.punch-panel .progress {
  background-color: rgba(255, 255, 255, 0.14);
}

.punch-panel .progress-bar:not(.bg-danger) {
  background-color: #7cc0ff;
}

.punch-panel .punch-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 18px;
}

/* Full-width, thumb-sized buttons on a phone. */
@media (max-width: 575.98px) {
  .punch-panel .punch-actions .btn {
    flex: 1 1 100%;
    padding-top: 0.75rem;
    padding-bottom: 0.75rem;
    font-size: 1rem;
  }
}

/* The day's numbers as glass tiles: four counters and the current task, one row on a
   wide screen. */
.punch-panel .punch-counters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 22px;
}

.punch-panel .punch-counters > div {
  min-width: 0;
  padding: 10px 14px;
  border: 1px solid var(--punch-tile-line);
  border-radius: var(--bs-border-radius);
  background: var(--punch-tile);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

@media (min-width: 768px) {
  .punch-panel .punch-counters {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .punch-panel .punch-counters .counter-wide {
    grid-column: span 4;
  }
}

@media (min-width: 1200px) {
  .punch-panel .punch-counters {
    grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 2fr);
  }

  .punch-panel .punch-counters .counter-wide {
    grid-column: auto;
  }
}

.punch-panel .counter-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--punch-ink-3);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.punch-panel .counter-value {
  margin-top: 2px;
  font-family: var(--bs-font-monospace);
  font-size: 17px;
  font-weight: 600;
  color: var(--punch-ink);
}

.punch-panel .counter-wide {
  grid-column: span 2;
}

/* The current task stands out a little from the plain counters. */
.punch-panel .punch-counters .counter-wide {
  border-color: rgba(124, 192, 255, 0.35);
  background: rgba(124, 192, 255, 0.12);
}

/* ---- Login split screen ---- */

.login-page {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 992px) {
  .login-page {
    grid-template-columns: 1.1fr 1fr;
  }
}

/* The same navy-into-blue as the time panel, so signing in already looks like the product. */
.login-page .login-brand {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background-color: var(--dsu-navy);
  background-image:
    radial-gradient(90% 70% at 100% 0%, rgba(26, 118, 209, 0.55) 0%, rgba(26, 118, 209, 0) 60%),
    radial-gradient(70% 60% at 0% 100%, rgba(61, 155, 255, 0.18) 0%, rgba(61, 155, 255, 0) 60%),
    linear-gradient(150deg, #0a1f3d 0%, #0f2f5c 60%, #134a8c 100%);
  color: #fff;
  padding: 48px 56px;
  display: none;   /* the marketing panel is desktop-only */
}

.login-page .login-brand::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: radial-gradient(80% 80% at 70% 30%, #000 0%, transparent 75%);
  mask-image: radial-gradient(80% 80% at 70% 30%, #000 0%, transparent 75%);
  pointer-events: none;
}

/* Headings take --bs-heading-color, which is the dark ink for the light pages. On the navy
   panels they must be white, or the headline disappears into the background. */
.login-page .login-brand,
.punch-panel {
  --bs-heading-color: #fff;
}

.login-page .login-brand h1 {
  color: #fff;
  line-height: 1.2;
  letter-spacing: -0.5px;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.25);
}

.login-page .login-brand .text-body-tertiary {
  color: rgba(214, 228, 245, 0.7) !important;
}

.login-page .login-brand .text-primary {
  color: #7cc0ff !important;
}

@media (min-width: 992px) {
  .login-page .login-brand {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

/* The full logo on a white plate at the top of the navy panel. */
.login-page .login-brand .login-logo {
  display: inline-flex;
  align-self: flex-start;
  padding: 12px 20px;
  background: #fff;
  border-radius: var(--bs-border-radius-lg);
  box-shadow: 0 16px 32px -16px rgba(0, 0, 0, 0.6), inset 0 -1px 0 rgba(15, 23, 42, 0.06);
}

.login-page .login-brand .login-logo img {
  display: block;
  width: auto;
  height: 56px;
}

/* Phones: the navy panel is hidden, so the logo sits at the top of the sign-in card. */
.login-page .login-card-logo {
  display: block;
  width: auto;
  height: 52px;
  margin-left: -4px;
}

/* Each feature as a small frosted row. */
.login-page .login-brand .feature-list {
  display: grid;
  gap: 8px;
  max-width: 420px;
}

.login-page .login-brand .feature-list li {
  margin: 0 !important;
  padding: 9px 14px;
  color: rgba(255, 255, 255, 0.86);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--bs-border-radius);
  background: rgba(255, 255, 255, 0.05);
}

.login-page .login-form-side {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  background:
    radial-gradient(60% 50% at 50% 0%, rgba(26, 118, 209, 0.08) 0%, rgba(26, 118, 209, 0) 70%),
    var(--dsu-bg);
}

.login-page .login-card {
  width: 100%;
  max-width: 440px;
  border: 1px solid var(--dsu-line);
  border-radius: var(--bs-border-radius-xl);
  box-shadow: var(--dsu-shadow-lg) !important;
}

.login-page .login-card .card-body {
  padding: 2.25rem !important;
}

.login-page .login-card h2 {
  font-size: 1.5rem !important;
  font-weight: 700;
}

/* ---- Timeline ---- */

.timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 18px;
  border-left: 2px solid var(--dsu-line);
}

.timeline li {
  position: relative;
  padding: 0 0 16px 16px;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: -25px;
  top: 4px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--dsu-blue);
  border: 2px solid #fff;
}

/* ---- Task history (_TaskHistory.cshtml, admin and employee task pages) ----
   One colour per kind of change: the dot, the field pill and the new value share it. */

.task-history {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

.task-history-item {
  --h-color: #5f6b7a;
  --h-bg: #eef1f4;
  position: relative;
  display: flex;
  gap: 12px;
  padding: 0 0 14px;
}

/* The connecting line, drawn behind the dots. */
.task-history-item:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 13px;
  top: 28px;
  bottom: 0;
  width: 2px;
  background: var(--dsu-line);
}

.task-history-dot {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  color: var(--h-color);
  background: var(--h-bg);
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--h-color);
}

.task-history-body {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 10px 8px;
  border-left: 3px solid var(--h-color);
  border-radius: 0 6px 6px 0;
  background: color-mix(in srgb, var(--h-bg) 45%, transparent);
}

.task-history-field {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--h-color);
  background: var(--h-bg);
}

.task-history-change {
  margin-top: 3px;
  overflow-wrap: anywhere;
}

.task-history-old {
  color: var(--bs-tertiary-color);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, currentColor 50%, transparent);
}

.task-history-arrow {
  margin: 0 4px;
  color: var(--bs-tertiary-color);
}

.task-history-new {
  font-weight: 600;
  color: var(--h-color);
}

.task-history-note {
  margin-top: 4px;
  padding: 3px 8px;
  border-radius: 4px;
  color: var(--dsu-ink);
  background: #fff;
  border: 1px dashed color-mix(in srgb, var(--h-color) 45%, transparent);
}

.task-history-item.is-created       { --h-color: var(--dsu-blue);  --h-bg: var(--dsu-blue-light); }
.task-history-item.is-status        { --h-color: #6f42c1;          --h-bg: #f0e9fb; }
.task-history-item.is-overdue       { --h-color: var(--dsu-red);   --h-bg: var(--dsu-red-light); }
.task-history-item.is-estimate-over { --h-color: #d9480f;          --h-bg: #fff0e6; }
.task-history-item.is-timer         { --h-color: #0b7285;          --h-bg: #e3f6f8; }
.task-history-item.is-estimate      { --h-color: var(--dsu-amber); --h-bg: var(--dsu-amber-light); }
.task-history-item.is-assignee      { --h-color: var(--dsu-green); --h-bg: var(--dsu-green-light); }
.task-history-item.is-due           { --h-color: #c2255c;          --h-bg: #fdebf2; }
.task-history-item.is-tags          { --h-color: #495057;          --h-bg: #eceff2; }

/* ---- Form section heading (Part C3) ---- */

.form-section-title {
  /* The brand blue measures 4.3:1 against the card — fine for a large heading, under
     the 4.5:1 minimum for 13px uppercase text like this. The darker step is the same
     hue and clears it comfortably, so these still read as brand blue.
     AppearanceTests measures the real value; do not trust a figure computed against
     pure white, which is not what these sit on. */
  color: var(--dsu-blue-active);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.3px;
  padding-bottom: 6px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--dsu-line);
}


/* ---- Task discussion: comments, chat, attachments ---- */

.avatar-sm {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
}

.comment-thread > .comment {
  padding: 14px 16px;
  border-bottom: 1px solid var(--dsu-line);
}

.comment-replies {
  margin: 10px 0 0 38px;
  padding-left: 12px;
  border-left: 2px solid var(--dsu-line);
}

.comment-replies > .comment + .comment {
  margin-top: 10px;
}

.comment-body {
  margin-top: 2px;
  overflow-wrap: anywhere;
}

.comment-actions {
  margin-top: 2px;
}

.comment-reply-form {
  margin: 10px 0 0 38px;
}

/* Part A §8.4: a mention is highlighted in blue. Darker step of the brand blue, so it
   clears the contrast minimum at body size. */
.mention {
  color: var(--dsu-blue-active);
  background: var(--dsu-blue-light);
  border-radius: 3px;
  padding: 0 3px;
  font-weight: 500;
}

.mention-host {
  position: relative;
}

.mention-menu {
  position: absolute;
  z-index: 20;
  left: 0;
  top: 100%;
  min-width: 240px;
  max-width: 100%;
  margin-top: 2px;
  background: #fff;
  border: 1px solid var(--dsu-line);
  border-radius: var(--bs-border-radius);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
}

.mention-menu li {
  padding: 6px 10px;
  cursor: pointer;
  font-size: 13px;
}

.mention-menu li.active,
.mention-menu li:hover {
  background: var(--dsu-blue-light);
}

.chat-messages {
  max-height: 420px;
  overflow-y: auto;
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.chat-message {
  max-width: 80%;
  align-self: flex-start;
}

.chat-message.chat-mine {
  align-self: flex-end;
  text-align: right;
}

.chat-bubble {
  display: inline-block;
  text-align: left;
  padding: 7px 11px;
  border-radius: 12px;
  background: #f1f3f6;
  overflow-wrap: anywhere;
}

.chat-mine .chat-bubble {
  background: var(--dsu-blue-light);
}

.chat-text {
  white-space: pre-wrap;
}

.chat-file {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
}

.chat-input {
  resize: vertical;
  min-height: 34px;
  max-height: 160px;
}

.chat-typing,
.chat-seen {
  min-height: 18px;
}

.attachment-list .list-group-item {
  padding: 8px 16px;
}

.min-w-0 {
  min-width: 0;
}

[data-drop-zone].drop-active {
  outline: 2px dashed var(--dsu-blue);
  outline-offset: -6px;
  background: var(--dsu-blue-light);
}

/* ---- Activity feed ----
   A timeline of what people did. Icons carry the kind; the red edge is kept for things
   somebody has to act on, the same meaning it has everywhere else. */

.activity-list {
  max-height: 640px;
  overflow-y: auto;
}

.activity-list .list-group-item {
  padding: 10px 16px;
}

.activity-icon {
  font-size: 16px;
  color: var(--dsu-ink-2);
  line-height: 1.4;
  flex: 0 0 18px;
}

.activity-attention {
  background-color: var(--dsu-red-light);
  box-shadow: inset 3px 0 0 0 var(--dsu-red);
}

.activity-attention .activity-icon {
  color: var(--dsu-red);
}

.activity-zone {
  font-size: 10px;
  letter-spacing: 0.3px;
}

/* ---- Attendance sheet grid ----
   Thirty-one narrow columns plus a name that has to stay readable while scrolling
   sideways. Only two states get colour: an absence, and a late arrival. */

.sheet-grid {
  font-size: 12px;
  border-collapse: separate;
  border-spacing: 0;
}

.sheet-grid th,
.sheet-grid td {
  padding: 4px 2px;
  white-space: nowrap;
}

.sheet-sticky {
  position: sticky;
  left: 0;
  z-index: 2;
  background: #fff;
  min-width: 180px;
  box-shadow: 1px 0 0 0 var(--dsu-line);
}

.sheet-grid thead th.sheet-sticky {
  z-index: 3;
}

.sheet-day {
  font-weight: 600;
  line-height: 1;
}

.sheet-dow {
  font-size: 10px;
  color: var(--dsu-ink-3);
  font-weight: 400;
  line-height: 1.4;
}

.sheet-weekend {
  background: var(--dsu-surface-2, #f7f8fa);
}

.sheet-absent {
  background: var(--dsu-red-light);
  color: var(--dsu-red);
  font-weight: 700;
}

.sheet-late {
  color: var(--dsu-red);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   5b. Surfaces — the navy & blue theme applied to Bootstrap's building blocks

   Every page is made of these, so this is where the product's look lives: white cards
   with soft depth on a cool grey page, slate text, brand blue for what is selected.
   The meaning colours (red "act now", green, amber) are untouched.
   -------------------------------------------------------------------------- */

::selection {
  background: var(--dsu-blue-tint);
  color: var(--dsu-ink);
}

hr {
  color: var(--dsu-line-strong);
  opacity: 1;
}

a {
  text-underline-offset: 2px;
}

/* ---- Cards ---- */

.card {
  --bs-card-border-color: var(--dsu-line);
  --bs-card-border-radius: var(--bs-border-radius-lg);
  --bs-card-inner-border-radius: calc(var(--bs-border-radius-lg) - 1px);
  --bs-card-cap-bg: #fff;
  --bs-card-cap-padding-y: 0.85rem;
  --bs-card-cap-padding-x: 1.15rem;
  --bs-card-spacer-x: 1.15rem;
  box-shadow: var(--dsu-shadow);
}

.card-header {
  font-weight: 600;
  color: var(--dsu-ink);
  border-bottom-color: var(--dsu-line);
}

.card-header .h6,
.card-header h2,
.card-header h3 {
  font-weight: 600;
  color: var(--dsu-ink);
}

.card-footer {
  background: var(--dsu-surface-2);
  border-top-color: var(--dsu-line);
}

/* ---- Tables ---- */

.table {
  --bs-table-color: var(--dsu-ink);
  --bs-table-border-color: var(--dsu-line);
  --bs-table-hover-bg: #f3f8fe;
  --bs-table-hover-color: var(--dsu-ink);
  --bs-table-striped-bg: var(--dsu-surface-2);
  margin-bottom: 0;
}

.table > :not(caption) > * > * {
  padding: 0.7rem 0.8rem;
}

.table-sm > :not(caption) > * > * {
  padding: 0.45rem 0.65rem;
}

/* Column headings: small, uppercase, slate, on a faint band. */
.table > thead > tr > th {
  background-color: var(--dsu-surface-2);
  color: var(--dsu-ink-3);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--dsu-line);
}

.table > tbody > tr:last-child > * {
  border-bottom-width: 0;
}

.table-hover > tbody > tr {
  transition: background-color 0.12s ease;
}

/* ---- Badges and status ---- */

.badge {
  --bs-badge-font-weight: 600;
  --bs-badge-border-radius: 6px;
  --bs-badge-padding-y: 0.36em;
  --bs-badge-padding-x: 0.6em;
  letter-spacing: 0.1px;
}

.badge.rounded-pill {
  --bs-badge-border-radius: 999px;
}

.text-bg-light {
  background-color: var(--dsu-surface-2) !important;
  color: var(--dsu-ink-2) !important;
}

.status-badge {
  border-radius: 999px;
  padding-left: 0.7em;
  padding-right: 0.7em;
}

/* ---- Tabs: an underline rather than folder tabs ---- */

.nav-tabs {
  --bs-nav-tabs-border-color: var(--dsu-line);
  --bs-nav-tabs-link-active-bg: transparent;
  gap: 4px;
}

.nav-tabs .nav-link {
  margin-bottom: -1px;
  padding: 0.6rem 0.9rem;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--dsu-ink-2);
  font-weight: 500;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus-visible {
  color: var(--dsu-ink);
  border-bottom-color: var(--dsu-line-strong);
  isolation: auto;
}

.nav-tabs .nav-link.active,
.nav-tabs .nav-item.show .nav-link {
  color: var(--dsu-blue-active);
  background: transparent;
  border-bottom-color: var(--dsu-blue);
  font-weight: 600;
}

.nav-pills {
  --bs-nav-pills-border-radius: 999px;
  --bs-nav-pills-link-active-bg: var(--dsu-blue);
}

/* ---- Alerts: a coloured edge, softer fill ---- */

.alert {
  --bs-alert-border-radius: var(--bs-border-radius);
  border-left-width: 4px;
}

.alert-primary { --bs-alert-border-color: var(--dsu-blue); }
.alert-danger { --bs-alert-border-color: var(--dsu-red); }
.alert-success { --bs-alert-border-color: var(--dsu-green); }
.alert-warning { --bs-alert-border-color: var(--dsu-amber); }

.alert-light {
  --bs-alert-bg: var(--dsu-surface-2);
  --bs-alert-border-color: var(--dsu-line);
  --bs-alert-color: var(--dsu-ink-2);
  border-left-width: 1px;
}

.alert-dark {
  --bs-alert-bg: #e6ecf5;
  --bs-alert-border-color: var(--dsu-navy-3);
  --bs-alert-color: var(--dsu-navy);
}

/* ---- Menus, lists, pagination, modals ---- */

.dropdown-menu {
  --bs-dropdown-border-color: var(--dsu-line);
  --bs-dropdown-border-radius: var(--bs-border-radius-lg);
  --bs-dropdown-link-color: var(--dsu-ink);
  --bs-dropdown-link-hover-bg: #eef2f7;
  --bs-dropdown-link-active-bg: var(--dsu-blue);
  --bs-dropdown-divider-bg: var(--dsu-line);
  padding: 6px;
  box-shadow: var(--dsu-shadow-lg);
}

.dropdown-item {
  border-radius: var(--bs-border-radius-sm);
  padding: 0.45rem 0.7rem;
}

.list-group {
  --bs-list-group-border-color: var(--dsu-line);
  --bs-list-group-action-hover-bg: #f3f8fe;
}

.pagination {
  --bs-pagination-color: var(--dsu-ink-2);
  --bs-pagination-border-color: var(--dsu-line);
  --bs-pagination-hover-color: var(--dsu-ink);
  --bs-pagination-hover-bg: #eef2f7;
  --bs-pagination-hover-border-color: var(--dsu-line-strong);
  --bs-pagination-active-bg: var(--dsu-blue);
  --bs-pagination-active-border-color: var(--dsu-blue);
  --bs-pagination-focus-box-shadow: 0 0 0 0.2rem rgba(26, 118, 209, 0.2);
  gap: 4px;
}

.pagination .page-link {
  margin-left: 0 !important;
  min-width: 2rem;
  text-align: center;
  border-radius: var(--bs-border-radius-sm) !important;
}

.modal {
  --bs-modal-border-radius: var(--bs-border-radius-xl);
  --bs-modal-inner-border-radius: calc(var(--bs-border-radius-xl) - 1px);
  --bs-modal-border-color: var(--dsu-line);
  --bs-modal-header-border-color: var(--dsu-line);
  --bs-modal-footer-border-color: var(--dsu-line);
  --bs-modal-box-shadow: var(--dsu-shadow-lg);
}

.modal-content {
  box-shadow: var(--bs-modal-box-shadow);
}

.modal-backdrop {
  --bs-backdrop-bg: #0b1f3a;
  --bs-backdrop-opacity: 0.45;
}

.modal-title {
  font-weight: 700;
}

.progress {
  --bs-progress-bg: var(--dsu-line);
  --bs-progress-border-radius: 999px;
}

.btn-group > .btn-check:checked + .btn,
.btn-group > .btn.active {
  box-shadow: none;
}

/* ---- The board ---- */

.kanban-board .kanban-column {
  background: #eef2f7;
  border-color: var(--dsu-line);
  box-shadow: none;
}

.kanban-board .kanban-column > .card-header {
  background: transparent !important;
  border-bottom-color: var(--dsu-line-strong);
}

.kanban-board .kanban-drop > .card {
  box-shadow: var(--dsu-shadow-sm);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.kanban-board .kanban-drop > .card:hover {
  box-shadow: var(--dsu-shadow);
}

/* ---- Task cards ---- */

.task-card {
  transition: box-shadow 0.2s ease;
}

.task-card:hover {
  box-shadow: 0 2px 4px rgba(15, 23, 42, 0.05), 0 14px 28px -14px rgba(15, 23, 42, 0.22);
}

/* ---- Slim scrollbars inside scrolling panels ---- */

.app-sidebar,
.table-responsive,
.kanban-board,
.activity-list,
.chat-messages {
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 transparent;
}

.app-sidebar {
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}

/* --------------------------------------------------------------------------
   6. Print
   -------------------------------------------------------------------------- */

@media print {
  .app-sidebar,
  .app-topbar,
  .page-header .actions,
  .no-print {
    display: none !important;
  }

  .app-shell {
    display: block;
  }

  .app-content {
    padding: 0;
    background: #fff;
  }

  /* Reports: the controls are for the screen; the table is the document. */
  .nav-tabs,
  .card-body.border-bottom form,
  .d-print-none {
    display: none !important;
  }

  .card {
    border: 0;
    box-shadow: none;
  }

  .table-responsive {
    overflow: visible !important;
  }

  /* Sticky positioning has no meaning on paper and shifts the column off the page. */
  .sheet-sticky {
    position: static;
    box-shadow: none;
  }

  .sheet-grid {
    font-size: 9px;
  }

  /* Backgrounds are how a red row reads as urgent; without this browsers drop them. */
  .table tr.row-attention > *,
  .sheet-absent {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
}

/* Admin → Errors: a stack trace scrolls inside its card instead of stretching the page. */
.error-trace {
  max-height: 32rem;
  overflow: auto;
  white-space: pre;
  font-size: .78rem;
  background: var(--bs-tertiary-bg);
}

/* ---- Task cards: every project's tasks on one page ----
   The project band on top is the point of the view: whose work this is, at a glance. */

.task-card {
  overflow: hidden;
}

.task-card .task-card-project {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 6px 12px;
  font-size: 12px;
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
  border-bottom: 1px solid var(--dsu-line);
}

.task-card-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 10px;
}

.task-card-facts dt {
  font-weight: 400;
  color: var(--dsu-ink-3);
}

.task-card-facts dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* A native progress element rather than a styled div, so the width needs no inline style. */
.task-progress {
  display: block;
  width: 100%;
  height: 4px;
  margin-top: 4px;
  border: 0;
  border-radius: 2px;
  background: var(--dsu-line);
  overflow: hidden;
  appearance: none;
}

.task-progress::-webkit-progress-bar { background: var(--dsu-line); }
.task-progress::-webkit-progress-value { background: var(--dsu-blue); }
.task-progress::-moz-progress-bar { background: var(--dsu-blue); }
.task-progress.is-over::-webkit-progress-value { background: var(--dsu-red); }
.task-progress.is-over::-moz-progress-bar { background: var(--dsu-red); }

/* ---- The active task on the employee dashboard ---- */

.active-task {
  border-top: 3px solid var(--dsu-blue);
}

.active-task.is-overdue {
  border-top-color: var(--dsu-red);
}

.active-task .active-task-timer {
  font-size: 28px;
  font-weight: 500;
  line-height: 1.1;
}

.active-task .active-task-facts {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px 16px;
  margin: 16px 0;
}

@media (min-width: 768px) {
  .active-task .active-task-facts {
    grid-template-columns: repeat(4, 1fr);
  }
}

.active-task .active-task-facts dt {
  font-size: 11px;
  font-weight: 400;
  color: var(--dsu-ink-3);
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.active-task .active-task-facts dd {
  margin: 0;
}

.list-group-item.item-attention {
  box-shadow: inset 3px 0 0 0 var(--dsu-red);
}

/* ---- Password rules on the admin change-password form ---- */

.password-rules li {
  position: relative;
  padding-left: 1.3em;
  color: var(--dsu-ink-3);
}

.password-rules li::before {
  content: "\25CB";
  position: absolute;
  left: 0;
}

.password-rules li.is-met {
  color: var(--dsu-green);
}

.password-rules li.is-met::before {
  content: "\2713";
}

/* ---- Task status: one look per stage, on every screen ----
   To Do, On Hold, In Process, Code Review, Testing / UAT, Done. The text always says the
   status, so the colour is an aid and never the only signal. */

.status-badge {
  font-weight: 500;
  border: 1px solid transparent;
}

.status-badge.stage-todo { background: #f2f2f2; color: #4a4a4a; border-color: var(--dsu-line); }
.status-badge.stage-onhold { background: var(--dsu-amber-light); color: var(--dsu-amber); }
.status-badge.stage-inprocess { background: var(--dsu-blue-light); color: var(--dsu-blue-active); }
.status-badge.stage-codereview { background: #efe7fb; color: #5b3a9e; }
.status-badge.stage-testing { background: #e0f3f3; color: #0b6466; }
.status-badge.stage-done { background: var(--dsu-green-light); color: var(--dsu-green); }

/* The status control on the task list wears the badge's colours (docs/PERMISSIONS.md: an employee
   changes the status of their own work from here). The flat background above wipes out the caret
   Bootstrap draws as a background image, so it is put back — after, and more specific, or the
   badge colour would win and the control would look like a flat field. */
select[class*="stage-"].status-badge {
  background-image: var(--bs-form-select-bg-img);
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  background-size: 14px 11px;
  padding-right: 2rem;
}

.stage-dot {
  display: inline-block;
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.stage-dot.stage-todo { background: #8a8a8a; }
.stage-dot.stage-onhold { background: #b26a00; }
.stage-dot.stage-inprocess { background: #1a76d1; }
.stage-dot.stage-codereview { background: #6f42c1; }
.stage-dot.stage-testing { background: #0b7a7c; }
.stage-dot.stage-done { background: #2e7d32; }

/* ---- The board: six stages in one row that scrolls sideways ---- */

.kanban-board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(260px, 1fr);
  gap: 1rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
  -webkit-overflow-scrolling: touch;
}

/* On a phone the columns stack, as before. */
@media (max-width: 767.98px) {
  .kanban-board {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    overflow-x: visible;
  }
}

.kanban-board .kanban-drop {
  min-height: 120px;
}

/* ---- Task tags ---- */

.tag-chip {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border: 1px solid var(--dsu-line);
  border-radius: 999px;
  background: #f3f4f6;
  color: var(--dsu-ink-2);
  font-size: 11.5px;
  line-height: 1.6;
  text-decoration: none;
  white-space: nowrap;
}

a.tag-chip:hover,
a.tag-chip:focus-visible {
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
}

button.tag-chip {
  cursor: pointer;
}

/* ---- The task somebody is working on now ----
   Blue, with a ribbon that says who and since when. Red stays the only colour for "act now". */

.task-card.is-active,
.kanban-board .card.is-active {
  border-color: var(--dsu-blue);
  box-shadow: 0 0 0 2px rgba(26, 118, 209, 0.22);
}

.task-active-ribbon {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  background: var(--dsu-blue);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
}

.task-active-ribbon time {
  color: #fff;
}

.pulse-dot {
  display: inline-block;
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  animation: dsu-pulse 1.6s ease-in-out infinite;
}

@keyframes dsu-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

@media (prefers-reduced-motion: reduce) {
  .pulse-dot { animation: none; }
}

.table tr.row-active > * {
  background-color: var(--dsu-blue-light);
  box-shadow: inset 3px 0 0 0 var(--dsu-blue);
}

.list-group-item.is-active-row {
  box-shadow: inset 3px 0 0 0 var(--dsu-blue);
}

/* The signed-in employee's own running task on the board: a heavier ring and a tinted body,
   so it stands out from teammates' running tasks, which keep the lighter blue outline. */
.kanban-board .card.is-active.is-mine {
  border-width: 2px;
  background: var(--dsu-blue-light);
  box-shadow: 0 0 0 3px rgba(26, 118, 209, 0.35), 0 4px 12px rgba(26, 118, 209, 0.18);
}

.kanban-board .card.is-active.is-mine .task-active-ribbon {
  background: var(--dsu-blue-active);
}

/* ---- Assignees: chips (_AssigneeList) and the picker (_AssigneePicker) ----
   A task can have several people; each is a small chip with an initial. A chip with a pulsing
   dot is somebody working on the task right now. */

.assignee-stack {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  vertical-align: middle;
}

.assignee-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  padding: 1px 8px 1px 2px;
  border: 1px solid var(--dsu-line);
  border-radius: 999px;
  background: #fff;
  color: var(--dsu-ink);
  font-size: 12px;
  line-height: 1.6;
  white-space: nowrap;
}

.assignee-chip-avatar {
  display: inline-grid;
  place-items: center;
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
  font-size: 10px;
  font-weight: 700;
}

.assignee-chip.is-working {
  border-color: var(--dsu-blue);
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
  font-weight: 600;
}

.assignee-chip.is-working .assignee-chip-avatar {
  background: var(--dsu-blue);
  color: #fff;
}

.assignee-chip .pulse-dot {
  width: 6px;
  height: 6px;
  color: var(--dsu-blue);
}

.assignee-chip-remove {
  margin-left: 2px;
  padding: 0 2px;
  border: 0;
  background: transparent;
  color: var(--dsu-ink-3);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.assignee-chip-remove:hover,
.assignee-chip-remove:focus-visible {
  color: var(--dsu-red);
}

.assignee-picker {
  display: grid;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--dsu-line-strong);
  border-radius: var(--bs-border-radius);
  background: #fff;
}

.is-invalid-group .assignee-picker {
  border-color: var(--dsu-red);
}

.assignee-picker-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 24px;
  align-items: center;
}

/* Project estimate: the unit and the amount side by side, half each. */
.estimate-input > .estimate-unit,
.estimate-input > [data-estimate-amount] {
  flex: 1 1 50%;
  min-width: 0;
}

/* Chosen people in the picker: brand blue, so a selection reads as chosen at a glance. */
.assignee-picker .assignee-chip {
  border-color: var(--dsu-blue-tint);
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
  font-weight: 600;
}

.assignee-picker .assignee-chip-avatar {
  background: var(--dsu-blue);
  color: #fff;
}

.assignee-picker .assignee-chip-remove {
  color: var(--dsu-blue-active);
}

.assignee-option:has(input:checked) .form-check-input {
  box-shadow: 0 0 0 0.15rem rgba(26, 118, 209, 0.2);
}

.assignee-picker-none {
  font-size: 12.5px;
  color: var(--dsu-ink-3);
}

.assignee-picker-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 2px 8px;
  max-height: 190px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.assignee-picker.is-compact .assignee-picker-list {
  max-height: 130px;
}

.assignee-option {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 5px 8px;
  border-radius: var(--bs-border-radius-sm);
  cursor: pointer;
  font-size: 13px;
}

.assignee-option:hover {
  background: var(--dsu-surface-2);
}

.assignee-option:has(input:checked) {
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
  font-weight: 500;
}

.assignee-option .form-check-input {
  margin: 0;
  flex: 0 0 auto;
}

.assignee-option-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.assignee-picker-empty {
  grid-column: 1 / -1;
  padding: 6px 8px;
}

/* ---- Adjust balance dialog: the balance it starts from and recent adjustments ---- */

.adjust-context-panel {
  padding: 12px 14px;
  border: 1px solid var(--dsu-line);
  border-radius: var(--bs-border-radius);
  background: var(--dsu-surface-2);
}

.adjust-context-balance {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 8px 16px;
  padding-bottom: 10px;
  border-bottom: 1px dashed var(--dsu-line-strong);
}

.adjust-context-figure {
  font-size: 22px;
  font-weight: 700;
  color: var(--dsu-ink);
}

.adjust-context-list li {
  padding: 4px 0;
  border-bottom: 1px solid var(--dsu-line);
}

.adjust-context-list li:last-child {
  border-bottom: 0;
}

/* ---- The common board of all projects: each card names its project ---- */

.kanban-card-project {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 4px 10px;
  font-size: 11.5px;
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
  border-bottom: 1px solid var(--dsu-line);
  border-radius: calc(var(--bs-border-radius-lg) - 1px) calc(var(--bs-border-radius-lg) - 1px) 0 0;
}

.kanban-card-project .mono {
  font-weight: 600;
}

/* Time on a task, person by person, in the admin time panel. */
.punch-panel .punch-person {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border: 1px solid var(--punch-tile-line);
  border-radius: 999px;
  background: var(--punch-tile);
  color: var(--punch-ink-2);
  font-size: 12.5px;
}

.punch-panel .punch-status .pulse-dot {
  color: #7cc0ff;
  margin-right: 4px;
}

/* ---- The employee's own running task, above lists and boards (_ActiveTaskBanner) ---- */

.active-task-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
  padding: 10px 14px;
  border: 1px solid var(--dsu-blue);
  border-left-width: 4px;
  border-radius: var(--bs-border-radius-lg);
  background: var(--dsu-blue-light);
}

.active-task-banner.is-overdue {
  border-color: var(--dsu-red);
  background: var(--dsu-red-light);
}

.active-task-banner-main {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  min-width: 0;
}

.active-task-banner-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--dsu-blue-active);
  font-weight: 600;
  font-size: 13px;
}

.active-task-banner.is-overdue .active-task-banner-label {
  color: var(--dsu-red);
}

.active-task-banner-link {
  font-weight: 600;
  color: var(--dsu-ink);
  overflow-wrap: anywhere;
}

.active-task-banner-meta {
  font-size: 12.5px;
  color: var(--bs-secondary-color);
}

.active-task-banner-hint {
  flex-basis: 100%;
  font-size: 12px;
  color: var(--bs-tertiary-color);
}

.active-task-banner-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* The strip above the board: every task being worked on, whichever column it is in. */
.kanban-active {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 8px 12px;
  border: 1px solid var(--dsu-blue);
  border-radius: var(--bs-border-radius-lg);
  background: var(--dsu-blue-light);
}

.kanban-active-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--dsu-blue-active);
  font-weight: 600;
  font-size: 13px;
}

.kanban-active-item {
  color: var(--dsu-ink);
  font-size: 13px;
  text-decoration: none;
}

.kanban-active-item:hover {
  text-decoration: underline;
}

.kanban-active-meta {
  color: var(--dsu-ink-3);
}

/* ==========================================================================
   Admin dashboard (docs/DASHBOARD-METRICS.md)
   Alert chips, the six KPI cards, the team table and the small charts. Built
   from the same tokens as everything else, so the page stays part of the set.
   ========================================================================== */

.dash-chip {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 16px;
  border: 1px solid var(--dsu-line);
  background: #fff;
  color: var(--dsu-ink-2);
  font-size: 12.5px;
  font-weight: 500;
  text-decoration: none;
}

.dash-chip:hover {
  text-decoration: none;
  filter: brightness(0.97);
}

.dash-chip-r {
  background: var(--dsu-red-light);
  color: var(--dsu-red);
  border-color: transparent;
}

.dash-chip-a {
  background: var(--dsu-amber-light);
  color: var(--dsu-amber);
  border-color: transparent;
}

.dash-kpis {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
}

.dash-kpi {
  display: block;
  background: #fff;
  border: 1px solid var(--dsu-line);
  border-top: 4px solid var(--dsu-blue);
  border-radius: 10px;
  padding: 14px 16px;
  color: inherit;
  text-decoration: none;
  min-width: 0;
}

.dash-kpi:hover {
  text-decoration: none;
  box-shadow: var(--dsu-shadow);
}

.dash-kpi-g { border-top-color: var(--dsu-green); }
.dash-kpi-r { border-top-color: var(--dsu-red); }
.dash-kpi-a { border-top-color: var(--dsu-amber); }
.dash-kpi-k { border-top-color: #111827; }

.dash-kpi-value {
  font-size: 26px;
  font-weight: 600;
  line-height: 1.1;
}

.dash-kpi-value small {
  font-size: 12px;
  font-weight: 500;
  color: var(--dsu-ink-3);
}

.dash-kpi-label {
  font-size: 13px;
  font-weight: 500;
  margin-top: 3px;
}

.dash-kpi-detail {
  font-size: 11.5px;
  color: var(--dsu-ink-3);
  margin-top: 5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-kpi-detail.is-bad {
  color: var(--dsu-red);
  font-weight: 600;
}

/* ---- team table ---- */

.dash-filter {
  border: 1px solid var(--dsu-line);
  background: #fff;
  border-radius: 14px;
  padding: 3px 10px;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--dsu-ink-2);
}

.dash-filter.is-on {
  background: #111827;
  border-color: #111827;
  color: #fff;
}

.dash-team tr.dash-bad > td,
tr.dash-bad > td {
  background: var(--dsu-red-light);
}

tr.dash-bad > td:first-child {
  box-shadow: inset 3px 0 0 var(--dsu-red);
}

.dash-who {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

.dash-who-text {
  min-width: 0;
}

.dash-who-text small {
  max-width: 260px;
}

.dash-avatar {
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--dsu-blue);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
}

.dash-dot {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid #fff;
  background: var(--dsu-green);
}

.dash-dot-a { background: var(--dsu-amber); }
.dash-dot-r { background: var(--dsu-red); }
.dash-dot-b { background: var(--dsu-blue); }
.dash-dot-g { background: #bbb; }

.dash-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.dash-p-g { background: var(--dsu-green-light); color: var(--dsu-green); }
.dash-p-a { background: var(--dsu-amber-light); color: var(--dsu-amber); }
.dash-p-r { background: var(--dsu-red-light); color: var(--dsu-red); }
.dash-p-b { background: var(--dsu-blue-light); color: var(--dsu-blue-active); }
.dash-p-k { background: #eef0f3; color: var(--dsu-ink-2); }

/* ---- attention list ---- */

.dash-attention {
  display: flex;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--dsu-line);
  color: inherit;
  text-decoration: none;
}

.dash-attention:last-child { border-bottom: 0; }

.dash-attention:hover {
  text-decoration: none;
  background: var(--dsu-surface-2);
}

.dash-attention b { font-size: 12.5px; font-weight: 500; }

.dash-attention-icon {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-size: 13px;
}

.dash-ic-r { background: var(--dsu-red-light); }
.dash-ic-a { background: var(--dsu-amber-light); }
.dash-ic-b { background: var(--dsu-blue-light); }

/* ---- bars, sparkline and doughnut ---- */

.dash-hbar {
  display: grid;
  grid-template-columns: 110px 1fr 78px;
  gap: 8px;
  align-items: center;
  padding: 4px 0;
  font-size: 12px;
}

.dash-bar {
  display: block;
  height: 10px;
  background: #eef0f3;
  border-radius: 3px;
  overflow: hidden;
  min-width: 60px;
}

.dash-bar-fill {
  display: block;
  height: 100%;
  background: var(--dsu-blue);
}

.dash-bar-r { background: var(--dsu-red); }
.dash-bar-a { background: var(--dsu-amber); }
.dash-bar-g { background: var(--dsu-green); }

.dash-spark {
  width: 100%;
  height: 110px;
}

.dash-donut {
  width: 110px;
  height: 110px;
  flex: none;
}

.dash-key {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 4px;
}

.dash-key-task { background: var(--dsu-blue); }
.dash-key-idle { background: #b26a00; }
.dash-key-break { background: #f2c94c; }

@media (max-width: 1399.98px) {
  .dash-kpis { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 575.98px) {
  .dash-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* Punch-out attachments (docs/ATTENDANCE-ATTACHMENTS.md): a quiet drop target that says what
   to do, and turns blue when something is dragged over it. */
.punch-drop {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 14px;
  border: 1px dashed var(--dsu-line-strong);
  border-radius: 8px;
  background: var(--dsu-surface-2);
  color: var(--dsu-ink-3);
  font-size: 12.5px;
}

.punch-drop.is-over {
  border-color: var(--dsu-blue);
  background: var(--dsu-blue-light);
  color: var(--dsu-blue-active);
}

/* ==========================================================================
   Daily work log report (docs/DAILY-WORKLOG.md): a day row with its task,
   break and note rows indented under it, and a print layout that breaks
   between employees.
   ========================================================================== */

.worklog tr.worklog-day > td {
  background: #f7f9fc;
  font-weight: 500;
  border-top: 2px solid var(--dsu-line);
}

.worklog tr.worklog-bad > td,
tr.worklog-bad > td {
  background: var(--dsu-red-light);
}

tr.worklog-bad > td:first-child {
  box-shadow: inset 3px 0 0 var(--dsu-red);
}

.worklog tr.worklog-note > td {
  background: #fffdf5;
}

.worklog tr.worklog-found > td {
  outline: 2px solid var(--dsu-blue);
  outline-offset: -2px;
}

.worklog-who {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  color: var(--dsu-ink);
}

.worklog-file {
  display: inline-block;
  border: 1px solid var(--dsu-line);
  border-radius: 4px;
  padding: 1px 7px;
  margin: 0 4px 0 0;
  font-size: 11px;
  background: #fff;
  text-decoration: none;
}

.worklog-file:hover {
  border-color: var(--dsu-blue);
  text-decoration: none;
}

/* An image file on the end-of-day note shows itself; clicking it opens the lightbox. */
.worklog-file .worklog-file-thumb {
  display: inline-block;
  width: 32px;
  height: 32px;
  object-fit: cover;
  border-radius: 3px;
  margin: 2px 4px 2px 0;
  vertical-align: middle;
  cursor: zoom-in;
}

@media print {
  /* A day collapsed on screen still prints: paper has no expand button. */
  .worklog tr[hidden] {
    display: table-row;
  }

  /* One employee per page, so a printed log can be handed round. */
  .worklog tr.worklog-day {
    break-before: page;
  }

  .worklog tr.worklog-day:first-child {
    break-before: auto;
  }

  .worklog tr {
    break-inside: avoid;
  }
}

/* ==========================================================================
   Task description: the editor (docs/TASK-DESCRIPTION.md) and what it writes.
   ========================================================================== */

.ck-editor__editable_inline {
  min-height: 160px;
}

.rich-text > :last-child {
  margin-bottom: 0;
}

.rich-text h3,
.rich-text h4 {
  font-size: 1rem;
  font-weight: 600;
  margin-top: 0.75rem;
}

.rich-text ul,
.rich-text ol {
  padding-left: 1.25rem;
  margin-bottom: 0.5rem;
}

.rich-text blockquote {
  border-left: 3px solid var(--dsu-line);
  padding-left: 0.75rem;
  margin-bottom: 0.5rem;
}
/* ==========================================================================
   Inline images — pasted or dropped into a description, a comment or the chat.
   ========================================================================== */

/* Every image inside rendered content, however it got there.

   Matched on the container rather than on a class: CKEditor writes a bare <img>
   inside <figure class="image">, with no class of its own, so a rule written
   only for .inline-image left description images completely unconstrained — a
   pasted 3000 px screenshot then filled the card and was cut off (TSK-0003).
   The container rules below are what actually hold the width. */
.inline-image,
.rich-text img,
.comment-body img,
.chat-bubble img {
  max-width: 100%;
  height: auto;
  max-height: 480px;
  object-fit: contain;
  border-radius: 6px;
  cursor: zoom-in;
}

.inline-image,
.rich-text img,
.comment-body img {
  border: 1px solid var(--dsu-line);
}

/* Room around an image in a body of text — but not around a thumbnail in a row
   of attachments or a chip, which have their own spacing. */
.rich-text img,
.comment-body img {
  margin: 0.5rem 0;
}

/* Block images stand on their own line; an image the author chose to put in
   line with the text stays in the text. */
.inline-image,
.rich-text figure.image img,
.comment-body figure.image img {
  display: block;
}

/* CKEditor's own wrapper. display:table is what the editor itself uses, so the
   figure hugs the image and a centred one is centred on the image, not on an
   invisible full-width box. */
.rich-text figure.image,
.comment-body figure.image {
  display: table;
  max-width: 100%;
  margin: 0.5rem 0;
}

.rich-text figure.image img,
.comment-body figure.image img {
  margin: 0;
}

/* An image the author resized in the editor carries its own width, as a
   percentage of the column. That has to win over the bounds above — but only
   downwards: max-width still stops it leaving the card. The img fills the
   figure it was given, which is how it looked while it was being dragged. */
.rich-text figure.image[style*="width"],
.comment-body figure.image[style*="width"],
.rich-text img[style*="width"],
.comment-body img[style*="width"] {
  height: auto;
  max-height: none;
}

.rich-text figure.image[style*="width"] img,
.comment-body figure.image[style*="width"] img {
  width: 100%;
  max-height: none;
}

/* Where the editor put it. The class names are CKEditor's own — see the
   ImageStyle options in rich-text.js, which is what decides the choices offered.
   A plain <figure class="image"> with no alignment class is the centred default. */
.rich-text figure.image,
.comment-body figure.image {
  margin-left: auto;
  margin-right: auto;
}

.rich-text figure.image-style-block-align-left,
.comment-body figure.image-style-block-align-left {
  margin-left: 0;
  margin-right: auto;
}

.rich-text figure.image-style-block-align-right,
.comment-body figure.image-style-block-align-right {
  margin-left: auto;
  margin-right: 0;
}

/* An image set in line with the text: no line of its own, no block margins. */
.rich-text p > img,
.comment-body p > img {
  display: inline-block;
  vertical-align: baseline;
  margin: 0 0.25rem;
}

.rich-text img.image-style-align-left,
.comment-body img.image-style-align-left {
  float: left;
  margin: 0.25rem 1rem 0.25rem 0;
}

.rich-text img.image-style-align-right,
.comment-body img.image-style-align-right {
  float: right;
  margin: 0.25rem 0 0.25rem 1rem;
}

/* A thumbnail beside a task in a list, or in a notification: small enough that a
   row stays a row. */
.inline-image-preview {
  width: 32px;
  height: 32px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--dsu-line);
  flex: 0 0 auto;
  cursor: zoom-in;
}

/* Several images on one comment sit in a row and wrap, rather than stacking
   into a wall of full-width pictures. */
.inline-images {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 0.5rem;
}

.inline-images .inline-image {
  max-width: 220px;
  max-height: 220px;
  object-fit: cover;
  margin: 0;
}

.chat-image {
  max-width: min(320px, 100%);
  max-height: 320px;
  margin-top: 4px;
}

.attachment-thumb {
  width: 40px;
  height: 40px;
  object-fit: cover;
  flex: 0 0 auto;
}

/* ---- The strip under a comment box or chat input, while composing ---- */

.inline-image-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.inline-image-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  border: 1px solid var(--dsu-line);
  border-radius: 8px;
  background: var(--dsu-surface, #fff);
}

.inline-image-chip.is-uploading {
  padding: 6px 10px;
  font-size: 0.8125rem;
  color: var(--dsu-muted, #6c757d);
}

.inline-image-chip-name {
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.inline-image-chip-thumb {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 6px;
  display: block;
}

/* Small, but still a 24px target — this is tapped on a phone. */
.inline-image-chip-remove {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 24px;
  height: 24px;
  line-height: 1;
  border: 1px solid var(--dsu-line);
  border-radius: 50%;
  background: #fff;
  color: #333;
  cursor: pointer;
  padding: 0;
}

.inline-image-chip-remove:hover,
.inline-image-chip-remove:focus {
  background: var(--dsu-red, #dc3545);
  color: #fff;
}

/* A box being dragged over. Matches the attachments zone's own cue. */
.is-drop-target {
  outline: 2px dashed var(--dsu-blue);
  outline-offset: -2px;
}

/* ---- The lightbox ---- */

.image-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1080;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, 0.82);
}

.image-lightbox-figure {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.image-lightbox-img {
  max-width: 100%;

  /* Room for the caption and the buttons underneath, on a phone too. */
  max-height: calc(100vh - 140px);
  object-fit: contain;
  border-radius: 6px;
  background: #fff;
}

.image-lightbox-caption {
  color: #fff;
  font-size: 0.875rem;
  text-align: center;
  word-break: break-all;
}

.image-lightbox-bar {
  display: flex;
  gap: 8px;
}

/* The page behind must not scroll while the lightbox is open. */
body.lightbox-open {
  overflow: hidden;
}

/* ==========================================================================
   Work entries — the day as a bar, and the status of each entry.
   ========================================================================== */

.work-timeline {
  position: relative;
  height: 34px;
  border-radius: 6px;
  background: var(--dsu-line, #e5e7eb);
  overflow: hidden;
}

.work-block {
  position: absolute;
  top: 0;
  bottom: 0;
  min-width: 2px;
  border-right: 1px solid rgba(255, 255, 255, 0.6);
}

/* A block that stands for an entry can be clicked open. */
.work-block[data-entry-open] { cursor: pointer; }
.work-block[data-entry-open]:hover { filter: brightness(0.92); }

/* The colours the mock-up uses: timer blue, manual purple, edited amber,
   break yellow, unaccounted grey. */
.work-auto,
.work-approved  { background: #2563eb; }
.work-pending   { background: #7c3aed; }
.work-edited    { background: #d97706; }
.work-break     { background: #facc15; }
.work-gap       { background: #9ca3af; }
.work-running   { background: #2563eb; opacity: 0.55; }
.work-rejected  { background: #dc2626; }

.work-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  color: var(--dsu-muted, #6c757d);
}

.work-key {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  margin-right: 4px;
  vertical-align: middle;
}

/* ---- status pills, matching the blocks ---- */

.work-pill { color: #fff; font-weight: 500; }

.work-pill-auto,
.work-pill-approved { background: #16a34a; }
.work-pill-pending  { background: #d97706; }
.work-pill-edited   { background: #d97706; }
.work-pill-rejected { background: #dc2626; }
.work-pill-running  { background: #2563eb; }

/* A row's own tint, so a table of entries reads at a glance. */
.work-row-pending,
.work-row-edited  { background: rgba(217, 119, 6, 0.06); }
.work-row-rejected { background: rgba(220, 38, 38, 0.06); }

/* ---- the live validation line in the modal ---- */

.work-check-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.work-check-list li { padding: 1px 0; }
.work-check-list .ok { color: #15803d; }
.work-check-list .bad { color: #b91c1c; font-weight: 500; }
