/* ============================================================
   Leave module styles — dashboard, booking, calendar
   ============================================================ */

/* ---------- §21 Timeline grid ---------- */
/* §52.2: weekend and bank holiday share ONE grey variable so they can never
   drift apart. Bank holiday is the same grey, diagonally striped. */
:root {
  --weekend-grey: #D6D9DE;
}
.scope-switcher {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
}
.scope-btn {
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--oasis-border);
  border-radius: var(--radius-sm);
  color: var(--oasis-slate);
  text-decoration: none;
  font-size: var(--text-sm);
}
.scope-btn--active {
  background: var(--oasis-blue-dark);
  border-color: var(--oasis-blue-dark);
  color: #fff;
}
.calendar-legend {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
  align-items: center;
  font-size: var(--text-sm);
}
.legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.legend-swatch {
  width: 18px;
  height: 12px;
  display: inline-block;
  border-radius: 3px;
  border: 1px solid var(--oasis-border);
}
.legend-swatch--weekend { background: var(--weekend-grey); }
.legend-swatch--holiday { background: repeating-linear-gradient(45deg, var(--weekend-grey) 0px, var(--weekend-grey) 5px, #FFFFFF 5px, #FFFFFF 9px); }
.legend-swatch--today { background: #2C5F8A; }
.legend-swatch--pending { background: repeating-linear-gradient(90deg, #E8842C 0 6px, #FFFFFF 6px 10px); }
.timeline-card { overflow: hidden; }
/* §44.2: one card per organisation, stacked vertically with 24px spacing
   so the organisational boundary is unmistakable. Both cards share the
   same width, column widths, and day alignment. */
.timeline-card-list {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.timeline-scroll { overflow-x: auto; }
/* Point 1: use the full card width for the grid; day columns flex-grow so
   more of the month fits without horizontal scroll, with a sensible
   minimum column width and overflow scrolling only beyond that. */
.timeline { width: 100%; min-width: 0; position: relative; isolation: isolate; }
/* §36: header and rows share the same grid track definition (emitted inline
   from the template: name column + repeat(days, minmax(34px,1fr))), so bars
   placed with grid-column align pixel-exactly with day column boundaries. */
/* § point 3 fix: header and rows resolve the SAME inherited custom property
   (--timeline-tracks), set once on the shared .timeline / card wrapper from the
   template. Both grids therefore use one track definition and can never drift —
   separate grid-template-columns declarations were the misalignment defect. */
.timeline__header,
.timeline__row {
  display: grid;
  grid-template-columns: var(--timeline-tracks);
  border-bottom: 1px solid var(--oasis-border);
}
.timeline__header {
  position: sticky;
  top: 0;
  background: var(--oasis-card-bg);
  z-index: 3; /* above sticky name column and event bars */
}
.timeline__sticky-name {
  position: sticky;
  left: 0;
  width: 340px;
  min-width: 340px;
  max-width: 340px;
  background: var(--oasis-card-bg);
  z-index: 2; /* above day columns while scrolling horizontally */
  padding: var(--space-2);
  /* §43.2 rule 6: staff rows indent one step beyond department (60px). */
  padding-left: 60px;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-right: 1px solid var(--oasis-border);
  font-weight: 600;
  font-size: var(--text-sm);
}
/* Part D: names take the full name-column width; role badges wrap to their own
   line instead of squeezing the name and forcing it to break. ~30 chars fit on
   one line in the widened column. */
.timeline__name { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 4px; }
.timeline__name-text { min-width: 0; }
/* §25 tags on the grid name column. */
.user-tag {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 999px;
  margin-left: 4px;
  vertical-align: middle;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.user-tag--manager { background: #DCE7F0; color: var(--oasis-blue-dark); }
.user-tag--super { background: var(--oasis-green); color: #fff; }
.user-tag--viewer { background: #EDE9F6; color: #4A3A7A; }
.user-tag--branch { background: #E0F2F1; color: #00695C; }
.user-tag--department { background: #E1F5FE; color: #01579B; }
.user-tag--user { background: #ECEFF1; color: #37474F; }
.timeline__day {
  /* §29.3.4: day columns expand to consume recovered space — the grid track
     is minmax(34px, 1fr), so columns grow beyond 34px to fill available width
     when the month fits. On a 1920px screen all 31 columns of any month are
     visible with no horizontal scrolling. */
  text-align: center;
  padding: var(--space-1) 0;
  font-size: var(--text-xs);
  border-left: 1px solid #B9C3CB;
}
.timeline__day--weekedge { border-left: 1px solid #8897A3; }
.timeline__day--weekend { background: var(--weekend-grey); }
/* §52.2: bank holiday is the SAME grey as weekend, diagonally striped —
   no blue tint, no separate colour. */
.timeline__day--holiday { background: repeating-linear-gradient(45deg, var(--weekend-grey) 0px, var(--weekend-grey) 5px, #FFFFFF 5px, #FFFFFF 9px); }
/* §52.2: today is the single strongest element — solid dark blue fill with
   bold white date + weekday. */
.timeline__day--today { background: #1F4E78; }
.timeline__day--today .timeline__day-num,
.timeline__day--today .timeline__day-wd { color: #fff; font-weight: 700; }
.timeline__day-num { display: block; font-weight: 700; }
.timeline__day-wd { color: var(--oasis-slate-muted); }
.timeline__row { position: relative; z-index: 1; }
/* Part B: column-wide shading layer — spans the full grid height behind every
   row so weekend / bank-holiday / today bands are continuous vertical lines,
   not per-person cells. Today is defined LAST so it wins precedence over bank
   holiday hatching and weekend grey. */
.timeline__shade {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: var(--timeline-tracks);
  z-index: 0;
  pointer-events: none;
}
.timeline__shade-day--weekend { background: var(--weekend-grey); }
.timeline__shade-day--holiday { background: repeating-linear-gradient(45deg, var(--weekend-grey) 0px, var(--weekend-grey) 5px, #FFFFFF 5px, #FFFFFF 9px); }
.timeline__shade-day--today { background: #1F4E78; }
/* Part B/C: full-height vertical day separators (hairline) + heavier week
   boundaries (Sunday→Monday), in the same background layer — below leave blocks
   — spanning every row continuously including the group-header rows. */
/* Day separators: solid hairlines so they are clearly visible on white weekday
   cells as well as on shaded ones. Week boundary = a slightly stronger hairline. */
.timeline__shade { border-right: 1px solid #B9C3CB; }
.timeline__shade-day { border-left: 1px solid #B9C3CB; }
.timeline__shade-day--weekedge { border-left: 1px solid #8897A3; }
/* § point 3: collapsible group section headers — span the full grid width
   with a subtle background, showing a member count. */
/* §35: the whole header row is the clickable/keyboard toggle target. */
.timeline__group-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  /* OPAQUE solid band: group header rows are LABELS, not data rows, so the day grid
     (separators, weekend/today shading, bank-holiday hatching) must NOT show through
     them. A full-width opaque fill hides the shade layer entirely within header rows.
     Staff rows below stay transparent, so the day separators/bands continue to run
     continuously through them — only header rows are filled. */
  background: #F2F4F1;
  border-bottom: 1px solid var(--oasis-border);
  width: 100%;
  position: sticky;
  left: 0;
  cursor: pointer;
  user-select: none;
  /* §44.4.4: group header rows are 36px minimum, comfortably fitting the
     32px caret target. */
  min-height: 36px;
}
.timeline__group-header:hover {
  background: #E9EDE6;
}
.timeline__group-header:focus-visible {
  outline: 2px solid var(--oasis-blue);
  outline-offset: -2px;
}
/* §43: exactly three tier styles — size & weight descend with depth,
   progressive indent (0 / 20 / 40px), tint intensity decreasing. No
   uppercase transforms, no letter-spacing (§43.2 rule 1). Names render
   exactly as stored, in the app's shared font family. */
.timeline__group-header--organisation {
  background: #E7EDE2;
  font-size: 15px;
  font-weight: 700;
}
.timeline__group-header--branch {
  background: #EDF0EA;
  font-size: 14px;
  font-weight: 600;
  padding-left: 20px;
}
.timeline__group-header--department {
  background: #F2F4F1;
  font-size: 13px;
  font-weight: 500;
  padding-left: 40px;
}
/* §44.1: caret renders at 16px inside a 32×32px click target (meets
   minimum touch-target guidance). Colour matches the header text colour
   at full opacity; hover tints the target so it reads as interactive.
   Rotation is smooth (~150ms) between expanded (down) and collapsed
   (right). */
.timeline__group-toggle {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  color: inherit;
  border-radius: 50%;
  transition: transform 150ms ease, background-color 150ms ease;
}
.timeline__group-toggle::after {
  content: "▾";
}
.timeline__group-header:hover .timeline__group-toggle {
  background: rgba(0, 0, 0, 0.06);
}
/* §35.2.3: caret rotates — down when expanded, right when collapsed. */
.timeline__group-header[data-collapsed] .timeline__group-toggle {
  transform: rotate(-90deg);
}
/* Collapse hides the following .timeline__group-body, which contains the
   group's member rows AND all descendant group headers. */
.timeline__group-header[data-collapsed] + .timeline__group-body {
  display: none;
}
.timeline__group-body {
  width: 100%;
}
/* §43.2 rule 5: name inherits the tier weight (the badge stays uniform). */
.timeline__group-name {
  font-weight: inherit;
}
.timeline__group-count {
  background: var(--oasis-border);
  color: var(--oasis-slate);
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 1px 8px;
}
/* §36: the row is a grid; day shading cells auto-place into the shared
   tracks. §44.4: row height is content-driven — 48px minimum so a
   two-line name plus its tag fits with breathing room, growing
   automatically if content needs more. Nothing in a row may ever be
   clipped. Leave bars stay vertically centred and keep their height. */
.timeline__row {
  min-height: 48px;
}
/* When overlapping requests stack a row into multiple 28px lanes, the sticky
   name must span the whole row height so it stays vertically centred. */
.timeline__sticky-name {
  grid-row: 1 / -1;
}
/* §23.2: full-height column cells — weekend / bank holiday / today marker.
   They share the same grid tracks as the header, so rows and header align.
   §37: each cell carries the day separator gridline (border-left), matching
   the header day columns, so vertical lines run the full height of the
   timeline and every day column reads clearly. */
.timeline__row-day {
  height: 100%;
  border-left: 1px solid var(--oasis-border);
}
.timeline__row-day--weekend { background: var(--weekend-grey); }
.timeline__row-day--holiday { background: repeating-linear-gradient(45deg, var(--weekend-grey) 0px, var(--weekend-grey) 5px, #FFFFFF 5px, #FFFFFF 9px); }
.timeline__row-day--today { background: #2C5F8A; }
/* §36: bars are grid items placed by grid-column (start/end day columns).
   grid-row: 1 overlaps them with the day shading cells beneath; the 1–2px
   symmetric inset keeps breathing room without crossing column boundaries. */
.timeline-event {
  position: relative;
  z-index: 1;
  grid-row: 1;
  align-self: center;
  height: 28px;
  border-radius: 0;
  background: var(--colour);
  color: #fff;
  font-size: var(--text-xs);
  display: flex;
  align-items: center;
  overflow: hidden;
  border: 1px solid rgba(0,0,0,0.25);
  cursor: default;
  margin: 0 1px;
}
/* Weekday segments of ONE request: rounded only on the outer edges of the whole
   booking (start of the first segment, end of the last); internal edges where a
   weekend interrupts stay square so it reads as one bar with gaps. A small outer
   margin separates ADJACENT blocks of DIFFERENT requests (e.g. two bookings on
   consecutive days) so they read as two items. Within-request segments are
   always separated by a non-working-day column, so this never splits one bar. */
.timeline-event--first { border-top-left-radius: 5px; border-bottom-left-radius: 5px; margin-left: 4px; }
.timeline-event--last { border-top-right-radius: 5px; border-bottom-right-radius: 5px; margin-right: 4px; }
/* §22.1: ALL pending = orange/white stripes (universal, supersedes §21.2). */
.timeline-event--pending {
  background: repeating-linear-gradient(
    90deg,
    #E8842C 0px, #E8842C 6px,
    #FFFFFF 6px, #FFFFFF 10px
  );
  border-color: #C4671F;
}
/* §22.2.3: label sits on a solid inset — orange on pending, white text.
   §34.3: font size scales within a bounded 11–14px range to fill the bar
   more comfortably; it must never exceed the bar height or force growth. */
.timeline-event__label {
  background: var(--colour);
  padding: 2px 8px;
  border-radius: 3px;
  white-space: nowrap;
  font-weight: 600;
  margin-left: 2px;
  color: #fff;
  font-size: clamp(11px, 1.1vw, 14px);
  line-height: 1.2;
  max-height: 100%;
  overflow: hidden;
}
.timeline-event--pending .timeline-event__label { background: #E8842C; }
.calendar-tooltip {
  position: fixed;
  z-index: 50;
  background: #fff;
  border: 1px solid var(--oasis-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  font-size: var(--text-sm);
  max-width: 280px;
  pointer-events: none;
}

/* ---------- Dashboard header ---------- */
.dash-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

.dash-header h1 {
  font-size: var(--text-3xl);
  margin-bottom: var(--space-1);
}

.btn--lg {
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-lg);
}

/* ---------- Dashboard grid ---------- */
.dash-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
  margin-bottom: var(--space-5);
}

.dash-lower-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--space-5);
}

/* ---------- §26.5b Summary strip (My Leave) ---------- */
.summary-strip {
  margin-top: var(--space-5);
}

.summary-strip__bar {
  height: 14px;
  border-radius: 999px;
  background: var(--oasis-border);
  overflow: hidden;
  margin-bottom: var(--space-3);
}

.summary-strip__fill {
  height: 100%;
  border-radius: 999px;
  background: var(--oasis-green);
  transition: width var(--transition-base);
}

.summary-strip__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.summary-chip {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
  background: #EEF1EE;
  border-radius: 999px;
  padding: 4px 12px;
}

.summary-chip strong {
  color: var(--oasis-slate);
}

.summary-chip--pending strong {
  color: var(--oasis-warning);
}

.summary-chip--remaining strong {
  color: var(--oasis-green);
}

/* Carry-over advisory chip (My Leave strip) — same pill shape/typography as the
   balance pills; sits in the empty space to the right. Advisory only. */
.summary-chip--carryover {
  margin-left: auto;            /* right of the balance pills */
  border: 1px solid transparent; /* keep height identical across variants */
  white-space: normal;
}
.summary-chip--carryover.summary-chip--neutral {
  background: #EEF1EE;
  color: var(--oasis-slate-muted);
}
.summary-chip--carryover.summary-chip--amber {
  background: #FFF7ED;
  border-color: #FBD38D;
  color: #92400E;
}
.summary-chip--carryover.summary-chip--red {
  background: #FEF2F2;
  border-color: #FECACA;
  color: #B91C1C;
  font-weight: 600;
}

/* ---------- Summary list ---------- */
.summary-list {
  margin: 0;
}

.summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--oasis-border);
}

.summary-row:last-child {
  border-bottom: none;
}

.summary-row dt {
  color: var(--oasis-slate-muted);
  font-size: var(--text-sm);
}

.summary-row dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  color: var(--oasis-slate);
  font-weight: 600;
}

.summary-row--total {
  padding-top: var(--space-3);
}

/* One value colour — no decorative green. Colour is reserved for status only. */
.summary-row--green {
  color: var(--oasis-slate);
  font-size: var(--text-base);
}

/* Status (used only where genuinely meaningful). */
.summary-row--pending {
  color: var(--oasis-warning);
}
.status-warn {
  color: var(--oasis-warning);
}

/* ---------- Request lists ---------- */
.request-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.request-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--oasis-border);
}

.request-item:last-child {
  border-bottom: none;
}

.request-item__dates {
  min-width: 120px;
  font-weight: 600;
  font-size: var(--text-sm);
}

.request-item__type {
  font-size: var(--text-sm);
  padding: 2px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--colour, #44759D) 15%, white);
  color: var(--oasis-slate);
}

.request-item__days {
  margin-left: auto;
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
}

.empty-state {
  color: var(--oasis-slate-muted);
  font-size: var(--text-sm);
}

/* ---------- Booking page ---------- */
.book-layout {
  max-width: 720px;
}

.book-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.half-day-row {
  display: flex;
  gap: var(--space-4);
}

.half-day-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.balance-preview {
  background: #EAF2E3;
  border: 1px solid #C9DCBC;
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  margin-top: var(--space-4);
  display: none;
}

.balance-preview--visible {
  display: block;
}

.balance-preview__impact {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--oasis-green);
}

.balance-preview__warning {
  color: var(--oasis-danger);
  font-weight: 600;
  margin-top: var(--space-1);
}

.balance-preview__pending {
  color: var(--oasis-slate-muted);
  font-size: var(--text-xs);
  margin-top: var(--space-1);
}

/* ---------- Clash notice (booking) ---------- */
.clash-notice {
  background: #FBF1E2;
  border: 1px solid #EDD8B7;
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  margin-top: var(--space-4);
}

.clash-notice__title {
  font-weight: 700;
  color: var(--oasis-warning);
  margin: 0 0 var(--space-2);
}

.clash-notice__list {
  margin: 0 0 var(--space-3);
  padding-left: 1.25rem;
  font-size: var(--text-sm);
}

.clash-notice__list li {
  margin-bottom: 2px;
}

.clash-notice__confirm {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}

.clash-notice__confirm input {
  margin-top: 2px;
}

/* ---------- Page title (bolder) ---------- */
.page-title {
  font-size: var(--text-3xl);
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* ---------- Greeting + stat chips ---------- */
.greeting-strip {
  margin-bottom: var(--space-5);
}

.greeting {
  font-size: var(--text-2xl);
  font-weight: 800;
  letter-spacing: -0.01em;
  margin-bottom: var(--space-3);
}

.stat-chips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}

.stat-chip {
  background: var(--oasis-card-bg);
  border: 1px solid var(--oasis-border);
  border-radius: var(--radius);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-shadow: 0 1px 2px rgba(43,52,64,0.04);
  transition: box-shadow var(--transition-fast), transform var(--transition-fast);
}

.stat-chip:hover {
  box-shadow: 0 4px 12px rgba(43,52,64,0.08);
  transform: translateY(-2px);
}

.stat-chip__icon {
  font-size: var(--text-lg);
}

.stat-chip__value {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--oasis-slate);
  letter-spacing: -0.02em;
}

.stat-chip__value--text {
  font-size: var(--text-lg);
}

.stat-chip__label {
  font-size: var(--text-xs);
  color: var(--oasis-slate-muted);
}

/* Off-today card (organisation scope): a plain "off today" label under the
   headline number (matches the "days available" label on the first card),
   then a single small, left-aligned, muted caption block listing each
   organisation and its count. The block joins onto one line separated by a
   "·" when it fits; when it does not, each "name count" pair wraps to its own
   line rather than breaking mid-name. Both organisation names use the muted
   caption colour and nothing on the card is clickable. */
.stat-chip--off .stat-chip__orgs {
  display: flex;
  flex-wrap: wrap;
  row-gap: 0.15rem;
  margin-top: 0.15rem;
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1.3;
  color: var(--oasis-slate-muted);
  text-align: left;
}
.stat-chip__org {
  white-space: normal;
}
.stat-chip__org:not(:last-child)::after {
  content: '\00a0·\00a0';   /* nbsp · nbsp between organisation pairs */
}
/* §29: on phones (and narrow tablets) stack the four stat cards into a single
   column so the off-today card's full organisation names get the whole card
   width — no mid-name wrapping or overflow inside a ~165px two-column card.
   Equal height and identical padding are preserved (each card is its own row). */
@media (max-width: 640px) {
  .stat-chips {
    grid-template-columns: 1fr;
  }
}

/* ---------- Coverage ring ---------- */
.coverage-ring {
  --ring-size: 120px;
  width: var(--ring-size);
  height: var(--ring-size);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: var(--space-2) 0;
}

.coverage-ring__inner {
  width: calc(var(--ring-size) - 20px);
  height: calc(var(--ring-size) - 20px);
  border-radius: 50%;
  background: var(--oasis-card-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.coverage-ring__pct {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--oasis-slate);
}

/* ---------- Coverage avatars ---------- */
.coverage-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--oasis-blue);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: 700;
  flex-shrink: 0;
}

/* ---------- Year planner months strip ---------- */
.planner-months {
  display: flex;
  gap: 2px;
}

.planner-month {
  width: 10px;
  height: 14px;
  border-radius: 2px;
  background: var(--oasis-bg);
  border: 1px solid var(--oasis-border);
}

.planner-month--approved {
  background: var(--oasis-blue);
  border-color: var(--oasis-blue);
}

.planner-month--pending {
  background: var(--oasis-warning);
  border-color: var(--oasis-warning);
}

/* ---------- Hover cards ---------- */
.hover-card {
  position: fixed;
  z-index: 200;
  background: #fff;
  border: 1px solid var(--oasis-border);
  border-left: 4px solid var(--card-colour, var(--oasis-blue));
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(43,52,64,0.18);
  padding: var(--space-3) var(--space-4);
  min-width: 180px;
  max-width: 320px;
  pointer-events: none;
}

/* §39.1: colour-coded type + status chips. Same corner radius + padding as
   the [Manager] / [Super User] tags (§25), so they read as one chip family.
   Colour is supplementary — the status text still states the status in words
   (§22.2.4). */
.hover-card__type {
  font-weight: 700;
  font-size: var(--text-sm);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
  /* Type + status pills wrap onto a second line when they don't fit together
     within the tooltip's max-width, so no pill is clipped or spills past the
     tooltip background. */
}

/* §61.2: chips are sentence case with no letter-spacing — the type chip is
   FILLED with the leave type's §22.1 colour and white text (background set
   inline from the colour map); the status chip is a muted neutral fill. */
.hover-card__chip {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 999px;
  color: #fff;
  line-height: 1.4;
}

.hover-card__chip--status {
  background: #4A5568;
}

.hover-card__name {
  font-weight: 600;
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
}

.hover-card__dates {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
  margin-bottom: var(--space-2);
}

.hover-card__status {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
}

.hover-card__status--approved {
  background: #DCE7F0;
  color: var(--oasis-blue-dark);
}

.hover-card__status--requested {
  background: #FBF1E2;
  color: var(--oasis-warning);
}

.calendar-event--unavailable {
  background: #8A94A6;
  color: #fff;
}

/* ---------- Coverage strip (Dashboard landing) ---------- */
.coverage-strip {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
  margin-bottom: var(--space-5);
}

.coverage-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.coverage-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--oasis-border);
  font-size: var(--text-sm);
}

.coverage-list li:last-child {
  border-bottom: none;
}

.coverage-name {
  font-weight: 600;
}

.coverage-type {
  font-size: var(--text-xs);
  padding: 2px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--colour, #44759D) 15%, white);
}

.coverage-pct {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 700;
  color: var(--oasis-green);
  margin: var(--space-2) 0 0;
}

.coverage-pct--low {
  color: var(--oasis-warning);
}

/* ---------- Calendar ---------- */
.calendar-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

.calendar-nav h1 {
  margin: 0;
}

.calendar-nav__controls {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* Toolbar row: scope switches left, legend in the middle, month controls far
   right. In self mode (My Leave) there are no scope switches, so the legend
   takes the middle space and the controls sit far right. */
.calendar-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
}
.calendar-toolbar .scope-switcher { margin-bottom: 0; }
.calendar-toolbar .calendar-legend {
  flex: 1 1 auto;
  flex-wrap: wrap;
  margin-bottom: 0;
  min-width: 0;
}
.calendar-toolbar .calendar-nav__controls {
  margin-left: auto;
  flex: 0 0 auto;
  white-space: nowrap;
}
/* When the legend would collide with the month controls, let the legend wrap to
   its own line above instead of compressing the controls. */
@media (max-width: 1180px) {
  .calendar-toolbar .calendar-legend { order: -1; flex-basis: 100%; }
}

.calendar-table {
  width: 100%;
  border-collapse: collapse;
}

.calendar-table th,
.calendar-table td {
  border: 1px solid var(--oasis-border);
  padding: var(--space-2);
  vertical-align: top;
  font-size: var(--text-sm);
  min-height: 90px;
}

.calendar-table th {
  background: var(--oasis-blue-dark);
  color: #fff;
  font-weight: 600;
  text-align: center;
}

.calendar-table td {

/* Section 10 — audit log table */
.table-wrap { overflow-x: auto; }
.audit-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.audit-table th, .audit-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid #dfe3df; vertical-align: top; }
.audit-table th { background: #f4f6f4; font-weight: 600; }
.audit-detail { font-family: monospace; font-size: 0.8rem; word-break: break-word; max-width: 420px; }
.filter-bar { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }

  height: 90px;
  background: var(--oasis-card-bg);
}

.calendar-table td.calendar-cell--other-month {
  background: #EEF1EE;
  color: var(--oasis-slate-muted);
}

.calendar-day-num {
  font-weight: 600;
  display: block;
  margin-bottom: var(--space-1);
}

.calendar-event {
  display: block;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.75rem;
  margin-bottom: 2px;
  background: color-mix(in srgb, var(--colour, #44759D) 15%, white);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.calendar-event--holiday {
  background: #DCE7F0;
  color: var(--oasis-blue-dark);
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-4);
  font-size: var(--text-sm);
}

.legend span::before {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  margin-right: 4px;
  background: var(--swatch, var(--oasis-blue));
  vertical-align: -1px;
}

/* ---------- Bank holidays page ---------- */
.bank-holiday-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.bank-holiday-list li {
  display: flex;
  justify-content: space-between;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--oasis-border);
  font-size: var(--text-sm);
}

.bank-holiday-list li:last-child {
  border-bottom: none;
}

.bank-holiday-list .date {
  font-weight: 600;
}

/* ---------- Checkbox rows (immediately left of the label) ---------- */
.checkbox-label { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; line-height: 1.4; }
.checkbox-label input[type="checkbox"] { flex: 0 0 auto; width: 16px; height: 16px; margin: 0; }

/* ---------- Responsive ---------- */
@media (max-width: 768px) {
  .dash-grid {
    grid-template-columns: 1fr;
  }

  .book-form-grid {
    grid-template-columns: 1fr;
  }

  .dash-header {
    flex-direction: column;
  }

  .book-form-grid {
    grid-template-columns: 1fr;
  }

  .coverage-strip {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .calendar-table td {
    height: 60px;
    padding: var(--space-1);
  }
}

/* §13.2 — "Balance not yet confirmed" marker chip. */
.summary-chip--unconfirmed {
  background: #FFF7ED;
  border: 1px dashed #B45309;
  color: #92400E;
}

/* ── Outstanding-item badges (nav + My Leave panels) ─────────── */
/* Small orange circular count badge, like a mobile-app notification badge. */
.nav-badge,
.panel-badge {
  display: inline-block;
  min-width: 1.25rem;
  height: 1.25rem;
  line-height: 1.25rem;
  padding: 0 0.375rem;
  margin-left: 0.375rem;
  border-radius: 999px;
  background: #E8842C;
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  text-align: center;
  vertical-align: middle;
}
.panel-badge {
  background: #E8842C;
}

/* ── Item 2 — "Balance unconfirmed" inline chip on Requests rows ─── */
.balance-unconfirmed-chip {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  border: 1px dashed #B45309;
  background: #FFF7ED;
  color: #92400E;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
  vertical-align: middle;
}
.balance-unconfirmed-chip a {
  color: inherit;
  text-decoration: underline;
  text-decoration-style: dotted;
}
.balance-unconfirmed-note {
  margin-bottom: 0.6rem;
  padding: 0.4rem 0.6rem;
  border-left: 3px solid #B45309;
  background: #FFFBEB;
  font-size: 0.82rem;
  color: #78350F;
}
.balance-unconfirmed-note .balance-unconfirmed-chip { margin-right: 0.35rem; }
button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* Form validation error state — deep saturated crimson, CLEARLY distinct from
   the amber used on pending cards / warning notes. Zero-green red cannot read
   as amber. The field itself is white so it reads as the thing under question
   on BOTH the tinted pending card (#FFF8F0) and a plain white surface, without
   two sets of styles.
   Contrast (WCAG AA, 4.5:1 for normal text):
     #B00020 on white (#FFF)            ≈ 7.3:1  (AA/AAA)
     #B00020 on pending tint (#FFF8F0)  ≈ 7.0:1  (AA/AAA)
   --oasis-danger is the palette's restrained amber-red (#B0523A) shared with the
   danger button/alert and deliberately NOT reused here — it falls too close to
   amber and failed the "reads as an error first" test. */
:root {
  --oasis-error: #B00020;
}
.form-field--error input,
.form-field--error select,
.form-field--error textarea {
  border: 2px solid var(--oasis-error);
  background-color: #ffffff;
}
.form-field__label--error,
.form-field--error label {
  color: var(--oasis-error);
  font-weight: 700;
}
.form-error {
  color: var(--oasis-error);
  font-size: 0.84rem;
  font-weight: 600;
  margin-top: 0.35rem;
}
.form-error::before {
  content: '\26A0\FE0E '; /* ⚠︎ text-presentation, avoids colourful emoji */
  font-weight: 700;
}

/* ── Item 3 — Unconfirmed balances report ─────────────── */
.year-switch { display: inline-flex; align-items: center; gap: 0.4rem; margin-left: 0.5rem; }
.year-switch input { width: 5rem; }
.confirm-form { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.confirm-form__field { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.78rem; }
.confirm-form__field input { width: 4.5rem; }
.bulk-list { list-style: none; padding: 0; margin: 0 0 0.75rem; columns: 3; }
.bulk-list li { margin: 0.15rem 0; }
.alert--warn { background: #FFFBEB; border: 1px solid #F59E0B; color: #78350F; padding: 0.6rem 0.8rem; border-radius: 0.4rem; margin-bottom: 1rem; }
.alert--success { background: #ECFDF5; border: 1px solid #10B981; color: #065F46; padding: 0.6rem 0.8rem; border-radius: 0.4rem; margin-bottom: 1rem; }
.alert--warn a { color: #92400E; font-weight: 700; }

/* ── REQUESTS page — per-request CARDS (replaces the continuous table) ── */
.req-cards {
  display: flex;
  flex-direction: column;
  gap: var(--space-5, 1.25rem); /* clear vertical space between cards */
  margin-top: var(--space-4, 1rem);
}
.req-card {
  background: #ffffff;
  border: 1px solid var(--border, #E5E7EB);
  border-radius: 0.75rem;
  padding: var(--space-5, 1.25rem);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
/* Pending — the pale state is carried INSIDE this card, not across the page. */
.req-card--pending {
  background: #FFF8F0;
  border-color: #F2D9BC;
  border-left: 4px solid #E8842C;
}
/* Decided — quieter, so the eye goes to what still needs a decision. */
.req-card--decided {
  background: #ffffff;
  border-color: #E8EAED;
}
.req-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.req-card__name {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
}
.req-status-pill {
  padding: 0.18rem 0.65rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.req-status-pill--pending {
  background: #FDE5C0;
  color: #7C2D12;
}
.req-card--decided .req-status-pill {
  background: #F1F2F4;
  color: #6B7280;
}
.req-card__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem 1.25rem;
  margin: 0 0 0.75rem;
}
.req-card__field {
  min-width: 0;
}
.req-card__field--wide {
  grid-column: 1 / -1;
}
.req-card__field dt {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  /* standard muted grey — matches .text-muted elsewhere in the app */
  color: var(--oasis-slate-muted, #5A6A7A);
  margin-bottom: 0.1rem;
}
.req-card__field dd {
  margin: 0;
  font-size: 0.95rem;
}
/* Ordinary values are the normal dark body text on both pending and decided
   cards; colour is reserved for things that carry meaning (the pending pill,
   the "Balance unconfirmed" warning, the red error state, and the action
   buttons). No amber/grey text on plain information. */
.req-card__overlap {
  padding: 0.6rem 0.75rem;
  border: 1px dashed #D8DEDA;
  border-radius: 0.5rem;
  background: #F7F8FA;
}
.req-card__form {
  margin-top: 0.8rem;
}
.req-card__actions {
  margin-top: 0.8rem;
}
.req-card__meta {
  font-size: 0.85rem;
  margin-bottom: 0.25rem;
}
.req-reason {
  margin-top: 0.25rem;
  font-style: italic;
}
.overlap-note {
  margin-bottom: 0.5rem;
  font-size: 0.85rem;
}
.overlap-item {
  margin-right: 0.75rem;
  white-space: nowrap;
}
/* Mobile: single column detail grid; keep buttons side by side. */
@media (max-width: 640px) {
  .req-card {
    padding: 1rem;
  }
  .req-card__grid {
    grid-template-columns: 1fr;
    gap: 0.6rem 0;
  }
  .req-card__head {
    align-items: flex-start;
  }
  .req-card__actions {
    flex-wrap: wrap;
  }
}
.dash-header__actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

/* §16.14 — larger collapse-caret target on touch viewports (44×44), retaining
   the 32px target on pointer/mouse devices. */
@media (pointer: coarse), (hover: none) {
  .timeline__group-header {
    min-height: 44px;
  }
  .timeline__group-toggle {
    width: 44px;
    height: 44px;
    font-size: 24px;
  }
}

/* ── Universal back navigation (admin / settings sub-pages only) ─────────
   A quiet inline link placed inside the page content, immediately above the
   page heading. No bar, no border, no band — it sits in the whitespace already
   there, matching the page background. It is a real <a> to the parent route. */
.back-nav-inline {
  margin: 0 0 0.5rem;
}
.back-nav-inline__link {
  color: #1F4E78;
  text-decoration: none;
  font-weight: 600;
}
.back-nav-inline__link:hover {
  text-decoration: underline;
}

/* ── Year planner — organisational hierarchy separation ─────────────────
   Branch = dark navy band + full-width rule + breathing space before each
   branch; Department = light band. OASIS palette, restrained. */
.planner-group td {
  border: none;
  padding: 0;
}
.planner-group--branch {
  border-top: 2px solid #1F4E78;
  margin-top: 1.25rem;
}
.planner-group--branch td {
  padding-top: 0.6rem;
}
.planner-group__band {
  background: #1F4E78;
  color: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.45rem 0.75rem;
}
.planner-branch-name {
  font-weight: 700;
  letter-spacing: 0.02em;
}
.planner-group__count {
  font-weight: 600;
  font-size: 0.8rem;
  opacity: 0.92;
}
.planner-group--dept td {
  background: #EFF3F7;
  border-bottom: 1px solid #D6DEE6;
  padding: 0.35rem 0.75rem;
  font-weight: 600;
  color: #1F4E78;
}

/* Settings: fact list */
.fact-list { margin:0; padding-left:1.1rem; }
.fact-list li { margin:.25rem 0; }

/* ── Settings: login table / security controls / leave-year facts ── */
.login-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.login-table th,
.login-table td {
  text-align: left;
  padding: 0.35rem 0.5rem;
  border-bottom: 1px solid var(--oasis-border);
}
.login-table th {
  color: var(--oasis-slate-muted);
  font-weight: 600;
}
.login-table td {
  color: var(--oasis-slate);
  font-variant-numeric: tabular-nums;
}

.security-controls {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-3);
}
.security-control {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}
.security-control .form-field__label {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
  margin: 0;
}

.leave-year-facts {
  margin: var(--space-3) 0 0;
  padding: var(--space-2) 0 0;
  list-style: none;
  border-top: 1px solid var(--oasis-border);
}
.leave-year-facts li {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
  margin: 0.15rem 0;
}
.leave-year-facts strong {
  color: var(--oasis-slate);
  font-weight: 600;
}

.summary-row--carryover {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
}

/* Users table: auto layout. Figure columns are narrow and right-aligned;
   Name and Department share the remaining width (min-width so they never
   collapse); the action column sizes to its content, so no cell can ever
   overflow into a neighbour. */
.users-table {
  width: 100%;
}
/* Spacing: roomier cells so 35 rows track easily and columns never abut.
   Overrides .audit-table's 8px 10px; the two Opening columns and the action
   column get extra air (below). */
.users-table th,
.users-table td {
  padding: 12px 14px;
}
.users-table th:nth-child(1),
.users-table td:nth-child(1) {
  min-width: 12rem;
  text-align: left;
}
.users-table th:nth-child(2),
.users-table td:nth-child(2) {
  min-width: 8rem;
  text-align: left;
}
.users-table th:nth-child(3),
.users-table th:nth-child(4),
.users-table th:nth-child(5),
.users-table th:nth-child(6),
.users-table td:nth-child(3),
.users-table td:nth-child(4),
.users-table td:nth-child(5),
.users-table td:nth-child(6) {
  width: 5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* The two Opening columns need the most separation — "Opening taken" and
   "Opening booked" must not read as one block of text. */
.users-table th:nth-child(4),
.users-table td:nth-child(4),
.users-table th:nth-child(5),
.users-table td:nth-child(5) {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}
.users-table th:nth-child(7),
.users-table td:nth-child(7) {
  text-align: right;
  /* Clear air between Remaining and the action buttons. */
  padding-left: 1.5rem;
}
.users-table td {
  vertical-align: middle;
}
.users-table .row-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}
/* Trailing spacer column: absorbs every bit of surplus width so Name,
   Department, the figures and the actions each keep only what their content
   needs. Genuinely inert — no content, no border, no padding, transparent. */
.users-table th.spacer,
.users-table td.spacer {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
}
.num {
  font-variant-numeric: tabular-nums;
}
.edit-form {
  display: block;
  margin-top: 0.4rem;
}
/* The `hidden` attribute must win — without this rule every row's form
   renders (an author display rule beats the UA [hidden] display:none). */
.edit-form[hidden] {
  display: none;
}
.edit-form label {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
}
.edit-form input[type="text"] {
  font-size: var(--text-sm);
}
.rem-preview {
  font-size: var(--text-sm);
  color: var(--oasis-slate-muted);
}

