/* HRE Internal — base stylesheet
   Brand:
   - HRE Orange #EE963F  (primary accent)
   - HRE Navy   #202338  (headers, dark surfaces)
   - HRE Sand   #E2DDC7  (page bg, alt rows) */

:root {
  --hre-orange: #EE963F;
  --hre-orange-dark: #d2802e;
  --hre-orange-rgb: 238, 150, 63;
  --hre-navy: #202338;
  --hre-navy-2: #2a2e48;
  --hre-sand: #E2DDC7;
  --hre-sand-2: #f1eee2;
  --text: #1a1a1a;
  --muted: #6c6f7a;
  --border: #d8d4c5;
  --danger: #b3261e;
  --success: #1f7a3a;
  --warning: #b88408;
  --info: #1f5b8b;
  --radius: 6px;
  --radius-sm: 4px;
  --sidebar-w: 240px;
  --sidebar-rail-w: 64px;
  --topbar-h: 52px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: var(--text);
  background: var(--hre-sand-2);
}

a { color: var(--hre-orange-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

h1 { margin: 0 0 .25rem; font-size: 1.6rem; color: var(--hre-navy); }
h2 { margin: 0 0 .5rem;  font-size: 1.3rem; color: var(--hre-navy); }
h3 { margin: 1rem 0 .5rem; font-size: 1.05rem; color: var(--hre-navy); }
.muted { color: var(--muted); margin: 0; }
.err   { color: var(--danger); display: block; margin-top: .25rem; }

/* Fluid container (v0.31.0).
 *
 * Scales with viewport instead of capping at a fixed pixel width, so list
 * tables (Employees, Audit log, Trash, Softwares, etc.) use the available
 * space on wide monitors. Width is bounded above so prose and forms remain
 * scannable on very large displays.
 *
 *   width  = min(100%, 96rem)         — never overflow viewport; cap ~1536px
 *   margin = 0 auto                    — center inside main-area
 *   padding-x = clamp(1rem, 2vw, 2rem) — modest breathing at edges, scales
 *   padding-y = 1rem                   — unchanged vertical rhythm
 *
 * Forms keep their own caps (.form = 480px, .form-wide = 900px), so the
 * wider container does not cause form fields to sprawl. Tables already
 * have width: 100%, so they absorb the new width naturally.
 *
 * On viewports narrower than the sidebar+padding budget the existing
 * mobile media queries hide the sidebar and the container takes the full
 * viewport width minus padding — no change there. */
.container {
  width: min(100%, 96rem);
  margin: 0 auto;
  padding: 1rem clamp(1rem, 2vw, 2rem);
}

/* sidebar (desktop: fixed left; mobile: off-canvas) */
.sidebar {
  position: fixed; top: 0; left: 0;
  width: var(--sidebar-w); height: 100vh;
  background: var(--hre-navy); color: #fff;
  display: flex; flex-direction: column;
  border-right: 3px solid var(--hre-orange);
  z-index: 30;
  transition: transform .2s ease;
}
/* v0.69.2 — sidebar header row: brand wordmark + in-sidebar mode
   toggle. The divider that used to sit on .sidebar-brand moves here so
   it spans the full header (wordmark + toggle). Per-mode layout is set
   under body.sb-pinned / body.sb-rail in the display-modes section. */
.sidebar-head {
  position: relative;
  display: flex; align-items: center;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.sidebar-brand {
  flex: 1 1 auto; min-width: 0;
  padding: 1rem 1.25rem;
  font-weight: 700; font-size: 1.05rem; color: #fff; letter-spacing: .02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: opacity .15s ease;
}
.sidebar-brand:hover { color: var(--hre-orange); text-decoration: none; }

/* v0.69.3 — minimal sidebar scrollbar. The nav is the scroll
   container (overflow-y:auto); the browser's default chrome scrollbar
   looks heavy against the navy. Restyle it to a thin, track-less bar:
   a translucent-white thumb that warms to the brand orange on hover,
   fully rounded, and effectively invisible until the nav overflows.
   Scoped to .sidenav (and the auto-hide peek overlay, same element) so
   the rest of the app keeps native scrollbars. Firefox uses the
   standard scrollbar-width/color properties; WebKit/Blink use the
   ::-webkit pseudo-elements. Both paths styled. */
.sidenav {
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.22) transparent;
}
.sidenav::-webkit-scrollbar { width: 8px; }
.sidenav::-webkit-scrollbar-track { background: transparent; }
.sidenav::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.18);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background-color .15s ease;
}
.sidenav:hover::-webkit-scrollbar-thumb { background: rgba(255,255,255,.30); }
.sidenav::-webkit-scrollbar-thumb:hover {
  background: var(--hre-orange);
}
.sidenav { display: flex; flex-direction: column; padding: .5rem 0; overflow-y: auto; }
.sidenav-link {
  display: block; padding: .6rem 1.25rem;
  color: rgba(255,255,255,.85); border-left: 3px solid transparent;
  font-size: .95rem;
}
.sidenav-link:hover {
  color: #fff; background: rgba(255,255,255,.05);
  border-left-color: var(--hre-orange); text-decoration: none;
}
.sidenav-link.is-active {
  color: #fff; background: var(--hre-navy-2);
  border-left-color: var(--hre-orange); font-weight: 600;
}
.sidenav-section {
  padding: 1rem 1.25rem .25rem;
  font-size: .7rem; color: rgba(255,255,255,.45);
  text-transform: uppercase; letter-spacing: .08em;
}
/* Pending-count badge inline inside a sidenav link.
   v0.47.0 — first used for the "Profile Requests" admin link. */
.sidenav-badge {
  display: inline-block; margin-left: .5rem;
  background: var(--hre-orange); color: #fff;
  font-size: .72rem; font-weight: 600;
  padding: .1rem .45rem; border-radius: 999px;
  vertical-align: middle; min-width: 1.4rem; text-align: center;
}

/* ----------------------------------------------------------------
   v0.69.1 — sidebar display modes (desktop only)

   The sidebar supports three desktop modes, chosen from the topbar
   cycle button and persisted in localStorage by app.js. The mode is
   expressed as a class on <body>:

     .sb-pinned   full 240px rail, content offset right   (default)
     .sb-rail     ~64px icon rail; labels reveal on hover as a flyout
     .sb-hidden   sidebar off-canvas; content full-width; left-edge
                  hotzone (or the topbar button) slides it back as an
                  overlay

   These rules live ABOVE the mobile @media (max-width:768px) block,
   which overrides all of them — below 768px the off-canvas drawer is
   the only behaviour and the desktop mode class is ignored. Print
   targets .sidenav/.topbar directly, so modes don't leak into print.

   --sidebar-rail-w is the collapsed width; keep label/icon paddings
   in sync with it if it changes.
   ---------------------------------------------------------------- */

/* Icon + label structure inside each link. Icon is always present;
   the label is what we hide/reveal per mode. Default (pinned): both
   visible, icon to the left of the label. */
.sidenav-link {
  display: flex; align-items: center; gap: .7rem;
  white-space: nowrap;
}
.sidenav-icon {
  flex: 0 0 auto; display: inline-flex;
  align-items: center; justify-content: center;
  width: 20px; height: 20px; color: inherit;
}
.sidenav-icon svg { display: block; }
.sidenav-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* The mode-cycle control. Two copies share this base: the topbar
   #sidebarModeToggle (used in Auto-hide) and the in-sidebar
   #sidebarModeToggleRail (used in Pinned + Icon-rail). Both render as
   a three-bar hamburger, matching the mobile drawer toggle so the app
   has a single "menu" glyph. (v0.69.2 — was a rect+line SVG.) */
.sidebar-mode-toggle {
  display: inline-flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  width: 40px; height: 40px; padding: 0;
  background: transparent; border: 1px solid rgba(255,255,255,.25);
  border-radius: var(--radius-sm); cursor: pointer; color: #fff;
}
.sidebar-mode-toggle span {
  display: block; width: 18px; height: 2px;
  background: currentColor; border-radius: 2px;
  transition: transform .16s ease, width .16s ease, opacity .16s ease;
}
.sidebar-mode-toggle:hover { border-color: var(--hre-orange); color: var(--hre-orange); }
.sidebar-mode-toggle[hidden] { display: none !important; }

/* v0.69.3 — hover affordance: on hover/focus the three bars morph
   from the neutral "menu" glyph into an arrow hinting at the action
   the click performs. The morph is keyed off the body mode class
   (each mode surfaces exactly one toggle copy) so the glyph always
   matches the next step in the Pinned → Icon-rail → Auto-hide → Pinned
   cycle. Built purely by transforming the existing three <span> bars —
   no extra DOM, no JS. Honours prefers-reduced-motion below. The
   accessible label (aria-label/title, kept in sync by app.js) already
   states the action in words; this is the visual echo of it.

   Pinned → collapse to icons: bars converge into a single chevron
   pointing LEFT ("‹", make the rail narrower). */
body.sb-pinned .sidebar-mode-toggle:hover span,
body.sb-pinned .sidebar-mode-toggle:focus-visible span {
  width: 11px;
}
body.sb-pinned .sidebar-mode-toggle:hover span:nth-child(1),
body.sb-pinned .sidebar-mode-toggle:focus-visible span:nth-child(1) {
  transform: translateX(-2px) translateY(3px) rotate(-45deg);
}
body.sb-pinned .sidebar-mode-toggle:hover span:nth-child(2),
body.sb-pinned .sidebar-mode-toggle:focus-visible span:nth-child(2) {
  transform: translateX(-2px) scaleX(1.25);
}
body.sb-pinned .sidebar-mode-toggle:hover span:nth-child(3),
body.sb-pinned .sidebar-mode-toggle:focus-visible span:nth-child(3) {
  transform: translateX(-2px) translateY(-3px) rotate(45deg);
}

/* Icon-rail → auto-hide: bars become a DOUBLE chevron pointing LEFT
   ("«", push the sidebar all the way off-canvas). The middle bar
   splits visually by riding the outer two outward; we fake the second
   arrowhead by widening the gap and using the same chevron geometry
   shifted left. */
body.sb-rail .sidebar-mode-toggle:hover span,
body.sb-rail .sidebar-mode-toggle:focus-visible span {
  width: 9px;
}
body.sb-rail .sidebar-mode-toggle:hover span:nth-child(1),
body.sb-rail .sidebar-mode-toggle:focus-visible span:nth-child(1) {
  transform: translateX(1px) translateY(5px) rotate(-45deg);
}
body.sb-rail .sidebar-mode-toggle:hover span:nth-child(2),
body.sb-rail .sidebar-mode-toggle:focus-visible span:nth-child(2) {
  transform: translateX(1px) translateY(-1px) rotate(-45deg);
}
body.sb-rail .sidebar-mode-toggle:hover span:nth-child(3),
body.sb-rail .sidebar-mode-toggle:focus-visible span:nth-child(3) {
  transform: translateX(-4px) translateY(-1px) rotate(45deg);
}

/* Auto-hide → pin open: bars converge into a single chevron pointing
   RIGHT ("›", pull the sidebar back in). Direction is reversed from
   the two collapse glyphs to read as "going back the other way". This
   targets the topbar copy, the only one surfaced in auto-hide. */
body.sb-hidden .sidebar-mode-toggle:hover span,
body.sb-hidden .sidebar-mode-toggle:focus-visible span {
  width: 11px;
}
body.sb-hidden .sidebar-mode-toggle:hover span:nth-child(1),
body.sb-hidden .sidebar-mode-toggle:focus-visible span:nth-child(1) {
  transform: translateX(2px) translateY(3px) rotate(45deg);
}
body.sb-hidden .sidebar-mode-toggle:hover span:nth-child(2),
body.sb-hidden .sidebar-mode-toggle:focus-visible span:nth-child(2) {
  transform: translateX(2px) scaleX(1.25);
}
body.sb-hidden .sidebar-mode-toggle:hover span:nth-child(3),
body.sb-hidden .sidebar-mode-toggle:focus-visible span:nth-child(3) {
  transform: translateX(2px) translateY(-3px) rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-mode-toggle span { transition: none; }
  .sidebar-rail-flyout { transition: none; transform: none; }
  .sidebar-rail-flyout.is-shown { transform: none; }
}

/* Which copy is live depends on the mode. Topbar copy: only in
   Auto-hide, where the sidebar (and its in-sidebar copy) is off
   screen. In-sidebar copy: everywhere the sidebar is on screen
   (Pinned, Icon-rail). The mobile @media hides both outright. */
body.sb-pinned #sidebarModeToggle,
body.sb-rail   #sidebarModeToggle { display: none !important; }
body.sb-hidden #sidebarModeToggleRail { display: none !important; }

/* Left-edge reveal hotzone — only interactive in auto-hide mode. */
.sidebar-hotzone {
  position: fixed; top: var(--topbar-h); left: 0; bottom: 0;
  width: 14px; z-index: 25; pointer-events: none;
}

/* ---- Mode: icon rail ---- */
body.sb-rail {
  --sidebar-cur-w: var(--sidebar-rail-w);
}
body.sb-rail .sidebar { width: var(--sidebar-rail-w); }
body.sb-rail.has-sidebar .topbar,
body.sb-rail.has-sidebar .main-area,
body.sb-rail.has-sidebar .footer { margin-left: var(--sidebar-rail-w); }
/* Brand collapses to a compact "HRE" mark in the rail. The wordmark
   text is hidden (zeroed font) and replaced by a centered mark, so it
   never wraps or clips mid-word. Pinned/mobile keep the full wordmark
   (this only applies under body.sb-rail). */
body.sb-rail .sidebar-brand {
  padding: 1rem 0; text-align: center;
  white-space: nowrap; overflow: hidden;
  font-size: 0;
}
body.sb-rail .sidebar-brand::before {
  content: "HRE"; font-size: 1rem; font-weight: 700;
  letter-spacing: .04em; color: inherit;
}
/* v0.69.2 — in-sidebar mode toggle placement.
   Pinned: sit at the right edge of the header, after the wordmark
   (the wordmark is flex:1 and pushes it over). */
body.sb-pinned .sidebar-mode-toggle-rail {
  flex: 0 0 auto; margin-right: .75rem;
}
/* Icon rail: the header is a fixed-height centred stack. The "HRE"
   mark shows by default; hovering or focusing the header cross-fades
   to the hamburger to signal it can be collapsed further. The toggle
   is absolutely centred so the swap never reflows the header. The
   brand link stays keyboard-activatable (Enter) even while faded. */
body.sb-rail .sidebar-head {
  justify-content: center; min-height: 56px;
}
body.sb-rail .sidebar-mode-toggle-rail {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0; transition: opacity .15s ease;
}
body.sb-rail .sidebar-head:hover .sidebar-brand,
body.sb-rail .sidebar-head:focus-within .sidebar-brand { opacity: 0; }
body.sb-rail .sidebar-head:hover .sidebar-mode-toggle-rail,
body.sb-rail .sidebar-head:focus-within .sidebar-mode-toggle-rail { opacity: 1; }
body.sb-rail .sidenav-section {
  text-align: center; padding-left: 0; padding-right: 0;
  font-size: 0; /* hide the words; keep the vertical rhythm */
}
body.sb-rail .sidenav-section::after {
  content: "•"; font-size: .8rem; color: rgba(255,255,255,.25);
}
body.sb-rail .sidenav-link {
  justify-content: center; padding-left: 0; padding-right: 0;
  gap: 0; position: relative;
}
/* Rail flyout label (v0.70.1). Frosted-orange chip that names the
   hovered icon. It is positioned with position:fixed and driven by
   app.js from the icon's getBoundingClientRect(), NOT by CSS offsets
   — the rail's scroll container (.sidenav has overflow-y:auto) clips
   any absolutely-positioned descendant, so an in-flow flyout can't
   escape the 64px rail. Fixed + JS coordinates lifts it out over the
   page content. JS writes --fly-top (label box top, clamped to the
   viewport) and --fly-caret (icon vertical centre, in px from the
   label box top) so the caret keeps pointing at the icon even when
   the box is clamped near a screen edge. The label text comes from
   the existing .sidenav-label element; app.js clones its text into a
   single shared #sidebarRailFlyout node on hover. This selector keeps
   the in-rail .sidenav-label itself hidden. */
body.sb-rail .sidenav-label {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* The shared flyout node, appended to <body> by app.js. Visible only
   while .is-shown is set. left is set inline (rail width + gap). */
.sidebar-rail-flyout {
  position: fixed;
  top: var(--fly-top, 0);
  display: flex; align-items: flex-start;
  pointer-events: none;
  opacity: 0; transform: translateX(-4px);
  transition: opacity .13s ease, transform .13s ease;
  z-index: 60;
}
.sidebar-rail-flyout.is-shown { opacity: 1; transform: translateX(0); }
/* Caret — a rotated square sharing the chip's frosted-orange fill so
   the two read as one piece. Pinned to the icon's centre via
   --fly-caret (px from the flyout's top), independent of the chip box
   so it tracks the icon even when the chip clamps to a screen edge. */
.sidebar-rail-flyout .fly-caret {
  position: absolute; left: 3px;
  top: var(--fly-caret, 18px);
  width: 10px; height: 10px; margin-top: -5px;
  background: rgba(var(--hre-orange-rgb), .82);
  border-left: 1px solid rgba(255,255,255,.30);
  border-bottom: 1px solid rgba(255,255,255,.30);
  transform: rotate(45deg);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.sidebar-rail-flyout .fly-chip {
  margin-left: 9px;
  background: rgba(var(--hre-orange-rgb), .82);
  color: #fff; font-size: .9rem; font-weight: 600; letter-spacing: .01em;
  padding: .4rem .7rem; border-radius: var(--radius);
  border: 1px solid rgba(255,255,255,.24);
  box-shadow: 0 8px 22px rgba(var(--hre-orange-rgb), .28),
              0 2px 6px rgba(0,0,0,.30);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  white-space: nowrap;
}
/* Badge in the rail: dot it onto the icon's top-right corner,
   staying clear of the rail's right edge. */
body.sb-rail .sidenav-badge {
  position: absolute; top: .3rem; left: 50%; margin-left: 4px;
  margin-top: 0; min-width: 0; padding: .05rem .28rem;
  font-size: .58rem; line-height: 1.2;
}

/* ---- Mode: auto-hide ---- */
body.sb-hidden .sidebar {
  transform: translateX(-100%);
  box-shadow: none;
  transition: transform .2s ease;
}
body.sb-hidden.has-sidebar .topbar,
body.sb-hidden.has-sidebar .main-area,
body.sb-hidden.has-sidebar .footer { margin-left: 0; }
body.sb-hidden .sidebar-hotzone { pointer-events: auto; }
/* Revealed overlay: app.js adds .sb-peek when the hotzone is hovered
   (or the topbar button toggles it). The sidebar floats over content
   at full width with a shadow; content does NOT reflow. */
body.sb-hidden.sb-peek .sidebar {
  transform: translateX(0);
  box-shadow: 0 0 24px rgba(0,0,0,.3);
}


/* backdrop for mobile slide-in */
.sidebar-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,.4);
  z-index: 20; opacity: 0; pointer-events: none;
  transition: opacity .2s ease;
}
.sidebar-backdrop.is-open { opacity: 1; pointer-events: auto; }

/* topbar (slim, sits to the right of sidebar on desktop) */
.topbar {
  position: sticky; top: 0; z-index: 10;
  background: var(--hre-navy); color: #fff;
  border-bottom: 3px solid var(--hre-orange);
  height: var(--topbar-h);
}
.topbar-inner {
  display: flex; align-items: center; gap: 1rem;
  padding: 0 1.25rem; height: 100%;
}
.topbar-spacer { flex: 1; }
.user-chip { display: flex; align-items: center; gap: .75rem; font-size: .9rem; color: rgba(255,255,255,.85); }
.user-chip .btn-ghost { color: #fff; border-color: rgba(255,255,255,.3); }
.user-chip .btn-ghost:hover { background: var(--hre-orange); border-color: var(--hre-orange); }

/* hamburger button */
.hamburger {
  display: none;
  width: 40px; height: 40px; padding: 0;
  background: transparent; border: 1px solid rgba(255,255,255,.25);
  border-radius: var(--radius-sm); cursor: pointer;
  flex-direction: column; justify-content: center; align-items: center; gap: 4px;
}
.hamburger span {
  display: block; width: 18px; height: 2px; background: #fff; border-radius: 2px;
}
.hamburger:hover { border-color: var(--hre-orange); }

/* main area offset to right of sidebar on desktop */
.has-sidebar .topbar,
.has-sidebar .main-area,
.has-sidebar .footer { margin-left: var(--sidebar-w); }

.main-area { min-height: calc(100vh - var(--topbar-h)); }

/* footer */
.footer { background: var(--hre-navy); color: var(--hre-sand); font-size: .8rem; padding: .75rem 0; margin-top: 3rem; }

/* page head */
.page-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 1rem; flex-wrap: wrap;
  padding: 1.25rem 0 1rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.25rem;
}
.page-head h1 { color: var(--hre-navy); }
.page-head-actions { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }

/* employee header — avatar next to name on detail page */
.employee-header { display: flex; align-items: center; gap: 1rem; }
.employee-header h1 { line-height: 1.1; }

/* avatars (employee photos) */
.avatar {
  display: inline-block; object-fit: cover;
  background: var(--hre-sand);
  border: 1px solid var(--border);
}
.avatar-sm { width: 36px; height: 36px; border-radius: 50%; vertical-align: middle; }
.avatar-lg { width: 96px; height: 96px; border-radius: 50%; }
.avatar-placeholder {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--hre-navy); color: var(--hre-orange);
  font-weight: 600; letter-spacing: .03em;
}
.avatar-sm.avatar-placeholder { font-size: .8rem; }
.avatar-lg.avatar-placeholder { font-size: 2rem; }
.avatar-col { width: 50px; padding-right: 0 !important; }

/* photo uploader on the employee form */
.photo-uploader {
  display: flex; gap: 1.25rem; align-items: flex-start;
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
  padding: 1rem 1.25rem; margin-bottom: 1.25rem;
}
.photo-uploader-preview { flex-shrink: 0; }
.photo-uploader-controls { display: flex; flex-direction: column; gap: .35rem; }
.field-label { font-size: .85rem; font-weight: 500; color: var(--hre-navy); }
.photo-upload-btn { cursor: pointer; align-self: flex-start; }
.photo-remove { font-size: .85rem; color: var(--muted); display: inline-flex; gap: .35rem; align-items: center; cursor: pointer; }

/* buttons */
.btn, .btn-ghost {
  display: inline-block; padding: .55rem 1rem;
  border-radius: var(--radius-sm); font-size: .9rem; font-weight: 500;
  cursor: pointer; border: 1px solid transparent;
  text-decoration: none; line-height: 1.2;
}
.btn-primary { background: var(--hre-orange); color: #fff; border-color: var(--hre-orange); }
.btn-primary:hover { background: var(--hre-orange-dark); border-color: var(--hre-orange-dark); text-decoration: none; }
.btn-danger { background: transparent; color: var(--danger); border-color: rgba(179,38,30,.4); }
.btn-danger:hover { background: var(--danger); color: #fff; border-color: var(--danger); text-decoration: none; }
.btn-danger-solid { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-danger-solid:hover { background: #8a1d17; border-color: #8a1d17; color: #fff; text-decoration: none; }
.btn-ghost { background: transparent; color: var(--hre-navy); border-color: var(--border); }
.btn-ghost:hover { background: var(--hre-sand); text-decoration: none; }
.btn-block { display: block; width: 100%; }
.inline-form { display: inline; margin: 0; }

/* forms */
.form { max-width: 480px; }
.form-wide { max-width: 900px; }
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .9rem 1rem; }
.field { display: flex; flex-direction: column; gap: .25rem; }
.field[hidden] { display: none; }       /* beat .field's flex */
.field-full { grid-column: 1 / -1; }
.field span { font-size: .85rem; font-weight: 500; color: var(--hre-navy); }
.form-section-title {
  margin: 1.5rem 0 .75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  font-size: 1rem;
  font-weight: 600;
  color: var(--hre-navy);
}

/* First section heading on a page: no top border / no extra padding,
 * since there's nothing above it to separate from. Used on form, show,
 * and print pages so the spacing rhythm stays consistent. */
.form-section-title-first {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* Radio group rendered inside the form-grid as a single .field cell.
 * The fieldset gets the same vertical structure as a label.field so
 * it lines up with the surrounding inputs. */
.field-radio-group {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;          /* avoid the legacy fieldset min-width: min-content */
}
.field-radio-group legend {
  font-size: .85rem;
  font-weight: 500;
  color: var(--hre-navy);
  padding: 0;
  margin-bottom: .35rem;
}
.field-radio-group .radio-option {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  margin-right: 1rem;
  font-size: .95rem;
  cursor: pointer;
}
.field-radio-group .radio-option input[type="radio"] {
  margin: 0;
  accent-color: var(--hre-orange);
}
.field input, .field select, .field textarea {
  padding: .5rem .65rem; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: .95rem; font-family: inherit; background: #fff;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid var(--hre-orange); outline-offset: -1px; border-color: var(--hre-orange);
}
.form-actions { margin-top: 1.25rem; display: flex; gap: .75rem; align-items: center; }

/* Vertical rhythm for stacked-field forms (login, etc.). The .form-grid
 * variant uses CSS grid gap and is unaffected. */
.form > .field + .field,
.form > .field + .btn,
.form > .field + button {
  margin-top: 1rem;
}

/* Password input with show/hide toggle (used on login). */
.password-wrap { position: relative; display: block; }
.password-wrap input[type="password"],
.password-wrap input[type="text"] {
  width: 100%;
  padding-right: 2.6rem; /* leave room for the eye button */
}
.password-toggle {
  position: absolute;
  top: 50%;
  right: .35rem;
  transform: translateY(-50%);
  background: transparent;
  border: 0;
  padding: .35rem;
  margin: 0;
  cursor: pointer;
  color: var(--muted);
  line-height: 0;
  border-radius: var(--radius-sm);
}
.password-toggle:hover,
.password-toggle:focus-visible {
  color: var(--hre-navy);
  background: rgba(32, 35, 56, .06);
  outline: none;
}
.password-toggle svg {
  width: 18px;
  height: 18px;
  display: block;
}
.password-toggle .icon-eye-off { display: none; }
.password-toggle.is-visible .icon-eye      { display: none; }
.password-toggle.is-visible .icon-eye-off  { display: block; }

/* alerts */
.alert { padding: .65rem .9rem; border-radius: var(--radius-sm); margin: .5rem 0; border-left: 4px solid; }
.alert-success { background: #e8f5ec; border-color: var(--success); color: #14532d; }
.alert-error   { background: #fbe9e8; border-color: var(--danger);  color: #7a1b15; }
.alert-info    { background: #e8f1fa; border-color: var(--info);    color: #14385e; }
.alert-warning { background: #fcf3da; border-color: var(--warning); color: #6a4a05; }

/* tables */
.table-wrap { overflow-x: auto; background: #fff; border: 1px solid var(--border); border-radius: var(--radius); }
.table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.table thead th {
  background: var(--hre-navy); color: #fff; text-align: left;
  padding: .65rem .8rem; font-weight: 600; font-size: .8rem;
  text-transform: uppercase; letter-spacing: .03em;
}
.table tbody td { padding: .6rem .8rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tbody tr:nth-child(even) { background: var(--hre-sand); }
.table tbody tr:nth-child(odd)  { background: #fff; }
.table tbody tr:hover { background: var(--hre-sand-2); }
.actions-col { white-space: nowrap; text-align: right; }

/* Sortable column headers on the Employees list. Headers sit on the
   navy header background, so links are white and the active icon uses
   orange. Same interaction model as the PTO dashboard. */
.table thead th.emp-sortable { padding: 0; }
.table thead th.emp-sortable a {
  display: flex; align-items: center; gap: .3rem;
  padding: .65rem .8rem; color: inherit; text-decoration: none;
}
.table thead th.emp-sortable a:hover { color: var(--hre-orange); }
.emp-sort-icon { font-size: .65rem; opacity: .7; }
.emp-sort-neutral { opacity: .4; }
.emp-sort-active { color: var(--hre-orange); opacity: 1; }

/* badges */
.badge { display: inline-block; padding: .15rem .55rem; border-radius: 999px; font-size: .75rem; font-weight: 600; text-transform: uppercase; }
.badge-active     { background: #e8f5ec; color: var(--success); }
.badge-inactive   { background: #f0eee4; color: #6a6553; }
.badge-terminated { background: #fbe9e8; color: var(--danger); }
/* v0.47.0 — inline marker next to a profile field whose new value has
   been submitted but not yet finalised by admin. Uses the HRE warning
   palette to read as "in flight" rather than as success or failure. */
.badge-pending {
  background: #fcf3da; color: #6a4a05;
  text-transform: none; font-weight: 500; margin-left: .5rem;
  font-size: .72rem;
}

/* v0.47.0 / retired in v0.48.1 — the situational "Need to update your
   personal details?" entry point used to live in its own banner above
   the tabs (.profile-edit-banner). It was relocated into the Account
   tab as a second .security-row beneath Password, so the dedicated
   styles were removed. If the row ever needs to differ visually from
   the Password row again, add scoped classes inside .security-row
   rather than reviving the standalone banner. */

/* key-value list */
.kv {
  display: grid; grid-template-columns: 180px 1fr; gap: .55rem 1rem;
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.25rem;
}
.kv dt { font-weight: 600; color: var(--hre-navy); }
.kv dd { margin: 0; }

/* stat cards */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; }
.stat-card {
  background: #fff; border: 1px solid var(--border);
  border-left: 4px solid var(--hre-orange); border-radius: var(--radius);
  padding: 1rem 1.25rem; color: inherit; text-decoration: none; display: block;
}
.stat-card:hover { background: var(--hre-sand-2); text-decoration: none; }
.stat-label { font-size: .8rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.stat-value { font-size: 2rem; font-weight: 700; color: var(--hre-navy); margin-top: .25rem; }

/* empty state */
.empty-state { background: #fff; border: 1px dashed var(--border); border-radius: var(--radius); padding: 3rem 2rem; text-align: center; }
.empty-state p { color: var(--muted); margin-bottom: 1rem; }

/* plain pages (login) — no sidebar */
.plain-body { min-height: 100vh; margin: 0; background: var(--hre-sand); }
.plain-main { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 2rem 1rem; }
.auth-card {
  background: #fff; border-top: 4px solid var(--hre-orange);
  padding: 2rem 2rem 2.25rem; border-radius: var(--radius);
  box-shadow: 0 4px 16px rgba(32,35,56,.12);
  width: 100%; max-width: 400px;
}
.auth-card-wide { max-width: 460px; }
.auth-brand { text-align: center; margin-bottom: 1.5rem; }
.auth-brand h1 { color: var(--hre-navy); margin-bottom: .25rem; }

/* v0.46.0 — single-device takeover confirmation page */
.auth-warn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px;
  border-radius: 50%;
  background: var(--hre-orange); color: #fff;
  margin-bottom: .85rem;
  box-shadow: 0 2px 8px rgba(238,150,63,.35);
}
.auth-warn-icon svg { width: 26px; height: 26px; }
.takeover-body {
  background: var(--hre-sand-2);
  border-left: 3px solid var(--hre-orange);
  border-radius: var(--radius-sm);
  padding: .85rem 1.1rem;
  margin: .25rem 0 1.5rem;
}
.takeover-body p { margin: 0 0 .5rem; }
.takeover-body p:last-child { margin-bottom: 0; }
.takeover-actions {
  display: flex; justify-content: flex-end; gap: .6rem; align-items: center;
}

/* installer */
.installer-body { background: var(--hre-sand); margin: 0; min-height: 100vh; }
.installer-shell {
  max-width: 720px; margin: 2rem auto; background: #fff;
  border-top: 4px solid var(--hre-orange); border-radius: var(--radius);
  box-shadow: 0 4px 16px rgba(32,35,56,.08); overflow: hidden;
}
.installer-header { background: var(--hre-navy); color: #fff; padding: 1.25rem 1.5rem; }
.installer-header h1 { color: #fff; margin: 0; }
.installer-header .muted { color: rgba(255,255,255,.7); }
.installer-main { padding: 1.5rem; }
.installer-actions { margin-top: 1.5rem; display: flex; justify-content: space-between; gap: .75rem; align-items: center; }

/* installer — restore step (v0.52.0, F-ops-7) */
.installer-choice {
  border: 1px solid var(--hre-sand-2);
  border-radius: var(--radius-sm);
  padding: 1rem 1.25rem;
  margin: 1rem 0 0;
}
.installer-choice legend { padding: 0 .5rem; font-size: .85rem; }
.installer-choice-row {
  display: flex; gap: .85rem; align-items: flex-start;
  padding: .85rem; margin: .25rem 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color .12s ease;
}
.installer-choice-row:hover { background: var(--hre-sand-2); }
.installer-choice-row input[type="radio"] {
  margin-top: .25rem; flex-shrink: 0;
}
.installer-choice-row strong { display: block; margin-bottom: .25rem; }
.installer-choice-row p { margin: 0; font-size: .9rem; }

.installer-restore-fields {
  margin: .25rem .25rem 1rem 2.25rem;
  padding: .85rem 1rem;
  background: var(--hre-sand-2);
  border-left: 4px solid var(--hre-orange);
  border-radius: var(--radius-sm);
  display: block;
}
/* [hidden] + display: footgun (see 10-conventions). The .installer-
   restore-fields rule above uses display:block to anchor its inset
   styling; without this matching rule the `hidden` attribute would
   be overridden and the file/passphrase fields would render even
   when the operator chose Fresh. */
.installer-restore-fields[hidden] { display: none !important; }

.installer-meta {
  display: grid; grid-template-columns: max-content 1fr; gap: .5rem 1rem;
  margin: 1rem 0;
}
.installer-meta dt { font-weight: 600; color: var(--hre-navy); }
.installer-meta dd { margin: 0; }
.installer-inventory { margin: 0; padding-left: 1.25rem; }
.installer-inventory li { padding: .1rem 0; }

.form-inline { display: inline; margin: 0; padding: 0; }

/* upgrader / install log */
.install-log-pre {
  background: var(--hre-sand-2); border-radius: var(--radius-sm);
  padding: 1rem 1.25rem; margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .85rem; white-space: pre-wrap; word-wrap: break-word;
}
.install-log {
  background: var(--hre-sand-2); border-radius: var(--radius-sm);
  padding: 1rem 1.25rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .85rem;
}
.install-log-line { padding: .15rem 0; }
.migration-list { padding-left: 1.25rem; margin: 0 0 1rem; }
.migration-list li { padding: .25rem 0; }

/* confirm modal */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(32,35,56,.55); /* HRE Navy w/ alpha */
  display: none; align-items: center; justify-content: center;
  z-index: 100; padding: 1rem;
  backdrop-filter: blur(2px);
}
.modal-backdrop.is-open { display: flex; }
.modal {
  background: #fff; border-radius: var(--radius);
  width: 100%; max-width: 460px;
  border-top: 4px solid var(--hre-orange);
  box-shadow: 0 12px 40px rgba(32,35,56,.35);
  animation: modal-pop .18s ease-out;
  overflow: hidden;
}
.modal-wide { max-width: 560px; }
@keyframes modal-pop {
  from { opacity: 0; transform: translateY(-8px) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.modal-header { padding: 1.1rem 1.5rem .5rem; }
.modal-title { color: var(--hre-navy); margin: 0; font-size: 1.2rem; }
.modal-subtitle { font-size: .85rem; margin-top: .15rem; }
.modal-body { padding: 0 1.5rem 1.25rem; }
.modal-message { margin: 0; color: var(--text); }
.modal-actions {
  display: flex; justify-content: flex-end; gap: .6rem;
  padding: .9rem 1.5rem; background: var(--hre-sand-2);
  border-top: 1px solid var(--border);
}

/* ===========================================================
   Work Experience Letter — preview surface (v0.66.0)

   Two render contexts share these styles:
   - The in-page modal opened from the history table
     (#wePreviewModal, opt-in via .we-preview-trigger).
   - The /admin/we-letters/history/{id}/preview page rendered
     through layout/plain when JS is disabled.

   The "paper" container mimics a sheet of letter paper —
   white background, sand border, navy meta header strip —
   to make the preview read as a document rather than a
   chunk of UI. Body-only by design (header/footer chrome
   isn't representable in HTML); the subtitle calls this
   out explicitly.
=========================================================== */

/* Wider modal sized for letter-paper content. */
.modal-preview {
  max-width: 820px;
  width: 100%;
}
.modal-preview .modal-body {
  max-height: 70vh;
  overflow-y: auto;
}

/* Meta strip — letter ref, employee, template, issuance time.
   Sits inside the modal body, above the paper, and on the
   layout/plain page above .we-letter-paper. */
.we-preview-meta {
  display: grid; grid-template-columns: 1fr 1fr; gap: .25rem .75rem;
  padding: .6rem .85rem; margin-bottom: .85rem;
  background: var(--hre-sand-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: .9rem;
}
.we-preview-meta > div { color: var(--text); }
.we-preview-meta code { font-size: .85rem; }

/* The paper. White surface, sand border, gentle shadow. */
.we-letter-paper {
  background: #ffffff;
  border: 1px solid var(--hre-sand);
  border-radius: var(--radius-sm);
  box-shadow: 0 2px 8px rgba(32,35,56,.06);
  padding: 1.75rem 2rem;
  font-family: Georgia, 'Times New Roman', serif;
  color: #2b2b2b;
  line-height: 1.55;
}
.we-letter-paper .we-letter-meta {
  display: grid; grid-template-columns: 1fr 1fr; gap: .25rem .75rem;
  padding: .6rem .85rem; margin-bottom: 1.25rem;
  background: var(--hre-sand-2);
  border-left: 3px solid var(--hre-orange);
  border-radius: var(--radius-sm);
  font-family: var(--font-sans, system-ui, sans-serif);
  font-size: .9rem;
  color: var(--text);
}

/* Paragraph defaults. Inline styles from DocxToHtml override
   alignment where the source paragraph specified one. */
.we-letter-body .we-letter-p {
  margin: 0 0 .6rem 0;
  text-align: left;
}
.we-letter-body .we-letter-p:last-child { margin-bottom: 0; }

/* Tables — neutral border, brand-coherent header cells.
   DocxToHtml doesn't distinguish thead/tbody (the source XML
   often doesn't either), so we style every cell uniformly. */
.we-letter-body .we-letter-table {
  width: 100%;
  border-collapse: collapse;
  margin: .75rem 0 1rem 0;
  font-size: .95rem;
}
.we-letter-body .we-letter-table td {
  border: 1px solid var(--border);
  padding: .45rem .65rem;
  vertical-align: top;
}
.we-letter-body .we-letter-table td .we-letter-p {
  margin-bottom: .35rem;
}

/* Residual-token flag — should never appear on an issued letter
   (generation aborts on unresolved tokens) but if it ever does,
   make it screamingly visible rather than blend in. */
.we-letter-token-unresolved {
  background: #fbe9e8;
  color: var(--danger, #b1382d);
  padding: 0 .25rem;
  border-radius: 2px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .9em;
}

/* layout/plain rendering — the no-JS fallback page. */
.we-preview-page { max-width: 820px; margin: 1.5rem auto; padding: 0 1rem; }
.we-preview-toolbar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap;
}

/* Mobile: meta strips fall to single column, paper tightens up. */
@media (max-width: 720px) {
  .we-preview-meta,
  .we-letter-paper .we-letter-meta { grid-template-columns: 1fr; }
  .we-letter-paper { padding: 1.1rem 1.1rem; }
  .modal-preview .modal-body { max-height: 78vh; }
}

/* progress steps (stepwise checklist) */
.progress-steps {
  list-style: none; margin: .5rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: .5rem;
}
.step-row {
  display: flex; align-items: center; gap: .75rem;
  padding: .55rem .75rem;
  background: var(--hre-sand-2); border-radius: var(--radius-sm);
  border-left: 3px solid var(--border);
  transition: border-color .2s, background .2s;
}
.step-row.step-running { border-left-color: var(--hre-orange); background: #fff5e6; }
.step-row.step-done    { border-left-color: var(--success);    background: #effaf1; }
.step-row.step-failed  { border-left-color: var(--danger);     background: #fbe9e8; }
.step-label { color: var(--text); }
.step-row.step-pending .step-label { color: var(--muted); }

.step-icon {
  width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; font-weight: 700; font-size: .8rem; color: #fff;
}
.step-pending {
  background: transparent; border: 2px solid var(--border);
}
.step-running {
  background: transparent; border: 2px solid var(--hre-orange);
  border-top-color: transparent;
  animation: step-spin .8s linear infinite;
}
@keyframes step-spin { to { transform: rotate(360deg); } }
.step-done   { background: var(--success); }
.step-failed { background: var(--danger); }
.step-skipped { background: var(--muted); }

.progress-error {
  margin-top: 1rem; padding: .65rem .9rem;
  background: #fbe9e8; color: #7a1b15;
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-sm);
  font-size: .9rem;
}

/* DB migration banner (top of admin pages) */
.migration-banner { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; }
.migration-banner .btn-sm { padding: .35rem .75rem; font-size: .8rem; }

/* ----------------------------------------------------------------
 * Notifications (v0.49.0)
 *
 * Three surfaces:
 *   1. .topbar-bell   — bell icon in the topbar with .topbar-bell-badge
 *   2. .notification-banner — inline alert reuses .alert .alert-info;
 *                       this rule just gives it the same flex shape
 *                       as .migration-banner so the CTA sits inline.
 *   3. .notification-list — the /notifications inbox page list.
 *
 * The bell uses the same colour vocabulary as .user-chip so the
 * topbar feels of-a-piece. Hover lifts the icon (orange accent
 * matches the .btn-ghost hover on the user chip).
 * ---------------------------------------------------------------- */
.topbar-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  color: rgba(255, 255, 255, .85);
  text-decoration: none;
  transition: color .15s, background .15s;
}
.topbar-bell:hover,
.topbar-bell.is-active { color: var(--hre-orange); background: rgba(255, 255, 255, .08); }
.topbar-bell svg { display: block; }
.topbar-bell-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--hre-orange);
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--hre-navy);
}

/* ----------------------------------------------------------------
 * Bell dropdown (v0.49.1)
 *
 * The bell is now a <details> element. The <summary> wraps the bell
 * icon (keeping its existing .topbar-bell styling); the sibling
 * .bell-dropdown panel appears when the details is open. No JS is
 * required for open/close — that's the browser's job. app.js adds
 * click-outside-to-close and Escape-to-close on top.
 *
 * The default disclosure triangle and cursor are stripped from the
 * summary so the bell appears as a regular icon button.
 * ---------------------------------------------------------------- */
.topbar-bell-wrap {
  position: relative;
  display: inline-block;
  margin-right: .5rem;
}
.topbar-bell-wrap > summary.topbar-bell {
  list-style: none;             /* Firefox triangle */
  cursor: pointer;
  user-select: none;
}
.topbar-bell-wrap > summary.topbar-bell::-webkit-details-marker {
  display: none;                /* WebKit triangle */
}
.topbar-bell-wrap[open] > summary.topbar-bell {
  color: var(--hre-orange);
  background: rgba(255, 255, 255, .08);
}
.bell-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 340px;
  max-width: calc(100vw - 1rem);
  background: #fff;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .2);
  z-index: 100;
  overflow: hidden;
}
.bell-dropdown-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: .65rem .85rem;
  border-bottom: 1px solid var(--border);
  background: var(--hre-sand);
}
.bell-dropdown-head strong { color: var(--hre-navy); }
.bell-dropdown-empty {
  padding: 1.25rem .85rem;
  text-align: center;
  font-size: .9rem;
}
.bell-dropdown-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 360px;
  overflow-y: auto;
}
.bell-dropdown-item { border-top: 1px solid var(--border); }
.bell-dropdown-item:first-child { border-top: 0; }
.bell-dropdown-item.is-unread { background: #fff8ee; }
.bell-dropdown-form { margin: 0; }
.bell-dropdown-btn {
  display: flex;
  align-items: center;
  gap: .6rem;
  width: 100%;
  padding: .65rem .85rem;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.bell-dropdown-btn:hover,
.bell-dropdown-btn:focus { background: rgba(238, 150, 63, .08); outline: none; }
.bell-dropdown-btn .notification-tone {
  flex: 0 0 4px;
  align-self: stretch;
  min-height: 28px;
  border-radius: 2px;
}
.bell-dropdown-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: .15rem;
}
.bell-dropdown-title {
  font-weight: 600;
  color: var(--hre-navy);
  font-size: .9rem;
  /* truncate long titles to a single line */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bell-dropdown-time { font-size: .75rem; }
.bell-dropdown-btn .notification-dot { margin-left: .25rem; align-self: center; }
.bell-dropdown-foot {
  padding: .55rem .85rem;
  border-top: 1px solid var(--border);
  background: #fafbfd;
  text-align: center;
}
.bell-dropdown-link {
  font-size: .85rem;
  font-weight: 600;
  color: var(--hre-navy);
  text-decoration: none;
}
.bell-dropdown-link:hover { color: var(--hre-orange); text-decoration: underline; }

.notification-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem;
}
.notification-banner .btn-sm { padding: .35rem .75rem; font-size: .8rem; }
/* v0.49.1 — banner dismiss × button. Sits at the right of the banner,
 * pushed by margin-left:auto. Reuses the alert's own text colour so it
 * inherits the alert-info hue without us hard-coding a shade. */
.notification-banner-dismiss-form { margin: 0 0 0 auto; display: inline-flex; }
.notification-banner-dismiss {
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 1.25rem;
  line-height: 1;
  padding: .25rem .5rem;
  cursor: pointer;
  opacity: .6;
  border-radius: 4px;
  transition: opacity .15s, background .15s;
}
.notification-banner-dismiss:hover,
.notification-banner-dismiss:focus { opacity: 1; background: rgba(0, 0, 0, .06); outline: none; }

.notification-list {
  list-style: none;
  padding: 0;
  margin: 1rem 0 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fff;
  overflow: hidden;
}
.notification-item {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: .85rem 1rem;
  border-top: 1px solid var(--border);
}
.notification-item:first-child { border-top: 0; }
.notification-item.is-unread { background: #fff8ee; }
.notification-tone {
  flex: 0 0 4px;
  align-self: stretch;
  border-radius: 2px;
  background: var(--border);
}
.notification-tone-success { background: #28a745; }
.notification-tone-danger  { background: #d9534f; }
.notification-tone-neutral { background: var(--hre-orange); }
.notification-body { flex: 1; min-width: 0; }
.notification-head {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: .25rem;
}
.notification-time { font-size: .8rem; }
.notification-title { font-weight: 600; color: var(--hre-navy); }
.notification-text { margin-top: .25rem; white-space: pre-line; font-size: .9rem; }
.notification-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--hre-orange);
  margin-left: auto;
}
.notification-action { flex: 0 0 auto; align-self: center; }

/* Pill colour extensions used by the notification list (and reused by
 * any future surface that wants a red or neutral pill — the existing
 * .pill-success / .pill-warning / .pill-muted / .pill-orange already
 * cover the others). */
.pill-danger  { background: #f8d7da; color: #721c24; }
.pill-neutral { background: #e9ecef; color: #495057; }

@media (max-width: 720px) {
  .notification-item { flex-wrap: wrap; }
  .notification-action { width: 100%; align-self: flex-start; }
}

.btn-sm { padding: .35rem .75rem !important; font-size: .8rem !important; }

/* responsive */
@media (max-width: 768px) {
  .has-sidebar .topbar,
  .has-sidebar .main-area,
  .has-sidebar .footer { margin-left: 0; }
  .sidebar { transform: translateX(-100%); }
  .sidebar.is-open { transform: translateX(0); box-shadow: 0 0 24px rgba(0,0,0,.3); }
  .hamburger { display: inline-flex; }
  body.sidebar-open { overflow: hidden; }

  /* v0.69.1 — below the breakpoint the off-canvas drawer is the only
     behaviour. Neutralise every desktop mode so a persisted rail/auto-
     hide choice can't bleed into mobile: force full-width content,
     restore the full-width slide-in sidebar, show labels inline, and
     hide the desktop-only controls. */
  .sidebar-mode-toggle { display: none !important; }
  .sidebar-hotzone { display: none !important; }
  body.sb-rail.has-sidebar .topbar,
  body.sb-rail.has-sidebar .main-area,
  body.sb-rail.has-sidebar .footer,
  body.sb-hidden.has-sidebar .topbar,
  body.sb-hidden.has-sidebar .main-area,
  body.sb-hidden.has-sidebar .footer { margin-left: 0; }
  body.sb-rail .sidebar,
  body.sb-hidden .sidebar { width: var(--sidebar-w); }
  body.sb-hidden .sidebar { transform: translateX(-100%); }
  body.sb-hidden.sb-peek .sidebar { transform: translateX(0); }
  body.sb-rail .sidebar.is-open,
  body.sb-hidden .sidebar.is-open { transform: translateX(0); }
  /* Restore inline labels + normal link layout on mobile. */
  body.sb-rail .sidenav-link { justify-content: flex-start; padding: .6rem 1.25rem; gap: .7rem; }
  body.sb-rail .sidenav-label {
    position: static; transform: none; opacity: 1; pointer-events: auto;
    background: none; border: 0; box-shadow: none; padding: 0;
    width: auto; height: auto; margin: 0; overflow: visible;
    clip: auto; white-space: normal;
    flex: 1 1 auto;
  }
  body.sb-rail .sidenav-section { font-size: .7rem; text-align: left; padding: 1rem 1.25rem .25rem; }
  body.sb-rail .sidenav-section::after { content: none; }
  body.sb-rail .sidebar-brand { padding: 1rem 1.25rem; text-align: left; font-size: 1.05rem; }
  body.sb-rail .sidebar-brand::before { content: none; }
  /* v0.69.2 — the header reverts to a plain left-aligned row on mobile
     (both mode-toggle copies are already hidden above); undo the rail
     centred-stack layout so a persisted rail choice can't reshape the
     drawer header. */
  .sidebar-head { justify-content: flex-start; min-height: 0; }
  body.sb-rail .sidenav-badge {
    position: static; margin-left: .5rem; min-width: 1.4rem;
    padding: .1rem .45rem; font-size: .72rem;
  }
}

@media (max-width: 700px) {
  .form-grid { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 1fr; }
  .photo-uploader { flex-direction: column; align-items: center; text-align: center; }
}

/* ===================================================================
   v0.10.0 — User & Role management UI
   =================================================================== */

/* Active/inactive status pills */
.badge-active   { background: #d4edda; color: #155724; }
.badge-inactive { background: #f1f3f5; color: #6c757d; }
.badge-info     { background: #fef3e7; color: #8a4b08; }

/* Two-column show grid */
.show-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;
  margin-bottom: 2rem;
}
.show-section { min-width: 0; }
@media (max-width: 800px) {
  .show-grid { grid-template-columns: 1fr; }
}

/* Definition list used for the show pages */
.data-list {
  display: grid; grid-template-columns: 9rem 1fr;
  gap: .35rem 1rem; margin: 0;
}
.data-list dt { color: var(--muted); font-size: .9rem; }
.data-list dd { margin: 0; }

/* Role chips on the user-show page */
.role-chip-list { list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; gap: .4rem; }
.role-chip {
  display: inline-block; padding: .25rem .65rem;
  background: var(--hre-sand); color: var(--hre-navy);
  border-radius: 999px; font-size: .85rem; font-weight: 500;
}

/* Action bar on user-show */
.action-bar {
  display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start;
  margin-bottom: 1.5rem;
}
.action-detail { min-width: 0; }
.action-detail summary { cursor: pointer; list-style: none; }
.action-detail summary::-webkit-details-marker { display: none; }
.action-detail[open] summary { margin-bottom: .75rem; }
.action-form {
  background: var(--hre-sand);
  padding: 1rem; border-radius: var(--radius-sm);
  max-width: 38rem;
}

/* Generic checkbox grid for role-pickers */
.checkbox-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: .75rem 1.25rem; margin-bottom: 1.5rem;
}
.checkbox-row {
  display: flex; align-items: flex-start; gap: .6rem;
  padding: .55rem .75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  cursor: pointer;
  line-height: 1.4;
}
.checkbox-row:hover { border-color: var(--hre-orange); }
.checkbox-row input[type=checkbox] {
  margin-top: .15rem; accent-color: var(--hre-orange);
}
.checkbox-row input[type=checkbox][disabled] { opacity: .5; }

/* Permissions grid — fieldsets per module */
.permissions-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1.25rem; margin-bottom: 1.5rem;
}
.perm-module {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: .9rem 1rem 1.1rem; margin: 0; background: #fff;
}
.perm-module legend {
  font-weight: 600; padding: 0 .4rem;
  text-transform: capitalize; color: var(--hre-navy);
}
.perm-module .btn-sm { float: right; margin-top: -.25rem; }
.perm-list { display: flex; flex-direction: column; gap: .4rem; margin-top: .5rem; clear: both; }
.perm-list .checkbox-row code { font-size: .8rem; color: var(--muted); margin-left: .35rem; }

/* Field helpers */
.req { color: var(--danger); }
.field-error {
  margin: .35rem 0 0; color: var(--danger); font-size: .85rem;
}
.field-help {
  margin: .35rem 0 0; color: var(--muted); font-size: .85rem;
}
.form-field-wide { grid-column: 1 / -1; }

/* ---------------------------------------------------------------------
   v0.12.0 additions
   --------------------------------------------------------------------- */

/* warning-tone badge + row tint for "Incomplete" employee records */
.badge-warning { background: #fff3cd; color: #856404; }
.text-warning  { color: #856404; }
.row-incomplete td:first-child { box-shadow: inset 3px 0 0 #d9a441; }

/* Profile page — tabbed layout (vertical tabs on the left) */
.profile-tabs {
  margin-top: 1rem;
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden;
  display: grid;
  grid-template-columns: 220px 1fr;
}
.tab-list {
  display: flex; flex-direction: column;
  background: var(--hre-sand-2);
  border-right: 1px solid var(--border);
  padding: .75rem 0;
  gap: .15rem;
}
.tab-button {
  appearance: none; background: transparent; border: 0;
  padding: .75rem 1.1rem;
  font-family: inherit; font-size: .92rem; font-weight: 600;
  color: var(--muted); cursor: pointer;
  border-left: 3px solid transparent;
  text-align: left;
  transition: color .15s, border-color .15s, background .15s;
}
.tab-button:hover { color: var(--hre-navy); background: rgba(255,255,255,.5); }
.tab-button.is-active {
  color: var(--hre-navy);
  border-left-color: var(--hre-orange);
  background: #fff;
}
.tab-button:focus-visible {
  outline: 2px solid var(--hre-orange); outline-offset: -2px;
}
.tab-panels { padding: 1.25rem 1.5rem 1.5rem; }
.tab-panel { display: none; }
.tab-panel.is-active { display: block; animation: tab-fade .15s ease-out; }
@keyframes tab-fade { from { opacity: 0; } to { opacity: 1; } }

.tab-panel .kv { border: 0; padding: 0; }
.tab-panel .kv + .kv { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.tab-panel h3 {
  color: var(--hre-navy); font-size: 1rem; margin: 0 0 .5rem;
  text-transform: uppercase; letter-spacing: .04em;
}
.tab-panel h3 + .kv { margin-top: 0; }
.tab-panel h3 + .kv + h3 { margin-top: 1.25rem; }

/* Account tab security row — change-password CTA */
.security-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1rem 1.25rem;
  background: var(--hre-sand-2); border: 1px solid var(--border);
  border-radius: var(--radius); margin-top: 1rem;
}
.security-row .security-text strong { color: var(--hre-navy); display: block; }
.security-row .security-text .muted { font-size: .85rem; }

/* Profile header refinements */
.profile-header {
  display: flex; align-items: center; gap: 1.25rem;
  padding: 1.25rem 1.5rem;
  background: linear-gradient(135deg, var(--hre-navy) 0%, #2e324d 100%);
  color: #fff; border-radius: var(--radius);
  border-left: 4px solid var(--hre-orange);
}
.profile-header h1 { color: #fff; margin: 0 0 .15rem; font-size: 1.5rem; }
.profile-header .muted { color: #d9d4be; }
.profile-header .badge { vertical-align: middle; }
.profile-header .avatar-placeholder {
  background: var(--hre-orange); color: #fff;
}

/* Password change modal — extends the existing .modal scaffolding */
.modal-form .form-field { margin-bottom: 1rem; }
.modal-form .form-field:last-of-type { margin-bottom: 0; }
.modal-form label {
  display: block; font-weight: 600; margin-bottom: .4rem;
  color: var(--hre-navy); font-size: .9rem;
}
.modal-form .password-wrap input { width: 100%; }
.pw-match-status { font-size: .85rem; margin: .4rem 0 0; min-height: 1.1em; }
.pw-match-status.is-mismatch { color: var(--danger); }
.pw-match-status.is-match    { color: var(--success); }

/* ---------------------------------------------------------------------
   v0.46.0 — polished password modal
   v0.47.2 — input styling, eye-toggle separator, header polish.
             The original v0.46.0 cut shipped without baseline input
             rules for `.modal-form .password-wrap input`, which meant
             the three password fields fell back to the raw browser
             default border (1px inset, no radius, no focus state).
             This block adds the missing input baseline + tightens the
             header and helper text.
   --------------------------------------------------------------------- */

/* Slightly wider modal so the heading + icon row breathes. */
.modal-pw { max-width: 480px; }

/* Header layout: icon disc on the left, title + subtitle on the right. */
.pw-modal-header {
  display: flex; align-items: flex-start; gap: .85rem;
  padding: 1.4rem 1.5rem .5rem;
}
.pw-modal-icon {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--hre-orange);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow:
    0 2px 8px rgba(238,150,63,.35),
    0 0 0 4px rgba(238,150,63,.12);
}
.pw-modal-icon svg { width: 22px; height: 22px; }
.pw-modal-heading { flex: 1 1 auto; min-width: 0; }
.pw-modal-heading .modal-title { font-size: 1.2rem; line-height: 1.25; }
.pw-modal-heading .modal-subtitle {
  margin-top: .3rem; line-height: 1.4; font-size: .88rem;
}

/* v0.47.2 — Password field baseline. The .modal-form uses .form-field
   (not .field), so the .field input rule above doesn't apply. This is
   the scoped equivalent for the modal — bordered input, sand-2 fill so
   it reads as an input on the white modal body, orange focus ring
   matching the rest of the app. */
.modal-form .password-wrap input[type="password"],
.modal-form .password-wrap input[type="text"] {
  width: 100%;
  padding: .6rem 2.75rem .6rem .8rem; /* right pad leaves room for the eye btn */
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--hre-navy);
  font-size: .95rem;
  font-family: inherit;
  line-height: 1.3;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.modal-form .password-wrap input::placeholder { color: #9c9785; }
.modal-form .password-wrap input:hover {
  border-color: #c2bda9;
}
.modal-form .password-wrap input:focus {
  outline: none;
  border-color: var(--hre-orange);
  box-shadow: 0 0 0 3px rgba(238,150,63,.22);
  background: #fff;
}
.modal-form .password-wrap input:disabled {
  background: var(--hre-sand-2); color: var(--muted); cursor: not-allowed;
}

/* v0.47.2 — Eye toggle: tighter hit area, slight separator from the
   input edge, hover/focus plate. The base .password-toggle styling
   (assets/css/app.css line ~302) covers the icon swap; this layer just
   places it nicely inside the wider modal input. */
.modal-form .password-toggle {
  right: .25rem;
  padding: .4rem;
  border-radius: var(--radius-sm);
  color: #6a6553;
}
.modal-form .password-toggle:hover,
.modal-form .password-toggle:focus-visible {
  color: var(--hre-orange-dark);
  background: rgba(238,150,63,.12);
}
.modal-form .password-toggle svg { width: 18px; height: 18px; }

/* v0.47.2 — Helper text styled as a soft inline hint rather than a
   stray paragraph. The "At least 8 characters." line now reads as a
   field affordance. */
.modal-form .form-field .field-help {
  margin: .4rem 0 0;
  font-size: .8rem;
  color: var(--muted);
}

/* "Contact your administrator" note shown only in force mode. */
.pw-modal-note {
  margin: 1.25rem 0 0;
  padding: .7rem .9rem;
  background: var(--hre-sand-2);
  border-left: 3px solid var(--hre-orange);
  border-radius: var(--radius-sm);
  font-size: .87rem;
  line-height: 1.4;
  color: var(--text);
}
.pw-modal-note strong { color: var(--hre-navy); }

/* Force-mode backdrop sits above the toast layer so nothing in the
   page can pop through it. Heavier blur + tint than the default
   modal-backdrop, to communicate "this is the only thing you can
   interact with right now." */
.pw-modal-backdrop.is-force {
  z-index: 1100;
  background: rgba(32,35,56,.78);
  backdrop-filter: blur(5px);
}
.pw-modal-backdrop.is-force .modal {
  border-top-width: 5px;
  box-shadow: 0 20px 60px rgba(32,35,56,.45);
}

/* v0.47.2 — Mobile: shrink modal padding and icon disc so the modal
   doesn't overflow a 380px viewport. */
@media (max-width: 480px) {
  .modal-pw { max-width: calc(100vw - 1.5rem); }
  .pw-modal-header { padding: 1.15rem 1.15rem .35rem; gap: .7rem; }
  .pw-modal-icon { width: 38px; height: 38px; }
  .pw-modal-icon svg { width: 19px; height: 19px; }
  .modal-body { padding: 0 1.15rem 1rem; }
  .modal-actions { padding: .8rem 1.15rem; }
}

@media (max-width: 600px) {
  .profile-tabs { grid-template-columns: 1fr; }
  .tab-list {
    flex-direction: row; flex-wrap: wrap;
    border-right: 0; border-bottom: 1px solid var(--border);
    padding: 0;
  }
  .tab-button {
    border-left: 0; border-bottom: 3px solid transparent;
    padding: .7rem .85rem; font-size: .85rem;
  }
  .tab-button.is-active {
    border-left-color: transparent;
    border-bottom-color: var(--hre-orange);
  }
  .tab-panels { padding: 1rem; }
  .security-row { flex-direction: column; align-items: stretch; }
}

/* ---------------------------------------------------------------------
   v0.13.0 additions — audit log
   --------------------------------------------------------------------- */

/* Audit-tone badges (extend the badge family). The danger/success/warning
   tones piggy-back on the existing variables. */
.badge-danger  { background: #fbe9e8; color: var(--danger); }
.badge-success { background: #e8f5ec; color: var(--success); }
.badge-neutral { background: #f0eee4; color: #6a6553; }

/* Filter bar */
.audit-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: .75rem 1rem;
  align-items: end;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin: 1rem 0;
}
.audit-filters .form-field { margin: 0; }
.audit-filters label {
  display: block; font-weight: 600; font-size: .8rem;
  color: var(--hre-navy); margin-bottom: .3rem;
  text-transform: uppercase; letter-spacing: .04em;
}
.audit-filters select,
.audit-filters input[type="date"] {
  width: 100%; padding: .45rem .6rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: #fff; font-family: inherit; font-size: .92rem;
}
.audit-filter-actions { display: flex; gap: .5rem; align-items: center; }

/* Table tweaks */
.audit-table .audit-when {
  white-space: nowrap; font-variant-numeric: tabular-nums;
  color: var(--muted); font-size: .88rem;
}
.audit-table .badge { font-family: var(--mono, ui-monospace, monospace); text-transform: none; letter-spacing: 0; }

/* Diff display on /audit/{id} */
.audit-diff { margin-top: .75rem; }
.audit-changes th, .audit-changes td { vertical-align: top; }
.audit-changes .audit-old {
  background: #fef2f2; color: #7a2727;
  font-family: var(--mono, ui-monospace, monospace); font-size: .9rem;
}
.audit-changes .audit-new {
  background: #f0fbf3; color: #1f5d33;
  font-family: var(--mono, ui-monospace, monospace); font-size: .9rem;
}
.audit-extra { margin-top: 1rem; }
.audit-raw {
  background: var(--hre-sand-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: .85rem 1rem;
  font-size: .85rem; overflow-x: auto;
  margin-top: .75rem;
}
.audit-ua {
  font-size: .8rem; word-break: break-all;
  background: var(--hre-sand-2); padding: .15rem .35rem;
  border-radius: var(--radius-sm);
}

/* Pagination */
.pagination {
  display: flex; gap: .75rem; align-items: center; justify-content: center;
  margin-top: 1.25rem;
}
.pagination .pagination-info { color: var(--muted); font-size: .9rem; }
.pagination .is-disabled {
  opacity: .45; cursor: not-allowed; pointer-events: none;
}

/* ===================================================================
   v0.17.0 — Backup pills & rollback affordances
   =================================================================== */

/* Compact status pill, used in the backups table for kind/DB-snapshot. */
.pill {
  display: inline-block;
  font-size: .75rem;
  font-weight: 600;
  padding: .12rem .55rem;
  border-radius: 999px;
  background: var(--hre-sand, #e2ddc7);
  color: var(--hre-navy, #202338);
  letter-spacing: .02em;
  vertical-align: middle;
  white-space: nowrap;
}
.pill-success { background: #d4edda; color: #155724; }
.pill-warning { background: #fef3e7; color: #8a4b08; }
.pill-muted   { background: #f1f3f5; color: #6c757d; }
.pill-orange  { background: #ffe7cc; color: #8a4b08; }

/* Make backup rows feel clickable when they carry data-href. */
.backups-table tbody tr.backup-row { cursor: pointer; }
.backups-table tbody tr.backup-row:hover { background: rgba(238, 150, 63, 0.06); }
.backups-table tbody tr.backup-row a,
.backups-table tbody tr.backup-row form,
.backups-table tbody tr.backup-row button {
  cursor: auto;
}
.backups-table tbody tr.backup-row button { cursor: pointer; }
.backups-table .actions-col { white-space: nowrap; }
.backups-table .actions-col .btn-ghost,
.backups-table .actions-col form { display: inline-block; vertical-align: middle; }
.backups-table .actions-col form { margin-left: .35rem; }

/* Smaller variant of the ghost button for inline table actions. */
.btn-sm {
  font-size: .82rem;
  padding: .25rem .65rem;
}

/* Danger ghost — used on the row's "Roll back" button. */
.btn-ghost.btn-danger {
  color: var(--danger, #b9241c);
  border-color: rgba(185, 36, 28, 0.35);
}
.btn-ghost.btn-danger:hover {
  background: rgba(185, 36, 28, 0.08);
  border-color: var(--danger, #b9241c);
  color: var(--danger, #b9241c);
}

/* Loud danger alert variant on the backup-detail page. */
.alert-danger {
  background: #fff1ef;
  border-left: 4px solid var(--danger, #b9241c);
  color: #6a1410;
  padding: .85rem 1rem;
  margin: .75rem 0 1rem;
  border-radius: 4px;
}
.alert-danger strong { color: var(--danger, #b9241c); }

/* =========================================================================
   v0.18.0 — HRE Benefits matrix
   One big editable table on /admin/benefits. Every cell, including column
   headers and the topic column, is an input. Sticky first three columns
   (#, topic) and sticky header row keep orientation while editing.
   ========================================================================= */

.benefits-form {
  margin-top: 1rem;
}

/* Toolbar: action buttons above and below the table. */
.benefits-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .75rem;
  padding: .65rem .85rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: .75rem;
}
.benefits-toolbar-bottom {
  margin-top: 1rem;
  margin-bottom: 0;
}
.benefits-toolbar-left,
.benefits-toolbar-right {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}
.benefits-counter {
  font-size: .82rem;
  margin-left: .25rem;
}

/* Outer wrap: lets the table scroll horizontally on narrow viewports
   without breaking the page layout. The shadow on the right edge hints
   at scrollability. */
.benefits-table-wrap {
  position: relative;
  overflow-x: auto;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* Subtle inner shadow on the right edge to suggest more content. */
  box-shadow: inset -8px 0 8px -8px rgba(32, 35, 56, .08);
}

.benefits-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: .9rem;
  table-layout: auto;
}

/* All header cells. */
.benefits-table thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--hre-navy);
  color: #fff;
  font-weight: 600;
  text-align: left;
  padding: .55rem .65rem;
  border-bottom: 1px solid var(--hre-navy-2);
  white-space: nowrap;
  vertical-align: middle;
}
.benefits-table thead th.bm-serial-head {
  width: 3.25rem;
  text-align: center;
  position: sticky;
  left: 0;
  z-index: 5;
}
.benefits-table thead th.bm-topic-head {
  position: sticky;
  left: 3.25rem;
  z-index: 5;
  min-width: 16rem;
}
.benefits-table thead th.bm-col-head {
  min-width: 13rem;
}
.benefits-table thead th.bm-rowctl-head {
  width: 2.25rem;
  background: var(--hre-navy);
}

/* Column header inner: input + delete-x sit side-by-side. */
.bm-col-head-inner {
  display: flex;
  align-items: center;
  gap: .35rem;
}
.bm-col-input {
  flex: 1 1 auto;
  min-width: 0;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .18);
  color: #fff;
  padding: .35rem .5rem;
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 600;
}
.bm-col-input::placeholder { color: rgba(255, 255, 255, .55); }
.bm-col-input:focus {
  outline: none;
  background: rgba(255, 255, 255, .14);
  border-color: var(--hre-orange);
  box-shadow: 0 0 0 2px rgba(238, 150, 63, .35);
}
.bm-col-del {
  flex: 0 0 auto;
  width: 1.55rem;
  height: 1.55rem;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, .55);
  font-size: 1.05rem;
  line-height: 1;
  border-radius: 4px;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.bm-col-del:hover {
  background: rgba(255, 100, 90, .25);
  color: #ffd9d4;
}

/* Body cells. */
.benefits-table tbody td {
  padding: .35rem .45rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  background: #fff;
}
.benefits-table tbody tr:nth-child(even) td { background: var(--hre-sand-2); }
.benefits-table tbody tr:hover td        { background: #fff8e9; }

/* Sticky serial + topic columns. */
.benefits-table tbody td.bm-serial {
  position: sticky;
  left: 0;
  z-index: 2;
  text-align: center;
  width: 3.25rem;
  color: var(--hre-navy);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  border-right: 1px solid var(--border);
}
.benefits-table tbody td.bm-topic {
  position: sticky;
  left: 3.25rem;
  z-index: 2;
  min-width: 16rem;
  border-right: 1px solid var(--border);
}
.bm-serial-num {
  display: inline-block;
  min-width: 1.5rem;
  padding: .15rem .4rem;
  border-radius: 999px;
  background: var(--hre-sand);
  color: var(--hre-navy);
  font-size: .78rem;
  letter-spacing: .02em;
}
.benefits-table tbody tr:hover td.bm-serial .bm-serial-num {
  background: var(--hre-orange);
  color: #fff;
}

/* All editable inputs in the body. */
.bm-topic-input,
.bm-cell-input {
  width: 100%;
  border: 1px solid transparent;
  background: transparent;
  padding: .4rem .55rem;
  font: inherit;
  border-radius: var(--radius-sm);
  color: var(--hre-navy);
  transition: background .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.bm-topic-input { font-weight: 600; }
.bm-cell-input  { font-weight: 400; }
.bm-topic-input::placeholder,
.bm-cell-input::placeholder { color: #b3aea0; }
.bm-topic-input:hover,
.bm-cell-input:hover {
  background: #fff;
  border-color: var(--border);
}
.bm-topic-input:focus,
.bm-cell-input:focus {
  outline: none;
  background: #fff;
  border-color: var(--hre-orange);
  box-shadow: 0 0 0 2px rgba(238, 150, 63, .25);
  position: relative;
  z-index: 1;
}

/* v0.69.0 — read-only matrix (GET /admin/benefits). The view-only
   page renders spans instead of inputs; these match the editable
   metrics so the two pages line up visually. */
.bm-col-label-ro {
  display: block;
  color: #fff;
  font-weight: 600;
  padding: .35rem .5rem;
}
.bm-topic-ro,
.bm-cell-ro {
  display: block;
  padding: .4rem .55rem;
  color: var(--hre-navy);
}
.bm-topic-ro { font-weight: 600; }
.bm-cell-ro  { font-weight: 400; }
.benefits-table-readonly tbody tr:hover td { background: #fff8e9; }

/* Row-control column on the right edge. */
.benefits-table tbody td.bm-rowctl { width: 2.25rem; text-align: center; }
.bm-row-del {
  width: 1.7rem;
  height: 1.7rem;
  border: 1px solid transparent;
  background: transparent;
  color: #b09e7a;
  font-size: 1.05rem;
  line-height: 1;
  border-radius: 4px;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.bm-row-del:hover {
  background: #fbe7e3;
  color: var(--danger);
  border-color: rgba(179, 38, 30, .3);
}

.benefits-empty {
  padding: 2rem 1rem;
  text-align: center;
}

/* My Benefits tab on the profile page. The table is rendered in a tab
   panel (no horizontal scroll wrapper here — the panel already handles
   width). The "Not eligible" pill is muted to keep the table calm even
   when several rows are not applicable to the user's tier. */
.my-benefits-table {
  margin-top: .25rem;
}
/* Serial column — narrow, centred, tabular-numerals so digits align. */
.my-benefits-table th.my-benefits-serial,
.my-benefits-table td.my-benefits-serial {
  width: 3rem;
  text-align: center;
  color: var(--hre-navy);
  font-variant-numeric: tabular-nums;
}
.my-benefits-table tbody td.my-benefits-serial {
  font-weight: 600;
}
/* Topic column — second column now — sized for readable benefit names. */
.my-benefits-table th:nth-child(2),
.my-benefits-table td:nth-child(2) { width: 38%; }
.benefit-not-eligible {
  font-style: italic;
  color: #8a8170;
}

/* =========================================================================
   v0.18.1 — HRE Benefits matrix: hover-insert affordances
   The `.bm-row-insert` button sits inside each row's serial cell,
   absolutely positioned to overlap the top edge between this row and
   the row above. The `.bm-col-insert` button sits inside each column
   header, positioned on the left edge between this column and its left
   neighbour. Both are invisible at rest and fade in on hover of the
   axis (row or column header).

   The parent cells (.bm-serial, .bm-col-head) are already
   `position: sticky` from the v0.18.0 block above; sticky establishes
   a positioning context for absolutely-positioned children, so the
   inserts anchor correctly without redeclaring position here.
   ========================================================================= */

.bm-row-insert,
.bm-col-insert {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border: 1px solid var(--hre-orange);
  background: #fff;
  color: var(--hre-orange);
  font-weight: 700;
  font-size: .9rem;
  line-height: 1;
  border-radius: 999px;
  padding: 0;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease, transform .12s ease, background .12s ease, color .12s ease;
  box-shadow: 0 1px 4px rgba(32, 35, 56, .15);
  z-index: 6;
}

/* Row insert: top edge of the serial cell, centred horizontally. */
.bm-row-insert {
  top: -.7rem;
  left: 50%;
  transform: translateX(-50%) scale(.85);
}
/* Column insert: left edge of the col header, centred vertically. */
.bm-col-insert {
  top: 50%;
  left: -.7rem;
  transform: translateY(-50%) scale(.85);
}

/* Reveal on hover of the row (any cell in the row) or column header. */
.benefits-table tbody tr:hover .bm-row-insert,
.benefits-table thead th.bm-col-head:hover .bm-col-insert,
.bm-row-insert:focus-visible,
.bm-col-insert:focus-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) scale(1);
}
.benefits-table thead th.bm-col-head:hover .bm-col-insert,
.bm-col-insert:focus-visible {
  /* Override the X transform with the Y one for the col case. */
  transform: translateY(-50%) scale(1);
}

.bm-row-insert:hover,
.bm-col-insert:hover {
  background: var(--hre-orange);
  color: #fff;
}

.bm-row-insert:focus-visible,
.bm-col-insert:focus-visible {
  outline: 2px solid rgba(238, 150, 63, .55);
  outline-offset: 2px;
}

/* v0.18.2 — first-row insert button fully visible.
   The first row's `+` previously sat at `top: -.5rem`, which placed it
   under the sticky thead and made it hard to spot against the column
   header row's dark navy background. Pushing it slightly further down
   (into the row's own white cell area) keeps it inside its own row's
   bounds and clearly visible against the cream/white body, so it
   reads as belonging to row 1, not row 0.

   v0.19.0 — first column's insert `+` is no longer relocated.
   v0.18.2 anchored the first-column `+` to `left: .35rem` (inside its
   own header) so it wouldn't spill onto the sticky topic column. In
   practice that broke visual symmetry with the rest of the row — the
   other columns' `+`s sit on the boundary between two columns, while
   the first column's sat inside its own cell. Reverted: the first
   column's `+` now uses the default `left: -.7rem`, putting it on the
   boundary between the topic column and the first tier column like
   every other `+`. The z-index relationship (`.bm-col-insert` z=6 vs
   `.bm-topic-head` / `.bm-topic` z=5/2) keeps it on top of the sticky
   topic column when scrolled. */
.benefits-table tbody tr:first-child .bm-row-insert { top: .35rem; }

/* =========================================================================
   v0.19.0 — Mirrored top horizontal scrollbar for the HRE Benefits matrix.

   The default `.benefits-table-wrap` has overflow-x: auto so the bottom
   of the wrap shows a scrollbar. On long matrices that scrollbar is
   below the fold and admins can't reach it without scrolling the page.
   We add a thin scrollable strip above the table, sized to match the
   table's scroll width via JS, so the user can scroll horizontally
   from the top of the matrix as well. The two scrollers are kept in
   sync by event handlers in the page script.

   The strip itself is just a 14px-tall scroller; the inner spacer is
   1px tall and grows as wide as the table. Visually quiet — it only
   shows the scrollbar thumb on browsers/platforms that paint one
   (macOS hides scrollbars by default, but the strip remains
   draggable/scroll-wheel-capable from the trackpad).
   ========================================================================= */
.benefits-table-scroller-top {
  overflow-x: auto;
  overflow-y: hidden;
  height: 14px;
  border: 1px solid var(--border);
  border-bottom: 0;
  border-top-left-radius: var(--radius);
  border-top-right-radius: var(--radius);
  background: #fff;
  margin-top: 0;
}
.benefits-table-scroller-top-inner {
  height: 1px;
  width: 100%; /* JS sets this to match table.scrollWidth */
}
/* When the top scroller is in use, the table-wrap below it loses its
   own top radius so the two pieces visually fuse into one frame. */
.benefits-table-scroller-top + .benefits-table-wrap {
  border-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

/* =========================================================================
   v0.19.0 — Sub-section heading inside a single tab panel.

   The Employees create/edit form uses tabs (matching My Profile), so the
   per-section .form-section-title rule no longer applies — every tab
   starts at the top of its panel. Instead, when one tab needs internal
   sub-headings (Employment + Benefits, or Emergency contact + Health &
   dietary inside the combined Health & Emergency tab), use this lighter
   sub-section style so they don't read as full sections.
   ========================================================================= */
.form-subsection-title {
  margin: 1.25rem 0 .65rem;
  padding-top: .85rem;
  border-top: 1px solid var(--border);
  font-size: .95rem;
  font-weight: 600;
  color: var(--hre-navy);
}
.form-subsection-title-first {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* The Employees form tabs share the .profile-tabs visual treatment but
   live inside a <form>, so a couple of margin tweaks help them sit
   between the page-head and the bottom .form-actions row without
   double-spacing. */
.employee-form-tabs {
  margin-top: .25rem;
  margin-bottom: 1.25rem;
}

/* v0.19.0 — Stacking fix for the first column's hover-insert `+`.
   `.bm-col-head` is `position: sticky` with z-index: 3 (from the
   generic `thead th` rule). `.bm-topic-head` is sticky with z-index: 5.
   That means the first column header's entire stacking context renders
   below the topic header — and its child `.bm-col-insert` (anchored at
   `left: -.7rem`, spilling into the topic column's visual area) is
   hidden behind the topic header even though the insert's own
   z-index is 6, because z-index of children only applies within
   their parent stacking context.
   On hover or keyboard focus of the first column header we promote
   it above the topic header so the `+` becomes visible. The promotion
   only applies during the brief moment the user is interacting with
   the column, so the navy-on-navy header bar stays visually quiet at
   rest. */
.benefits-table thead th.bm-col-head:first-of-type:hover,
.benefits-table thead th.bm-col-head:first-of-type:focus-within {
  z-index: 7;
}

/* =================================================================
   v0.21.0 — Softwares vault (admin index + employee /me panel).

   Two surfaces, related but distinct:

   1. Admin index (.sw-admin / .sw-card / .sw-list / .sw-row)
      — A grid of category cards. Each card has a head with title,
        action buttons, and a count pill, then a list of software
        rows beneath. Designed for fast scanning when the admin is
        looking for a specific entry to edit or delete.

   2. Employee /me vault (.sw-vault*)
      — Collapsible <details> panels per category, each holding a
        row of name / link / username / password / notes. Matches
        the visual brief: bullet-masked credentials with reveal +
        copy affordances. Uses native <details>/<summary> for
        collapse so it works without JS for keyboard users.
   ================================================================= */

/* ---- Admin index --------------------------------------------- */
.sw-admin { display: grid; gap: 1rem; }

.sw-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(32,35,56,.04);
}
.sw-card.is-virtual {
  border-style: dashed;
  background: var(--hre-sand-2);
}

.sw-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: .9rem 1rem;
  background: var(--hre-navy);
  color: #fff;
  border-bottom: 3px solid var(--hre-orange);
}
.sw-card.is-virtual .sw-card-head {
  background: var(--hre-navy-2);
  border-bottom-color: var(--border);
}
.sw-card-title h2 {
  color: #fff;
  font-size: 1.05rem;
  margin: 0;
}
.sw-card-title .muted {
  color: rgba(255,255,255,.7);
  font-size: .85rem;
  margin-top: .15rem;
}
.sw-card-actions {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
  flex-shrink: 0;
}
.sw-card-actions .btn-ghost {
  color: #fff;
  border-color: rgba(255,255,255,.3);
}
.sw-card-actions .btn-ghost:hover {
  background: var(--hre-orange);
  border-color: var(--hre-orange);
  color: #fff;
}
.sw-card-actions .btn-ghost.btn-danger {
  color: #fff;
  border-color: rgba(255,180,180,.4);
}
.sw-card-actions .btn-ghost.btn-danger:hover {
  background: var(--danger);
  border-color: var(--danger);
}
.sw-count-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.6rem;
  height: 1.4rem;
  padding: 0 .5rem;
  border-radius: 999px;
  background: var(--hre-orange);
  color: #fff;
  font-size: .8rem;
  font-weight: 600;
}

.sw-list { list-style: none; margin: 0; padding: 0; }
.sw-row {
  display: grid;
  grid-template-columns: 1.5fr 1.4fr 1.4fr 1.4fr auto;
  gap: 1rem;
  align-items: center;
  padding: .65rem 1rem;
  border-bottom: 1px solid var(--border);
  font-size: .9rem;
}
.sw-row:nth-child(even) { background: var(--hre-sand); }
.sw-row:nth-child(odd)  { background: #fff; }
.sw-row:last-child { border-bottom: 0; }
.sw-row-name { font-weight: 600; color: var(--hre-navy); }
.sw-row-url a {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  max-width: 100%;
  overflow: hidden;
}
.sw-url-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sw-row-user, .sw-row-pw {
  display: flex;
  align-items: center;
  gap: .4rem;
}
.sw-mono {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: .85rem;
  color: var(--text);
}
.sw-row-pw .sw-mono { color: var(--hre-orange-dark); }
.sw-pw-bad { color: var(--danger) !important; }
.sw-icon { color: var(--muted); font-size: .85rem; }
.sw-row-actions {
  display: flex;
  gap: .35rem;
  justify-content: flex-end;
}
.sw-empty {
  padding: 1rem;
  text-align: center;
  font-style: italic;
}

/* Software-form: clear-password checkbox */
.sw-pw-remove {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  margin-top: .5rem;
  font-size: .85rem;
  color: var(--muted);
  cursor: pointer;
}
.sw-pw-remove input { margin: 0; }

/* Inline hints below a field input. Same vertical position as .err but
 * neutral styling — used for "must start with http://" type guidance.
 * Lives in v0.21.0 because that's where I noticed it was missing; the
 * Departments/Users/Employees forms can adopt it freely. */
.field-hint {
  display: block;
  margin-top: .25rem;
  font-size: .8rem;
  color: var(--muted);
  line-height: 1.35;
}
.field-hint code {
  font-size: .85em;
  background: var(--hre-sand);
  padding: 0 .25rem;
  border-radius: 3px;
}
.field-hint a { color: var(--hre-orange-dark); text-decoration: underline; }
.field-hint a:hover { color: var(--hre-orange); }

/* The existing .password-wrap was sized for a narrow login form. When
 * embedded inside a .field grid cell it needs to fill its parent. */
.field .password-wrap { width: 100%; }
.field .password-wrap input { width: 100%; }

/* ---- Employee /me vault ------------------------------------- */
.sw-vault {
  display: flex;
  flex-direction: column;
  gap: .6rem;
  margin-top: .25rem;
}

.sw-vault-cat {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(32,35,56,.04);
}
.sw-vault-cat[open] {
  box-shadow: 0 2px 6px rgba(32,35,56,.08);
}
.sw-vault-cat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .8rem 1rem;
  background: var(--hre-sand-2);
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  color: var(--hre-navy);
  border-bottom: 1px solid var(--border);
  user-select: none;
  outline-offset: -2px;
}
.sw-vault-cat-head::-webkit-details-marker { display: none; }
.sw-vault-cat-head:focus-visible { outline: 2px solid var(--hre-orange); }
.sw-vault-cat:not([open]) .sw-vault-cat-head { border-bottom-color: transparent; }
.sw-vault-cat[open] .sw-vault-chevron { transform: rotate(180deg); }
.sw-vault-chevron {
  transition: transform .18s ease;
  color: var(--hre-navy);
}
.sw-vault-cat-meta {
  display: flex;
  align-items: center;
  gap: .55rem;
}
/* v0.23.3: a left-cluster wrapping handle + title so the parent's
   space-between only sees two children (lead + meta). Without this
   wrapper, the handle, title, and meta would all be distributed
   across the row, leaving the title visually centred. */
.sw-vault-cat-lead {
  display: inline-flex;
  align-items: center;
  min-width: 0;
}
.sw-vault-cat-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  height: 1.25rem;
  padding: 0 .45rem;
  border-radius: 999px;
  background: var(--hre-orange);
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
}
.sw-vault-cat-title { letter-spacing: .01em; }

.sw-vault-list { list-style: none; margin: 0; padding: 0; }
.sw-vault-row {
  display: grid;
  grid-template-columns: 1.4fr 1.3fr 1.3fr 1.4fr;
  gap: 1rem;
  align-items: center;
  padding: .65rem 1rem;
  border-bottom: 1px solid var(--border);
  font-size: .92rem;
  background: #fff;
  transition: background .12s;
}
.sw-vault-row:nth-child(even) { background: var(--hre-sand-2); }
.sw-vault-row:hover { background: var(--hre-sand); }
.sw-vault-row:last-child { border-bottom: 0; }

.sw-vault-cell { display: flex; align-items: center; gap: .35rem; min-width: 0; }
.sw-vault-name {
  font-weight: 600;
  color: var(--hre-navy);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sw-vault-link-anchor {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  max-width: 100%;
  overflow: hidden;
}
.sw-vault-link-anchor svg { color: var(--info); flex-shrink: 0; }
.sw-vault-link-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: .9rem;
}
.sw-vault-icon { color: var(--muted); flex-shrink: 0; }
.sw-vault-icon-key { color: var(--hre-orange); }

.sw-vault-secret {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: .9rem;
  color: var(--text);
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sw-vault-row .sw-vault-pw .sw-vault-secret[data-sw-state="hidden"] {
  color: var(--hre-orange-dark);
}
.sw-vault-row .sw-vault-pw .sw-vault-secret[data-sw-state="shown"] {
  color: var(--hre-orange-dark);
  font-weight: 600;
  background: rgba(238,150,63,.08);
  border-radius: 3px;
  padding: 0 .25rem;
}
.sw-vault-na {
  color: var(--muted);
  font-style: italic;
  font-size: .85rem;
}

.sw-vault-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--muted);
  cursor: pointer;
  flex-shrink: 0;
  transition: all .12s;
}
.sw-vault-btn:hover {
  background: rgba(32,35,56,.06);
  color: var(--hre-navy);
  border-color: var(--border);
}
.sw-vault-btn:focus-visible {
  outline: 2px solid var(--hre-orange);
  outline-offset: 1px;
}
.sw-vault-btn:disabled,
.sw-vault-btn[disabled] {
  opacity: .35;
  cursor: not-allowed;
}
.sw-vault-btn:disabled:hover,
.sw-vault-btn[disabled]:hover {
  background: transparent;
  color: var(--muted);
  border-color: transparent;
}
.sw-vault-btn-eye .icon-eye-off { display: none; }
.sw-vault-btn-eye.is-visible .icon-eye      { display: none; }
.sw-vault-btn-eye.is-visible .icon-eye-off  { display: block; }
.sw-vault-btn-spacer { display: inline-block; width: 24px; height: 24px; flex-shrink: 0; }

.sw-vault-notes {
  grid-column: 1 / -1;
  font-size: .85rem;
  padding-top: .15rem;
}

.sw-vault-toast {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  padding: .55rem 1rem;
  background: var(--hre-navy);
  color: #fff;
  border-radius: var(--radius);
  font-size: .85rem;
  box-shadow: 0 4px 16px rgba(32,35,56,.25);
  opacity: 0;
  transition: opacity .15s ease;
  z-index: 1000;
  pointer-events: none;
}
.sw-vault-toast.is-visible { opacity: 1; }

/* Mobile: stack the row cells. The grid is too tight on narrow
   viewports for the four-column credential layout; stacking gives
   each cell a full row with its own icon + value + button cluster. */
@media (max-width: 760px) {
  .sw-vault-row {
    grid-template-columns: 1fr;
    gap: .35rem;
  }
  .sw-vault-name { font-size: 1rem; }
  .sw-vault-cell { padding-left: .25rem; }
  .sw-row {
    grid-template-columns: 1fr 1fr;
    gap: .5rem;
  }
  .sw-row-name { grid-column: 1 / -1; }
  .sw-row-actions { grid-column: 1 / -1; justify-content: flex-start; }
}

/* =================================================================
   v0.23.0 — Softwares: collapsible categories + toolbar.

   Adds a shared toolbar (search / sort / expand-all / collapse-all)
   above both the admin index and the employee /me vault, and
   converts the admin index cards from <section> to <details> so the
   "all collapsed by default" requirement is met natively.

   The employee /me vault was already <details>-based; this section
   also re-skins its category head to match the admin palette (navy
   background, white text, orange accent bar) so the two surfaces
   feel like the same product.
   ================================================================= */

/* ---- Toolbar (shared by admin + /me) -------------------------- */
.sw-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: .65rem .85rem;
  margin: .25rem 0 .9rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(32,35,56,.04);
}
.sw-toolbar-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 260px;
  min-width: 200px;
}
.sw-toolbar-search-icon {
  position: absolute;
  left: .55rem;
  color: var(--muted);
  pointer-events: none;
}
.sw-toolbar-search input[type="search"] {
  width: 100%;
  padding: .45rem .55rem .45rem 2rem;
  font: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--hre-sand-2);
  color: var(--text);
  outline-offset: 1px;
  transition: border-color .12s, background .12s;
  /* Hide the browser's default search "X" — we render our own to
     keep the appearance consistent across Chromium / Firefox / Safari. */
  -webkit-appearance: none;
          appearance: none;
}
.sw-toolbar-search input[type="search"]::-webkit-search-decoration,
.sw-toolbar-search input[type="search"]::-webkit-search-cancel-button,
.sw-toolbar-search input[type="search"]::-webkit-search-results-button,
.sw-toolbar-search input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none;
}
.sw-toolbar-search input[type="search"]:focus {
  border-color: var(--hre-orange);
  background: #fff;
  outline: 2px solid rgba(238,150,63,.25);
  outline-offset: 0;
}
.sw-toolbar-search-clear {
  position: absolute;
  right: .35rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 999px;
  color: var(--muted);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}
.sw-toolbar-search-clear:hover {
  background: rgba(32,35,56,.08);
  color: var(--hre-navy);
}

.sw-toolbar-controls {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
}
.sw-toolbar-sort-label {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-size: .85rem;
  color: var(--muted);
  white-space: nowrap;
}
.sw-toolbar-sort-label select {
  font: inherit;
  font-size: .85rem;
  color: var(--text);
  padding: .35rem .4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fff;
  cursor: pointer;
}
.sw-toolbar-sort-label select:focus {
  outline: 2px solid rgba(238,150,63,.25);
  border-color: var(--hre-orange);
}
.sw-toolbar-collapse-group {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}
.sw-toolbar-empty {
  margin: -.4rem 0 .9rem;
  text-align: center;
  font-style: italic;
}

/* ---- Admin index: <details>-based collapsible cards ----------- */
/* The .sw-card baseline (border, background, shadow) is already
   defined above; here we layer the details-element specifics. */
.sw-card[data-sw-cat] > summary {
  list-style: none;
  cursor: pointer;
}
.sw-card[data-sw-cat] > summary::-webkit-details-marker { display: none; }
.sw-card[data-sw-cat] > summary:focus-visible {
  outline: 2px solid var(--hre-orange);
  outline-offset: -2px;
}
.sw-card-title {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  min-width: 0;
}
.sw-card-title-text { min-width: 0; }
.sw-card-chevron {
  color: #fff;
  flex-shrink: 0;
  margin-top: .15rem;
  transition: transform .18s ease;
}
.sw-card[open] .sw-card-chevron { transform: rotate(90deg); }
.sw-card.is-virtual .sw-card-chevron { color: rgba(255,255,255,.85); }

/* ---- Employee /me vault: adopt admin palette ------------------ */
/* Override the v0.21.0 .sw-vault-cat-head (sand background, navy
   text) with the admin treatment (navy background, white text,
   orange bottom accent + orange count pill). The override lives in
   the v0.23.0 block so the diff is visible and easy to revert. */
.sw-vault-cat-head {
  background: var(--hre-navy);
  color: #fff;
  border-bottom: 3px solid var(--hre-orange);
}
.sw-vault-cat:not([open]) .sw-vault-cat-head {
  border-bottom-color: transparent;
}
.sw-vault-cat-title { color: #fff; }
.sw-vault-chevron { color: #fff; }
.sw-vault-cat-head:focus-visible {
  outline: 2px solid var(--hre-orange);
  outline-offset: -2px;
}

/* v0.23.1 — [hidden] vs display:grid.
   .sw-vault-row and .sw-row both set display:grid in author CSS, which
   wins over the user-agent's display:none on [hidden]. The result was
   that searching hid rows in the JS dataset but they stayed visible on
   screen (see v0.23.1 wobble). Force display:none with !important on
   the grid-display row selectors when [hidden] is set. Same for
   <details> cards that get hidden in their entirety. */
.sw-row[hidden],
.sw-vault-row[hidden],
.sw-card[hidden],
.sw-vault-cat[hidden] { display: none !important; }

/* Mobile: keep the toolbar compact. Search takes a full row, the
   controls cluster underneath. v0.23.4 — tightened spacing so the
   toolbar reads as a single block instead of stretching down the
   page on narrow viewports. */
@media (max-width: 640px) {
  .sw-toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: .55rem;
    padding: .55rem .65rem;
  }
  .sw-toolbar-search { flex: 1 1 auto; min-width: 0; }
  .sw-toolbar-search input[type="search"] { padding-top: .55rem; padding-bottom: .55rem; }
  .sw-toolbar-controls {
    justify-content: space-between;
    gap: .5rem;
  }
  .sw-toolbar-sort-label { flex: 1 1 auto; min-width: 0; }
  .sw-toolbar-sort-label select {
    flex: 1 1 auto;
    min-width: 0;
    padding-top: .4rem;
    padding-bottom: .4rem;
  }
  .sw-toolbar-collapse-group { flex: 0 0 auto; }
}

/* =================================================================
   v0.23.2 — Drag-and-drop reorder of CATEGORIES.

   This replaces the v0.23.1 design (which dragged entries within a
   category). The handle now lives in each category's <summary>; the
   <details> element itself carries draggable="true" when sort = custom
   and the category is not virtual. Drop markers go on the category
   card (top or bottom edge) rather than on individual rows.

   Row layout reverts to the v0.21.0 grid templates (no leading handle
   column on rows). The handle CSS stays — same selector — but its
   visual targets are the summary on both surfaces.
   ================================================================= */

.sw-drag-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: grab;
  border-radius: 4px;
  flex-shrink: 0;
  margin-right: .3rem;
  transition: background .12s, color .12s, opacity .12s;
  user-select: none;
  -webkit-user-select: none;
}
.sw-drag-handle:hover {
  background: rgba(238,150,63,.18);
  color: var(--hre-orange);
}
.sw-drag-handle:active { cursor: grabbing; }
.sw-drag-handle:focus-visible {
  outline: 2px solid var(--hre-orange);
  outline-offset: 1px;
}

/* On the admin card head (navy background) the handle starts at muted-
   on-dark; on hover it shows the orange accent. Tone slightly different
   from the row-level handle so the contrast against navy is readable. */
.sw-card-head .sw-drag-handle {
  color: rgba(255,255,255,.55);
}
.sw-card-head .sw-drag-handle:hover {
  background: rgba(238,150,63,.25);
  color: #fff;
}

/* Same treatment on the My Software (post-v0.23.0) navy category head.
   Marked with a helper class to make the intent obvious in markup; the
   selector also matches the parent context for robustness. */
.sw-vault-cat-head .sw-drag-handle,
.sw-drag-handle-on-dark {
  color: rgba(255,255,255,.55);
}
.sw-vault-cat-head .sw-drag-handle:hover,
.sw-drag-handle-on-dark:hover {
  background: rgba(238,150,63,.25);
  color: #fff;
}

/* Spacer keeps the chevron and title aligned on virtual categories
   (which carry no handle). Same width as a real handle. */
.sw-drag-handle-spacer {
  display: inline-block;
  width: 22px;
  height: 22px;
  margin-right: .3rem;
  flex-shrink: 0;
}

/* When sort mode != custom, handles are inert. We keep them in the
   layout but visually deemphasise. The JS also removes [draggable]
   from the <details> element so the drag never starts. */
[data-sw-sort-mode]:not([data-sw-sort-mode="custom"]) .sw-drag-handle {
  opacity: .25;
  cursor: not-allowed;
}
[data-sw-sort-mode]:not([data-sw-sort-mode="custom"]) .sw-drag-handle:hover {
  background: transparent;
}

/* Dragging visual feedback. Now applied to whole category cards. */
.sw-card.is-dragging,
.sw-vault-cat.is-dragging {
  opacity: .35;
}
.sw-card.is-drop-above,
.sw-vault-cat.is-drop-above {
  box-shadow: inset 0 3px 0 var(--hre-orange);
}
.sw-card.is-drop-below,
.sw-vault-cat.is-drop-below {
  box-shadow: inset 0 -3px 0 var(--hre-orange);
}

/* Mobile: drag-on-touch is awkward. Hide the handle entirely; the
   admin can still reorder from a desktop. Note that this DOES leave
   the spacer visible on virtual categories so the chevron alignment
   stays consistent; hide that too. */
@media (max-width: 760px) {
  .sw-drag-handle,
  .sw-drag-handle-spacer { display: none !important; }
}

/* ============================================================
   v0.24.0 — Employment Timeline module
   ============================================================

   Twelve event types each get a colour from the palette below.
   The colour drives three things on every event card / picker
   tile: the left "strip" background, the dot, and a soft tint
   behind the type badge. We use rgba() in-place rather than CSS
   variables so the tint reads correctly without preprocessor
   magic. Per-type colours live in `.timeline-event-type-X`
   rules near the bottom of this section.

   Naming convention: every class is prefixed `.timeline-` to
   avoid clashes with the rest of the app. The few state classes
   (.is-up / .is-down / .is-flat / .is-selected / .is-hidden /
   .is-current) follow the existing house style.
*/

.timeline-page {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* ----- Header card ----- */
.timeline-header {
  background: var(--hre-navy);
  color: #fff;
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--hre-navy-2);
}
.timeline-header-top { margin-bottom: .75rem; }
.timeline-breadcrumb {
  display: flex; gap: .35rem; align-items: center; flex-wrap: wrap;
  font-size: .85rem; color: rgba(255, 255, 255, .65);
}
.timeline-breadcrumb a {
  color: var(--hre-sand);
}
.timeline-breadcrumb a:hover { color: var(--hre-orange); }
.timeline-breadcrumb .is-current { color: var(--hre-orange); font-weight: 600; }

.timeline-header-body {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) auto auto;
  gap: 1rem 1.5rem;
  align-items: center;
}
.timeline-header-id { display: flex; gap: .85rem; align-items: center; min-width: 0; }
.timeline-header-photo {
  width: 56px; height: 56px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--hre-navy-2);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--hre-sand);
  font-weight: 700;
  letter-spacing: .04em;
  flex-shrink: 0;
  border: 2px solid var(--hre-orange);
}
.timeline-header-photo-placeholder { font-size: 1.1rem; }
.timeline-header-name { min-width: 0; }
.timeline-header-name h1 {
  color: #fff;
  font-size: 1.45rem;
  margin: 0 0 .15rem;
}
.timeline-header-meta {
  margin: 0;
  color: rgba(255, 255, 255, .75);
  font-size: .9rem;
  display: flex; gap: .25rem; flex-wrap: wrap;
}
.timeline-header-jobtitle { color: var(--hre-sand); }

/* The timeline header has a navy background, so the default .btn-ghost
   (navy text on transparent) renders invisible. Mirror the .user-chip
   precedent (line ~104): white text + translucent border + orange hover.
   This covers both "View Diagram" on /me/timeline and "Back to Timeline"
   on /me/timeline/diagram. */
.timeline-header .btn-ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, .35);
}
.timeline-header .btn-ghost:hover {
  background: var(--hre-orange);
  border-color: var(--hre-orange);
  color: #fff;
}

.timeline-stats {
  display: flex; gap: .6rem;
  list-style: none; padding: 0; margin: 0;
  flex-wrap: wrap;
}
.timeline-stat-pill {
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--radius);
  padding: .55rem .85rem;
  min-width: 100px;
  display: flex; flex-direction: column; gap: .15rem;
  line-height: 1.2;
}
.timeline-stat-pill .timeline-stat-label {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: rgba(255, 255, 255, .65);
}
.timeline-stat-pill .timeline-stat-value {
  font-size: 1.1rem;
  font-weight: 600;
  color: #fff;
}
.timeline-stat-pill.is-tenure  { border-left: 3px solid var(--hre-orange); }
.timeline-stat-pill.is-events  { border-left: 3px solid var(--hre-sand); }
.timeline-stat-pill.is-awards  { border-left: 3px solid #b8860b; }
.timeline-stat-pill.is-salary  { border-left: 3px solid #2e7d32; }

.timeline-header-actions {
  display: flex; gap: .5rem;
  align-items: center;
  justify-content: flex-end;
}

/* ----- Filter strip ----- */
.timeline-filters {
  display: flex; gap: .75rem;
  align-items: center;
  flex-wrap: wrap;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .5rem .75rem;
}
.timeline-filter-group { position: relative; }
.timeline-filter-trigger {
  background: var(--hre-sand-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .35rem .7rem;
  display: inline-flex; gap: .4rem;
  align-items: center;
  cursor: pointer;
  font: inherit;
  color: var(--hre-navy);
}
.timeline-filter-trigger:hover { background: var(--hre-sand); }
.timeline-filter-label {
  font-size: .8rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.timeline-filter-value { font-weight: 600; }
.timeline-filter-caret { font-size: .7rem; opacity: .7; }
.timeline-filter-menu {
  position: absolute;
  top: calc(100% + .25rem);
  left: 0;
  z-index: 50;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .12);
  padding: .35rem 0;
  min-width: 200px;
  max-height: 320px;
  overflow-y: auto;
}
.timeline-filter-option {
  display: flex; gap: .5rem;
  align-items: center;
  padding: .35rem .75rem;
  cursor: pointer;
  font-size: .9rem;
}
.timeline-filter-option:hover { background: var(--hre-sand-2); }
.timeline-filter-option input { margin: 0; }
.timeline-filter-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--muted);
}
.timeline-filter-counter {
  margin-left: auto;
  font-size: .85rem;
  color: var(--muted);
}

/* ----- Timeline body ----- */
.timeline-body {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.timeline-year-section.is-hidden,
.timeline-event-card.is-hidden,
.is-hidden { display: none !important; }

.timeline-year-label {
  display: flex; gap: .75rem;
  align-items: baseline;
  margin-bottom: .75rem;
  padding-bottom: .35rem;
  border-bottom: 2px solid var(--hre-orange);
}
.timeline-year-number {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--hre-navy);
}
.timeline-year-annotation {
  font-size: .85rem;
  color: var(--muted);
  font-style: italic;
}

.timeline-year-events {
  display: flex;
  flex-direction: column;
  gap: .75rem;
}

/* ----- Event card ----- */
.timeline-event-card {
  position: relative;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .85rem 1rem .85rem 1.5rem;
  padding-left: calc(.5rem + 6px + 1rem); /* strip + gap */
  overflow: hidden;
}
.timeline-event-strip {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 6px;
  background: var(--muted); /* overridden per type */
}
.timeline-event-head {
  display: flex; gap: .6rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: .25rem;
}
.timeline-event-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--muted); /* overridden per type */
  flex-shrink: 0;
}
.timeline-event-badge {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: .15rem .55rem;
  border-radius: 999px;
  color: var(--hre-navy);
  background: rgba(108, 111, 122, .12); /* overridden per type */
  display: inline-flex; gap: .4rem; align-items: center;
}
.timeline-event-date {
  font-size: .9rem;
  color: var(--muted);
}
.timeline-event-actions {
  margin-left: auto;
  display: flex; gap: .35rem;
}
.timeline-event-body {
  margin-top: .25rem;
}
.timeline-event-title {
  margin: 0 0 .35rem;
  color: var(--hre-navy);
  font-size: 1.05rem;
}
.timeline-event-toggle {
  background: none;
  border: none;
  color: var(--hre-orange-dark);
  cursor: pointer;
  padding: 0;
  font: inherit;
  font-size: .85rem;
}
.timeline-event-toggle:hover { text-decoration: underline; }
.timeline-event-details {
  margin: .5rem 0 .25rem;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: .25rem 1rem;
  background: var(--hre-sand-2);
  border-radius: var(--radius-sm);
  padding: .6rem .85rem;
}
.timeline-event-detail-row {
  display: contents;
}
.timeline-event-detail-row dt {
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  margin: 0;
  align-self: center;
}
.timeline-event-detail-row dd {
  margin: 0;
  color: var(--hre-navy);
  align-self: center;
}
.timeline-event-notes {
  margin: .35rem 0 0;
  color: var(--muted);
  font-style: italic;
  font-size: .9rem;
}
.timeline-event-foot {
  margin-top: .5rem;
  font-size: .75rem;
  color: var(--muted);
  border-top: 1px dashed var(--border);
  padding-top: .35rem;
}
.timeline-event-foot strong { color: var(--hre-navy); }

.timeline-event-pct-change {
  font-size: .75rem;
  font-weight: 700;
  padding: .1rem .5rem;
  border-radius: 999px;
}
.timeline-event-pct-change.is-up   { background: rgba(46, 125, 50, .15); color: #2e7d32; }
.timeline-event-pct-change.is-down { background: rgba(198, 40, 40, .15); color: #c62828; }
.timeline-event-pct-change.is-flat { background: rgba(108, 111, 122, .15); color: var(--muted); }

/* ----- Empty state ----- */
.timeline-empty-state {
  background: #fff;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 3rem 2rem;
  text-align: center;
}
.timeline-empty-state h2 { margin-top: .5rem; }
.timeline-empty-state p { color: var(--muted); margin: .25rem 0 1rem; }
.timeline-empty-icon {
  font-size: 3rem;
  line-height: 1;
}

/* ----- Form: type picker (create mode) ----- */
.timeline-picker-fieldset,
.timeline-common-fieldset,
.timeline-detail-fieldset,
.timeline-attach-fieldset {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
.timeline-picker-fieldset legend,
.timeline-common-fieldset legend,
.timeline-detail-fieldset legend,
.timeline-attach-fieldset legend {
  font-weight: 600;
  color: var(--hre-navy);
  padding: 0 .35rem;
}
/* The attach-salary fieldset is the optional step 4 — visually a touch
   lighter than the type-specific fieldset so it reads as supplementary. */
.timeline-attach-fieldset {
  background: var(--hre-sand-2);
  border-style: dashed;
}
.timeline-attach-fieldset legend {
  color: var(--hre-orange-dark);
}
.timeline-attach-toggle {
  margin: 0 0 .5rem 0;
}
.timeline-attach-toggle .checkbox-row {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .55rem .75rem;
  cursor: pointer;
}
.timeline-attach-toggle .checkbox-row:hover {
  border-color: var(--hre-orange);
}
/* Slim inline percentage-toggle inside the salary_revision fieldset so
   it doesn't claim a full form-grid slot of its own. */
.timeline-salary-pct-toggle .checkbox-row {
  border: 0;
  padding: 0;
  cursor: pointer;
}
.timeline-type-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: .6rem;
  margin-top: .5rem;
}
.timeline-type-tile {
  position: relative;
  background: var(--hre-sand-2);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  padding: .85rem .75rem;
  display: flex; gap: .55rem; align-items: center;
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition: background-color .15s, border-color .15s;
}
.timeline-type-tile:hover {
  background: var(--hre-sand);
}
.timeline-type-tile.is-selected {
  border-color: var(--hre-orange);
  background: #fff;
  box-shadow: 0 0 0 3px rgba(238, 150, 63, .15);
}
.timeline-type-tile-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--muted); /* overridden per type */
  flex-shrink: 0;
}
.timeline-type-tile-label {
  color: var(--hre-navy);
  font-weight: 600;
  flex: 1;
}
.timeline-type-tile-check {
  color: var(--hre-orange);
  font-weight: 700;
  opacity: 0;
}
.timeline-type-tile.is-selected .timeline-type-tile-check { opacity: 1; }

.timeline-locked-type {
  margin-bottom: 1rem;
  display: flex; gap: .5rem; align-items: center;
}
.timeline-locked-details {
  background: var(--hre-sand-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
.timeline-locked-note {
  margin: 0 0 .5rem;
  font-size: .85rem;
  color: var(--muted);
  font-style: italic;
}
.timeline-form {
  display: block;
}
.timeline-salary-row {
  display: flex; gap: .5rem; align-items: center;
}
.timeline-salary-row input {
  flex: 1;
}

/* ============================================================
   Per-type colour rules.
   Each rule paints:
     1. the event card's left strip
     2. the event card's dot
     3. the badge background (12% opacity tint)
     4. the picker tile's dot
     5. the picker tile's selected border (subtle)
     6. the filter strip dot
   ============================================================ */
.timeline-event-type-hired                .timeline-event-strip,
.timeline-event-type-hired                .timeline-event-dot,
.timeline-event-type-hired.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-hired { background: #EE963F; }
.timeline-event-type-hired .timeline-event-badge { background: rgba(238, 150, 63, .12); }

.timeline-event-type-salary_revision      .timeline-event-strip,
.timeline-event-type-salary_revision      .timeline-event-dot,
.timeline-event-type-salary_revision.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-salary_revision { background: #2e7d32; }
.timeline-event-type-salary_revision .timeline-event-badge { background: rgba(46, 125, 50, .12); }

.timeline-event-type-promotion            .timeline-event-strip,
.timeline-event-type-promotion            .timeline-event-dot,
.timeline-event-type-promotion.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-promotion { background: #202338; }
.timeline-event-type-promotion .timeline-event-badge { background: rgba(32, 35, 56, .12); }

.timeline-event-type-department_transfer  .timeline-event-strip,
.timeline-event-type-department_transfer  .timeline-event-dot,
.timeline-event-type-department_transfer.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-department_transfer { background: #455a64; }
.timeline-event-type-department_transfer .timeline-event-badge { background: rgba(69, 90, 100, .12); }

.timeline-event-type-designation_change   .timeline-event-strip,
.timeline-event-type-designation_change   .timeline-event-dot,
.timeline-event-type-designation_change.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-designation_change { background: #202338; }
.timeline-event-type-designation_change .timeline-event-badge { background: rgba(32, 35, 56, .12); }

.timeline-event-type-award                .timeline-event-strip,
.timeline-event-type-award                .timeline-event-dot,
.timeline-event-type-award.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-award { background: #b8860b; }
.timeline-event-type-award .timeline-event-badge { background: rgba(184, 134, 11, .14); }

.timeline-event-type-probation_end        .timeline-event-strip,
.timeline-event-type-probation_end        .timeline-event-dot,
.timeline-event-type-probation_end.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-probation_end { background: #00695c; }
.timeline-event-type-probation_end .timeline-event-badge { background: rgba(0, 105, 92, .12); }

.timeline-event-type-leave_of_absence     .timeline-event-strip,
.timeline-event-type-leave_of_absence     .timeline-event-dot,
.timeline-event-type-leave_of_absence.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-leave_of_absence { background: #f57c00; }
.timeline-event-type-leave_of_absence .timeline-event-badge { background: rgba(245, 124, 0, .12); }

.timeline-event-type-disciplinary         .timeline-event-strip,
.timeline-event-type-disciplinary         .timeline-event-dot,
.timeline-event-type-disciplinary.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-disciplinary { background: #b71c1c; }
.timeline-event-type-disciplinary .timeline-event-badge { background: rgba(183, 28, 28, .12); }

.timeline-event-type-contract_change      .timeline-event-strip,
.timeline-event-type-contract_change      .timeline-event-dot,
.timeline-event-type-contract_change.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-contract_change { background: #6a1b9a; }
.timeline-event-type-contract_change .timeline-event-badge { background: rgba(106, 27, 154, .12); }

.timeline-event-type-exit                 .timeline-event-strip,
.timeline-event-type-exit                 .timeline-event-dot,
.timeline-event-type-exit.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-exit { background: #c62828; }
.timeline-event-type-exit .timeline-event-badge { background: rgba(198, 40, 40, .12); }

.timeline-event-type-custom               .timeline-event-strip,
.timeline-event-type-custom               .timeline-event-dot,
.timeline-event-type-custom.timeline-type-tile .timeline-type-tile-dot,
.timeline-filter-dot.timeline-event-type-custom { background: #455a64; }
.timeline-event-type-custom .timeline-event-badge { background: rgba(69, 90, 100, .12); }

/* Mobile breakpoint. Stack the header grid, drop the filter counter
   below the triggers, and remove the extra horizontal padding on
   event cards so the text isn't squeezed. */
@media (max-width: 640px) {
  .timeline-header-body {
    grid-template-columns: 1fr;
  }
  .timeline-header-actions {
    justify-content: flex-start;
  }
  .timeline-stats {
    width: 100%;
  }
  .timeline-stat-pill {
    flex: 1 1 calc(50% - .3rem);
    min-width: 0;
  }
  .timeline-filters {
    gap: .5rem;
  }
  .timeline-filter-counter {
    margin-left: 0;
    width: 100%;
    order: 99;
  }
  .timeline-event-card {
    padding: .75rem .75rem .75rem 1.25rem;
  }
  .timeline-event-actions {
    width: 100%;
    margin-left: 0;
    margin-top: .25rem;
  }
  .timeline-type-picker {
    grid-template-columns: 1fr 1fr;
  }
}

/* v0.24.1 — [hidden] vs display:flex on .form-actions.
   Same family of bug as v0.23.1's .sw-row[hidden] fix: .form-actions
   sets display:flex in author CSS (line ~253), which wins over the
   user-agent's display:none on [hidden]. The result was that the
   Timeline "Add Event" form rendered with the action buttons visible
   from page load, even before the user picked an event type — so
   users could submit a form with empty event_type and the POST would
   fail validation with no obvious explanation. Force display:none
   with !important when [hidden] is set. */
.form-actions[hidden] { display: none !important; }

/* =====================================================================
 * Employment Timeline diagram view
 *
 * Used by both /me/timeline/diagram (employee self) and
 * /employees/{id}/timeline/diagram (admin/HR), introduced in v0.25.0
 * and substantially redesigned in v0.26.0 / v0.27.0.
 *
 * v0.27.0 layout:
 *   - Single vertical spine running top→bottom down the centre of the
 *     diagram column. (The pre-v0.27 salary rail SVG is removed; the
 *     spine is the only track.)
 *   - Each event renders as a row with:
 *       [date] — stem — •dot — stem — [heading + card]
 *     The stems align with the dot/heading vertical centre and stop
 *     short of the date / body text with a small visual gap, so neither
 *     side of the diagram touches its labels.
 *   - Highlight rows (Joined, Award, Exit) get a larger dot and a
 *     warmer card background to draw the eye to career milestones.
 *
 * Class names: tld-* (TimeLine Diagram) for diagram internals. The
 * per-type colour classes (`.timeline-event-type-*`) ARE reused from
 * the card view so the per-event dot colour matches throughout.
 *
 * Print: the @media print block at the bottom hides the sidebar, top
 * header, legend, and action buttons so the diagram fills the printed
 * page.
 * =================================================================== */

/* ---- Page shell ---- */
.timeline-diagram-page {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}
.timeline-header-diagram {
  position: relative;
}
.timeline-diagram-actions {
  display: flex;
  gap: .5rem;
  justify-content: flex-end;
  margin-top: .75rem;
}
/* v0.28.0 — sort toggle on the diagram. Inherits .btn-ghost.btn-sm
   styling; just a small visual marker before the label so the icon and
   the label read as a single control. */
.timeline-diagram-actions [data-tl-sort] .tl-sort-icon {
  display: inline-block;
  margin-right: .3rem;
  font-size: .95em;
  font-weight: 700;
  color: var(--hre-orange-dark);
}
.timeline-diagram-empty {
  background: var(--hre-sand-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2rem;
  text-align: center;
  color: var(--muted);
}

/* ---- Header back/print button matches existing btn-sm sizing ---- */
.timeline-header-actions {
  margin-top: .5rem;
}
.timeline-header-actions .btn-sm {
  font-size: .85rem;
}

/* ---- Legend ---- */
.timeline-diagram-legend {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
  padding: .75rem 1rem;
  background: var(--hre-sand-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: .9rem;
}
.timeline-diagram-legend-item {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  color: var(--hre-navy);
}
.timeline-diagram-legend-line {
  display: inline-block;
  width: 28px;
  height: 0;
  border-top: 2px dashed var(--hre-orange);
}

/* ---- Diagram figure (canvas wrapper) ---- */
.timeline-diagram-figure {
  margin: 0;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1rem;
  overflow-x: auto; /* allow horizontal scroll if salary rail + rows overflow */
}

/* ---- Canvas wrapper. As of v0.27.0 the salary rail is gone; only the
   single main column lives here. The grid is therefore single-column. */
.tld-canvas {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 880px;
  margin: 0 auto;
}

/* ---- Main timeline column ---- */
.tld-main {
  position: relative;
  padding-top: 12px;
}
.tld-rows {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* ---- Per-event row.
 * 3-column grid: [date | spine | body]. Date right-aligns to a small gap
 * before the spine; spine is fixed-width with the dot at column centre;
 * body extends right with a small gap from the dot.
 *
 * Row min-height keeps adjacent rows visually separated even when the
 * card holds little content. v0.26 used 150px paired with a PHP geometry
 * constant for the salary rail; v0.27 drops the rail so the coupling is
 * gone, but we keep the same row height for visual continuity with the
 * prior release.
 */
.tld-row {
  display: grid;
  grid-template-columns: 170px 86px minmax(0, 1fr);
  align-items: stretch;
  min-height: 150px;
  position: relative;
}

/* The vertical spine: a pseudo-element on the spine column that runs
   the full height of each row, joining row to row. */
.tld-row-spine {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 22px; /* dot vertical centre — keep in sync with stem `top` */
}
.tld-row-spine::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--hre-navy);
  transform: translateX(-50%);
}
/* First row: spine starts at the dot, not above it. */
.tld-row:first-child .tld-row-spine::before {
  top: 30px;
}
/* Last row: spine ends at the dot (no trailing line into empty space). */
.tld-row:last-child .tld-row-spine::before {
  bottom: auto;
  height: 30px;
}

/* Dot on the spine. The colour comes from the per-type rules below.
   Sits at the row's heading vertical-centre line. */
.tld-row-dot {
  position: relative;
  z-index: 2;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--hre-navy); /* default; overridden per type */
  border: 3px solid #fff;
  box-shadow: 0 0 0 1px var(--hre-navy);
  margin-top: 0;
}
/* Highlight rows (Joined, Award, Exit) get a slightly larger dot to draw
   the eye to career milestones. */
.tld-row.is-highlight .tld-row-dot {
  width: 20px;
  height: 20px;
  margin-top: -2px;
  box-shadow: 0 0 0 1px var(--hre-navy), 0 0 0 5px rgba(238, 150, 63, .18);
}

/* Horizontal stem reaching RIGHT from the spine. v0.27.0: vertically
   aligned with the dot/heading centre and stopped short of the body
   content with an 8px gap so it doesn't touch the heading or card. */
.tld-row-stem {
  position: absolute;
  top: 30px; /* dot vertical centre */
  left: 50%;
  width: calc(50% + 5px); /* extends a hair into the body column but
                              stops 8px before the body's text edge */
  height: 2px;
  background: var(--hre-navy);
  opacity: .55;
}

/* Symmetric stem reaching LEFT from the spine to the date label. Same
   geometry as the right stem, mirrored. Stops 8px before the date text. */
.tld-row-stem-left {
  position: absolute;
  top: 30px; /* dot vertical centre */
  right: 50%;
  width: calc(50% + 5px);
  height: 2px;
  background: var(--hre-navy);
  opacity: .55;
}

/* Date column (left of spine). v0.27.0: vertically aligned with the dot
   centre (line-height 24px puts text centre at top:18px). Right-aligned
   so the date sits flush with the gap before the left stem. */
.tld-row-date {
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  padding-top: 18px;
  padding-right: 1rem; /* gap between date text and the left stem */
}
.tld-row-date-text {
  color: var(--hre-navy);
  font-weight: 600;
  font-size: .92rem;
  text-align: right;
  line-height: 1.5;
}
.tld-row.is-highlight .tld-row-date-text {
  color: var(--hre-orange-dark);
}

/* v0.28.0 — same-date merge: when two events share a date, the SECOND
   (and later) display the spine + dot + card normally but suppress the
   redundant date label. The cell stays in place (grid alignment is
   preserved); only the visible text is hidden. The class is toggled by
   the diagram's JS recompute path after sort flips so the marker stays
   correct in both directions. */
.tld-row.tld-row-date-hidden .tld-row-date-text {
  visibility: hidden;
}

/* Body column (right of spine). v0.27.0: padding-left provides the gap
   between the stem end and the heading text. Heading sits at the same
   vertical position as the dot (line-height 24px ⇒ centre at top:18px;
   heading row's margin-bottom is the gap to the card below). */
.tld-row-body {
  padding: 18px 0 12px 1rem;
  min-width: 0;
}
.tld-row-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .35rem .65rem;
  margin-bottom: .5rem;
  line-height: 1.5;
}
.tld-row-type {
  color: var(--hre-navy);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: .01em;
}
.tld-row.is-highlight .tld-row-type {
  color: var(--hre-orange-dark);
}
.tld-row-title {
  color: var(--muted);
  font-weight: 500;
  font-size: .92rem;
}
.tld-row-title::before {
  content: "·";
  margin-right: .35rem;
  color: var(--border);
}

/* The "note card" — the rounded rectangle box from the sketch.
   Holds structured details + free-text notes. */
.tld-row-card {
  background: var(--hre-sand-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: .65rem .9rem;
  margin-top: .25rem;
  position: relative;
}
.tld-row.is-highlight .tld-row-card {
  border-color: rgba(238, 150, 63, .45);
  background: #fff8ef;
}

.tld-row-details {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: .25rem .85rem;
}
.tld-row-detail {
  display: flex;
  gap: .35rem;
  align-items: baseline;
  font-size: .88rem;
  line-height: 1.35;
  min-width: 0;
}
.tld-row-detail dt {
  color: var(--muted);
  font-weight: 500;
  flex-shrink: 0;
}
.tld-row-detail dt::after { content: ":"; }
.tld-row-detail dd {
  margin: 0;
  color: var(--hre-navy);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.tld-row-notes {
  margin: .5rem 0 0 0;
  padding-top: .5rem;
  border-top: 1px dashed var(--border);
  color: var(--hre-navy);
  font-size: .9rem;
  line-height: 1.45;
  white-space: pre-wrap;
}
/* If there are no structured details, the notes shouldn't have a top
   divider — they're the only child. */
.tld-row-card > .tld-row-notes:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* Per-event-type dot colours. Mirrors the existing filter-dot palette. */
.tld-row.timeline-event-type-hired                .tld-row-dot { background: #EE963F; }
.tld-row.timeline-event-type-salary_revision      .tld-row-dot { background: #2e7d32; }
.tld-row.timeline-event-type-promotion            .tld-row-dot { background: #202338; }
.tld-row.timeline-event-type-department_transfer  .tld-row-dot { background: #455a64; }
.tld-row.timeline-event-type-designation_change   .tld-row-dot { background: #202338; }
.tld-row.timeline-event-type-award                .tld-row-dot { background: #b8860b; }
.tld-row.timeline-event-type-probation_end        .tld-row-dot { background: #00695c; }
.tld-row.timeline-event-type-leave_of_absence     .tld-row-dot { background: #f57c00; }
.tld-row.timeline-event-type-disciplinary         .tld-row-dot { background: #b71c1c; }
.tld-row.timeline-event-type-contract_change      .tld-row-dot { background: #6a1b9a; }
.tld-row.timeline-event-type-exit                 .tld-row-dot { background: #c62828; }
.tld-row.timeline-event-type-custom               .tld-row-dot { background: #455a64; }

/* ===== v0.29.0 — Same-date event grouping =====
 *
 * When two or more events share an event_date, the view renders them in
 * one date-group row. The main spine no longer carries a dot at the
 * date level; instead, it carries a small junction where a short
 * horizontal branch tees off into the body column. The body then holds
 * a vertical sub-spine with one dot per event, each with its own short
 * stem to the event's heading + card.
 *
 * The single-event row (no `.is-group` class) is structurally
 * unchanged; this section only adds rules that scope to
 * `.tld-row.is-group`.
 */

/* The group row's outer min-height shrinks to a minimum and grows with
   content — unlike single-event rows which use a fixed 150px to keep
   visual rhythm. Multi-event rows are naturally taller, so the rhythm
   comes from per-event spacing instead. */
.tld-row.is-group {
  min-height: auto;
}

/* Date label inside a group row aligns to the FIRST event's heading,
   not to the row's geometric centre. Same line-height/top math as a
   single-event row, so the date sits at the heading baseline. */
.tld-row.is-group .tld-row-date {
  padding-top: 18px;
  align-self: flex-start;
}

/* Date label inherits the highlight orange if any event in the group
   is a milestone (hired/award/exit). Matches the single-event
   .is-highlight rule above. */
.tld-row.is-group-highlight .tld-row-date-text {
  color: var(--hre-orange-dark);
}

/* The spine cell still draws the continuous main vertical line (the
   `.tld-row-spine::before` pseudo-element already does that for every
   .tld-row). The cell's contents change: instead of a dot at top:30px,
   we draw a horizontal branch + a small junction node. */
.tld-row.is-group .tld-row-group-branch {
  position: absolute;
  top: 30px; /* aligns with first event's heading centre + first inner dot */
  left: 50%;
  /* v0.29.2 — branch ends at the first inner dot's CENTRE (so the
     dot, which has z-index:2, sits on top of the branch terminus —
     same z-pattern as a single-event spine-dot covering its stem).
     Geometry: branch end x = li-left + (-15) = body-col-left +
     body-padding-left - 15. From spine-centre (= spine-col-w/2 to
     the left of body-col-left), that distance is:
       (spine-col-w / 2) + body-padding-left - 15
     The desktop body-group padding-left is 1rem, so:
       calc(50% + 1rem - 15px) = 50% + 1px on the spine column.
     Mobile uses .6rem padding-left → override below. */
  width: calc(50% + 1rem - 15px);
  height: 2px;
  background: var(--hre-navy);
  opacity: .55;
}
/* v0.29.2 — Group anchor (junction) dot. Sized larger than the inner
   event dots so it visually reads as the "parent" of the group, and
   coloured HRE Orange so it doesn't blend into the navy spine line. */
.tld-row.is-group .tld-row-group-junction {
  position: absolute;
  z-index: 2;
  top: 20px; /* junction centre at y=30, box is 20px tall */
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--hre-orange);
  border: 3px solid #fff;
  box-shadow: 0 0 0 1px var(--hre-navy);
}

/* Body column in a group row hosts the nested events list. v0.29.2:
   padding-left is now 1rem (matching single-event .tld-row-body) so
   the inner-event headings start at the SAME page-x as single-event
   headings. The inner-event dots are absolutely positioned to the
   LEFT of this padding edge (see .tld-row-event-dot below) — they
   sit in the gap between the main spine column and the heading text.
   padding-top is 0 so the first inner event's dot/heading aligns with
   the same row-y as the date label and the horizontal branch (row-y=30). */
.tld-row-body.tld-row-body-group {
  position: relative;
  padding: 0 0 12px 1rem;
}

/* The sub-spine — drawn as ::after pseudo segments on each inner event
   EXCEPT the last. Each segment runs from this event's dot centre down
   to the next event's dot centre, covering the within-li tail + the
   inter-li gap + the next-li head in one continuous line. This makes
   the spine start exactly at the FIRST dot and end exactly at the LAST
   dot, regardless of card height (which an absolute span could not
   express in pure CSS).

   v0.29.2: dots are now in the negative-x region (see .tld-row-event
   below), so the sub-spine sits at left:-15px from li-left — the new
   dot-centre x in li-local coordinates. */
.tld-row-event:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 30px;                          /* this event's dot centre */
  /* Extend past this li's bottom by (gap + 30px) to land exactly at
     the next li's dot centre. The gap matches .tld-row-events `gap`. */
  bottom: calc(-.75rem - 30px);
  left: -15px;                        /* dot centre in li-local coords */
  width: 2px;
  margin-left: -1px;
  background: var(--hre-navy);
  opacity: .55;
  pointer-events: none;
  z-index: 1;
}

/* Inner events list. Reset list styles; spacing between events comes
   from the gap on the <ol>. */
.tld-row-events {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}

/* Each inner event — a single-column mini "row". v0.29.2: the inner
   event's body content (heading + card) sits at li-x=0 so it aligns
   horizontally with single-event headings (both at page-x = body-col-
   left + body-padding-left). The DOT is absolutely positioned in the
   negative-x region (sitting in the gap between the main spine column
   and the body content), so the horizontal branch from the main spine
   reaches the dot the same way a single-event stem reaches its dot.
   This was the v0.29.1 → v0.29.2 fix for "inner headings line up with
   single-event headings". */
.tld-row-event {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  position: relative;
  min-height: 0;
}
/* Inner-event dot. Absolute, sized 14px, occupying li-x = -22 to -8
   (so dot centre at li-x = -15, right edge 8px before heading). The
   group branch above ends inside this dot (the same z-index pattern
   single-event rows use for spine-dot + stem). */
.tld-row-event-dot {
  position: absolute;
  z-index: 2;
  top: 23px; /* dot top at y=23, centre at 23 + 7 = 30 */
  left: -22px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--hre-navy); /* overridden per type below */
  border: 3px solid #fff;
  box-shadow: 0 0 0 1px var(--hre-navy);
}
.tld-row-event.is-highlight .tld-row-event-dot {
  top: 21px; /* dot centre at 21 + 9 = 30 */
  left: -24px; /* re-centre the bigger dot on the same dot-centre x */
  width: 18px;
  height: 18px;
  box-shadow: 0 0 0 1px var(--hre-navy), 0 0 0 5px rgba(238, 150, 63, .18);
}
.tld-row-event-body {
  padding: 18px 0 0 0; /* heading-centre at y=30 (18 + line-height-mid 12) */
  min-width: 0;
}

/* Per-event-type colours for inner events. Mirrors the outer
   .tld-row.timeline-event-type-X .tld-row-dot palette so a salary-
   revision event has the same green whether it's the sole event of its
   day or one of many. */
.tld-row-event.timeline-event-type-hired                .tld-row-event-dot { background: #EE963F; }
.tld-row-event.timeline-event-type-salary_revision      .tld-row-event-dot { background: #2e7d32; }
.tld-row-event.timeline-event-type-promotion            .tld-row-event-dot { background: #202338; }
.tld-row-event.timeline-event-type-department_transfer  .tld-row-event-dot { background: #455a64; }
.tld-row-event.timeline-event-type-designation_change   .tld-row-event-dot { background: #202338; }
.tld-row-event.timeline-event-type-award                .tld-row-event-dot { background: #b8860b; }
.tld-row-event.timeline-event-type-probation_end        .tld-row-event-dot { background: #00695c; }
.tld-row-event.timeline-event-type-leave_of_absence     .tld-row-event-dot { background: #f57c00; }
.tld-row-event.timeline-event-type-disciplinary         .tld-row-event-dot { background: #b71c1c; }
.tld-row-event.timeline-event-type-contract_change      .tld-row-event-dot { background: #6a1b9a; }
.tld-row-event.timeline-event-type-exit                 .tld-row-event-dot { background: #c62828; }
.tld-row-event.timeline-event-type-custom               .tld-row-event-dot { background: #455a64; }

/* Highlight styling for inner events (hired/award/exit) — mirrors the
   single-row .is-highlight treatment so a milestone event still reads
   as a milestone when it's part of a group. */
.tld-row-event.is-highlight .tld-row-type {
  color: var(--hre-orange-dark);
}
.tld-row-event.is-highlight .tld-row-card {
  border-color: rgba(238, 150, 63, .45);
  background: #fff8ef;
}

/* ---- Mobile breakpoint ---- */
@media (max-width: 720px) {
  .timeline-diagram-actions {
    justify-content: flex-start;
  }
  /* Tighter row geometry on mobile. */
  .tld-row {
    grid-template-columns: 100px 56px minmax(0, 1fr);
    min-height: 130px;
  }
  .tld-row-date-text {
    font-size: .82rem;
  }
  .tld-row-date {
    padding-right: .6rem;
  }
  .tld-row-body {
    padding-left: .6rem;
  }
  .tld-row-type {
    font-size: .94rem;
  }
  /* v0.29.0 — same-date group rows. v0.29.2: the body padding-left
     still mirrors the single-event mobile padding (.6rem) so the
     inner-event headings line up with single-event headings on mobile
     too. The branch-width formula tracks body-padding-left (.6rem on
     mobile vs 1rem on desktop) so the branch still ends at the first
     inner dot's centre. */
  .tld-row-body.tld-row-body-group {
    padding-left: .6rem;
  }
  .tld-row.is-group .tld-row-group-branch {
    width: calc(50% + .6rem - 15px);
  }
}

/* ---- Print stylesheet ----
 * The browser print() output should be the diagram or the card list,
 * not the chrome. Hide the sidebar, top app header, footer, action
 * buttons, and the legend / filter strip. The main content gets full
 * page width.
 *
 * Both the diagram view (.timeline-diagram-page) and the index card
 * view (.timeline-page) use this stylesheet — the diagram page binds
 * the print button on the header itself, while the index page binds
 * it via [data-tl-index-print] in the actions row.
 */
@media print {
  .sidenav,
  .topbar,
  .footer,
  .alert,
  .migration-banner,
  .timeline-diagram-actions,
  .timeline-diagram-legend,
  .timeline-filters,
  .timeline-header-actions,
  .timeline-breadcrumb,
  .timeline-event-actions {
    display: none !important;
  }
  .main-area,
  .container {
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
  }
  .timeline-diagram-figure {
    border: none !important;
    padding: 0 !important;
    overflow: visible !important;
  }
  .timeline-header,
  .timeline-header-diagram {
    border: none !important;
    box-shadow: none !important;
    background: #fff !important;
    color: var(--hre-navy) !important;
    margin-bottom: .5rem;
  }
  .timeline-header h1,
  .timeline-header .timeline-header-meta,
  .timeline-header .timeline-stat-label,
  .timeline-header .timeline-stat-value,
  .timeline-header-diagram h1,
  .timeline-header-diagram .timeline-header-meta,
  .timeline-header-diagram .timeline-stat-label,
  .timeline-header-diagram .timeline-stat-value {
    color: var(--hre-navy) !important;
  }
  .tld-canvas {
    max-width: none !important;
  }
  /* Avoid splitting an event row / card across pages. For a multi-event
     group (.tld-row.is-group), allow the row itself to break BETWEEN
     inner events; just keep each inner event's heading + card together
     via .tld-row-event. */
  .tld-row:not(.is-group),
  .tld-row-event,
  .timeline-event-card {
    page-break-inside: avoid;
    break-inside: avoid;
  }
}

/* ============================================================
   ID Cards module (v0.33.0)
   ============================================================ */

/* Two-column layout: picker/history left, form/preview right.
   Falls back to stacked on narrow viewports. */
.idc-layout {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 1.5rem;
  align-items: start;
}
@media (max-width: 1000px) {
  .idc-layout { grid-template-columns: 1fr; }
}

.idc-left {
  position: sticky;
  top: calc(var(--topbar-h) + 1rem);
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.idc-picker {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}

/* The v0.34.0 generation-log panel was removed in v0.35.0 — the audit
   log is now the canonical record of "who generated what when". The
   .idc-history* class block previously here is gone. */

.idc-right {
  min-width: 0;
}

.idc-form-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem;
}
@media (max-width: 1200px) {
  .idc-form-grid { grid-template-columns: 1fr; }
}

.idc-form-col h3 {
  margin: 0 0 .75rem 0;
  font-size: 1rem;
  color: var(--hre-navy);
}

/* ------ Live preview (v0.34.0) ------
   The HTML/CSS approximation was replaced by server-rendered PNGs
   (front + back) produced on demand via the Refresh preview button.
   The preview stack just stacks the two card-sized image slots. */

.idc-preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .25rem;
}
.idc-preview-head h3 {
  margin: 0;
  font-size: 1rem;
  color: var(--hre-navy);
}

.idc-preview-stack {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: center;
}

.idc-card {
  position: relative;
  width: 100%;
  max-width: 325px;       /* template is 650px wide; render at 50% */
  aspect-ratio: 650 / 1028;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.10);
  overflow: hidden;
  background: #fff;
}

.idc-preview-card {
  background: var(--hre-sand);
}

.idc-preview-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: none;          /* shown by JS once the PNG loads */
  background: #fff;
}

.idc-preview-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  text-align: center;
  font-size: .8rem;
  color: var(--muted);
  background: #fff;
}

/* Reuse: small badge for DRAFT marker in history list */
.badge {
  display: inline-block;
  padding: .1rem .4rem;
  font-size: .7rem;
  font-weight: 600;
  border-radius: 999px;
  background: var(--hre-sand-2);
  color: var(--hre-navy);
}
.badge-warn {
  background: rgba(184, 132, 8, 0.15);
  color: var(--warning);
}
/* v0.44.0: locked account state — red-ish, distinct from inactive (grey) */
.badge-locked {
  background: #fbe9e8;
  color: var(--danger);
}

/* =====================================================================
   My ID (v0.40.0) — /me read-only display of the operator-generated
   front ID card. Lives in the My Profile tab strip after My Benefits,
   gated by id_cards.view_self. Reuses the .idc-card aspect-ratio sized
   frame from the admin ID Cards module but uses its own (.myid-*) image
   class so it doesn't interact with that module's JS-toggled
   .idc-preview-img display:none rule.
   ===================================================================== */
.myid-card-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
}
.myid-card-frame {
  /* .idc-card already sets max-width 325px and the 650/1028 ratio. */
  background: #fff;
}
.myid-card-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #fff;
}
.myid-card-meta {
  margin: 0;
  font-size: 0.85rem;
}

/* =====================================================================
   Portable Backup card (v0.51.0) — F-ops-6
   Sits above the in-place backups list on /update. Calls out the
   "different artefact than the rollback backups below" framing.
   Reuses the global .btn .btn-primary for the CTA so brand colours
   stay consistent.
   ===================================================================== */
.portable-backup-card {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  padding: 1rem 1.25rem;
  background: var(--hre-sand-2);
  border: 1px solid var(--border);
  border-left: 4px solid var(--hre-orange);
  border-radius: var(--radius);
  margin: .5rem 0 1.5rem;
}
.portable-backup-card-body {
  flex: 1 1 auto;
  min-width: 0;
}
.portable-backup-card-body p {
  margin: 0;
}
.portable-backup-card-actions {
  flex: 0 0 auto;
}
@media (max-width: 640px) {
  .portable-backup-card {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* Scope tables inside the portable backup form. Section headings use
   the standard HRE Navy h3 colour from the base sheet; only the table
   itself needs tightening for the two-column included/excluded layout. */
.portable-backup-scope {
  margin-top: 2rem;
}
.portable-backup-scope table.table {
  table-layout: fixed;
}
.portable-backup-scope table.table th,
.portable-backup-scope table.table td {
  vertical-align: top;
  width: 50%;
}

/* ============================================================
   PTO & Workforce — v0.68.0
   Dashboard table, status pills, edit-page section-with-side-nav,
   categories Layer 3 admin, settings.
   ============================================================ */

/* Page-head right-side cluster: year picker + action buttons. */
.pto-head-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}
.pto-year-form {
  display: flex;
  gap: 0.35rem;
  align-items: center;
}
.pto-year-form select {
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #fff;
  font: inherit;
  cursor: pointer;
}

/* Dashboard table — high-contrast, compact, horizontally scrollable. */
.pto-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: #fff;
}
.pto-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.pto-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--hre-navy);
  color: #fff;
  font-weight: 600;
  text-align: left;
  padding: 0.6rem 0.5rem;
  white-space: nowrap;
  border-bottom: 2px solid var(--hre-orange);
}
.pto-table thead th a {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.pto-table thead th a:hover {
  color: var(--hre-orange);
}
.pto-table tbody td {
  padding: 0.55rem 0.5rem;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.pto-table tbody tr:nth-child(even) {
  background: var(--hre-sand-2);
}
.pto-table tbody tr:hover {
  background: rgba(238, 150, 63, 0.08);
}
.pto-sn {
  text-align: right;
  width: 3rem;
  color: var(--muted);
}
.pto-name a {
  color: var(--hre-navy);
  font-weight: 600;
  text-decoration: none;
}
.pto-name a:hover {
  color: var(--hre-orange);
  text-decoration: underline;
}
.pto-emp-code {
  font-size: 0.75rem;
  margin-top: 0.1rem;
}
.pto-cell {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.pto-cell-total {
  font-weight: 600;
  background: rgba(32, 35, 56, 0.04);
}
.pto-cell-remaining {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.pto-actions {
  text-align: right;
}
.pto-sort-icon {
  font-size: 0.65rem;
  opacity: 0.7;
}
.pto-sort-neutral {
  opacity: 0.4;
}
.pto-sort-active {
  color: var(--hre-orange);
  opacity: 1;
}

/* Status pills — high-contrast colour coding for Remaining. */
.pto-pill {
  display: inline-block;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  border: 1px solid transparent;
}
.pto-pill-success {
  background: #e6f4ea;
  color: #1e7a3a;
  border-color: #b8dec3;
}
.pto-pill-warning {
  background: #fff4e0;
  color: #8a5a00;
  border-color: #f0d49a;
}
.pto-pill-danger {
  background: #fdecec;
  color: #a02121;
  border-color: #f1b6b6;
}
.pto-pill-neutral {
  background: #eef0f4;
  color: var(--hre-navy);
  border-color: var(--border);
}

/* Edit page — section-with-side-nav layout. */
.pto-edit-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 1.5rem;
  align-items: start;
}
.pto-side-nav {
  position: sticky;
  top: 1rem;
  background: var(--hre-navy);
  border-radius: 6px;
  padding: 0.5rem 0;
  display: flex;
  flex-direction: column;
}
.pto-side-link {
  padding: 0.65rem 1rem;
  color: rgba(255,255,255,0.85);
  text-decoration: none;
  border-left: 3px solid transparent;
  font-weight: 500;
}
.pto-side-link:hover {
  background: rgba(255,255,255,0.05);
  color: #fff;
}
.pto-side-link.is-active {
  background: rgba(238, 150, 63, 0.12);
  color: var(--hre-orange);
  border-left-color: var(--hre-orange);
  font-weight: 600;
}
.pto-side-stats {
  margin-top: 0.5rem;
  border-top: 1px solid rgba(255,255,255,0.1);
  padding: 0.85rem 1rem 0.5rem;
}
.pto-side-stat-head {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(255,255,255,0.5);
  margin-bottom: 0.5rem;
}
.pto-side-stat-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.3rem 0;
  color: rgba(255,255,255,0.85);
  font-size: 0.85rem;
}
.pto-side-stat-row .muted {
  color: rgba(255,255,255,0.5);
}
.pto-stat-val {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #fff;
}
.pto-side-stat-note {
  margin-top: 0.4rem;
  padding-top: 0.4rem;
  border-top: 1px solid rgba(255,255,255,0.12);
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--hre-orange);
}
.pto-edit-sections {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.pto-section {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1.25rem 1.5rem;
}
.pto-section-title {
  margin: 0 0 0.25rem;
  color: var(--hre-navy);
  font-size: 1.15rem;
  border-bottom: 2px solid var(--hre-orange);
  padding-bottom: 0.5rem;
  display: inline-block;
}
.pto-form {
  margin-top: 1rem;
}
.pto-month-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.75rem;
}
.pto-elig-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
}
.pto-readonly-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
}
.pto-month-field,
.pto-elig-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  position: relative;
}
.pto-month-field label,
.pto-elig-field label {
  font-size: 0.8rem;
  color: var(--hre-navy);
  font-weight: 600;
}
.pto-num-input {
  padding: 0.45rem 1.6rem 0.45rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font: inherit;
  font-variant-numeric: tabular-nums;
  background: #fff;
  width: 100%;
}
.pto-num-input:focus {
  outline: 2px solid var(--hre-orange);
  outline-offset: -1px;
  border-color: var(--hre-orange);
}
.pto-input-suffix {
  position: absolute;
  right: 0.55rem;
  bottom: 0.5rem;
  color: var(--muted);
  font-size: 0.75rem;
  pointer-events: none;
}
.pto-month-field.is-readonly {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.45rem 0.55rem;
  background: rgba(32,35,56,0.02);
}
.pto-month-label {
  font-size: 0.75rem;
  color: var(--muted);
}
.pto-month-val {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--hre-navy);
}
.pto-form-actions {
  margin-top: 1.25rem;
  display: flex;
  gap: 0.5rem;
}
.pto-perm-note {
  margin-top: 1rem;
  font-size: 0.85rem;
}
.pto-perm-note code {
  background: rgba(32,35,56,0.06);
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  font-size: 0.8rem;
}

/* Mid-year-exit proration note (PTO detail page). */
.pto-prorate-note {
  margin-top: 1rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--hre-orange);
  border-left-width: 4px;
  border-radius: 4px;
  background: rgba(var(--hre-orange-rgb), 0.08);
  font-size: 0.85rem;
  color: var(--hre-navy);
  line-height: 1.5;
}
.pto-prorate-note strong {
  color: var(--hre-navy);
}
.pto-prorate-math {
  display: block;
  margin-top: 0.4rem;
  font-variant-numeric: tabular-nums;
}
.pto-prorate-math small {
  margin-left: 0.35rem;
}

/* Layer 3 — categories admin. */
.pto-cat-section {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.5rem;
}
.pto-cat-form-row {
  display: grid;
  grid-template-columns: 2fr 1fr 1.5fr auto;
  gap: 0.75rem;
  align-items: end;
  margin-top: 0.75rem;
}
.pto-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.pto-field label {
  font-size: 0.8rem;
  color: var(--hre-navy);
  font-weight: 600;
}
.pto-field input[type="text"],
.pto-field input[type="number"],
.pto-field select {
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font: inherit;
  background: #fff;
}
.pto-field-action {
  align-self: end;
}
.pto-cat-table tr.is-inactive {
  opacity: 0.55;
}
.pto-cat-inline-form {
  display: inline;
}
.pto-cat-inline-form input[type="text"],
.pto-cat-inline-form select {
  padding: 0.35rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font: inherit;
  background: #fff;
  max-width: 100%;
}
.pto-cat-actions {
  white-space: nowrap;
  display: flex;
  gap: 0.4rem;
  justify-content: flex-end;
}
.pto-cat-active-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  cursor: pointer;
}
.pto-cat-del-btn {
  color: #a02121;
}
.pto-cat-tip {
  margin-top: 1rem;
  font-size: 0.85rem;
}

.pto-settings-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 480px;
}
.pto-settings-form .pto-field {
  max-width: 280px;
}
.muted.small {
  font-size: 0.78rem;
}

/* Hide sections via the [hidden] attribute used by the JS side-nav switch.
   Codified as required by 10-conventions §"The [hidden] + display: footgun". */
.pto-section[hidden] {
  display: none !important;
}

/* Mobile: collapse the side-nav over the sections, shrink month grid. */
@media (max-width: 900px) {
  .pto-edit-layout {
    grid-template-columns: 1fr;
  }
  .pto-side-nav {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    padding: 0.25rem;
  }
  .pto-side-stats {
    width: 100%;
    border-top: none;
    border-left: 1px solid rgba(255,255,255,0.1);
    margin-top: 0;
    padding: 0.5rem 1rem;
  }
}
@media (max-width: 720px) {
  .pto-month-grid,
  .pto-readonly-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .pto-elig-grid {
    grid-template-columns: 1fr;
  }
  .pto-cat-form-row {
    grid-template-columns: 1fr;
  }
}

/* My PTO tab (v0.68.0) — read-only summary on /me. */
.mypto-summary {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin: 0.75rem 0 1.25rem;
  padding: 0.85rem 1rem;
  background: var(--hre-sand-2);
  border-radius: 6px;
  border: 1px solid var(--border);
}
.mypto-summary-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.mypto-summary-val {
  font-weight: 600;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  color: var(--hre-navy);
}
.mypto-section-h3 {
  margin: 1.25rem 0 0.5rem;
  color: var(--hre-navy);
  font-size: 1rem;
  border-bottom: 2px solid var(--hre-orange);
  padding-bottom: 0.35rem;
  display: inline-block;
}
.mypto-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.mypto-month-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.mypto-month-cell {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.5rem 0.65rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 4px;
}
.mypto-month-name {
  font-size: 0.75rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.mypto-month-val {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--hre-navy);
}
@media (max-width: 720px) {
  .mypto-month-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* v0.75.0 — Employee Field Requirements grouped section headers.
   Sub-header rows inside the single settings table, one per employee-
   view category (Personal / Contact / Employment / Health & Emergency).
   Navy band + white caps to read clearly as a divider, not a data row. */
.table .efr-group th {
  background: var(--hre-navy);
  color: #fff;
  font-size: .82rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding-top: .55rem;
  padding-bottom: .55rem;
}
