/* ============================================================
   ITB Servicedesk - design tokens and modern overrides on top
   of vendored Bootstrap 5. All colours flow through CSS
   variables so the auto / light / dark switch in the topbar
   keeps everything coherent.
   ============================================================ */

:root {
  /* Brand accent - deep teal on warm paper neutrals (the "Slate & Teal"
     identity: flat, precise, no decorative shadows). */
  --sd-accent:        #0f766e;
  --sd-accent-hover:  #115e59;
  --sd-accent-soft:   rgba(15, 118, 110, 0.12);
  --sd-accent-ring:   rgba(15, 118, 110, 0.28);

  /* Sidebar: a warm paper panel one step darker than the body; the
     active item is a solid teal block with white text. */
  --sd-sidebar-bg:        #f0f0ec;
  --sd-sidebar-bg-hover:  #e7e7e1;
  --sd-sidebar-bg-active: var(--sd-accent);
  --sd-sidebar-fg:        #39423d;
  --sd-sidebar-fg-hover:  #1b2420;
  --sd-sidebar-fg-muted:  #8b948d;
  --sd-sidebar-fg-active: #ffffff;
  --sd-sidebar-border:    #e2e2dc;
  --sd-sidebar-section:   #8b948d;

  /* Topbar wants to feel light and unobtrusive. */
  --sd-topbar-bg:     rgba(255, 255, 255, 0.85);
  --sd-topbar-border: #e6e6e0;
  --sd-topbar-fg:     #1b2420;
  --sd-topbar-btn-hover: rgba(27, 36, 32, 0.06);

  /* Surfaces and lines on the main content: warm paper, not cool gray. */
  --sd-body-bg:       #f7f7f4;
  --sd-surface:       #ffffff;
  --sd-surface-muted: #f2f2ee;
  --sd-border:        #e6e6e0;
  --sd-text:          #1b2420;
  --sd-text-muted:    #68716b;

  /* Flat design: hairline shadows only; depth comes from borders.
     The -lg tier keeps a modest lift for floating layers (dropdowns). */
  --sd-shadow-sm:  0 1px 2px rgba(27, 36, 32, 0.04);
  --sd-shadow:     0 1px 2px rgba(27, 36, 32, 0.05);
  --sd-shadow-lg:  0 10px 24px -12px rgba(27, 36, 32, 0.18);

  /* Radius - tighter than before: precise, not bubbly. */
  --sd-radius-sm: 0.3rem;
  --sd-radius:    0.45rem;
  --sd-radius-lg: 0.6rem;
}

[data-bs-theme="dark"] {
  --sd-body-bg:       #101614;
  --sd-surface:       #182019;
  --sd-surface-muted: #1f2a22;
  --sd-border:        #2a352f;
  --sd-text:          #e4ece7;
  --sd-text-muted:    #93a099;

  --sd-topbar-bg:     rgba(16, 22, 20, 0.85);
  --sd-topbar-border: #2a352f;
  --sd-topbar-fg:     #e4ece7;
  --sd-topbar-btn-hover: rgba(255, 255, 255, 0.06);

  --sd-shadow-sm:  0 1px 2px rgba(0, 0, 0, 0.35);
  --sd-shadow:     0 1px 2px rgba(0, 0, 0, 0.4);
  --sd-shadow-lg:  0 10px 24px -12px rgba(0, 0, 0, 0.6);

  /* Brighter teal for text/links/charts on dark ground; buttons flip to
     dark ink on this fill (see .btn-primary below). */
  --sd-accent:       #2fbfa9;
  --sd-accent-hover: #56d0bc;
  --sd-accent-soft:  rgba(47, 191, 169, 0.16);
  --sd-accent-ring:  rgba(47, 191, 169, 0.35);

  /* Dark mode sidebar: same green-black family as the body; the active
     block keeps the light theme's deep teal so white text stays readable. */
  --sd-sidebar-bg:        #101614;
  --sd-sidebar-bg-hover:  rgba(255, 255, 255, 0.05);
  --sd-sidebar-bg-active: #0f766e;
  --sd-sidebar-fg:        #cfd8d1;
  --sd-sidebar-fg-hover:  #ffffff;
  --sd-sidebar-fg-muted:  #6d7a72;
  --sd-sidebar-fg-active: #ffffff;
  --sd-sidebar-border:    rgba(255, 255, 255, 0.06);
  --sd-sidebar-section:   #93a099;
}

/* Steer Bootstrap's own tokens so existing utility classes follow suit. */
:root {
  --bs-primary:     var(--sd-accent);
  --bs-primary-rgb: 15, 118, 110;
  --bs-link-color:  var(--sd-accent);
  --bs-link-hover-color: var(--sd-accent-hover);
  --bs-body-bg:     var(--sd-body-bg);
  --bs-body-color:  var(--sd-text);
  --bs-border-color: var(--sd-border);
  --bs-border-radius: var(--sd-radius);
  --bs-border-radius-sm: var(--sd-radius-sm);
  --bs-border-radius-lg: var(--sd-radius-lg);
  --bs-tertiary-bg: var(--sd-surface-muted);
}
[data-bs-theme="dark"] { --bs-primary-rgb: 47, 191, 169; }

/* ---- Typography ------------------------------------------------------- */

/* Inter variable font, vendored (scripts/fetch_vendor.sh). The family
   list below always asked for Inter; these declarations make it actually
   load instead of silently falling back to the OS UI font. */
@font-face {
  font-family: "Inter";
  src: url("../vendor/inter/InterVariable.2bf3d951bf9d.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("../vendor/inter/InterVariable-Italic.8d1dc86da258.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

html, body {
  font-family:
    "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable",
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif,
    "Apple Color Emoji", "Segoe UI Emoji";
  font-feature-settings: "cv11", "ss01", "ss03";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  letter-spacing: -0.005em;
}

body {
  background-color: var(--sd-body-bg);
  color: var(--sd-text);
}

h1, h2, h3, h4, h5, h6 {
  letter-spacing: -0.015em;
  font-weight: 600;
}

a { text-decoration: none; }
a:hover { text-decoration: underline; }

code, pre, .font-monospace {
  font-family:
    ui-monospace, "JetBrains Mono", "SF Mono", "Cascadia Code",
    Menlo, Consolas, "Liberation Mono", monospace;
}

/* ---- Brand assets ----------------------------------------------------- */

.logo-img {
  max-height: 32px;
  max-width: 160px;
  object-fit: contain;
}

.login-logo {
  max-height: 96px;
  max-width: 260px;
  object-fit: contain;
}

/* ---- App shell: left sidebar + main column ---------------------------- */

.app-shell { background-color: var(--sd-body-bg); }

/* Defensively clip horizontal overflow inside the main column. The
   topbar is sticky on the OUTER document so this won't break it; we
   only want to keep a stray wide element (a long URL, a too-wide
   <pre>) from forcing the whole page to scroll horizontally on mobile. */
.app-main { min-width: 0; overflow-x: hidden; }

/* On very narrow viewports Bootstrap's container-fluid gutter is wider
   than necessary. Reduce horizontal + vertical breathing room so forms
   and cards have more room to actually breathe. */
@media (max-width: 575.98px) {
  .app-main .container-fluid { padding-left: 0.75rem; padding-right: 0.75rem; }
  .app-main .container-fluid.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
  h1.h4 { font-size: 1.15rem; }
}

.app-sidebar {
  --sidebar-width: 248px;
  /* Bootstrap's offcanvas-* variants default --bs-offcanvas-width to
     400 px which overflows on a 360-375 px phone. Override it so the
     drawer never exceeds the viewport. The selector below was wrong
     (.app-sidebar.offcanvas never matched our .offcanvas-lg element);
     setting --bs-offcanvas-width on .app-sidebar applies via the
     `width: var(--bs-offcanvas-width)` rule Bootstrap already ships. */
  --bs-offcanvas-width: 280px;
  background-color: var(--sd-sidebar-bg);
  color: var(--sd-sidebar-fg);
  border-right: 1px solid var(--sd-sidebar-border);
}

@media (min-width: 992px) {
  .app-sidebar {
    width: var(--sidebar-width);
    min-height: 100vh;
    position: sticky;
    top: 0;
    align-self: flex-start;
  }
}

.app-sidebar .offcanvas-header { border-bottom: 1px solid var(--sd-sidebar-border); }

/* Section headings (Customers / Insights / Administration). */
.app-sidebar .text-uppercase {
  color: var(--sd-sidebar-section) !important;
  font-weight: 600;
  letter-spacing: 0.08em;
  font-size: 0.7rem;
}

/* Nav items: pill-style with subtle hover and accent active state. */
.app-sidebar .nav-link {
  border-radius: var(--sd-radius-sm);
  padding: 0.5rem 0.75rem;
  margin: 0.1rem 0.5rem;
  color: var(--sd-sidebar-fg) !important;
  font-weight: 500;
  font-size: 0.92rem;
  display: flex;
  align-items: center;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.app-sidebar .nav-link i.bi {
  font-size: 1rem;
  opacity: 1;
  margin-right: 0.65rem;
  color: var(--sd-sidebar-fg-muted);
}
.app-sidebar .nav-link:hover i.bi,
.app-sidebar .nav-link.active i.bi {
  color: inherit;
}

/* Mobile offcanvas close button: btn-close-white is correct against
   a dark sidebar; in light mode flip it back to the default dark X. */
:root:not([data-bs-theme="dark"]) .app-sidebar .btn-close-white {
  filter: none;
}

.app-sidebar .nav-link:hover,
.app-sidebar .nav-link:focus {
  background-color: var(--sd-sidebar-bg-hover);
  color: var(--sd-sidebar-fg-hover) !important;
}

/* Active item is a solid teal block with white text - no accent bar
   needed, the block itself is the marker. */
.app-sidebar .nav-link.active {
  background-color: var(--sd-sidebar-bg-active);
  color: var(--sd-sidebar-fg-active) !important;
}

/* ---- Topbar ----------------------------------------------------------- */

.app-topbar {
  background-color: var(--sd-topbar-bg) !important;
  color: var(--sd-topbar-fg) !important;
  border-bottom: 1px solid var(--sd-topbar-border);
  backdrop-filter: saturate(180%) blur(8px);
  -webkit-backdrop-filter: saturate(180%) blur(8px);
  z-index: 1030;
}

.app-topbar > div { min-height: 56px; }

.app-topbar-btn {
  background-color: transparent;
  border: 1px solid transparent;
  color: var(--sd-topbar-fg);
  padding: 0.35rem 0.7rem;
  border-radius: var(--sd-radius-sm);
  transition: background-color 0.12s ease, border-color 0.12s ease;
  font-weight: 500;
}

.app-topbar-btn:hover,
.app-topbar-btn:focus,
.app-topbar-btn[aria-expanded="true"] {
  background-color: var(--sd-topbar-btn-hover);
  color: var(--sd-topbar-fg);
  border-color: var(--sd-topbar-border);
}

.app-topbar-btn .bi { font-size: 1.05rem; line-height: 1; }

/* ---- Buttons ---------------------------------------------------------- */

.btn {
  border-radius: var(--sd-radius-sm);
  font-weight: 500;
  transition: background-color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease, transform 0.05s ease;
}
.btn:active { transform: translateY(0.5px); }

.btn-primary {
  --bs-btn-bg: var(--sd-accent);
  --bs-btn-border-color: var(--sd-accent);
  --bs-btn-hover-bg: var(--sd-accent-hover);
  --bs-btn-hover-border-color: var(--sd-accent-hover);
  --bs-btn-active-bg: var(--sd-accent-hover);
  --bs-btn-active-border-color: var(--sd-accent-hover);
  --bs-btn-focus-shadow-rgb: 15, 118, 110;
  box-shadow: var(--sd-shadow-sm);
}
/* Dark mode's accent is a bright teal - white text can't hold contrast on
   it, so primary buttons flip to dark ink there. */
[data-bs-theme="dark"] .btn-primary {
  --bs-btn-color: #08211d;
  --bs-btn-hover-color: #08211d;
  --bs-btn-active-color: #08211d;
  --bs-btn-focus-shadow-rgb: 47, 191, 169;
}

.btn-outline-secondary {
  --bs-btn-color: var(--sd-text);
  --bs-btn-border-color: var(--sd-border);
  --bs-btn-hover-bg: var(--sd-surface-muted);
  --bs-btn-hover-border-color: var(--sd-border);
  --bs-btn-hover-color: var(--sd-text);
}

.btn-link {
  --bs-btn-color: var(--sd-accent);
  --bs-btn-hover-color: var(--sd-accent-hover);
}

/* ---- Forms ------------------------------------------------------------ */

.form-control,
.form-select {
  border-radius: var(--sd-radius-sm);
  border-color: var(--sd-border);
  background-color: var(--sd-surface);
  color: var(--sd-text);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.form-control:focus,
.form-select:focus {
  border-color: var(--sd-accent);
  box-shadow: 0 0 0 3px var(--sd-accent-ring);
}
.form-label { font-weight: 500; font-size: 0.92rem; }
.form-text { color: var(--sd-text-muted); }

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

.card {
  background-color: var(--sd-surface);
  border: 1px solid var(--sd-border);
  border-radius: var(--sd-radius);
  box-shadow: var(--sd-shadow-sm);
}
.card .card-header {
  background-color: transparent;
  border-bottom: 1px solid var(--sd-border);
  font-weight: 600;
}
.card.shadow-sm { box-shadow: var(--sd-shadow) !important; }
a:hover > .card {
  box-shadow: 0 0 0 2px var(--sd-accent-ring), var(--sd-shadow) !important;
  border-color: var(--sd-accent) !important;
}

/* ---- List groups (settings index, dashboards) ------------------------- */

.list-group {
  border-radius: var(--sd-radius);
  overflow: hidden;
  border: 1px solid var(--sd-border);
  background-color: var(--sd-surface);
}
.list-group-item {
  background-color: transparent;
  border-color: var(--sd-border);
  padding: 0.85rem 1.1rem;
}
.list-group-item-action:hover,
.list-group-item-action:focus {
  background-color: var(--sd-surface-muted);
}
.list-group-item.active {
  background-color: var(--sd-accent-soft);
  border-color: transparent;
  color: var(--sd-text);
}

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

.table {
  --bs-table-bg: transparent;
  color: var(--sd-text);
}
.table thead th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sd-text-muted);
  border-bottom: 1px solid var(--sd-border);
  font-weight: 600;
  padding: 0.65rem 0.75rem;
}
.table tbody td {
  border-bottom: 1px solid var(--sd-border);
  padding: 0.7rem 0.75rem;
  vertical-align: middle;
}
.table-hover tbody tr:hover {
  background-color: var(--sd-surface-muted);
}

/* ---- Badges / chips --------------------------------------------------- */

.badge {
  font-weight: 600;
  font-size: 0.72rem;
  padding: 0.32em 0.6em;
  border-radius: 999px;
  letter-spacing: 0.02em;
}

/* Status chips (custom palette - soft tinted backgrounds). Open carries
   the teal accent; resolved uses a deliberately yellower green so the two
   stay apart at a glance. */
.status-new       { background-color: rgba(120, 130, 124, 0.18); color: #4b544e; }
.status-open      { background-color: rgba(15, 118, 110, 0.16);  color: #0f766e; }
.status-awaiting  { background-color: rgba(217, 119, 6, 0.18);   color: #92400e; }
.status-resolved  { background-color: rgba(22, 163, 74, 0.16);   color: #15803d; }
.status-closed    { background-color: rgba(43, 54, 48, 0.16);    color: #2b3630; }
[data-bs-theme="dark"] .status-new      { color: #c8d0ca; }
[data-bs-theme="dark"] .status-open     { color: #7fd8c9; }
[data-bs-theme="dark"] .status-awaiting { color: #fcd34d; }
[data-bs-theme="dark"] .status-resolved { color: #86efac; }
[data-bs-theme="dark"] .status-closed   { color: #c8d0ca; }

/* Bootstrap's `.bg-light` / `.text-bg-light` paint a fixed light-grey
   background. Under the dark theme the surrounding text stays light, so a
   `.bg-light` card (e.g. a "system" entry in a ticket's Activity feed)
   becomes light-on-light and unreadable, and `.text-bg-light` chips glare.
   Repoint both at the theme's muted surface with the theme text colour so
   they stay legible in dark mode. Light mode is untouched. */
[data-bs-theme="dark"] .bg-light,
[data-bs-theme="dark"] .text-bg-light {
  background-color: var(--sd-surface-muted) !important;
  color: var(--sd-text) !important;
}
/* `.table-light` headers/rows have the same problem. */
[data-bs-theme="dark"] .table-light,
[data-bs-theme="dark"] .table-light > th,
[data-bs-theme="dark"] .table-light > td {
  --bs-table-bg: var(--sd-surface-muted);
  --bs-table-color: var(--sd-text);
  color: var(--sd-text);
}

/* ---- Alerts ----------------------------------------------------------- */

.alert {
  border-radius: var(--sd-radius);
  border: 1px solid var(--sd-border);
  background-color: var(--sd-surface);
}
.alert-info {
  border-color: rgba(15, 118, 110, 0.3);
  background-color: var(--sd-accent-soft);
  color: var(--sd-text);
}
.alert-danger {
  border-color: rgba(220, 38, 38, 0.3);
  background-color: rgba(220, 38, 38, 0.08);
  color: #991b1b;
}
[data-bs-theme="dark"] .alert-danger { color: #fecaca; }

/* ---- Dropdown menus --------------------------------------------------- */

.dropdown-menu {
  border-radius: var(--sd-radius);
  border: 1px solid var(--sd-border);
  background-color: var(--sd-surface);
  box-shadow: var(--sd-shadow-lg);
  padding: 0.35rem;
}
.dropdown-item {
  border-radius: var(--sd-radius-sm);
  padding: 0.45rem 0.7rem;
  color: var(--sd-text);
}
.dropdown-item:hover,
.dropdown-item:focus {
  background-color: var(--sd-surface-muted);
}
.dropdown-divider {
  border-color: var(--sd-border);
  margin: 0.35rem 0;
}

/* ---- Modals / offcanvas ---------------------------------------------- */

.modal-content,
.offcanvas {
  border-radius: var(--sd-radius-lg);
  border: 1px solid var(--sd-border);
}
.offcanvas-end, .offcanvas-start { border-radius: 0; }
.offcanvas { background-color: var(--sd-surface); color: var(--sd-text); }
/* `.app-sidebar.offcanvas` never matched our element (the class is
   `.offcanvas-lg`); the sidebar's palette is already set on
   `.app-sidebar` itself above. */

/* ---- Footer ----------------------------------------------------------- */

footer {
  border-top: 1px solid var(--sd-border) !important;
  background-color: transparent !important;
  color: var(--sd-text-muted) !important;
}

/* ---- Long-form content (KB / ticket bodies) -------------------------- */

.prose img { max-width: 100%; height: auto; }
.prose pre {
  background: var(--sd-surface-muted);
  padding: 0.85rem;
  border-radius: var(--sd-radius-sm);
  overflow-x: auto;
}
.prose code {
  background: var(--sd-surface-muted);
  padding: 0.1rem 0.35rem;
  border-radius: 0.25rem;
}

/* ---- Charts (server-rendered SVG) ------------------------------------ */
/* Geometry is emitted as SVG attributes by the view; only colours/fonts
   live here so the charts follow the theme and stay CSP-clean (no inline
   styles). */
.sd-chart {
  /* The <svg> carries explicit width/height attributes for an intrinsic
     size; cap it to the container and scale height proportionally so it
     never collapses to zero or overflows on mobile. */
  max-width: 100%;
  height: auto;
  overflow: visible;
}
/* Bars are filled via an SVG gradient (fill="url(#sd-bar-grad)" attribute,
   defined per-chart in reports/_chart_defs.html); no fill here so the
   gradient shows. They gently fade on hover for a touch of interactivity. */
.sd-chart-bar   { transition: opacity .15s ease; cursor: default; }
.sd-chart-bar:hover { opacity: .82; }
.sd-chart-track { fill: var(--sd-surface-muted); }
.sd-chart-axis  { stroke: var(--sd-border); stroke-width: 1; }
.sd-chart-label { fill: var(--sd-text); font-size: 12px; font-weight: 500; }
.sd-chart-value { fill: var(--sd-text-muted); font-size: 11px; font-weight: 700; }
.sd-chart-axislabel { fill: var(--sd-text-muted); font-size: 10px; }

/* ---- Metric meters (System status) ----------------------------------- */
/* Horizontal usage bars rendered as SVG so width comes from a geometry
   attribute (CSP-clean) and colour from these theme-aware classes. */
.metric-meter   { display: block; border-radius: 0.25rem; overflow: hidden; }
.metric-track   { fill: var(--sd-surface-muted); }
.metric-fill    { fill: var(--sd-accent); }
.metric-warn    { fill: var(--bs-warning, #f59e0b); }
.metric-danger  { fill: var(--bs-danger, #dc2626); }
.metric-threshold-input { max-width: 7rem; }

/* Preserve newlines without an inline style (CSP-clean). */
.text-preline { white-space: pre-wrap; }

/* Intro text under a page title (e.g. the project description): keep the
   line length readable instead of spanning the full page width. */
.sd-page-intro { max-width: 72ch; }

/* ---- Stacking tables (projects detail on small screens) --------------- */
/* Below lg a table whose cells are form controls (the inline-edit task
   list: six columns of inputs) is unusable - every control gets a sliver
   of width. Stack each row into a bordered mini-card instead: cells
   become full-width rows labelled via their data-label attribute (CSS
   renders it, so desktop markup is untouched). */
@media (max-width: 991.98px) {
  .sd-stack-table thead { display: none; }
  .sd-stack-table tbody { display: block; }
  .sd-stack-table tbody tr {
    display: block;
    position: relative;
    border: 1px solid var(--sd-border);
    border-radius: var(--sd-radius-sm);
    padding: 0.5rem 2.1rem 0.5rem 0.75rem;
    margin-bottom: 0.6rem;
    background: var(--sd-surface);
  }
  /* display:block above beats the UA's [hidden] rule; restate it so
     folded-away rows (the per-task log-time row) stay hidden on mobile. */
  .sd-stack-table tbody tr[hidden] { display: none; }
  /* Collapsed by default: only the primary cell (title / date /
     description) shows, one compact line per row; tapping the row
     (project_detail.js) reveals the rest. Rows with a single cell
     (empty-state messages) always show. */
  .sd-stack-table tbody td { display: none; }
  .sd-stack-table tbody td.sd-primary,
  .sd-stack-table tbody td:only-child,
  .sd-stack-table tbody tr.sd-open td {
    display: block;
    width: 100%;
    border: 0;
    padding: 0.3rem 0;
  }
  /* Chevron affordance, flipping when open. */
  .sd-stack-table tbody tr::after {
    content: "";
    position: absolute;
    top: 1.05rem;
    right: 0.9rem;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--sd-text-muted);
    border-bottom: 2px solid var(--sd-text-muted);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
  }
  .sd-stack-table tbody tr.sd-open::after { transform: rotate(225deg); top: 1.2rem; }
  .sd-stack-table tbody tr:has(td:only-child)::after { display: none; }
  .sd-stack-table tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--sd-text-muted);
    margin-bottom: 0.15rem;
  }
  /* The always-visible primary cell needs no caption while collapsed. */
  .sd-stack-table tbody tr:not(.sd-open) td.sd-primary::before { display: none; }
  /* Action buttons: left-aligned in the stacked card. */
  .sd-stack-table tbody td.text-end { text-align: left !important; }
}

/* ---- Donut chart (project budget) ------------------------------------ */
/* Geometry (dasharray/offset) comes from SVG attributes computed server-
   side; only colours live here so the chart stays CSP-clean and follows
   the theme. Segment indexes: 0 labour, 1 expenses, 2 remaining, 3 over.
   Remaining is a slate blue (not green) so it can't blur into the teal
   accent; keep in sync with BUDGET_COLORS in project_report_pdf.py. */
.sd-donut { max-width: 100%; height: auto; }
.sd-donut-track { stroke: var(--sd-surface-muted); }
.sd-seg-0 { stroke: var(--sd-accent); }
.sd-seg-1 { stroke: #d97706; }
.sd-seg-2 { stroke: #52718a; }
.sd-seg-3 { stroke: #dc2626; }
.sd-chip {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 3px;
}
.sd-chip-0 { background: var(--sd-accent); }
.sd-chip-1 { background: #d97706; }
.sd-chip-2 { background: #52718a; }
.sd-chip-3 { background: #dc2626; }

/* Progress bar (projects). Width comes from a class, not an inline style,
   so it stays CSP-clean; buckets are rounded to 10%. */
.sd-progress {
  height: 6px;
  background: var(--sd-surface-muted);
  border-radius: 999px;
  overflow: hidden;
}
.sd-progress-bar { height: 100%; background: var(--sd-accent); border-radius: 999px; }
.sd-w-00 { width: 0; }
.sd-w-10 { width: 10%; }
.sd-w-20 { width: 20%; }
.sd-w-30 { width: 30%; }
.sd-w-40 { width: 40%; }
.sd-w-50 { width: 50%; }
.sd-w-60 { width: 60%; }
.sd-w-70 { width: 70%; }
.sd-w-80 { width: 80%; }
.sd-w-90 { width: 90%; }
.sd-w-100 { width: 100%; }

/* Small sizing caps that used to be inline styles (CSP-clean). */
.app-username { max-width: 14rem; }   /* topbar name, truncated */
.totp-qr      { max-width: 220px; }   /* TOTP enrolment QR code */

/* ---- Login page polish ------------------------------------------------ */

.login-screen {
  min-height: calc(100vh - 56px);
  display: flex;
  align-items: center;
  background:
    radial-gradient(circle at 20% 20%, rgba(15, 118, 110, 0.10), transparent 50%),
    radial-gradient(circle at 80% 60%, rgba(82, 113, 138, 0.08), transparent 50%),
    var(--sd-body-bg);
}
.login-screen .card { box-shadow: var(--sd-shadow-lg); }

/* ---- In-app rendered manuals ----------------------------------------- */

.help-doc { max-width: 72ch; line-height: 1.65; color: var(--sd-text); }
.help-doc h1 { font-size: 1.7rem; margin-top: 0; }
.help-doc h2 {
  font-size: 1.3rem;
  margin-top: 2.25rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--sd-border);
}
.help-doc h3 { font-size: 1.1rem; margin-top: 1.5rem; }
.help-doc p, .help-doc ul, .help-doc ol { margin-bottom: 1rem; }
.help-doc code {
  background: var(--sd-surface-muted);
  padding: 0.12rem 0.35rem;
  border-radius: 0.25rem;
  font-size: 0.88em;
}
.help-doc pre {
  background: var(--sd-surface-muted);
  padding: 0.85rem;
  border-radius: var(--sd-radius-sm);
  overflow-x: auto;
}
.help-doc pre code { background: transparent; padding: 0; }
.help-doc table { width: 100%; margin-bottom: 1.25rem; }
.help-doc table th,
.help-doc table td {
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--sd-border);
  vertical-align: top;
}
.help-doc table th {
  text-align: left;
  background: var(--sd-surface-muted);
  font-weight: 600;
  font-size: 0.88rem;
}
.help-doc blockquote {
  border-left: 3px solid var(--sd-accent);
  padding: 0.25rem 0.9rem;
  color: var(--sd-text-muted);
  margin: 1rem 0;
  background: var(--sd-accent-soft);
  border-radius: 0 var(--sd-radius-sm) var(--sd-radius-sm) 0;
}
.help-doc hr { margin: 1.75rem 0; border-color: var(--sd-border); }
.help-doc a { color: var(--sd-accent); }
