/* "Deep Navy Authority" palette (2026-10-16): chosen from six mocked-up
   options (see the design canvas) over the earlier moderate-blue pass. One
   navy (--accent) is now the ENTIRE brand/action color everywhere — the
   former ICT teal / Procurement gold / Approver indigo per-portal identity
   colors are gone; --ict-*/--procurement-*/--approver-* are kept only as
   aliases (dozens of rules still reference them) and now resolve to this
   same navy family, so every portal renders identically. --brand-navy and
   --brand-gold are likewise aliases for --accent/--accent-dark. The one
   place that gets its own dedicated tokens is the sidebar: it's a solid
   navy-filled panel (not just a thin accent line), so its text needs
   "foreground on navy" treatment regardless of the app's own light/dark
   mode — see --sidebar-* below. */
:root {
  --canvas: #fafafa;
  --surface: #ffffff;
  --border: #e4e4e7;
  --primary: #18181b;
  --primary-teal: #0d9488;
  --primary-teal-dark: #0f766e;
  --text: #27272a;
  --text-muted: #71717a;
  --text-faint: #a1a1aa;
  --success-bg: #ecfdf5;
  --success-text: #047857;
  --success-border: #a7f3d0;
  --warn-bg: #fffbeb;
  --warn-text: #b45309;
  --warn-border: #fde68a;
  --danger-bg: #fff1f2;
  --danger-text: #be123c;
  --danger-border: #fecdd3;
  --ms-blue: #2f5ea8;
  --brand-navy: #1d4ed8;
  --brand-navy-dark: #13294b;
  --ict-accent: #13294b;
  --ict-accent-dark: #1d4ed8;
  --ict-bg: #eef1f7;
  --ict-border: #c7d2e3;
  --procurement-accent: #13294b;
  --procurement-accent-dark: #1d4ed8;
  --procurement-bg: #eef1f7;
  --procurement-border: #c7d2e3;
  --procurement-hover-bg: #e3e8f2;
  --approver-accent: #13294b;
  --approver-accent-dark: #1d4ed8;
  --approver-bg: #eef1f7;
  --approver-border: #c7d2e3;
  --brand-gold: #13294b;
  --brand-gold-dark: #1d4ed8;
  --shadow-card: 0 1px 2px rgba(24, 24, 27, 0.04), 0 8px 24px -12px rgba(24, 24, 27, 0.08);
  --shadow-elevated: 0 20px 50px -12px rgba(24, 24, 27, 0.25);
  --canvas-dot: rgba(24, 24, 27, 0.05);
  /* Previously inline hex scattered across neutral badges/pills/chips —
     pulled into tokens so the dark-mode override below can flip them in one
     place instead of hunting down every literal color. */
  --neutral-bg: #f4f4f5;
  --neutral-text: #52525b;
  --surface-muted: #f4f4f5;
  --info-bg: #eff6ff;
  --info-text: #1d4ed8;
  --info-border: #bfdbfe;

  /* App shell (sidebar + topbar) design tokens. --accent is the deep navy
     fill (buttons, avatars, active indicators); --accent-dark is the
     brighter blue used for TEXT/links on a light surface (navy itself is
     too close to body text to read as a link). */
  --accent: #13294b;
  --accent-dark: #1d4ed8;
  --accent-bg: #eef1f7;
  /* Sidebar-only: the panel is solid navy regardless of app theme, so its
     foreground needs its own "on navy" tokens rather than the normal
     light/dark text tokens, which assume a light or dark SURFACE, not a
     colored one. */
  --sidebar-bg: #13294b;
  --sidebar-text: #ffffff;
  --sidebar-text-muted: rgba(255, 255, 255, 0.68);
  --sidebar-active-bg: rgba(255, 255, 255, 0.14);
  --sidebar-active-border: #8ab4ff;
  --sidebar-border: rgba(255, 255, 255, 0.14);
  --sidebar-width: 248px;
  --topbar-height: 64px;
}

/* Dark mode — a full override of every surface/text/semantic token above,
   so existing component CSS (badges, cards, tables, buttons) picks it up
   automatically through the same var() references rather than needing a
   parallel dark ruleset per component. Applied explicitly via a toggle
   (data-theme, set by theme-init.js/theme.js) and, for a first-time visitor
   who hasn't chosen yet, from the OS preference. An explicit choice always
   wins over the media query. */
/* Progressive-enhancement fallback for the rare case JS didn't run (so
   theme-init.js never set data-theme at all) — matches the OS preference.
   Normally data-theme is always explicitly 'light' or 'dark' by first
   paint, so this rule is mostly inert. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']):not([data-theme='dark']) {
    --canvas: #0a0a0b;
    --surface: #18181b;
    --border: #3f3f46;
    --primary: #e4e4e7;
    --text: #d4d4d8;
    --text-muted: #a1a1aa;
    --text-faint: #71717a;
    --success-bg: rgba(16, 185, 129, 0.14);
    --success-text: #34d399;
    --success-border: rgba(16, 185, 129, 0.3);
    --warn-bg: rgba(245, 158, 11, 0.14);
    --warn-text: #fbbf24;
    --warn-border: rgba(245, 158, 11, 0.3);
    --danger-bg: rgba(244, 63, 94, 0.14);
    --danger-text: #fb7185;
    --danger-border: rgba(244, 63, 94, 0.3);
    --neutral-bg: #27272a;
    --neutral-text: #d4d4d8;
    --surface-muted: #27272a;
    --info-bg: rgba(37, 99, 235, 0.16);
    --info-text: #60a5fa;
    --info-border: rgba(37, 99, 235, 0.35);
    /* Brighter than --sidebar-bg on purpose — a button/avatar needs to read
       as a shape against the dark CARD surface (#18181b), and the deep
       sidebar navy is too close to that surface's own lightness to show up
       as a solid fill there; the sidebar panel itself doesn't have this
       problem since it sits against the page canvas, not a card. */
    --accent: #2f5aa8;
    --accent-dark: #8ab4ff;
    --accent-bg: rgba(138, 180, 255, 0.16);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px -12px rgba(0, 0, 0, 0.5);
    --shadow-elevated: 0 20px 50px -12px rgba(0, 0, 0, 0.6);
    --canvas-dot: rgba(228, 228, 231, 0.045);
    /* --brand-navy/--brand-gold/--ict-*/--procurement-*/--approver-* are all
       aliases for --accent/--accent-dark now (see the :root block) — kept in
       sync here rather than deleted so every existing rule that reads them
       still resolves to the one navy accent, in dark mode too. */
    --brand-navy: #8ab4ff;
    --brand-navy-dark: #16264a;
    /* --ict-accent/--procurement-accent/--approver-accent (no -dark suffix)
       weren't overridden here in the original teal/gold/indigo palette —
       those hues stayed legible as a dark-mode fill unchanged. Deep navy
       does not: left alone it would stay pinned to the light-mode value and
       repeat the same invisible-fill problem --accent itself had. */
    --ict-accent: #2f5aa8;
    --ict-accent-dark: #8ab4ff;
    --ict-bg: rgba(138, 180, 255, 0.16);
    --ict-border: rgba(138, 180, 255, 0.35);
    --procurement-accent: #2f5aa8;
    --procurement-accent-dark: #8ab4ff;
    --procurement-bg: rgba(138, 180, 255, 0.16);
    --procurement-border: rgba(138, 180, 255, 0.35);
    --procurement-hover-bg: rgba(138, 180, 255, 0.24);
    --approver-accent: #2f5aa8;
    --approver-accent-dark: #8ab4ff;
    --approver-bg: rgba(138, 180, 255, 0.16);
    --approver-border: rgba(138, 180, 255, 0.35);
    /* Both brand-gold variants are small foreground marks (an eyebrow dot, a
       card-heading underline, hover text) sitting directly on the canvas,
       not a fill behind white text — the deep navy used for --accent in
       dark mode would be nearly invisible there, so both read from the
       bright blue instead. */
    --brand-gold: #8ab4ff;
    --brand-gold-dark: #8ab4ff;
    /* Sidebar navy is a touch lighter/bluer in dark mode than in light mode
       (#16264a vs #13294b) so it still reads as a distinct panel against a
       near-black canvas rather than blending into it. */
    --sidebar-bg: #16264a;
    --sidebar-active-border: #8ab4ff;
  }
}

:root[data-theme='dark'] {
  --canvas: #0a0a0b;
  --surface: #18181b;
  --border: #3f3f46;
  --primary: #e4e4e7;
  --text: #d4d4d8;
  --text-muted: #a1a1aa;
  --text-faint: #71717a;
  --success-bg: rgba(16, 185, 129, 0.14);
  --success-text: #34d399;
  --success-border: rgba(16, 185, 129, 0.3);
  --warn-bg: rgba(245, 158, 11, 0.14);
  --warn-text: #fbbf24;
  --warn-border: rgba(245, 158, 11, 0.3);
  --danger-bg: rgba(244, 63, 94, 0.14);
  --danger-text: #fb7185;
  --danger-border: rgba(244, 63, 94, 0.3);
  --neutral-bg: #27272a;
  --neutral-text: #d4d4d8;
  --surface-muted: #27272a;
  --info-bg: rgba(37, 99, 235, 0.16);
  --info-text: #60a5fa;
  --info-border: rgba(37, 99, 235, 0.35);
  --accent: #2f5aa8;
  --accent-dark: #8ab4ff;
  --accent-bg: rgba(138, 180, 255, 0.16);
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px -12px rgba(0, 0, 0, 0.5);
  --shadow-elevated: 0 20px 50px -12px rgba(0, 0, 0, 0.6);
  --canvas-dot: rgba(228, 228, 231, 0.045);
  --brand-navy: #8ab4ff;
  --brand-navy-dark: #16264a;
  --ict-accent: #2f5aa8;
  --ict-accent-dark: #8ab4ff;
  --ict-bg: rgba(138, 180, 255, 0.16);
  --ict-border: rgba(138, 180, 255, 0.35);
  --procurement-accent: #2f5aa8;
  --procurement-accent-dark: #8ab4ff;
  --procurement-bg: rgba(138, 180, 255, 0.16);
  --procurement-border: rgba(138, 180, 255, 0.35);
  --procurement-hover-bg: rgba(138, 180, 255, 0.24);
  --approver-accent: #2f5aa8;
  --approver-accent-dark: #8ab4ff;
  --approver-bg: rgba(138, 180, 255, 0.16);
  --approver-border: rgba(138, 180, 255, 0.35);
  --brand-gold: #8ab4ff;
  --brand-gold-dark: #8ab4ff;
  --sidebar-bg: #16264a;
  --sidebar-active-border: #8ab4ff;
}

/* An explicit light choice must win over a dark OS preference too — without
   this, the @media block above would re-darken a user who picked light
   mode while their OS happens to prefer dark. */
:root[data-theme='light'] {
  --canvas: #fafafa;
  --surface: #ffffff;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background:
    radial-gradient(circle at 1px 1px, var(--canvas-dot) 1px, transparent 0) 0 0/24px 24px,
    var(--canvas);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  transition: background-color 0.15s ease, color 0.15s ease;
}

/* Headings use the same sans-serif stack as body text — previously a serif
   display face for an "editorial, university-press" character, dropped in
   the 2026-10-14 industrial-palette redesign in favor of the plainer,
   single-typeface look most enterprise dashboards use. */
:root {
  --font-display: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

a {
  color: inherit;
}

/* A fixed pixel cap regardless of viewport meant a wide desktop monitor sat
   mostly empty, with content pinned to a narrow, centered column no matter
   how much screen was actually available. Scaling with the viewport (up to
   a ceiling that keeps text readable and tables from stretching absurdly
   wide) lets the layout genuinely use larger screens instead of ignoring
   them. */
.container {
  max-width: min(92vw, 1600px);
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

.container-wide {
  max-width: min(92vw, 1700px);
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

@media (max-width: 480px) {
  .container,
  .container-wide {
    padding: 1.25rem 1rem;
  }
}

/* --- Two-column detail layouts (ICT/Procurement review screens) --- */
.detail-grid {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: 2rem;
  align-items: start;
}

@media (max-width: 900px) {
  .detail-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
}

/* --- Site-wide brand bar (identical on every page) --- */
.site-header {
  width: 100%;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.05);
  position: relative;
}

/* A thin signature line — the one consistent accent touch across every page. */
.site-header::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
  background: linear-gradient(90deg, var(--brand-navy) 0%, var(--brand-gold) 50%, var(--brand-navy) 100%);
}

.site-header-inner {
  max-width: min(92vw, 1700px);
  margin: 0 auto;
  padding: 1rem 1.5rem;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
}

/* --- Thin strip directly under the header, just for a back action — kept off
   the header row itself so it never competes with the brand/nav for space --- */
.sub-nav {
  width: 100%;
  background: var(--canvas);
  border-bottom: 1px solid var(--border);
}

.sub-nav-inner {
  max-width: min(92vw, 1700px);
  margin: 0 auto;
  padding: 0.6rem 1.5rem;
}

.brand-logo-col {
  justify-self: start;
}

.brand-logo {
  height: 64px;
  width: auto;
  display: block;
  margin-left: 0.5rem;
}

.brand-title-col {
  justify-self: center;
  min-width: 0;
}

.brand-title {
  display: block;
  font-family: var(--font-display);
  font-size: 1.85rem;
  font-weight: 700;
  color: var(--brand-navy);
  letter-spacing: -0.01em;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
}

.nav-col {
  justify-self: end;
}

@media (max-width: 860px) {
  .site-header-inner {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
  }
  .brand-logo-col,
  .brand-title-col,
  .nav-col {
    justify-self: center;
  }
  .brand-title {
    font-size: 1.4rem;
    white-space: normal;
  }
}

.brand-subtitle {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  margin-top: 0.1rem;
}

/* --- Per-page heading (sits below the brand bar, inside the content container) --- */
.page-heading-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2rem;
  gap: 1rem;
  flex-wrap: wrap;
}

.eyebrow {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--primary-teal);
  position: relative;
  padding-left: 0.9rem;
}

.page-title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--primary);
  margin: 0.15rem 0 0;
}

.eyebrow::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.15em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--brand-gold);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.8rem;
  font-weight: 600;
}

.nav-links a {
  color: var(--text-muted);
  text-decoration: none;
}

.nav-links a:hover {
  color: var(--primary);
}

.nav-links button {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  color: var(--text);
  font: inherit;
  font-weight: 600;
  font-size: 0.78rem;
  cursor: pointer;
  padding: 0.4rem 0.85rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.nav-links button:hover {
  border-color: var(--danger-border);
  color: var(--danger-text);
  background: var(--danger-bg);
}

/* --- User menu: avatar + dropdown, replacing plain "Name (email) [Sign out]" text --- */
.user-menu {
  position: relative;
}

.user-avatar-btn {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  border-radius: 999px;
}
.user-avatar-btn:hover .user-avatar {
  box-shadow: 0 0 0 3px var(--ict-bg);
}
.theme-procurement .user-avatar-btn:hover .user-avatar {
  box-shadow: 0 0 0 3px var(--procurement-bg);
}

.user-avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
}
.theme-ict .user-avatar {
  background: var(--ict-accent);
}
.theme-procurement .user-avatar {
  background: var(--procurement-accent);
}
.theme-approver .user-avatar {
  background: var(--approver-accent);
}

.user-menu-dropdown {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  min-width: 230px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.7rem;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.14);
  padding: 0.75rem;
  z-index: 50;
}

.user-menu-info {
  padding: 0.1rem 0.4rem 0.65rem;
  margin-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
}

.user-menu-name {
  display: block;
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--text);
}

.user-menu-email {
  display: block;
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-top: 0.1rem;
  word-break: break-all;
}

.user-menu-dropdown .nav-links-signout {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0.55rem 0.4rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--danger-text);
  cursor: pointer;
  border-radius: 0.45rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.user-menu-dropdown .nav-links-signout:hover {
  background: var(--danger-bg);
}

.user-menu-dropdown .nav-links-item {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0.55rem 0.4rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
  border-radius: 0.45rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.user-menu-dropdown .nav-links-item:hover {
  background: var(--canvas);
}

.theme-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 0.4rem 0.1rem;
  margin-top: 0.3rem;
  border-top: 1px solid var(--border);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
}

.theme-toggle-row .app-icon-btn {
  padding: 0.25rem;
}

/* --- "Back to X" navigation affordance: deliberately understated (no border
   or button chrome) since it's a wayfinding link, not an action — the gold
   arrow-slide on hover ties it to the same accent used for card headings. --- */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  background: none;
  padding: 0.3rem 0.1rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--brand-navy);
  text-decoration: none;
  cursor: pointer;
}

.back-link-arrow {
  display: inline-block;
  transition: transform 0.15s ease;
}

.back-link:hover {
  color: var(--brand-gold-dark);
}

.back-link:hover .back-link-arrow {
  transform: translateX(-3px);
}

/* --- Cards --- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 3px solid var(--border);
  border-radius: 0.75rem;
  padding: 1.5rem;
  box-shadow: var(--shadow-card);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.theme-ict .card {
  border-top-color: var(--ict-accent);
}

.theme-procurement .card {
  border-top-color: var(--procurement-accent);
}

.theme-approver .card {
  border-top-color: var(--approver-accent);
}

@media (max-width: 480px) {
  .card {
    padding: 1.1rem;
  }
  .question-card {
    padding: 1.75rem 1.1rem;
  }
}

.card h2 {
  position: relative;
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--primary);
  margin: 0 0 1.25rem;
  padding-bottom: 0.6rem;
}

.card h2::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 2rem;
  height: 2px;
  background: var(--brand-gold);
}

.card h3 {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--primary);
  margin: 0 0 0.75rem;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1rem;
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1rem;
}

@media (max-width: 640px) {
  .grid-2,
  .grid-3 {
    grid-template-columns: 1fr;
  }
}

/* --- Forms --- */
label {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
}

input[type='text'],
input[type='email'],
input[type='number'],
input[type='password'],
select,
textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  padding: 0.55rem 0.7rem;
  font-size: 0.85rem;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--primary-teal);
  outline-offset: 1px;
}

/* Edge/Chromium add their own built-in reveal-password eye icon on top of
   our custom SVG toggle button, showing two overlapping eye icons in the
   same field. This is the standard way to suppress the native one. */
input[type='password']::-ms-reveal,
input[type='password']::-ms-clear {
  display: none;
}

select:disabled {
  background: var(--surface-muted);
  color: var(--text-muted);
  cursor: not-allowed;
}

.field {
  margin-bottom: 1rem;
}

.field:last-child {
  margin-bottom: 0;
}

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border: none;
  border-radius: 0.5rem;
  padding: 0.65rem 1.25rem;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}

.btn:not(:disabled):hover {
  transform: translateY(-1px);
}

.btn:not(:disabled):active {
  transform: translateY(0);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Built from --accent/--accent-dark, not --primary/--brand-navy — those
   invert to light values in dark mode (correct for foreground text, wrong
   for a solid fill sitting behind white button text). --accent is already
   calibrated to stay a vivid, white-text-safe fill in both themes (see
   .stepper-tab-index/.app-sidebar-nav-item, which rely on the same thing). */
.btn-primary {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
  color: #fff;
  box-shadow: 0 4px 14px -4px rgba(24, 24, 27, 0.4);
}
.btn-primary:hover:not(:disabled) {
  background: linear-gradient(135deg, var(--accent-dark) 0%, var(--accent) 100%);
  box-shadow: 0 6px 18px -4px rgba(24, 24, 27, 0.5);
}

.btn-teal {
  background: var(--primary-teal);
  color: #fff;
}
.btn-teal:hover:not(:disabled) {
  background: var(--primary-teal-dark);
}

.btn-danger {
  background: #e11d48;
  color: #fff;
}
.btn-danger:hover:not(:disabled) {
  background: #be123c;
}

.btn-outline {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}
.btn-outline:hover:not(:disabled) {
  border-color: var(--primary);
}

.btn-block {
  width: 100%;
}

.btn-ms {
  background: var(--ms-blue);
  color: #fff;
}
.btn-ms:hover:not(:disabled) {
  background: #244a86;
}

.btn-lg {
  padding: 0.9rem 1.5rem;
  font-size: 0.95rem;
}

/* --- Compact button variant for nav bars and inline actions. Declared after
   .btn so it actually wins the cascade — with equal selector specificity,
   whichever rule comes later in the file wins, and this used to sit above
   .btn, so its smaller padding/font-size was silently overridden and never
   took effect no matter where the class was added in markup. --- */
.btn-sm {
  padding: 0.3rem 0.7rem;
  font-size: 0.72rem;
  gap: 0.35rem;
}

/* --- Alerts --- */
/* A plain block-level pastel box with just text used to stretch full-width
   and look like an oversized, empty pill for a short one-line message. Sizing
   to its own content (inline-flex) and adding a small icon badge gives it
   actual visual weight instead of a wide box with nothing in it. */
.alert {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 100%;
  border-radius: 0.5rem;
  padding: 0.55rem 0.9rem;
  font-size: 0.78rem;
  font-weight: 600;
}

.alert::before {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  font-size: 0.65rem;
  font-weight: 800;
  line-height: 1;
  color: #fff;
}

.alert-error {
  background: var(--danger-bg);
  color: var(--danger-text);
  border: 1px solid var(--danger-border);
}

.alert-error::before {
  content: '\2715';
  background: var(--danger-text);
}

.alert-success {
  background: var(--success-bg);
  color: var(--success-text);
  border: 1px solid var(--success-border);
}

.alert-success::before {
  content: '\2713';
  background: var(--success-text);
}

.alert-info {
  background: var(--info-bg);
  color: var(--info-text);
  border: 1px solid var(--info-border);
}

.alert-info::before {
  content: 'i';
  background: var(--info-text);
  font-style: italic;
}

/* --- Badges --- */
.badge {
  display: inline-block;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.badge-pending {
  background: var(--warn-bg);
  color: var(--warn-text);
}
.badge-approved {
  background: var(--success-bg);
  color: var(--success-text);
}
.badge-rejected {
  background: var(--danger-bg);
  color: var(--danger-text);
}
.badge-neutral {
  background: var(--neutral-bg);
  color: var(--neutral-text);
}

/* --- Table --- */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

thead th {
  text-align: left;
  font-size: 0.7rem;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.5rem;
  padding-right: 1rem;
}

tbody td {
  padding: 0.6rem 1rem 0.6rem 0;
  border-bottom: 1px solid var(--border);
}

tbody tr:last-child td {
  border-bottom: none;
}

.table-scroll {
  overflow-x: auto;
}

/* --- Quotation comparison matrix --- */
.quote-matrix th,
.quote-matrix td {
  text-align: right;
  white-space: nowrap;
}
.quote-matrix th:first-child,
.quote-matrix td:first-child {
  text-align: left;
  white-space: normal;
}
.quote-matrix .is-lowest {
  background: var(--success-bg);
  color: var(--success-text);
  font-weight: 700;
  border-radius: 0.3rem;
}

/* Below this width, a horizontal-scrolling multi-column table pushes the
   Status column and the action link off-screen with no visible scrollbar
   hint — a reviewer landing on the queue from a phone would never know
   those columns exist. Restructuring each row into a small stacked card
   (label: value pairs, sourced from each cell's data-label) keeps every
   field visible without any hidden horizontal content. */
@media (max-width: 640px) {
  .table-scroll {
    overflow-x: visible;
  }

  .table-scroll table,
  .table-scroll tbody,
  .table-scroll tr,
  .table-scroll td {
    display: block;
    width: 100%;
  }

  .table-scroll thead {
    display: none;
  }

  .table-scroll tr {
    border: 1px solid var(--border);
    border-radius: 0.6rem;
    padding: 0.6rem 0.75rem;
    margin-bottom: 0.75rem;
  }

  .table-scroll tbody tr:last-child {
    margin-bottom: 0;
  }

  .table-scroll td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--border);
    text-align: right;
  }

  .table-scroll td:last-child {
    border-bottom: none;
  }

  .table-scroll td[data-label]::before {
    content: attr(data-label);
    font-weight: 600;
    font-size: 0.68rem;
    color: var(--text-muted);
    text-align: left;
    flex-shrink: 0;
  }

  .table-scroll td[data-label='']::before {
    content: none;
  }

  .table-scroll td[data-label=''] {
    justify-content: flex-end;
  }
}

/* --- Questionnaire wizard --- */
.wizard-progress {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-bottom: 0.5rem;
}

.wizard-progress-bar {
  height: 6px;
  background: var(--border);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 1.5rem;
}

.wizard-progress-fill {
  height: 100%;
  background: var(--primary-teal);
  transition: width 0.25s ease;
}

.question-card {
  text-align: center;
  padding: 2.5rem 1.5rem;
}

.question-title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--primary);
  margin: 0 0 0.75rem;
}

.question-description {
  color: var(--text-muted);
  font-size: 0.9rem;
  max-width: 32rem;
  margin: 0 auto 2rem;
}

.question-actions {
  display: flex;
  justify-content: center;
  gap: 1rem;
}

.answer-btn {
  min-width: 6.5rem;
  padding: 0.65rem 1.25rem;
  border-radius: 0.55rem;
  font-size: 0.9rem;
  font-weight: 700;
  border: 2px solid var(--border);
  background: var(--surface);
  cursor: pointer;
}

.answer-btn.yes:hover {
  border-color: var(--success-text);
  color: var(--success-text);
  background: var(--success-bg);
}

.answer-btn.no:hover {
  border-color: var(--danger-text);
  color: var(--danger-text);
  background: var(--danger-bg);
}

/* --- Level selector (e.g. Regular / High / Advanced usage) --- */
.level-options {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 24rem;
  margin: 1.25rem auto 0;
  text-align: left;
}

.level-option {
  display: block;
  width: 100%;
  padding: 0.45rem 0.65rem;
  border-radius: 0.45rem;
  border: 1.5px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  text-align: left;
}

.level-option:hover {
  border-color: var(--primary-teal);
  background: #f0fdfa;
}

.level-option .level-label {
  display: block;
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--text);
}

.level-option .level-desc {
  display: block;
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-top: 0.1rem;
}

/* --- Recommendation detail --- */
.spec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1rem;
  background: #f8fafc;
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  padding: 1rem;
  margin-bottom: 1rem;
}

/* System Type's value ("64-bit operating system, x64-based processor") is by
   far the longest text in this grid — confined to one narrow column it wraps
   onto three lines, stretching its row and leaving an empty gap in whatever
   short field shares that row. Spanning the full width instead gives the
   text room to lay out on far fewer lines, and it's placed last in the grid
   so that extra width doesn't disrupt the alignment of the shorter fields
   above it. */
.spec-item-wide {
  grid-column: 1 / -1;
}

.spec-item .label {
  display: block;
  font-size: 0.7rem;
  color: var(--text-muted);
}

.spec-item .value {
  font-weight: 700;
  color: var(--text);
}

.feature-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.pill {
  background: var(--neutral-bg);
  border: 1px solid var(--border);
  color: var(--neutral-text);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.72rem;
}

.justification-list {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.85rem;
  color: var(--text);
}

.justification-list li {
  margin-bottom: 0.35rem;
}

.text-muted {
  color: var(--text-muted);
}

.text-xs {
  font-size: 0.75rem;
}

.center {
  text-align: center;
}

.hidden {
  display: none !important;
}

.mt-1 {
  margin-top: 0.5rem;
}
.mt-2 {
  margin-top: 1rem;
}
.mb-1 {
  margin-bottom: 0.5rem;
}

.link {
  color: var(--primary-teal);
  font-weight: 600;
  text-decoration: none;
}
.link:hover {
  text-decoration: underline;
}

.login-shell {
  min-height: calc(100vh - 100px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.login-wrap {
  width: 100%;
  max-width: 26rem;
}

.login-card {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.9rem;
  padding: 2rem;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
}

/* --- Clean, centered sign-in — a single focused card, no marketing panel. --- */
.login-centered {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.5rem;
  background:
    radial-gradient(circle at 1px 1px, rgba(15, 23, 42, 0.05) 1px, transparent 0) 0 0/24px 24px,
    var(--canvas);
}

/* Fixed to the viewport corner rather than stacked above the card — a "back"
   affordance reads as page-level navigation, not part of the sign-in form
   itself, so it shouldn't visually compete with or shift the centered card. */
.login-fixed-back {
  position: fixed;
  top: 1.5rem;
  left: 1.5rem;
  z-index: 1;
}

.login-fixed-theme-toggle {
  position: fixed;
  top: 1.5rem;
  right: 1.5rem;
  z-index: 1;
}

.login-centered-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 1rem;
  padding: 3.5rem 2.25rem;
  box-shadow: var(--shadow-elevated);
  max-width: 25rem;
  width: 100%;
  text-align: center;
  animation: loginFadeUp 0.5s ease both;
}

.sso-section {
  margin-top: 1.25rem;
}

.sso-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
  color: var(--text-faint);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sso-divider::before,
.sso-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

.sso-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
}

.login-centered-card #login-form {
  text-align: left;
  margin-top: 1.5rem;
}

.login-centered-logo {
  height: 56px;
  width: auto;
  display: block;
  margin: 0 auto 1.5rem;
}

.login-centered-title {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 700;
  color: var(--brand-navy);
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 0;
}

@keyframes loginFadeUp {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.input-icon-wrap {
  position: relative;
}

.input-icon-wrap .input-icon {
  position: absolute;
  left: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-faint);
  pointer-events: none;
}

.input-icon-wrap input {
  padding-left: 2.35rem;
}

.input-icon-wrap:focus-within .input-icon {
  color: var(--primary-teal);
}

.input-icon-wrap:has(.input-icon-toggle) input {
  padding-right: 2.35rem;
}

.input-icon-toggle {
  position: absolute;
  right: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 0.25rem;
  color: var(--text-faint);
  cursor: pointer;
  display: flex;
  align-items: center;
  border-radius: 0.3rem;
}

.input-icon-toggle:hover {
  color: var(--text-muted);
}

.input-icon-toggle:focus-visible {
  outline: 2px solid var(--primary-teal);
  outline-offset: 1px;
}

@media (max-width: 480px) {
  .login-centered-card {
    padding: 2rem 1.25rem;
  }
}

.divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--text-faint);
  font-size: 0.72rem;
  margin: 1.5rem 0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.divider::before,
.divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

.dev-box {
  border: 1px dashed var(--warn-border);
  background: var(--warn-bg);
  border-radius: 0.6rem;
  padding: 1rem;
}

.dev-box .dev-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--warn-text);
  display: block;
  margin-bottom: 0.75rem;
}

.loading-shell {
  min-height: 40vh;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.85rem;
}

/* --- Staff-portal access footer (bottom of the public request page) --- */
/* --- Portal theming: ICT (teal) vs Procurement (gold/bronze) --- */
.theme-ict .eyebrow {
  color: var(--ict-accent);
}
.theme-ict .btn-teal,
.theme-ict .btn-approve {
  background: var(--ict-accent);
}
.theme-ict .btn-teal:hover,
.theme-ict .btn-approve:hover {
  background: var(--ict-accent-dark);
}

.theme-procurement .eyebrow {
  color: var(--procurement-accent);
}
.theme-procurement .btn-primary-action {
  background: var(--procurement-accent);
}
.theme-procurement .btn-primary-action:hover {
  background: var(--procurement-accent-dark);
}
.theme-procurement .badge-pending {
  background: var(--procurement-bg);
  color: var(--procurement-accent-dark);
}

.theme-approver .eyebrow {
  color: var(--approver-accent);
}
.theme-approver .btn-primary-action {
  background: var(--approver-accent);
}
.theme-approver .btn-primary-action:hover {
  background: var(--approver-accent-dark);
}
.theme-approver .badge-pending {
  background: var(--approver-bg);
  color: var(--approver-accent-dark);
}

/* --- ICT override picker --- */
.override-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.override-note {
  font-size: 0.72rem;
  color: var(--text-muted);
  margin: 0.5rem 0 1.25rem;
}

/* --- Section tabs (Procurement Active / Completed) --- */
.section-heading-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}

.count-chip {
  background: var(--neutral-bg);
  color: var(--neutral-text);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.15rem 0.65rem;
  font-size: 0.7rem;
  font-weight: 700;
  min-width: 1.6rem;
  text-align: center;
  display: inline-block;
}

.theme-ict .count-chip {
  background: var(--ict-bg);
  color: var(--ict-accent-dark);
  border-color: var(--ict-border);
}

.theme-procurement .count-chip {
  background: var(--procurement-bg);
  color: var(--procurement-accent-dark);
  border-color: var(--procurement-border);
}

.theme-approver .count-chip {
  background: var(--approver-bg);
  color: var(--approver-accent-dark);
  border-color: var(--approver-border);
}

@media (prefers-reduced-motion: reduce) {
  .login-centered-card,
  .btn {
    animation: none !important;
    transition: none !important;
  }
}

/* --- Activity log: full timestamped history of every action taken --- */
.activity-log {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 22rem;
  overflow-y: auto;
}

.activity-log-item {
  position: relative;
  padding: 0.7rem 0 0.7rem 1rem;
  border-left: 2px solid var(--border);
  margin-left: 0.3rem;
}

.activity-log-item::before {
  content: '';
  position: absolute;
  left: -5px;
  top: 1.1rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary-teal);
}

.theme-procurement .activity-log-item::before {
  background: var(--procurement-accent);
}

.activity-log-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.activity-log-action {
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--text);
}

.activity-log-time {
  font-size: 0.72rem;
  color: var(--text-muted);
  white-space: nowrap;
}

.activity-log-actor {
  font-size: 0.72rem;
  color: var(--text-faint);
  margin-top: 0.1rem;
}

.activity-log-note {
  margin-top: 0.4rem;
  padding: 0.5rem 0.7rem;
  background: var(--canvas);
  border-radius: 0.4rem;
  font-size: 0.78rem;
  font-style: italic;
  color: var(--text);
}

/* --- Requester-facing status stepper (lookup page) --- */
.status-stepper {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 0.75rem 0;
}

.status-step {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 5.5rem;
}

.status-step-dot {
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}

.status-step-line {
  flex: 1 1 auto;
  height: 2px;
  background: var(--border);
  margin: 0 0.3rem;
  min-width: 0.75rem;
}

.status-step-label {
  font-size: 0.68rem;
  color: var(--text-muted);
  margin-left: 0.35rem;
  white-space: nowrap;
}

.status-step.is-done .status-step-dot {
  background: var(--primary-teal);
  border-color: var(--primary-teal);
}

.status-step.is-done .status-step-line {
  background: var(--primary-teal);
}

.status-step.is-current .status-step-dot {
  border-color: var(--primary-teal);
  background: var(--surface);
  box-shadow: 0 0 0 3px rgba(13, 148, 136, 0.18);
}

.status-step.is-current .status-step-label {
  color: var(--text);
  font-weight: 700;
}

.status-action-banner {
  margin-top: 0.5rem;
  padding: 0.6rem 0.8rem;
  border-radius: 0.5rem;
  font-size: 0.78rem;
  background: var(--warn-bg);
  color: var(--warn-text);
  border: 1px solid var(--warn-border);
}

/* ==========================================================================
   App Shell — sidebar + topbar, shared by every signed-in portal page.
   Rendered by public/js/appShell.js into #shell-sidebar/#shell-topbar.
   ========================================================================== */

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

#shell-sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  background: var(--sidebar-bg);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 40;
  transition: transform 0.2s ease;
}

.app-sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1.1rem 1.2rem;
  border-bottom: 1px solid var(--sidebar-border);
}

.app-sidebar-logo {
  width: 28px;
  height: 28px;
  object-fit: contain;
  border-radius: 6px;
}

.app-sidebar-brand-text {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--sidebar-text);
  flex: 1;
}

.app-sidebar-close {
  display: none;
  background: none;
  border: none;
  color: var(--sidebar-text-muted);
  cursor: pointer;
  padding: 0.2rem;
}

.app-sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.app-sidebar-nav-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.75rem;
  border-radius: 0.5rem;
  color: var(--sidebar-text-muted);
  text-decoration: none;
  font-size: 0.86rem;
  font-weight: 600;
  border-left: 3px solid transparent;
}

.app-sidebar-nav-item:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--sidebar-text);
}

.app-sidebar-divider {
  border: none;
  border-top: 1px solid var(--sidebar-border);
  margin: 0.5rem 0.4rem;
}

/* One navy sidebar for every portal, no per-role accent — the active item
   reads via a translucent white highlight plus a brighter blue edge, not a
   different hue per ICT/Procurement/Approver. */
.app-sidebar-nav-item.is-active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-text);
  border-left-color: var(--sidebar-active-border);
}

.app-sidebar-nav-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  display: inline-flex;
}

.app-sidebar-nav-icon svg {
  width: 100%;
  height: 100%;
}

.app-sidebar-user {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.9rem 1rem;
  border-top: 1px solid var(--sidebar-border);
}

.app-sidebar-user-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-sidebar-user-name {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--sidebar-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-sidebar-user-role {
  font-size: 0.72rem;
  color: var(--sidebar-text-muted);
}

/* The sidebar's own avatar circle needs a light fill — the normal
   navy-bg/white-text .user-avatar pattern (used everywhere else, against
   white/dark CARD surfaces) would be invisible against this navy panel. */
.app-sidebar-user .user-avatar {
  background: var(--sidebar-active-border);
  color: var(--sidebar-bg);
}

.app-sidebar-signout {
  background: none;
  border: none;
  color: var(--sidebar-text-muted);
  cursor: pointer;
  padding: 0.3rem;
  flex-shrink: 0;
}

.app-sidebar-signout:hover {
  color: var(--danger-text);
}

.app-sidebar-signout svg,
.app-sidebar-close svg {
  width: 18px;
  height: 18px;
}

#shell-overlay {
  display: none;
}

.app-main {
  flex: 1;
  min-width: 0;
  margin-left: var(--sidebar-width);
}

#shell-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--topbar-height);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 1.25rem;
}

.app-topbar-menu-btn {
  display: none;
  background: none;
  border: none;
  color: var(--text);
  cursor: pointer;
  padding: 0.3rem;
}

.app-topbar-menu-btn svg {
  width: 20px;
  height: 20px;
}

.app-topbar-title {
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--primary);
  margin: 0;
  white-space: nowrap;
}

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

.app-topbar-search-icon {
  position: absolute;
  left: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--text-faint);
  pointer-events: none;
}

.app-topbar-search-icon svg {
  width: 100%;
  height: 100%;
}

.app-topbar-search input {
  width: 100%;
  padding: 0.5rem 0.75rem 0.5rem 2.1rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: var(--canvas);
  color: var(--text);
  font-size: 0.85rem;
}

.app-search-results {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  box-shadow: var(--shadow-elevated);
  max-height: 320px;
  overflow-y: auto;
  z-index: 50;
}

.app-search-result {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.55rem 0.8rem;
  text-decoration: none;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}

.app-search-result:last-child {
  border-bottom: none;
}

.app-search-result:hover {
  background: var(--canvas);
}

.app-search-result-ref {
  font-family: monospace;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--accent-dark);
}

.app-search-result-title {
  font-size: 0.82rem;
  font-weight: 600;
}

.app-search-result-meta {
  font-size: 0.72rem;
  color: var(--text-muted);
}

.app-search-empty {
  padding: 0.7rem 0.8rem;
  margin: 0;
}

.app-topbar-actions {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}

.app-icon-btn {
  position: relative;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.4rem;
  border-radius: 0.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.app-icon-btn:hover {
  background: var(--canvas);
  color: var(--text);
}

.app-icon-btn svg {
  width: 19px;
  height: 19px;
}

.theme-toggle-btn .icon-moon {
  display: none;
}

:root[data-theme='dark'] .theme-toggle-btn .icon-sun {
  display: none;
}

:root[data-theme='dark'] .theme-toggle-btn .icon-moon {
  display: block;
}

.app-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  background: var(--danger-text);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 700;
  line-height: 1;
  padding: 0.2rem 0.35rem;
  border-radius: 999px;
  min-width: 1rem;
  text-align: center;
}

.app-shell-content {
  padding: 1.75rem;
}

.app-panel {
  display: none;
}

.app-panel.is-active {
  display: block;
}

@media (max-width: 960px) {
  #shell-sidebar {
    transform: translateX(-100%);
    box-shadow: var(--shadow-elevated);
  }
  #shell-sidebar.is-open {
    transform: translateX(0);
  }
  .app-sidebar-close {
    display: inline-flex;
  }
  .app-main {
    margin-left: 0;
  }
  .app-topbar-menu-btn {
    display: inline-flex;
  }
  .app-topbar-title {
    display: none;
  }
  #shell-overlay:not(.hidden) {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.4);
    z-index: 35;
  }
}

@media (max-width: 560px) {
  .app-topbar-search {
    max-width: none;
  }
}

/* ==========================================================================
   Dashboard — stat cards, donut chart, stepper tabs.
   ========================================================================== */

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1.5rem;
}

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

@media (max-width: 560px) {
  .dashboard-grid {
    grid-template-columns: 1fr;
  }
}

.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 3px solid var(--border);
  border-radius: 0.75rem;
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow-card);
}

.theme-ict .stat-card {
  border-top-color: var(--ict-accent);
}
.theme-procurement .stat-card {
  border-top-color: var(--procurement-accent);
}
.theme-approver .stat-card {
  border-top-color: var(--approver-accent);
}

.stat-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 0.6rem;
}

.stat-card-icon {
  width: 36px;
  height: 36px;
  border-radius: 0.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-bg);
  color: var(--accent-dark);
}

.stat-card-icon svg {
  width: 18px;
  height: 18px;
}

.stat-card-icon.is-success {
  background: var(--success-bg);
  color: var(--success-text);
}

.stat-card-icon.is-warn {
  background: var(--warn-bg);
  color: var(--warn-text);
}

.stat-card-icon.is-danger {
  background: var(--danger-bg);
  color: var(--danger-text);
}

.stat-card-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin: 0 0 0.2rem;
}

.stat-card-value {
  font-size: 1.65rem;
  font-weight: 700;
  color: var(--primary);
  margin: 0;
}

.stat-trend {
  font-size: 0.76rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  margin-top: 0.45rem;
}

.stat-trend.is-up {
  color: var(--success-text);
}

.stat-trend.is-down {
  color: var(--danger-text);
}

.stat-trend.is-flat {
  color: var(--text-muted);
}

.stat-trend-context {
  color: var(--text-muted);
  font-weight: 400;
}

.donut-wrap {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.donut-svg {
  flex-shrink: 0;
}

.donut-empty {
  margin: 0;
}

.donut-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  flex: 1;
  min-width: 140px;
}

.donut-legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
}

.donut-legend-swatch {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.donut-legend-label {
  flex: 1;
  color: var(--text);
}

.donut-legend-value {
  font-weight: 700;
  color: var(--primary);
}

.stepper-tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}

.stepper-tab {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.stepper-tab-index {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--neutral-bg);
  color: var(--text-muted);
  font-size: 0.7rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.stepper-tab.is-active {
  color: var(--accent-dark);
  border-bottom-color: var(--accent);
}

.stepper-tab.is-active .stepper-tab-index {
  background: var(--accent);
  color: #fff;
}

.stepper-tab.is-done .stepper-tab-index {
  background: var(--success-text);
  color: #fff;
}

.stepper-tab.is-done .stepper-tab-index::before {
  content: '\2713';
}
