/* SLEEP BETTER — admin panel stylesheet.
   Served at /admin/static/admin.css (StaticFiles mount in app/main.py), linked from
   templates/admin/base.html. Relocated here from base.html's inline <style> block so
   the admin panel no longer needs a per-page style element; inline style= attributes
   in the admin templates were folded into the component/utility classes below.

   Palette and font are deliberately unchanged (neutral blue, system-ui) — this is a
   tidy-up, not a rebrand. WCAG-AA contrast notes are inline where a value was tuned. */

:root {
  --bg: #f5f6f8;
  --card: #fff;
  --ink: #1f2933;
  --muted: #5b6472;      /* darkened from #6b7280 (4.47:1) → clears WCAG-AA 4.5:1 on --bg */
  --line: #e5e7eb;
  --accent: #2b6cb0;
  --accent-ink: #fff;
  --danger: #c0392b;
  --ok: #276749;         /* darkened from #2f855a (4.33:1) → clears WCAG-AA on the .pill.ok mint */

  /* Spacing + radius scale — replaces the ad-hoc per-element values that used to
     live in inline style= attributes, so padding/margins stay consistent. */
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: .75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.75rem;
  --radius-sm: 6px;
  --radius-md: 8px;
  --row-hover: #f9fafb;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--ink);
  background: var(--bg);
}

/* --- Top bar ------------------------------------------------------------- */
header.topbar {
  background: var(--card);
  border-bottom: 1px solid var(--line);
  padding: var(--space-3) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;                 /* nav + brand + session wrap instead of overflowing */
}
header.topbar a { color: var(--ink); text-decoration: none; font-weight: 600; }
/* Brand label — a non-interactive heading, not a link (the dashboard is the default
   landing and is intentionally not reachable from the banner). */
header.topbar .brand { color: var(--ink); font-weight: 600; }
header.topbar nav { display: flex; flex-wrap: wrap; gap: 0 var(--space-4); }
header.topbar nav a { font-weight: 500; color: var(--muted); }
header.topbar nav a:hover { color: var(--accent); }
/* Active tab (X1): accent colour + weight + an underline marker; aria-current="page"
   carries the same state to assistive tech. Applies to both nav levels. */
header.topbar nav a.active,
nav.subnav a.active { color: var(--accent); font-weight: 600; }
header.topbar nav a.active { box-shadow: inset 0 -2px 0 var(--accent); }
header.topbar .spacer { flex: 1; }
/* Account cluster link (Change password, CP1) — sits with the study_id + Log out. */
header.topbar .account-link { font-weight: 500; color: var(--muted); }
header.topbar .account-link:hover { color: var(--accent); }

/* --- CMS secondary nav (C1) --------------------------------------------- */
/* A thin strip of plain links below the topbar, shown only inside the CMS section. */
nav.subnav {
  background: var(--card);
  border-bottom: 1px solid var(--line);
  padding: var(--space-2) var(--space-5);
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-4);
}
nav.subnav a { font-weight: 500; color: var(--muted); text-decoration: none; }
nav.subnav a:hover { color: var(--accent); }
nav.subnav a.active { box-shadow: inset 0 -2px 0 var(--accent); }

/* --- Layout -------------------------------------------------------------- */
main { max-width: 980px; margin: var(--space-6) auto; padding: 0 var(--space-5); }
h1 { font-size: 1.4rem; margin: 0 0 var(--space-4); }

/* Card section headings (were <h1 style="font-size:1.1rem"> inline). */
.section-title { font-size: 1.1rem; margin: 0 0 var(--space-4); }
/* A heading that follows other content needs air above it; a card's leading heading does not. */
.section-title:not(:first-child) { margin-top: var(--space-6); }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}
/* Highlight card (e.g. the one-time temporary-password panel). */
.card.highlight { border-color: #f0c36d; background: #fffbea; }
/* Centered narrow card for the sign-in / change-password screens. */
.card.card-auth { max-width: 420px; margin-left: auto; margin-right: auto; margin-top: 2.5rem; }

/* --- Tables -------------------------------------------------------------- */
/* Wrap every list table in <div class="table-wrap"> so wide tables scroll
   horizontally on narrow screens instead of breaking the page layout. */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
th { color: var(--muted); font-size: .8rem; text-transform: uppercase; letter-spacing: .03em; }
tbody tr:hover { background: var(--row-hover); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Compact tables fill the whole card block (client request). Column widths are
   auto-distributed, NOT forced to 1% on the numeric columns — that dumped every
   spare pixel into the first column and made it read absurdly wide. The numeric
   columns get a modest shared width so the leftover space is spread across the
   table rather than piled into the label column; numbers stay right-aligned and
   on one line. */
table.compact { width: 100%; }
table.compact td.num, table.compact th.num { width: 9rem; white-space: nowrap; }
/* Quiz-by-week has a short first column ("Week"), unlike per-module's long page
   titles, so the label column would otherwise hog the slack and leave a big blank.
   Pin Week narrow and let the three metric columns share the remaining width evenly
   (table-layout:fixed), keeping the table full-width without the empty gap. */
table.compact.quiz-weeks { table-layout: fixed; }
table.compact.quiz-weeks th:first-child, table.compact.quiz-weeks td:first-child { width: 6rem; }
table.compact.quiz-weeks td.num, table.compact.quiz-weeks th.num { width: auto; }
/* Thicker rule under a user's data row, above its inline profile-edit row. */
td.row-divider { border-bottom: 2px solid var(--line); }

/* --- Forms --------------------------------------------------------------- */
label { display: block; font-size: .85rem; color: var(--muted); margin: var(--space-3) 0 var(--space-1); }
input, select, textarea {
  width: 100%;
  padding: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font: inherit;
  background: #fff;
}
textarea { min-height: 5rem; resize: vertical; }
textarea.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* Two-column create/edit form grid; collapses to one column when narrow. */
.form-2col { display: grid; gap: var(--space-3); grid-template-columns: repeat(2, 1fr); }
/* Inline filter/action rows (label+input+button on one wrapping line). */
.form-inline { display: flex; gap: var(--space-3); align-items: end; flex-wrap: wrap; }
.form-inline label { margin-top: 0; }
/* Zero-height full-width flex item that forces a deterministic line break inside a
   .form-inline row (everything after it wraps to the next line). */
.form-break { flex-basis: 100%; height: 0; margin: 0; }
.field-narrow { width: 8rem; }
.input-auto { width: auto; }
.self-end { align-self: end; }
/* Checkbox + its label on one baseline. */
.checkbox-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  font-size: .9rem;
  color: var(--ink);
}

/* Native <details> disclosure summary (U2 profile editor) — a clickable affordance
   styled as an accent link, no JavaScript. */
summary { cursor: pointer; color: var(--accent); font-weight: 500; width: max-content; }
details[open] > summary { margin-bottom: var(--space-3); }

/* Button/link row under a form or table (Save/Cancel, pager). */
.toolbar { margin-top: var(--space-4); display: flex; gap: var(--space-4); align-items: center; flex-wrap: wrap; }

/* --- Buttons ------------------------------------------------------------- */
button, .btn {
  display: inline-block;
  border: 0;
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  background: var(--accent);
  color: var(--accent-ink);
  text-decoration: none;
}
button:hover, .btn:hover { filter: brightness(0.95); }
button.secondary, .btn.secondary { background: #e2e8f0; color: var(--ink); }
button.danger, .btn.danger { background: var(--danger); color: #fff; }
form.inline { display: inline; }

/* --- Stats / grid / pills / flashes -------------------------------------- */
.grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
/* Fixed 4-column stat grid for blocks whose tile count divides evenly by 4 (the
   participant cohort row and the 8-tile Engagement summary) so rows are balanced
   instead of leaving a lopsided short last row. Collapses to 2 then 1 column — both
   still even — on narrower viewports. */
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 760px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 440px) { .grid-4 { grid-template-columns: 1fr; } }
.stat { text-align: center; }
.stat b { display: block; font-size: 1.8rem; }
.muted { color: var(--muted); }
.subtitle { margin-top: 0; }                 /* muted lead paragraph under a section title */
.count-note { font-size: 1rem; }             /* the "(N entries)" beside a heading */
.code-lg { font-size: 1.1rem; }              /* emphasised inline <code> (temp password) */
.pill { font-size: .78rem; padding: .1rem var(--space-2); border-radius: 999px; }
.pill.ok { background: #e6fffa; color: var(--ok); }
.pill.off { background: #fdecea; color: var(--danger); }
.flash { padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); margin-bottom: var(--space-4); }
.flash.error { background: #fdecea; color: var(--danger); }
.flash.ok { background: #e6fffa; color: var(--ok); }

/* --- Hover/focus tooltips (CSS only — no JS, CSP script-src 'self') ------- */
/* A .tip element shows its data-tip text as a bubble on hover AND keyboard focus.
   aria-label (set in the macro) carries the same text for screen readers, since
   ::after content is not announced. Positioned below the trigger so it is not
   clipped by a table-wrap's vertical overflow. */
.tip {
  position: relative;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  cursor: help;
}
.tip::after {
  content: attr(data-tip);
  position: absolute;
  left: 0;
  top: calc(100% + 6px);
  z-index: 30;
  width: max-content;
  max-width: 18rem;
  background: var(--ink);
  color: #fff;
  font: 400 .8rem/1.45 system-ui, -apple-system, sans-serif;
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
  padding: .45rem .6rem;
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
  /* Hidden with display:none, NOT opacity/visibility. A hidden but still-laid-out
     absolute bubble (visibility:hidden) keeps its box in the flow, so a wide bubble
     near a table's right edge expands the .table-wrap scroll region and shows a
     phantom horizontal scrollbar even though the cells are narrow. display:none
     removes it from layout entirely; it only exists while hovered/focused. */
  display: none;
  pointer-events: none;
}
/* Data-cell tips (value_tip) open upward so the bubble is never clipped by the
   scrollable table wrapper on the last row (overflow-x:auto forces overflow-y:auto,
   so a downward bubble past the wrapper's bottom edge would be cut off). */
.tip.tip-up::after { top: auto; bottom: calc(100% + 6px); }
/* Right-anchor the bubble (extends leftward from the trigger's right edge) so a
   tooltip on the rightmost column of a wide .table-wrap is not clipped by the same
   overflow that forces horizontal scroll. Orthogonal to tip-up (vertical). */
.tip.tip-end::after { left: auto; right: 0; }
.tip:hover::after, .tip:focus::after, .tip:focus-visible::after { display: block; }

/* --- Accessible focus ring ---------------------------------------------- */
a:focus-visible, button:focus-visible, .btn:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
.tip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- Site-content field form ---------------------------------------------- */
/* One editable copy field: its label (with a "Modified" pill), its input, the help
   text, and the per-field restore button. The rule below separates fields visually
   so a long page of copy stays scannable. */
.field-block { padding: var(--space-3) 0; border-bottom: 1px solid var(--line); }
.field-block:last-of-type { border-bottom: 0; }
.field-block label { margin-bottom: 0; }
.field-block .pill { margin-left: var(--space-2); }
.field-note { margin: var(--space-1) 0 var(--space-2); font-size: .85rem; }
.field-default { display: block; font-style: italic; }
.field-blank { display: block; }

/* --- Responsive ---------------------------------------------------------- */
@media (max-width: 640px) {
  main { margin-top: var(--space-4); padding: 0 var(--space-4); }
  h1 { font-size: 1.25rem; }
  .card { padding: var(--space-4); }
  .form-2col { grid-template-columns: 1fr; }
  header.topbar { gap: var(--space-3); }
}

/* Admin accounts are staff, not study subjects: hide the participant-only fields of
   the Create-user form when Role = Admin. Pure CSS (:has) — the panel adds no
   JavaScript under script-src 'self'. Presentation only; services/accounts.py nulls
   both fields for admin roles and users_admin_no_participant_fields_chk enforces it,
   so a browser without :has() support merely shows two fields whose values are ignored. */
.form-2col:has(select[name="role"] option[value="admin"]:checked) .participant-only {
  display: none;
}
