/* Admin web app -- desktop-oriented (replaces DXS.exe), same color language
   as the worker portal's style.css (navy header, light gray background,
   white cards) but a sidebar layout instead of mobile tabs. */
* { box-sizing: border-box; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; }
body { background: #f2f4f8; color: #16181d; }
.hidden { display: none !important; }
.muted { color: #667085; font-size: 14px; }
.error { color: #b42318; font-size: 14px; margin-top: 8px; }

/* Login (same card pattern as the worker portal) */
#login-view { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px; }
.login-card { background: #fff; border-radius: 12px; padding: 28px 24px; width: 100%; max-width: 360px;
              box-shadow: 0 4px 16px rgba(16, 24, 40, .08); }
.login-card h1 { font-size: 22px; margin-bottom: 4px; }
.login-card p { margin-bottom: 16px; }
label { display: block; font-size: 14px; font-weight: bold; margin-bottom: 12px; }
input, select { width: 100%; padding: 8px 10px; margin-top: 4px; border: 1px solid #d0d5dd; border-radius: 8px; font-size: 15px; }
/* "Remember me" row: inline checkbox + normal-weight text (overrides the
   block/bold label default and the input width:100% rule above). */
.remember-label { display: flex; align-items: center; gap: 8px; font-weight: normal; cursor: pointer; }
.remember-label input[type="checkbox"] { width: auto; margin: 0; }
button { cursor: pointer; }
button[type="submit"], .btn-primary { padding: 10px 16px; background: #1f2a44; color: #fff; border: 0; border-radius: 8px;
                        font-size: 15px; font-weight: bold; }
.btn-secondary { padding: 10px 16px; background: #eef1f6; color: #1f2a44; border: 0; border-radius: 8px; font-size: 15px; }
.btn-danger { padding: 6px 12px; background: #fee4e2; color: #b42318; border: 0; border-radius: 8px; font-size: 13px; font-weight: bold; }
.btn-small { padding: 4px 10px; font-size: 13px; border-radius: 6px; }

/* App shell: sidebar + content */
#app-view { display: flex; min-height: 100vh; }
#sidebar { background: #1f2a44; color: #fff; width: 200px; flex: none; padding: 16px 0; position: sticky; top: 0;
           height: 100vh; overflow-y: auto; }
#sidebar h1 { font-size: 16px; padding: 0 16px 16px; color: #fff; }
#sidebar .whoami { padding: 0 16px 16px; font-size: 12px; color: #b7c0d8; border-bottom: 1px solid #2a3757; margin-bottom: 8px; }
.nav-link { display: block; width: 100%; text-align: left; padding: 10px 16px; background: none; border: 0;
            color: #cdd5e8; font-size: 14px; font-weight: bold; }
.nav-link.active { background: #2a3757; color: #fff; border-left: 3px solid #fff; }
.nav-link.logout { color: #ffb4a9; margin-top: 12px; }
a.nav-link { text-decoration: none; }
.nav-link.nav-external { color: #9fb0d6; }
.sidebar-version { padding: 12px 16px 0; font-size: 11px; color: #6b7699; }
/* Sidebar section groups (2026-07-22: Schedule / HR) -- native <details>/
   <summary> disclosures, collapsed by default (app.js opens the relevant one
   when a tab inside it becomes active). Dashboard and Information stay
   outside any group, flush with the section labels. */
.nav-group { width: 100%; }
.nav-section { display: flex; align-items: center; justify-content: center; gap: 6px;
               padding: 14px 16px 4px; font-size: 11px; font-weight: bold; text-transform: uppercase;
               letter-spacing: .6px; color: #7b88ab; cursor: pointer; list-style: none; user-select: none; }
.nav-section::-webkit-details-marker { display: none; }
.nav-section::marker { content: ""; }
/* Custom disclosure chevron, rotates open (::after avoids the native marker
   entirely, so it looks the same across browsers). */
.nav-section::after { content: "\25B8"; font-size: 10px; transition: transform .15s ease; }
.nav-group[open] > .nav-section::after { transform: rotate(90deg); }
.nav-link.nav-sub { padding-left: 28px; }
.nav-link.nav-sub.active { border-left-width: 3px; padding-left: 25px; }
/* flex:1 + min-width:0 lets the content area both fill the whole window on
   wide screens (no fixed max-width cap) and shrink below its content's
   intrinsic width on narrow ones, so a wide table scrolls inside its own
   overflow-x wrapper instead of forcing the whole page to scroll sideways. */
#content { flex: 1; min-width: 0; padding: 20px 28px; }
#content h2 { font-size: 20px; margin-bottom: 16px; }
/* Wide tables/grids scroll inside their own box; page body never scrolls x. */
.table-scroll { overflow-x: auto; }

/* Data table */
table.admin-table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 10px; overflow: hidden;
                     box-shadow: 0 1px 3px rgba(16, 24, 40, .07); }
table.admin-table th { background: #eef1f6; text-align: left; padding: 8px 10px; font-size: 12px; text-transform: uppercase;
                        color: #667085; letter-spacing: .3px; }
table.admin-table td { padding: 8px 10px; font-size: 14px; border-top: 1px solid #eef1f6; }
table.admin-table tr:hover td { background: #f8fafc; }
.row-link { color: #175cd3; font-weight: bold; text-decoration: underline; background: none; border: 0; font-size: 14px; cursor: pointer; padding: 0; }
.toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; gap: 8px; }
.toolbar-right { display: flex; gap: 8px; }

/* Modal (plain JS show/hide -- see app.js) */
#modal-overlay { position: fixed; inset: 0; background: rgba(16, 24, 40, .45); display: flex; align-items: flex-start;
                 justify-content: center; padding: 40px 16px; z-index: 20; overflow-y: auto; }
#modal-card { background: #fff; border-radius: 12px; padding: 22px 24px; width: 100%; max-width: 480px; }
#modal-card h3 { font-size: 17px; margin-bottom: 14px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.form-grid label { grid-column: span 1; }
.form-wide { grid-column: 1 / -1; }

/* Credential reveal panel (shown once after creating/resetting a login) */
.credential-panel { background: #fff8e1; border: 1px solid #f4d35e; border-radius: 8px; padding: 14px; margin-bottom: 12px; }
.credential-panel .cred-row { font-family: monospace; font-size: 14px; margin-top: 4px; }

/* Schedule tab's sub-tabs (Schedule grid / Teams, 2026-07-23 merge) --
   plain client-side show/hide (app.js), not htmx-backed like the top-level
   sidebar tabs, since both sub-panels arrive in the same response. */
.subtab-bar { display: flex; gap: 6px; margin-bottom: 14px; }
.subtab-link { padding: 8px 18px; background: #eef1f6; color: #1f2a44; border: 0;
               border-radius: 8px 8px 0 0; font-size: 14px; font-weight: bold; }
.subtab-link.active { background: #1f2a44; color: #fff; }

/* Schedule grid */
.schedule-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.status-pill { padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: bold; }
.status-pill.empty { background: #eef1f6; color: #667085; }
.status-pill.draft { background: #fef0c7; color: #b54708; }
.status-pill.published { background: #d1fadf; color: #067647; }
.schedule-grid { display: flex; flex-direction: column; gap: 10px; }
.schedule-day { background: #fff; border: 1px solid #c9d0dc; border-radius: 10px; padding: 10px 14px;
                box-shadow: 0 2px 8px rgba(16, 24, 40, .14);
                display: flex; flex-direction: column; gap: 6px; }
.schedule-day .day-label { font-weight: bold; font-size: 14px; }
/* Date shown same size + weight as the weekday name (2026-07-19 request) so
   it's easy to read at a glance; drops the old smaller muted-gray styling. */
.schedule-day .day-label .weekday { display: block; font-weight: bold; color: inherit; font-size: inherit; }
/* Day and night shift side by side within each day cell (2026-07 request). */
.shift-row { display: flex; gap: 8px; align-items: stretch; }
.shift-row .slot-box { flex: 1 1 0; min-width: 0; }
.slot-box { border-radius: 8px; padding: 8px 10px; font-size: 13px; background: #eef1f6; border: 1px solid rgba(16, 24, 40, .12); }
.slot-box .slot-title { font-size: 12px; font-weight: bold; color: #475467; margin-bottom: 5px; }
.slot-entry { display: inline-block; margin: 2px 4px 2px 0; padding: 2px 8px; border-radius: 999px; background: #eef1f6;
              cursor: pointer; border: 0; font-size: 12px; color: #16181d; }
.slot-entry.leave { background: #fef0c7; }
.slot-entry.rest { background: #e0e7ff; }
.slot-entry.holiday-off { background: #fee4e2; }
.slot-entry.overtime { border: 1px solid #175cd3; }
.slot-entry.moved { text-decoration: underline; }
/* "Remove" status (2026-07-22): scheduled but did not work it (no-show, or
   before a mid-month hire's actual start) -- struck-through and dimmed
   rather than hidden, so it stays clickable to undo (set back to Normal). */
.slot-entry.removed { text-decoration: line-through; opacity: .55; }
.standby-row { font-size: 13px; color: #475467; margin-top: 10px; }

/* Teams drag-and-drop */
.teams-board { display: flex; gap: 12px; flex-wrap: wrap; }
.team-column { background: #fff; border-radius: 10px; padding: 10px; width: 200px; box-shadow: 0 1px 3px rgba(16, 24, 40, .07); min-height: 160px; }
.team-column h4 { font-size: 13px; margin-bottom: 8px; }
.team-column.drag-over { outline: 2px dashed #175cd3; }
.member-chip { background: #f8fafc; border-radius: 6px; padding: 6px 8px; font-size: 13px; margin-bottom: 4px; cursor: grab; }
.member-chip.coordinator { border-left: 3px solid #175cd3; font-weight: bold; }

/* Salary grid */
table.salary-table input { width: 90px; padding: 4px 6px; font-size: 13px; }

/* Checks tab excess/leave-check color coding */
td.excess-green { background: #d7f5d3; }
td.excess-yellow { background: #fff3b0; }
td.excess-red { background: #ffd6d6; }

/* Fixed, site-wide team colors (2026-07 request, C/D swapped 2026-07-29) --
   Team A = sunflower yellow, B = navy blue, C = orange, D = green, no team
   = white. Used on the Teams board's column headers, the Schedule grid's
   shift boxes, and the Checks tab's Name column -- kept in sync with the
   worker portal's own copy of these colors in static/app.js. */
.team-badge { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 13px; }
.team-a { background: #ffd500; color: #16181d; }
.team-b { background: #00bcd4; color: #16181d; }
.team-c { background: #ff8c00; color: #16181d; }
.team-d { background: #2e7d32; color: #fff; }
.team-unassigned { background: #ffffff; color: #16181d; border: 1px solid #d0d5dd; }
/* Slot-title text color per team (2026-08-05 supervisor request): the flat
   grey used everywhere had poor contrast against the lighter team colors
   (yellow/cyan/orange) -- reuse the same per-team contrast pairs
   .team-badge.team-* already establish below, instead of one grey for
   every background. */
.slot-box.team-a .slot-title { color: #4a3b00; }
.slot-box.team-b .slot-title { color: #003944; }
.slot-box.team-c .slot-title { color: #4a2600; }
.slot-box.team-d .slot-title { color: #fff; }
td.team-a, td.team-b, td.team-c, td.team-d, td.team-unassigned { font-weight: bold; }

/* On-duty headcount badge (2026-08-05 supervisor request): "a quick look to
   see how many will be on duty" -- next to the team letter on each shift box
   (count of entries actually marked worked, see payroll._slot_view) and next
   to each team's name on the Teams tab (team size). Fixed dark pill so it
   stays readable no matter which team color sits behind it, rather than
   needing its own per-team contrast tuning like the slot-title text above. */
.on-duty-count { display: inline-block; min-width: 16px; padding: 0 5px; border-radius: 999px;
                 background: rgba(16, 24, 40, .75); color: #fff; font-size: 11px; font-weight: bold;
                 text-align: center; vertical-align: middle; }

/* ----------------------------------------------------------------------
   Responsive: the shell is fluid by default (see #content above). Below
   ~820px the fixed navy sidebar turns into a wrapping top bar so the admin
   app stays usable on a tablet / phone / narrow window instead of leaving a
   cramped 200px column beside an unusable sliver of content.
   ---------------------------------------------------------------------- */
@media (max-width: 820px) {
  #app-view { flex-direction: column; min-height: 100vh; }
  #sidebar { position: static; width: auto; height: auto; overflow: visible;
             padding: 8px 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
  #sidebar h1 { width: 100%; padding: 4px 6px; margin: 0; }
  #sidebar .whoami { width: 100%; padding: 0 6px 6px; margin: 0; }
  .nav-link { width: auto; padding: 8px 12px; border-radius: 8px; }
  .nav-link.active { border-left: 0; background: #2a3757; }
  .nav-link.logout { margin-left: auto; }
  /* Section labels/indents only make sense in the vertical layout -- on the
     wrapping top bar every button sits at the same level, with just a small
     label chip ahead of its group. display:contents flattens each <details>
     so its summary/buttons become direct flex items of #sidebar again (the
     open/closed disclosure behavior itself is unaffected -- it hides/shows
     the children, not the group's own box). */
  .nav-group { display: contents; }
  .nav-section { width: auto; padding: 4px 4px; }
  .nav-link.nav-sub, .nav-link.nav-sub.active { padding-left: 12px; }
  #content { padding: 16px 14px; }
}

/* On a phone the 7-column week calendar can't stay readable at 1fr each, so
   let each week keep a sensible min width and scroll the grid horizontally. */
@media (max-width: 640px) {
  .schedule-grid { overflow-x: auto; }
  .schedule-week { min-width: 600px; }
  #content { padding: 14px 10px; }
  /* Three shift cards side by side get too narrow on a phone -- stack them. */
  .dash-shifts { grid-template-columns: 1fr; }
}

/* ---------- Fit-the-whole-month-on-one-screen (2026-07-19 request:
   "make the schedule fully visible on the screen when maximized").
   Only on a real desktop (>=821px, where the sidebar is a side column and
   doesn't eat vertical space -- below that the sidebar becomes a top bar and
   this height math wouldn't hold, so the normal vertical flow stays). The
   Schedule tab becomes a fixed-height flex column that fills the viewport
   (minus #content's 20px top/bottom padding); the week rows share the leftover
   height equally so all ~5-6 weeks are visible at once with no page scroll.
   Spacing/fonts are tightened to make a typical month fit comfortably, and any
   unusually dense day cell scrolls inside itself instead of pushing the page.
   Scoped to #tab-schedule so no other tab is affected. ---------- */
@media (min-width: 821px) {
  #tab-schedule { display: flex; flex-direction: column; height: calc(100vh - 40px); }
  /* #schedule-content (2026-07-30, wraps everything below for the
     refresh-schedule self-refresh listener) sits between #tab-schedule and
     h2/.subtab-bar/the sub-tab panels now -- it has to relay the flex
     column itself, or none of the flex/min-height rules below (which target
     h2/.subtab-bar/.schedule-subtab via descendant selectors that still
     match fine through the extra nesting) actually take effect, since flex
     item behavior only applies to DIRECT children of a flex container. */
  #tab-schedule > #schedule-content { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
  #schedule-content > h2 { flex: none; margin-bottom: 8px; }
  #tab-schedule .subtab-bar { flex: none; margin-bottom: 8px; }
  /* Whichever sub-tab (Schedule grid / Teams) is showing takes the rest of
     the height -- the .hidden utility (display:none !important) wins over
     this for the one not showing, same pattern as the top-level tabs. */
  #tab-schedule .schedule-subtab { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  #tab-schedule #schedule-subtab-teams { overflow-y: auto; }
  #tab-schedule .schedule-toolbar { flex: none; margin-bottom: 10px; }
  #tab-schedule .schedule-grid { flex: 1 1 auto; min-height: 0; gap: 6px; }
  #tab-schedule .schedule-week { flex: 1 1 0; min-height: 0; }
  /* Each day cell can shrink within its row and scrolls internally if it holds
     an unusually large crew, so the row height (and the page) never grows. */
  #tab-schedule .schedule-day { min-height: 0; overflow-y: auto; padding: 6px 10px; gap: 4px; }
  #tab-schedule .schedule-day.today { padding: 5px 9px; border-width: 2px; }
  #tab-schedule .schedule-day .day-label { font-size: 13px; }
  /* Date on the same line as the weekday name to save a row of height. */
  #tab-schedule .schedule-day .day-label .weekday { display: inline; margin-left: 6px; }
  #tab-schedule .standby-row { margin-top: 4px; font-size: 12px; }
  #tab-schedule .slot-box { padding: 5px 8px; }
  #tab-schedule .slot-box .slot-title { margin-bottom: 3px; }
  #tab-schedule .slot-entry { margin: 1px 3px 1px 0; padding: 1px 7px; font-size: 11px; }
}

/* Information tab: rich-text instructions editor (contenteditable) */
.rte-toolbar { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; background: #fff;
               border: 1px solid #c9d0dc; border-bottom: 0; border-radius: 10px 10px 0 0; padding: 6px 8px; }
.rte-toolbar button { padding: 4px 9px; background: #eef1f6; color: #1f2a44; border: 0; border-radius: 6px;
                      font-size: 13px; cursor: pointer; }
.rte-toolbar button:hover { background: #dfe5ee; }
.rte-toolbar select { width: auto; padding: 4px 6px; font-size: 13px; }
.rte-sep { width: 1px; align-self: stretch; background: #e4e7ec; margin: 0 4px; }
.rte-color { display: inline-flex; align-items: center; gap: 3px; font-size: 13px; font-weight: bold;
             cursor: pointer; padding: 0 2px; }
.rte-color input[type="color"] { width: 24px; height: 24px; padding: 0; border: 1px solid #c9d0dc;
                                 border-radius: 4px; background: none; cursor: pointer; }
.rte-editor { background: #fff; border: 1px solid #c9d0dc; border-radius: 0 0 10px 10px; min-height: 320px;
              padding: 14px 16px; font-size: 14px; line-height: 1.5; overflow-y: auto; overflow-wrap: break-word; }
.rte-editor:focus { outline: 2px solid #175cd3; outline-offset: -2px; }
.rte-editor h1 { font-size: 22px; margin: 10px 0 6px; }
.rte-editor h2 { font-size: 18px; margin: 10px 0 6px; }
.rte-editor h3 { font-size: 15px; margin: 8px 0 4px; }
.rte-editor p, .rte-editor div { margin: 4px 0; }
.rte-editor ul, .rte-editor ol { padding-left: 24px; margin: 6px 0; }
.rte-editor a { color: #175cd3; }
.rte-editor blockquote { border-left: 3px solid #c9d0dc; margin: 6px 0; padding: 2px 12px; color: #475467; }

/* Column visibility (2026-07-15, user request: "make the columns more
   visible" in all tabs): vertical separators between columns, a stronger
   line under the header row, and zebra striping so the eye can follow one
   row across a wide table (Personnel, Payroll, Logs...). Applies to every
   admin tab -- all of them render tables with this one class. */
table.admin-table th, table.admin-table td { border-right: 1px solid #dbe1ea; }
table.admin-table th:last-child, table.admin-table td:last-child { border-right: 0; }
table.admin-table th { border-bottom: 2px solid #b7c2d4; }
table.admin-table tbody tr:nth-child(even) td { background: #f4f7fb; }
table.admin-table tr:hover td { background: #e8eef7; }

/* Payroll (2026-07-31, user request: "make the tables fit the window"):
   S1 has 25 columns / S2-3 has 14 -- table-layout:auto (the admin-table
   default) sizes every column to its unwrapped header width, which is what
   pushed the S1 table past 2000px and forced horizontal scrolling on any
   normal screen. table-layout:fixed instead respects the panel's own width
   and wraps header text into it; Personal Number/Name get a fixed width
   since they're the only columns with real text, and the rest (all short
   numbers/euro amounts) split the remaining space evenly. */
table.payroll-table th, table.payroll-table td { font-size: 10.5px; padding: 4px 3px; white-space: nowrap; line-height: 1.2; }
table.payroll-table td { font-size: 11.5px; }
table.payroll-table th { white-space: normal; word-break: normal; overflow-wrap: break-word; }
table.payroll-table td:nth-child(2), table.payroll-table th:nth-child(2) { text-align: left; }
table.payroll-table td:nth-child(2) { white-space: normal; max-width: 125px; }

/* ...but a cell that carries a MEANINGFUL color must survive both of those
   (2026-07-21 bug: "the checks menu is buged, the colors are not correct").
   The striping/hover selectors above are more specific than the bare
   .team-a / .excess-* class selectors, so they were silently blanking the
   Checks tab's Name / Excess Shifts / Leave Check colors on every even row
   and on whatever row the mouse happened to be over. Restated here, after
   them, at matching specificity so the semantic color always wins. */
table.admin-table tbody tr td.team-a,
table.admin-table tbody tr:hover td.team-a { background: #ffd500; }
table.admin-table tbody tr td.team-b,
table.admin-table tbody tr:hover td.team-b { background: #00bcd4; }
table.admin-table tbody tr td.team-c,
table.admin-table tbody tr:hover td.team-c { background: #ff8c00; }
table.admin-table tbody tr td.team-d,
table.admin-table tbody tr:hover td.team-d { background: #2e7d32; }
table.admin-table tbody tr td.team-unassigned,
table.admin-table tbody tr:hover td.team-unassigned { background: #ffffff; }
table.admin-table tbody tr td.excess-green,
table.admin-table tbody tr:hover td.excess-green { background: #d7f5d3; }
table.admin-table tbody tr td.excess-yellow,
table.admin-table tbody tr:hover td.excess-yellow { background: #fff3b0; }
table.admin-table tbody tr td.excess-red,
table.admin-table tbody tr:hover td.excess-red { background: #ffd6d6; }

/* ---------- connection-problem banner + in-flight indicators (2026-07-16,
   slow/frozen Schedule complaint): the banner surfaces network drops and
   timeouts that htmx used to swallow silently; the spinner on nav links and
   dimmed buttons make a slow load through the Funnel relay look like
   loading instead of frozen. ---------- */
#net-error { position: fixed; top: 0; left: 0; right: 0; z-index: 40; background: #b3261e; color: #fff;
             padding: 10px 16px; text-align: center; font-size: 14px; cursor: pointer; }
#net-error button { margin-left: 12px; padding: 4px 14px; border: 1px solid #fff; border-radius: 6px;
                    background: transparent; color: #fff; font-size: 13px; cursor: pointer; }
#net-error button:hover { background: rgba(255, 255, 255, .15); }

.nav-link.htmx-request::after { content: ""; display: inline-block; width: 10px; height: 10px; margin-left: 8px;
                                border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%;
                                vertical-align: middle; animation: hr-spin .7s linear infinite; }
button.htmx-request { opacity: .65; }
@keyframes hr-spin { to { transform: rotate(360deg); } }

/* Current-day highlight in the Schedule grid (2026-07-16) -- same blue as
   the worker portal's today mark; no team color uses blue so it can't be
   read as a team marking. Padding shrinks by the border growth (1->3px)
   so today's cell keeps the exact size of its neighbours. */
.schedule-day.today { border: 3px solid #1a56db; padding: 8px 12px;
                      box-shadow: 0 0 0 3px rgba(26, 86, 219, .2); background: #f0f5ff; }

/* ---------- Dashboard tab (2026-07-16): landing view after login. Cards
   are <button>s that jump to the acting tab (data-goto). Team slot colors
   come from the shared .team-a/.team-b/... classes above; the :not()
   fallback greys a slot with no team without out-cascading those. ---------- */
.dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; margin: 14px 0 6px; }
.dash-card { background: #fff; border: 1px solid #c9d0dc; border-radius: 10px; padding: 14px; text-align: left;
             cursor: pointer; font: inherit; box-shadow: 0 1px 3px rgba(16, 24, 40, .07); }
.dash-card:hover { border-color: #1a56db; box-shadow: 0 0 0 3px rgba(26, 86, 219, .12); }
.dash-value { font-size: 26px; font-weight: bold; margin-bottom: 2px; }
.dash-value.dash-attention, .dash-sub.dash-attention { color: #b54708; font-weight: bold; }
/* Title sits on top of each card (2026-07-19 request); small gap to the value below. */
.dash-label { font-weight: bold; font-size: 14px; margin-bottom: 6px; }
.dash-sub { color: #667085; font-size: 12px; margin-top: 2px; }
.dash-heading { margin: 18px 0 8px; font-size: 15px; }
.dash-today { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* Previous / active / next shift board (2026-07-20). */
.dash-shifts { grid-template-columns: 1fr 1fr 1fr; }
.dash-slot { border-radius: 10px; padding: 10px 12px; font-size: 14px; font-weight: bold; word-break: break-word;
             border: 2px solid transparent; }
.dash-slot:not(.team-a):not(.team-b):not(.team-c):not(.team-d) { background: #eef1f6; }
.dash-slot .slot-role { font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: .04em;
                        color: #667085; margin-bottom: 3px; }
.dash-slot.dash-slot-active { border-color: #175cd3; box-shadow: 0 0 0 1px #175cd3 inset; }
.dash-slot.dash-slot-active .slot-role { color: #175cd3; }
.dash-slot .slot-title { font-size: 12px; margin-bottom: 5px; opacity: .85; }
.dash-legend { font-size: 12px; margin-top: 6px; }
/* Today's Leave/Rest Days + Birthdays this month (2026-07-31): a wrapped row
   of small chips rather than a table -- both lists are short and don't need
   columns, and this reads at a glance the same way the shift cards do. */
.dash-off-list { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-off-chip { background: #fff; border: 1px solid #c9d0dc; border-radius: 8px; padding: 6px 10px;
                 font-size: 13px; display: inline-flex; align-items: center; gap: 6px; }
.dash-birthday-today { border-color: #f79009; background: #fffaeb; font-weight: bold; }

/* Server-status dashboard card (2026-07-16): informational, not a tab
   jump -- no pointer, no hover ring. */
.dash-card.dash-static { cursor: default; }
.dash-card.dash-static:hover { border-color: #c9d0dc; box-shadow: 0 1px 3px rgba(16, 24, 40, .07); }

/* ---------- Center-alignment pass (2026-07-16, user request: "most of the
   project needs to be center aligned, lists, menu, schedule, all of it").
   Nav menu, tables, schedule grid, dashboard, teams board and headings are
   centered. Deliberately NOT centered: form labels/inputs inside modals
   (left-aligned forms stay readable) and the rich-text editor (it's a
   document; authors center via its own toolbar). ---------- */
#content h2, #content h3 { text-align: center; }
#content > .tab-panel > .muted, .tab-panel > p.muted { text-align: center; }

/* Menu */
#sidebar h1, #sidebar .whoami { text-align: center; }
.nav-link { text-align: center; }

/* Lists: every tab's table */
table.admin-table th, table.admin-table td { text-align: center; }

/* Schedule grid */
.subtab-bar { justify-content: center; }
.schedule-subtab > p.muted { text-align: center; }
.schedule-toolbar { justify-content: center; }
.schedule-day .day-label { text-align: center; }
.slot-box { text-align: center; }
.slot-box .slot-title { text-align: center; }
.standby-row { text-align: center; }

/* Dashboard */
.dash-card { text-align: center; }
.dash-slot { text-align: center; }
.dash-legend { text-align: center; }
#tab-dashboard .row-link { display: block; margin: 0 auto; }

/* Teams board */
.teams-board { justify-content: center; }
.team-column h4 { text-align: center; }
.member-chip { text-align: center; }

/* Modal titles (forms below them stay left-aligned) */
#modal-card h3 { text-align: center; }

/* ---------- Performance Reports tab ---------- */
.perf-picker { text-align: center; margin: 8px 0 18px; }
.perf-picker select { min-width: 260px; }
.perf-toolbar { display: flex; justify-content: center; margin-bottom: 16px; }

.perf-list { display: flex; flex-direction: column; gap: 12px; max-width: 720px; margin: 0 auto; }
.perf-card { border: 1px solid #e4e7ec; border-radius: 10px; padding: 12px 14px; background: #fff;
             text-align: left; }
.perf-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.perf-date { margin-left: auto; color: #667085; font-size: 13px; }
.perf-rating { font-weight: bold; font-size: 13px; color: #344054; }
/* Report body is sanitized rich text (rendered with |safe). */
.perf-body { word-break: break-word; line-height: 1.45; }
.perf-body h1 { font-size: 18px; margin: 8px 0 4px; }
.perf-body h2 { font-size: 16px; margin: 8px 0 4px; }
.perf-body h3 { font-size: 14px; margin: 6px 0 3px; }
.perf-body ul, .perf-body ol { padding-left: 22px; margin: 6px 0; }
.perf-body blockquote { border-left: 3px solid #c9d0dc; margin: 6px 0; padding: 2px 12px; color: #475467; }
.perf-body a { color: #175cd3; }

/* New/Edit report is a bigger, document-style dialog: widen the shared modal
   only when it holds the report form (:has), and give the editor room. */
#modal-card:has(.perf-form) { max-width: 820px; }
.perf-form .perf-body-label { display: block; text-align: left; font-weight: 600;
                              margin: 16px 0 6px; color: #344054; }
.perf-form .rte-editor { min-height: 340px; }
.perf-meta { display: flex; align-items: center; gap: 10px; margin-top: 10px;
             font-size: 13px; color: #667085; }
.perf-actions { margin-left: auto; display: flex; gap: 6px; }

/* Category badges */
.perf-badge { display: inline-block; padding: 2px 10px; border-radius: 999px;
              font-size: 12px; font-weight: 600; }
.perf-commendation { background: #e7f6ec; color: #1b7a3d; }
.perf-concern      { background: #fef3e2; color: #b25e09; }
.perf-incident     { background: #fdeaea; color: #c0392b; }
.perf-review       { background: #e8f0fe; color: #1a56db; }
.perf-note         { background: #eef1f6; color: #475467; }

/* ---------- Records tab (2026-07-22: replaces the old "Reports" tab -- a
   worker's full personnel file: info/salary/leave/overtime cards plus the
   embedded, unchanged Performance Reports fragment below them). ---------- */
.records-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
                gap: 16px; max-width: 1100px; margin: 0 auto; align-items: start; }
.records-card { border: 1px solid #e4e7ec; border-radius: 10px; padding: 14px 16px;
                background: #fff; text-align: left; }
.records-card h3 { margin: 0 0 10px; display: flex; align-items: center; gap: 8px; }
.records-full { grid-column: 1 / -1; }

.records-dl { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.records-dl > div { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; }
.records-dl dt { color: #667085; }
.records-dl dd { margin: 0; font-weight: 600; text-align: right; }

.records-stat { margin: 0 0 10px; font-size: 14px; color: #344054; }

.records-mini-table th, .records-mini-table td { font-size: 13px; padding: 6px 8px; }

.records-status { display: inline-block; padding: 1px 8px; border-radius: 999px;
                   font-size: 12px; font-weight: 600; text-transform: capitalize; }
.records-status-approved { background: #e7f6ec; color: #1b7a3d; }
.records-status-pending  { background: #fff3b0; color: #7a5b00; }
.records-status-rejected { background: #fdeaea; color: #c0392b; }

/* Team badge -- same fixed colors as the schedule/Checks tab, applied to a
   pill next to the person's name instead of a table cell. */
.team-badge { font-size: 12px; }
.team-badge.team-a { background: #ffd500; color: #4a3b00; }
.team-badge.team-b { background: #00bcd4; color: #003944; }
.team-badge.team-c { background: #ff8c00; color: #4a2600; }
.team-badge.team-d { background: #2e7d32; color: #fff; }
.team-badge.team-unassigned { background: #eef1f6; color: #475467; }
