/*
 * Cognition 360 Reporting — the one custom stylesheet (SPEC §3, §9).
 *
 * Pico CSS classless does typography, forms and base table styling. This file
 * does the app shell, the filter bar, the data table and the states.
 *
 * Design rules, from §9:
 *   white and light gray, with the Concept Technology palette carried by the
 *   custom properties below (Resources/Brand Guide/BRAND_GUIDE.md §4). Emerald
 *   anchors, Midnight Green does the interactive work, Gold is jewelry and is
 *   used twice on the whole app. Data tables stay neutral: this is a tool, not
 *   a brochure. No animations; no dark mode; responsive down to tablet, where
 *   the sidebar collapses at 1024px. Nobody uses this on a phone.
 *
 * Type is the system UI stack everywhere, headings included: a reporting page
 * is read, not admired, and the system face is the one the reader's machine
 * renders best. No web fonts, no @font-face, nothing fetched to draw text.
 *
 * The one moving thing in the app is the loading spinner, which has to move to
 * mean anything. It stops for prefers-reduced-motion.
 */

:root {
  /* ---- Concept Technology palette (BRAND_GUIDE.md §4) --------------------
   * The whole palette lives here and nowhere else; the Chart.js series colours
   * are read off these same properties at runtime, so a chart can never drift
   * from the page around it.
   *
   * Emerald is the anchor: the sidebar header and primary buttons. Midnight
   * Green is the friendlier sibling and does every interactive job on paper —
   * links, the current nav item, focus rings, chart series. Gold is jewelry,
   * never paint: it appears twice in this stylesheet, as the hairline under
   * the sidebar logo and the rule over the sign-in card. Sand and Stone are
   * the warm and cool neutrals. */
  --brand-emerald: #123138;
  --brand-emerald-dark: #0a1f24;
  --brand-midnight: #185960;
  --brand-midnight-dark: #0f3f44;
  --brand-gold: #ceb97c;
  --brand-sand: #e5e4db;
  --brand-stone: #bacacc;
  --brand-paper: #faf9f4;
  --brand-ink: #0b1f24;

  /* What each one is for. Everything below points at these three. */
  --brand-primary: var(--brand-emerald);
  --brand-primary-dark: var(--brand-emerald-dark);
  --brand-secondary: var(--brand-midnight);
  --brand-secondary-dark: var(--brand-midnight-dark);
  --brand-accent: var(--brand-gold);
  /* Midnight at 6% on white: the wash behind the current nav item and a
     hovered row. Light enough that a dense table still reads as white. */
  --brand-tint: #eef3f3;

  /* Ink on paper. Every one of these clears WCAG AA (4.5:1) as body text on
     both --surface and --page: 16.1, 6.0 and 4.6 respectively. */
  --ink: var(--brand-ink);
  --ink-soft: #4b5e63;
  --ink-faint: #5f6f73;

  --page: #f1f0e9;
  --surface: #ffffff;
  /* Table furniture. The guide would put Sand behind a table header; a dense
     40-column grid is where that stops being restful, so the header, the
     totals row and the zebra stripe take a plain light gray and the brand
     stays on the chrome around them. */
  --surface-alt: #f2f3f2;
  --surface-zebra: #fafaf9;
  /* The brand's hairline, rgba(18, 49, 56, .16) and .08, resolved over white
     so a border can also be used as a fill. */
  --line: #d9dedf;
  --line-soft: #ecefef;

  /* In-palette status (BRAND_GUIDE.md §4). The brand's success #2c8d96 reads
     3.9:1 on white, under AA, so it is darkened one step to 5.4:1; the brand's
     warning #b6a065 is 2.6:1 and is darkened to 4.8:1. Danger is the brand's
     own #8a3a3a at 7.6:1. */
  --danger: #8a3a3a;
  --danger-tint: #f6eeee;
  --warn: #7a6a3e;
  --warn-tint: #f7f4ea;

  /* Wide enough that a team name and both its frequency pills fit on one line
     (SPEC §9). "Business Operations  Weekly Monthly" is the widest row, and a
     sidebar that wraps every row back to two lines is the thing this nav was
     built to stop. */
  --sidebar-width: 20.5rem;
  --radius: 4px;

  /* §9 and James, Sept 2026: one plain system stack for everything, headings
     and KPI values included. Nothing is fetched to draw text. */
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;

}

/*
 * Pico overrides: light only, tighter spacing, our type scale, our palette.
 *
 * They sit on `:root:not([data-theme="dark"])` rather than `:root` because
 * that is the selector Pico declares its own light theme with, and a plain
 * `:root` loses to it however late it is in the cascade. That is why the
 * primary button was Pico's blue and not the brand's: the override never
 * applied. There is no dark theme here; the negation is only specificity.
 */
:root:not([data-theme="dark"]) {
  --pico-font-family: var(--font-ui);
  --pico-font-size: 100%;
  --pico-line-height: 1.45;
  --pico-border-radius: var(--radius);
  --pico-color: var(--ink);

  /* Emerald fills a primary button and darkens on press, the way the guide
     asks; Midnight Green is the text-and-link primary beside it. */
  --pico-primary: var(--brand-secondary);
  --pico-primary-background: var(--brand-primary);
  --pico-primary-border: var(--brand-primary);
  --pico-primary-inverse: var(--brand-paper);
  --pico-primary-hover: var(--brand-primary);
  --pico-primary-hover-background: var(--brand-primary-dark);
  --pico-primary-hover-border: var(--brand-primary-dark);
  --pico-primary-underline: rgba(24, 89, 96, 0.5);
  --pico-primary-hover-underline: rgba(18, 49, 56, 0.6);

  /* The focus ring: Midnight at 45%, wide enough to see on white. */
  --pico-primary-focus: rgba(24, 89, 96, 0.45);
  --pico-form-element-focus-color: var(--brand-secondary);

  --pico-spacing: 1rem;
  --pico-form-element-spacing-vertical: 0.4rem;
  --pico-form-element-spacing-horizontal: 0.6rem;
}

html {
  font-size: 15px;
  color-scheme: light;
}

body {
  margin: 0;
  padding: 0;
  /* Pico paints <html> white, so the page colour only reaches the bottom of the
     viewport if the body itself is that tall. Under 1024px the shell no longer
     claims a full viewport (the top bar takes its share), and without this a
     short page ends in a white band. */
  min-height: 100vh;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font-ui);
}

/* Headings, group titles and KPI values are the same face as the body, a shade
   tighter and darker. A reporting page earns its hierarchy from size and
   weight, not from a second typeface nobody asked to download. */
h1,
h2,
h3,
h4,
.kpi-value {
  font-family: var(--font-ui);
  color: var(--brand-emerald);
  letter-spacing: -0.01em;
}

/* The guide puts text links in Midnight Green and darkens them on hover;
   Emerald is reserved for buttons, which Pico takes from --pico-primary. */
a {
  color: var(--brand-secondary);
}

a:hover {
  color: var(--brand-primary);
}

/* ------------------------------------------------------------------ shell */

.shell {
  display: grid;
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  min-height: 100vh;
}

.sidebar {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--line);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

/* Emerald, because the guide anchors a layout on it, with the reversed
   horizontal lockup: the gold C and a white wordmark (James, Sept 23, 2026).
   The hairline under it is the guide's border on an emerald surface, gold at
   32%, and it is one of the two places gold appears in this app. */
.sidebar-header {
  background: var(--brand-primary);
  color: var(--brand-paper);
  padding: 1.1rem 1.1rem 0.9rem;
  border-bottom: 1px solid rgba(206, 185, 124, 0.32);
}

.sidebar-header a {
  color: var(--brand-paper);
  text-decoration: none;
  display: block;
}

/* Clear space: the lockup keeps its own cap height clear on every side, which
   here is the 1.1rem padding around it and the line below. The wordmark stops
   being legible somewhere under 10rem wide; this is 13rem and never shrinks,
   because the sidebar itself is a fixed 20.5rem. */
.sidebar-logo {
  display: block;
  width: 13rem;
  max-width: 100%;
  height: auto;
}

.sidebar-product {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  color: var(--brand-sand);
}

.sidebar-nav {
  flex: 1;
  padding: 0.75rem 0.6rem 1.5rem;
}

.sidebar-category {
  margin: 1rem 0 0.35rem;
  padding: 0 0.5rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.sidebar-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sidebar-nav li {
  margin: 0;
  padding: 0;
}

.sidebar-nav a {
  display: block;
  padding: 0.38rem 0.5rem;
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
  font-size: 0.92rem;
  border-left: 3px solid transparent;
}

.sidebar-nav a:hover {
  background: var(--line-soft);
}

.sidebar-nav a[aria-current="page"] {
  background: var(--brand-tint);
  border-left-color: var(--brand-secondary);
  color: var(--brand-secondary-dark);
  font-weight: 600;
}

/* ---- team rows (SPEC §9) -------------------------------------------------
 * One row per team: the name on the left, its frequencies as pills on the
 * right. Nine wrapped titles became six rows, and the word "Scorecard" is not
 * repeated on any of them. The pills wrap under the name only when the sidebar
 * is too narrow to hold both, which is why this is `wrap` and not a grid. */
.sidebar-nav ul.nav-teams {
  /* Pico gives a <nav>'s first and last list a negative horizontal margin for
     its own horizontal menus. This is a vertical one. */
  margin: 0;
}

.nav-teams .nav-team {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  column-gap: 0.35rem;
  row-gap: 0.1rem;
  padding: 0.15rem 0.35rem 0.15rem 0.35rem;
  border-left: 3px solid transparent;
  border-radius: var(--radius);
}

/* The team whose scorecard is open. A rule, not a fill: the filled pill beside
   it already says which one, and two highlights in one row is noise. */
.nav-teams .nav-team.is-current {
  border-left-color: var(--brand-secondary);
}

/* `margin-right: auto` rather than `justify-content: space-between` on the row:
   it pushes the pills to the right edge when they fit on the line, and leaves
   both the name and the pills flush left when they do not. Pico's own negative
   margin on a <nav> anchor is zeroed here, or the rows sit half a gap out. */
.nav-team-name {
  display: block;
  margin: 0 auto 0 0;
  padding: 0.25rem 0.1rem;
  border-left: 0;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}

/* Colour only, never bold: bold is wider, and on the longest name it pushed
   the pill onto a line of its own (James, Sept 23, 2026). The rule and the
   filled pill already say which row is open. */
.nav-team.is-current .nav-team-name {
  color: var(--brand-secondary-dark);
}

.nav-team-name:hover {
  background: none;
  color: var(--brand-secondary);
  text-decoration: underline;
}

/* A report that is not a team row, the TPG Beige Book: laid out exactly as a
   team row is, so its name lines up with the team names above it (James,
   Sept 23, 2026). The link keeps the sidebar's own padding and size, as the
   team names do; only Pico's pull to the left is undone. The current page gets
   the team rows' rule rather than a fill. */
.sidebar-nav ul.nav-reports {
  margin: 0;
}

.nav-reports .nav-report {
  display: flex;
  align-items: center;
  column-gap: 0.35rem;
  padding: 0.15rem 0.35rem;
  border-left: 3px solid transparent;
  border-radius: var(--radius);
}

.nav-reports .nav-report.is-current {
  border-left-color: var(--brand-secondary);
}

.sidebar-nav .nav-report a {
  margin: 0;
  font-weight: 500;
}

.sidebar-nav .nav-report a:hover {
  background: none;
  color: var(--brand-secondary);
  text-decoration: underline;
}

.sidebar-nav .nav-report a[aria-current="page"] {
  background: none;
  border-left-color: transparent;
  font-weight: 500;
  color: var(--brand-secondary-dark);
}

/* When a long team name does push the pills onto their own line, they sit
   flush under the name rather than out at the right edge: two lines that read
   as one row. */
.nav-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  padding-left: 0.1rem;
}

.sidebar-nav a.nav-pill {
  display: block;
  margin: 0;
  padding: 0.12rem 0.4rem;
  border: 1px solid var(--line);
  border-left: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.7rem;
  line-height: 1.3;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.sidebar-nav a.nav-pill:hover {
  border-color: var(--brand-secondary);
  color: var(--brand-secondary-dark);
  background: var(--brand-tint);
}

/* The report on screen: filled with the brand primary, so one glance down the
   sidebar answers "where am I". */
.sidebar-nav a.nav-pill.is-current,
.sidebar-nav a.nav-pill[aria-current="page"] {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: var(--brand-paper);
  /* The same weight as an unfilled pill, so filling it never widens it. */
  font-weight: 400;
}

.sidebar-empty {
  padding: 0 0.5rem;
  color: var(--ink-faint);
  font-size: 0.9rem;
}

.sidebar-footer {
  border-top: 1px solid var(--line);
  padding: 0.75rem 1.1rem 1rem;
}

.sidebar-user {
  margin: 0;
  font-weight: 600;
  font-size: 0.9rem;
}

.sidebar-role {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  color: var(--ink-faint);
  text-transform: capitalize;
}

.sidebar-footer form {
  margin: 0;
}

button.linkish {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  width: auto;
  color: var(--brand-secondary);
  font-size: 0.85rem;
  text-decoration: underline;
  cursor: pointer;
}

.content {
  padding: 1.5rem 1.75rem 4rem;
  min-width: 0;
}

/* SPEC §9: the narrow-width top bar. Nothing at all above 1024px, where the
   sidebar is always on screen; a slim sticky strip below it, in the normal
   flow, so the Reports button sits above the page instead of on top of it. */
.topbar {
  display: none;
}

.nav-toggle {
  display: none;
}

/* ------------------------------------------------------------- page header */

.page-header {
  margin-bottom: 1.1rem;
}

.page-header h1 {
  margin: 0 0 0.2rem;
  font-size: 1.5rem;
  line-height: 1.2;
}

/* The title line of a report: "<Team> Scorecard", with the frequency control
   beside it rather than under it. Wraps on a narrow window. */
.page-title-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem 0.75rem;
}

/* SPEC §9: Weekly | Monthly, beside the report title. One hairline box, one
   filled segment, no gaps between them: it reads as one control and not as two
   buttons that happen to be next to each other. */
.segmented {
  display: inline-flex;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}

/* Pico gives a <nav>'s anchors a negative margin for its own horizontal menus;
   these are segments of one control and sit flush. */
.segmented .segment {
  margin: 0;
  padding: 0.15rem 0.6rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
  text-decoration: none;
  border-left: 1px solid var(--line);
  white-space: nowrap;
}

.segmented .segment:first-child {
  border-left: 0;
}

.segmented .segment:hover {
  background: var(--brand-tint);
  color: var(--brand-secondary-dark);
}

.segmented .segment.is-current {
  background: var(--brand-primary);
  color: var(--brand-paper);
  font-weight: 600;
}

.page-subtitle {
  margin: 0;
  color: var(--ink-soft);
  max-width: 60rem;
}

.muted {
  color: var(--ink-faint);
}

/* --------------------------------------------------------------- home page */

/* SPEC §9: one card per team. Team name, one plain sentence, and a button per
   frequency. Six cards, and nothing else moved onto this page. */
.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.75rem;
}

.team-card {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand-secondary);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
}

.team-card-name {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.25;
}

.team-card-name a {
  color: var(--brand-secondary-dark);
  text-decoration: none;
}

.team-card-name a:hover {
  text-decoration: underline;
}

.team-card-line {
  margin: 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.team-card-frequencies {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.15rem 0 0;
  /* Pushes the buttons to the foot of a card whose sentence ran short, so a row
     of cards has one line of buttons rather than three. */
  margin-top: auto;
  padding-top: 0.35rem;
}

.frequency-button {
  display: inline-block;
  padding: 0.28rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--brand-secondary-dark);
  font-size: 0.85rem;
  text-decoration: none;
}

.frequency-button:hover {
  border-color: var(--brand-secondary);
  background: var(--brand-tint);
  color: var(--brand-secondary-dark);
}

.category {
  margin-bottom: 1.75rem;
}

.category-title {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 0.6rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--line);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 0.75rem;
}

.report-card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand-secondary);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  text-decoration: none;
  color: inherit;
}

.report-card:hover {
  border-color: var(--brand-secondary);
  background: var(--brand-tint);
}

.report-card h3 {
  margin: 0 0 0.3rem;
  font-size: 1rem;
  color: var(--brand-secondary-dark);
}

.report-card p {
  margin: 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* -------------------------------------------------------------- filter bar */

.filter-bar {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.7rem 0.8rem;
  margin-bottom: 1.25rem;
}

.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: flex-start;
}

.filter-chip {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-zebra);
  min-width: 11rem;
  max-width: 22rem;
  padding: 0.4rem 0.55rem;
}

.filter-chip.is-adhoc {
  border-left: 3px solid var(--brand-secondary);
}

/* A filter no section in this report applies. Shown, but never editable. */
.filter-chip.is-inert {
  background: var(--line-soft);
  border-style: dashed;
}

.filter-chip-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.filter-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  display: block;
  margin-bottom: 0.25rem;
}

.filter-note {
  font-size: 0.75rem;
  color: var(--ink-faint);
  margin: 0.25rem 0 0;
}

.filter-remove {
  background: none;
  border: 0;
  color: var(--ink-faint);
  font-size: 0.9rem;
  line-height: 1;
  padding: 0 0.15rem;
  width: auto;
  margin: 0;
  cursor: pointer;
}

.filter-remove:hover {
  color: var(--danger);
}

.filter-chip input[type="text"],
.filter-chip input[type="date"],
.filter-chip input[type="number"],
.filter-chip input[type="search"],
.filter-chip select {
  margin-bottom: 0.3rem;
  font-size: 0.88rem;
  height: auto;
}

.filter-chip .date-pair,
.filter-chip .range-pair {
  display: flex;
  gap: 0.35rem;
}

.option-list {
  max-height: 11rem;
  overflow-y: auto;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 0.3rem 0.4rem;
  background: var(--surface);
}

.option-list label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  margin: 0;
  padding: 0.12rem 0;
  cursor: pointer;
  line-height: 1.3;
}

.option-list input[type="checkbox"],
.option-list input[type="radio"] {
  margin: 0;
  width: 0.95rem;
  height: 0.95rem;
}

.option-empty {
  font-size: 0.82rem;
  color: var(--ink-faint);
  padding: 0.25rem 0;
  margin: 0;
}

.filter-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.75rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--line-soft);
  flex-wrap: wrap;
}

.filter-actions button {
  width: auto;
  margin: 0;
  padding: 0.35rem 0.9rem;
  font-size: 0.88rem;
}

.filter-actions .secondary {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink);
}

.add-filter {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.add-filter select {
  width: auto;
  min-width: 14rem;
  margin: 0;
  font-size: 0.85rem;
}

/* ----------------------------------------------------------------- section */

.section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 1.5rem;
}

.section-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}

.section-title {
  margin: 0;
  font-size: 1.1rem;
}

/* SPEC §5: the owner, on the section's own title line. Quieter than the metric
   name because it answers "is this my row", not "what is this". */
.section-owner {
  font-weight: 400;
  color: var(--ink-soft);
}

/* SPEC §5: the Strety category a run of sections sits under, drawn once where
   the group changes, so the page reads down the scorecard in Strety's order. */
.section-group {
  margin: 1.6rem 0 0.6rem;
}

.section-group:first-child {
  margin-top: 0;
}

.section-group-title {
  margin: 0;
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--brand-secondary);
}

/* The metrics under this heading that live somewhere else. Muted, because it
   is a footnote; present, because a scorecard missing four rows should say so */
.section-group-note {
  margin: 0.25rem 0 0;
  max-width: 78ch;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

/* SPEC §5: a Strety row this tool does not compute, kept in its scorecard
   position. One muted line, no card and no table: it is a marker in the
   sequence, not a number, and it must never be mistaken for one. */
.section-placeholder {
  margin: 0.35rem 0;
  /* Lined up with the section titles inside the cards, the header's 1rem plus
     the card's 1px border, rather than out at the page edge (James, Sept 23,
     2026: Proposal Revenue read as sitting in the wrong place). */
  padding: 0.35rem calc(1rem + 1px);
  font-size: 0.85rem;
  color: var(--ink-faint);
  border-bottom: 1px dashed var(--line);
}

.section-placeholder-title {
  font-weight: 600;
  color: var(--ink-soft);
}

/* SPEC §5: the section's own sentence, under its title. On a scorecard this is
   where the assumption behind the number lives, so it reads as prose. */
.section-description {
  margin: 0.2rem 0 0;
  max-width: 78ch;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.section-source {
  margin: 0.15rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

/* SPEC §5: the metric owner's own wording, quoted above the table. Quiet, but
   boxed and labelled, because it is somebody else's sentence and not ours: the
   whole point is that the owner can read it and check the logic under it is
   hers, rather than take our paraphrase on trust. */
.section-definition {
  margin: 0.45rem 0 0;
  max-width: 78ch;
  padding: 0.45rem 0.65rem;
  background: var(--surface-alt);
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand-secondary);
  border-radius: var(--radius);
}

.section-definition-label {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.section-definition-text {
  margin: 0.2rem 0 0;
  font-size: 0.84rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

/* SPEC §5: the fixed scope of a section. Never a control, always visible. */
.section-scope {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-soft);
  border-left: 3px solid var(--brand-secondary);
  padding-left: 0.45rem;
}

.section-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* SPEC §9: secondary. Columns, Filter rows and Export CSV are there when they
   are wanted and out of the way when they are not; the number is what the
   reader came for, and three dark buttons beside every section title compete
   with it. Quiet border, quiet label, brand colour only on hover. */
.section-toolbar button,
.section-toolbar summary {
  width: auto;
  margin: 0;
  padding: 0.28rem 0.65rem;
  font-size: 0.78rem;
  background: var(--surface-zebra);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  color: var(--ink-faint);
  cursor: pointer;
}

.section-toolbar button:hover,
.section-toolbar summary:hover {
  border-color: var(--brand-secondary);
  background: var(--surface);
  color: var(--brand-secondary-dark);
}

/* The Filter rows toggle, when it is on. Still quiet: it is a state, not an
   alert. */
.section-toolbar button[aria-pressed="true"] {
  border-color: var(--brand-secondary);
  background: var(--brand-tint);
  color: var(--brand-secondary-dark);
}

/* SPEC §9: the technical lines a section used to print under its title — the
   source view, the fixed scope, how many rows came back — folded into a native
   disclosure, closed. They answer "where does this come from", which is a
   question somebody asks once, not every week. */
.section-details {
  margin: 0.35rem 0 0;
  max-width: 78ch;
}

.section-details > summary {
  display: inline-block;
  list-style: none;
  font-size: 0.78rem;
  color: var(--ink-faint);
  cursor: pointer;
}

.section-details > summary::-webkit-details-marker {
  display: none;
}

.section-details > summary::before {
  content: "\203A\00a0";
}

.section-details[open] > summary::before {
  content: "\2039\00a0";
}

.section-details > summary:hover {
  color: var(--brand-secondary);
}

/* Pico dresses every summary as an accordion heading: darker text, a chevron
   floated after it and a gap under it when open. This one is a quiet line with
   its own arrow, so all three go (James, Sept 23, 2026). The extra class and
   :not([role]) are what it takes to outrank Pico's own selectors. */
.section .section-details > summary:not([role]),
.section .section-details[open] > summary:not([role]) {
  margin-bottom: 0;
  line-height: inherit;
  color: var(--ink-faint);
}

.section .section-details > summary:not([role]):hover {
  color: var(--brand-secondary);
}

.section-details > summary::after {
  display: none;
}

.section-details-body {
  margin: 0.3rem 0 0;
  padding-left: 0.75rem;
  border-left: 2px solid var(--line-soft);
}

.section-details-body p {
  margin: 0.15rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

.section-details-body p:first-child {
  margin-top: 0;
}

.section-body {
  padding: 0.9rem 1rem 1rem;
}

.section-note {
  margin: 0.4rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
  background: var(--line-soft);
  border-radius: var(--radius);
  padding: 0.3rem 0.5rem;
  display: inline-block;
}

/* ------------------------------------------------------------ column menu */

.column-menu {
  position: relative;
  /* Pico gives every <details> a bottom margin, which lifted Columns above
     the buttons beside it (James, Sept 23, 2026). */
  margin: 0;
}

/* Pico styles a summary as an accordion heading: darker text, a tighter line
   and a chevron. Here it is a button like its neighbours, so all three go. */
.section-toolbar .column-menu > summary:not([role]) {
  list-style: none;
  display: inline-block;
  margin-bottom: 0;
  line-height: inherit;
  color: var(--ink-faint);
}

/* Open, Pico would also push a gap under it, lifting it off the line. */
.section-toolbar .column-menu > summary:not([role]):hover,
.section-toolbar .column-menu[open] > summary:not([role]) {
  margin-bottom: 0;
  color: var(--brand-secondary-dark);
}

.column-menu > summary::-webkit-details-marker {
  display: none;
}

.column-menu > summary::after {
  display: none;
}

.column-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.25rem);
  z-index: 20;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 2px 8px rgba(28, 37, 48, 0.12);
  padding: 0.5rem 0.6rem;
  width: 15rem;
  max-height: 18rem;
  overflow-y: auto;
}

.column-menu-panel label {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.85rem;
  margin: 0;
  padding: 0.12rem 0;
  cursor: pointer;
}

/* ------------------------------------------------------------------ table */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

table.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  margin: 0;
  font-size: 0.85rem;
  background: var(--surface);
}

table.data-table th,
table.data-table td {
  padding: 0.35rem 0.6rem;
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
  text-align: left;
  vertical-align: top;
}

/* A column of sentences (column override `wrap`): wraps inside a readable width. */
table.data-table td.wrap {
  white-space: normal;
  min-width: 20rem;
  max-width: 34rem;
}

table.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-alt);
  border-bottom: 1px solid var(--line);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink-soft);
}

table.data-table thead tr.filter-row th {
  top: 2rem;
  padding: 0.2rem 0.35rem;
  background: var(--surface);
}

table.data-table tbody tr:nth-child(even) {
  background: var(--surface-zebra);
}

table.data-table tbody tr:hover {
  background: var(--brand-tint);
}

th.sortable {
  cursor: pointer;
  user-select: none;
}

th.sortable:hover {
  color: var(--brand-secondary-dark);
}

.sort-indicator {
  color: var(--brand-secondary);
  font-size: 0.7rem;
  margin-left: 0.25rem;
}

/* Specificity has to beat `table.data-table th, td` above, hence the prefix. */
table.data-table th.numeric,
table.data-table td.numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

table.data-table th.pinned,
table.data-table td.pinned {
  position: sticky;
  left: var(--pin-left, 0);
  z-index: 1;
  background: var(--surface);
  border-right: 1px solid var(--line);
}

table.data-table thead th.pinned {
  z-index: 3;
  background: var(--surface-alt);
}

table.data-table thead tr.filter-row th.pinned {
  background: var(--surface);
}

.column-filter {
  width: 100%;
  min-width: 5rem;
  margin: 0;
  padding: 0.12rem 0.3rem;
  font-size: 0.78rem;
  height: auto;
  border-radius: var(--radius);
}

.table-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.pager {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.pager button {
  width: auto;
  margin: 0;
  padding: 0.2rem 0.6rem;
  font-size: 0.82rem;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink);
}

.pager button:disabled {
  color: var(--ink-faint);
  border-color: var(--line-soft);
  cursor: default;
  opacity: 1;
}

.page-size {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.page-size select {
  width: auto;
  margin: 0;
  padding: 0.15rem 1.6rem 0.15rem 0.4rem;
  font-size: 0.82rem;
  height: auto;
}

/* ----------------------------------------------------------------- charts */

.charts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 1rem;
  margin-bottom: 1rem;
}

.chart-box {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 0.6rem 0.7rem;
}

.chart-title {
  margin: 0 0 0.4rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink-soft);
}

.chart-canvas-wrap {
  position: relative;
  height: 16rem;
}

/* ----------------------------------------------------------------- states */

.report-status,
.section-loading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
  padding: 0.75rem 0;
}

.spinner {
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--line);
  border-top-color: var(--brand-secondary);
  border-radius: 50%;
  display: inline-block;
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation: none;
  }
}

.error-box {
  background: var(--danger-tint);
  border: 1px solid #f3c2cb;
  border-left: 3px solid var(--danger);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  color: #7a0017;
  font-size: 0.88rem;
}

.error-box strong {
  display: block;
  margin-bottom: 0.2rem;
}

.truncation-banner {
  background: var(--warn-tint);
  border: 1px solid #efd9a8;
  border-left: 3px solid var(--warn);
  border-radius: var(--radius);
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
  font-size: 0.85rem;
  color: var(--warn);
}

.empty-state {
  background: var(--surface);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  text-align: center;
  color: var(--ink-soft);
}

.error-code {
  font-size: 2rem;
  font-weight: 700;
  color: var(--ink-faint);
  margin: 0 0 0.3rem;
}

.form-error {
  background: var(--danger-tint);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius);
  color: #7a0017;
  padding: 0.5rem 0.7rem;
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

/* ------------------------------------------------------------- login page */

.login-body {
  background: var(--page);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1rem;
}

/* The second and last place gold appears: the rule over the card, the guide's
   one accent per composition. */
.login-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--brand-accent);
  border-radius: var(--radius);
  padding: 1.5rem 1.75rem 1.25rem;
  width: 100%;
  max-width: 22rem;
}

.login-header {
  margin-bottom: 1.2rem;
}

/* Full colour on a white card, the treatment the guide asks for on paper.
   13rem wide, well over the point where the wordmark stops being legible, with
   its own cap height clear beneath it before the product name. */
.login-logo {
  display: block;
  width: 13rem;
  max-width: 100%;
  height: auto;
}

.login-brand {
  margin: 1.1rem 0 0;
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--brand-emerald);
}

.login-brand-sub {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.login-card label {
  font-size: 0.85rem;
  font-weight: 600;
}

.login-card button {
  margin-top: 0.5rem;
}

.login-note {
  margin: 1rem 0 0;
  font-size: 0.75rem;
  color: var(--ink-faint);
  text-align: center;
}

/* ------------------------------------------- Microsoft 365 sign-in (SPEC §6)
 *
 * The button is a link, because starting the flow is a GET. It is drawn in the
 * brand's own emerald rather than in Microsoft's grey box: this is Concept
 * Technology's app, and the four squares beside the wording are the only part
 * of the mark that has to be Microsoft's. Nothing is fetched to draw it; the
 * squares are an inline SVG in the template.
 */

.ms-button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.7rem 1rem;
  background: var(--brand-primary);
  color: #ffffff;
  border: 1px solid var(--brand-primary);
  border-radius: var(--radius);
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
}

.ms-button:hover,
.ms-button:focus {
  background: var(--brand-primary-dark);
  border-color: var(--brand-primary-dark);
  color: #ffffff;
  text-decoration: none;
}

/* The mark keeps its own colours on the emerald; a white square panel behind
   it would be a second shape on a one-button page. */
.ms-mark {
  flex: 0 0 auto;
  display: block;
}

/* The small way out, under either door: the password form under the button,
   and the way back to the button under the form. */
.login-alt {
  margin: 0.9rem 0 0;
  font-size: 0.8rem;
  text-align: center;
}

.login-alt a {
  color: var(--ink-soft);
}

/* ------------------------------------------------------- tablet and under */

@media (max-width: 1024px) {
  /* The top bar takes its own height out of the viewport, so the shell stops
     claiming a full one: a short page should not gain a scrollbar for it. */
  .shell {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }

  /* SPEC §9: a slim sticky strip, in the flow. The old button was
     `position: fixed` and sat on top of whatever the page began with. */
  .topbar {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    position: sticky;
    top: 0;
    z-index: 60;
    padding: 0.4rem 0.6rem;
    background: var(--brand-primary);
    border-bottom: 1px solid rgba(206, 185, 124, 0.32);
  }

  .topbar-title {
    font-size: 0.8rem;
    letter-spacing: 0.02em;
    color: var(--brand-sand);
  }

  .nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    width: auto;
    margin: 0;
    padding: 0.28rem 0.7rem;
    font-size: 0.85rem;
    background: var(--brand-primary-dark);
    color: var(--brand-paper);
    border: 1px solid rgba(206, 185, 124, 0.32);
    border-radius: var(--radius);
    cursor: pointer;
  }

  .nav-toggle-bars,
  .nav-toggle-bars::before,
  .nav-toggle-bars::after {
    display: block;
    width: 0.85rem;
    height: 2px;
    background: var(--brand-paper);
  }

  .nav-toggle-bars {
    position: relative;
  }

  .nav-toggle-bars::before,
  .nav-toggle-bars::after {
    content: "";
    position: absolute;
    left: 0;
  }

  .nav-toggle-bars::before {
    top: -4px;
  }

  .nav-toggle-bars::after {
    top: 4px;
  }

  /* The drawer. It is closed on load and stays closed until the Reports button
     is pressed: `display: none` here, `flex` only under `body.nav-open`, and
     the dimming that used to sit on the closed element moved in there with it,
     so a page can never open with the content greyed out behind a drawer
     nobody asked for. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--sidebar-width);
    z-index: 70;
    display: none;
  }

  body.nav-open .sidebar {
    display: flex;
    box-shadow: 0 0 0 100vmax rgba(28, 37, 48, 0.35);
  }

  .content {
    padding: 1.1rem 1rem 3rem;
  }

  .team-grid,
  .card-grid {
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  }

  .charts {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------------------------------------------- scorecard (SPEC §5, Sept 2026)
 *
 * Targets, KPI tiles and the totals row. Status is carried by a mark and a
 * border, never by colour alone: the marks are ● for met and ○ for missed, and
 * each one has an aria-label, so a scorecard read in greyscale or by a screen
 * reader says the same thing. Nothing here moves (§9).
 */

/* The brand's own status pair, not a stock green and red: the guide's in-palette
   success and danger, each darkened only as far as WCAG AA on white needs
   (5.4:1 and 7.6:1). The washes behind a marked cell are the same two hues at
   a few percent, so a dense table still reads as white and light gray rather
   than as a coloured grid. */
:root {
  --met: #25757d;
  --met-tint: #f1f6f6;
  --missed: #8a3a3a;
  --missed-tint: #f8f1f0;
}

/* SPEC §5 "Period picker": the one control a scorecard's filter bar leads with.
   A dropdown of real periods with an arrow either side; wider than the other
   chips, because "Sep 7 – Sep 13, 2026 (in progress)" has to fit. */
.filter-chip.is-period {
  border-left: 3px solid var(--brand-primary);
  min-width: 17rem;
}

.period-control {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.period-control .period-select {
  flex: 1 1 auto;
  min-width: 0;
}

.period-step {
  flex: 0 0 auto;
  width: 2rem;
  margin: 0;
  padding: 0.25rem 0;
  font-size: 0.8rem;
  line-height: 1;
  text-align: center;
}

/* The period line under the report title, and the one under a section title.
   Same words, same place, every section: what time span these numbers cover. */
.page-period {
  margin: 0 0 0.25rem;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--brand-secondary);
}

.section-period {
  margin: 0.2rem 0 0;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--brand-secondary);
}

.as-of {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.as-of label {
  margin: 0;
}

.as-of input {
  width: auto;
  margin: 0;
  padding: 0.25rem 0.4rem;
  font-size: 0.85rem;
}

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.1rem;
}

.kpi-tile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--line);
  border-radius: var(--radius);
  padding: 0.7rem 0.9rem 0.8rem;
}

.kpi-tile.is-met {
  border-top-color: var(--met);
}

.kpi-tile.is-missed {
  border-top-color: var(--missed);
}

.kpi-label {
  margin: 0;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
}

.kpi-value {
  margin: 0.2rem 0 0;
  font-size: 1.6rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.kpi-target {
  margin: 0.25rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

.kpi-status.met {
  color: var(--met);
}

.kpi-status.missed {
  color: var(--missed);
}

/* SPEC §15.8: today's reading, beside the number the period was frozen at and
 * only when the two differ. Muted and lighter than the figure it follows, so a
 * column still reads as a column and the eye lands on the frozen number. */
.cell-now {
  margin-left: 0.15rem;
  font-size: 0.78em;
  font-weight: 400;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* The line under a frozen table. It is the same quiet note style the ignored
 * filters use: something true of the table, not a warning about it. */
.frozen-note {
  margin-top: 0.55rem;
  max-width: 78ch;
}

/* A cell that carries a target. The mark sits after the number, right-aligned
 * with it, so a column of figures still reads as a column of figures. */
.cell-status {
  margin-left: 0.4rem;
  font-size: 0.7rem;
  vertical-align: 0.08em;
}

/* SPEC §9: what the marks mean, once per page, under the first table that has
 * any. Every mark also carries an aria-label, so this line is for the eye; the
 * screen reader has already been told. */
.status-legend {
  margin: 0.55rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

.status-legend .legend-met {
  color: var(--met);
}

.status-legend .legend-missed {
  color: var(--missed);
}

.status-legend .legend-gap {
  display: inline-block;
  width: 1.1rem;
}

table.data-table td.is-met {
  background: var(--met-tint);
}

table.data-table td.is-met .cell-status {
  color: var(--met);
}

table.data-table td.is-missed {
  background: var(--missed-tint);
}

table.data-table td.is-missed .cell-status {
  color: var(--missed);
}

/* SPEC §5 "Period picker": the row for the period the reader picked, and the
   row for a period that has not finished.

   The selected row is marked with a rule down its left edge rather than a wash,
   because the target marks already colour the cells and a second background
   would fight them. An open period is muted and says so in its own period cell:
   it carries no target mark at all, so nothing but the grey says "not yet". */
table.data-table tbody tr.is-selected-period td:first-child {
  box-shadow: inset 3px 0 0 var(--brand-secondary);
}

table.data-table tbody tr.is-selected-period td {
  font-weight: 600;
}

table.data-table tbody tr.is-open-period td {
  color: var(--ink-faint);
  font-style: italic;
}

.cell-open-period {
  font-size: 0.78em;
  font-style: normal;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* The totals row: pinned under the table, outside the paging. */
table.data-table tfoot tr.totals-row td {
  background: var(--surface-alt);
  border-top: 2px solid var(--line);
  font-weight: 600;
}

table.data-table tfoot tr.totals-row td.pinned {
  background: var(--surface-alt);
}

/* SPEC §5: a live snapshot says when "now" was. */
.section-snapshot {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  color: var(--warn);
}

/* The dashed target rule has no legend entry of its own; the caption names it. */
.chart-target {
  margin: 0 0 0.4rem;
  font-size: 0.76rem;
  color: var(--ink-faint);
}

.chart-target::before {
  content: "– – ";
  letter-spacing: -0.08em;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------------------
 * Snapshot history (SPEC §15)
 *
 * A live view with no history of its own carries three quiet controls: the
 * captured History chart above the section's own charts, an "As of" list of the
 * stored captures, and, for an admin, Capture now with its result inline.
 * ------------------------------------------------------------------------- */

.snapshot-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.snapshot-asof {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.snapshot-asof select {
  width: auto;
  margin: 0;
  padding: 0.25rem 1.6rem 0.25rem 0.5rem;
  font-size: 0.82rem;
  height: auto;
}

.section-toolbar .capture-now {
  white-space: nowrap;
}

/* Beside Capture now while a section has no stored captures: what the button
 * does, and that production does it every morning unasked. */
.capture-hint {
  font-size: 0.76rem;
  color: var(--ink-faint);
  max-width: 34rem;
}

/* A disabled "As of" picker is the empty state, not a broken control. */
.snapshot-asof select:disabled {
  color: var(--ink-faint);
  cursor: default;
}

.capture-result {
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.capture-result.is-ok {
  color: var(--met);
}

.capture-result.is-warn {
  color: var(--warn);
}

.capture-result.is-error {
  color: var(--danger);
}

/* A stored capture is not the live view, and the line under the title says so
 * in a different colour from the live one. */
.section-snapshot.is-stored {
  color: var(--brand-secondary-dark);
  font-weight: 600;
}

/* The history chart sits above the section's own charts, separated by a rule so
 * a reader can tell "what this has been" from "what this is". */
.history-charts:not(:empty) {
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: 0.8rem;
  padding-bottom: 0.4rem;
}

/* ------------------------------------------------------- drill-through (§7)
 *
 * James: "In Power BI you could click 'view data source' and see the table
 * supporting the report... Without that, it requires a level of trust with no
 * way for the user to confirm the data is right."
 *
 * So every number that came from a query is clickable, and the rule is **quiet
 * but obvious**: nothing here shouts on a page nobody is drilling, and nothing
 * here is invisible to somebody looking for it. The links are real buttons, so
 * they focus, and they show their focus ring like every other control. */

/* Screen-reader-only, for the header over the column of "rows" links. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The quiet "rows" link at the end of a row, and on a KPI tile. Underlined
   rather than coloured-only, because a link that is only a colour is not a link
   to somebody who cannot see the colour. */
.drill-link {
  all: unset;
  font-size: 0.72rem;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  padding: 0 0.15rem;
  border-radius: var(--radius);
}

.drill-link:hover,
.drill-link:focus-visible {
  color: var(--brand-secondary-dark);
}

.drill-link:focus-visible {
  outline: 2px solid var(--brand-secondary);
  outline-offset: 1px;
}

/* The row's own label, which opens the same panel. It keeps the cell's type:
   a dotted underline says "there is more here" without turning a column of
   client names into a column of links. */
.drill-label {
  all: unset;
  cursor: pointer;
  border-bottom: 1px dotted var(--line);
}

.drill-label:hover,
.drill-label:focus-visible {
  color: var(--brand-secondary-dark);
  border-bottom-color: var(--brand-secondary);
}

.drill-label:focus-visible {
  outline: 2px solid var(--brand-secondary);
  outline-offset: 1px;
}

td.drill-cell,
th.drill-column {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}

/* A chart whose bars open their own rows. */
canvas.is-drillable {
  cursor: pointer;
}

.kpi-drill {
  margin: 0.35rem 0 0;
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* ---- the panel ---------------------------------------------------------
 * Directly under the section, never a modal: the number the rows explain has
 * to stay on screen above them. */
.drill-host:not(:empty) {
  margin-top: 0.9rem;
}

.drill-panel {
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand-secondary);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 0.7rem 0.8rem 0.8rem;
}

.drill-panel:focus {
  outline: none;
}

.drill-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.drill-title {
  margin: 0;
  font-size: 0.95rem;
}

.drill-close {
  all: unset;
  font-size: 0.78rem;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  border-radius: var(--radius);
}

.drill-close:hover,
.drill-close:focus-visible {
  color: var(--brand-secondary-dark);
}

.drill-close:focus-visible {
  outline: 2px solid var(--brand-secondary);
  outline-offset: 2px;
}

.drill-meta {
  margin: 0.25rem 0 0.6rem;
}

.drill-meta p {
  margin: 0.1rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
  max-width: 90ch;
}

.drill-count {
  font-weight: 600;
  color: var(--ink-soft) !important;
}

/* The rows are live; the number above them is not. Said in the warning tone
   the rest of the app uses for "true, and easy to misread". */
.drill-notice {
  color: var(--warn) !important;
  background: var(--warn-tint);
  border-radius: var(--radius);
  padding: 0.25rem 0.45rem;
  display: inline-block;
  margin-top: 0.35rem !important;
}

.drill-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 0.35rem;
}

.drill-toolbar button {
  font-size: 0.78rem;
  padding: 0.25rem 0.6rem;
  background: var(--surface);
  color: var(--ink-soft);
  border: 1px solid var(--line);
}

/* ---- "Show query", admins only (§9) ------------------------------------
 * The server sends the statement to an admin and to nobody else, so there is
 * nothing here to hide for anybody else. */
.query-disclosure {
  margin-top: 0.5rem;
}

.query-disclosure > summary {
  display: inline-block;
  list-style: none;
  font-size: 0.78rem;
  color: var(--ink-faint);
  cursor: pointer;
}

.query-disclosure > summary::-webkit-details-marker {
  display: none;
}

.query-disclosure > summary::before {
  content: "\203A\00a0";
}

.query-disclosure[open] > summary::before {
  content: "\2039\00a0";
}

.query-disclosure > summary:hover {
  color: var(--brand-secondary);
}

.query-sql {
  margin: 0.3rem 0 0;
  padding: 0.5rem 0.6rem;
  background: var(--surface-alt);
  border-radius: var(--radius);
  font-size: 0.72rem;
  line-height: 1.45;
  white-space: pre;
  overflow-x: auto;
}

.query-params-label {
  margin: 0.4rem 0 0.1rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.query-params {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.72rem;
  color: var(--ink-faint);
}

.query-params li {
  margin: 0;
}

.sidebar-admin {
  margin: 0 0 0.35rem;
  font-size: 0.78rem;
}

/* The footer is white under the emerald header (Sept 23, 2026), so the admin
   links are the brand's own link colour; stone and white, from when the whole
   sidebar was dark, vanished there, the page you are on worst of all. */
.sidebar-admin a {
  color: var(--brand-secondary);
  text-decoration: none;
}

.sidebar-admin a:hover,
.sidebar-admin a[aria-current="page"] {
  color: var(--brand-primary);
  text-decoration: underline;
}

/* --------------------------------------------------- connectivity (§11)
 * The admin diagnostics page. One card per check, each with a verdict line
 * somebody can read at a glance and a definition list of the facts under it.
 * The outbound address is set large because it is the one thing on the page
 * that gets copied into an email to Cognition 360. */

.check .section-body {
  padding-top: 0.8rem;
}

.check-value {
  margin: 0 0 0.5rem;
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
}

.check-verdict {
  margin: 0 0 0.6rem;
  font-weight: 600;
}

.check-verdict.is-ok {
  /* The scorecard's own "met" teal, so a good verdict here is the same colour
     as a met target on a report page. */
  color: var(--met);
}

.check-verdict.is-blocked {
  color: var(--danger);
}

.check-verdict.is-off {
  color: var(--warn);
  font-weight: 400;
}

.check-facts {
  display: grid;
  grid-template-columns: 11rem 1fr;
  gap: 0.25rem 1rem;
  margin: 0.8rem 0 0;
  font-size: 0.85rem;
}

.check-facts dt {
  color: var(--ink-faint);
}

.check-facts dd {
  margin: 0;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.check-facts code,
.check .error-box + .muted code,
.check-verdict code {
  font-size: 0.82em;
}

@media (max-width: 40rem) {
  .check-facts {
    grid-template-columns: 1fr;
    gap: 0.05rem;
  }

  .check-facts dd {
    margin-bottom: 0.45rem;
  }
}

/* ------------------------------------------------ who sees what (§6)
 * The admin check before the app is announced: one row per person on a
 * Strety team, their teams as quiet chips, and what they can open in words.
 * A person who can open nothing is not hidden, only quieter, because that is
 * the row James is looking for. */

.sidebar-admin-sep {
  margin: 0 0.35rem;
  color: var(--ink-faint);
}

.who-wrap {
  overflow-x: auto;
}

.who-table {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.who-table th,
.who-table td {
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--line-soft);
  text-align: left;
  vertical-align: top;
  background: transparent;
}

.who-table thead th {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--line);
}

.who-table tbody th {
  font-weight: 400;
  min-width: 16rem;
}

.who-name {
  display: block;
  font-weight: 600;
  color: var(--ink);
}

/* An address on one line; the table scrolls sideways on a phone instead. */
.who-email {
  display: block;
  font-size: 0.78rem;
  color: var(--ink-faint);
  white-space: nowrap;
}

.who-teams {
  min-width: 12rem;
}

.who-chip {
  display: inline-block;
  margin: 0 0.3rem 0.3rem 0;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--brand-tint);
  color: var(--brand-secondary-dark);
  font-size: 0.75rem;
  white-space: nowrap;
}

.who-chip.is-admin {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: var(--brand-paper);
}

.who-opens {
  color: var(--ink);
}

.who-table tr.is-empty .who-name,
.who-table tr.who-anyone .who-name {
  color: var(--ink-soft);
}

.who-table tr.who-anyone th,
.who-table tr.who-anyone td {
  background: var(--surface-alt);
  border-bottom: 0;
}

/* ------------------------------------------ a month or quarter toggle (§5) */

/* SPEC §5 "A month or quarter toggle": Month | Quarter in the filter bar, the
   header's segmented control drawn with buttons. It applies on click, like the
   period picker. */
.grain-control {
  margin-top: 0.2rem;
}

.grain-control .segment {
  width: auto;
  margin: 0;
  padding: 0.3rem 0.8rem;
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.3;
  box-shadow: none;
}

.grain-control .segment:first-child {
  border-left: 0;
}

.grain-control .segment:hover {
  background: var(--brand-tint);
  color: var(--brand-secondary-dark);
}

.grain-control .segment.is-current {
  background: var(--brand-primary);
  color: var(--brand-paper);
  font-weight: 600;
}

/* ------------------------------------------ a panel above the table (§5) */

/* SPEC §5 "A panel above the table": one line per entity (label, diverging
   bar, values, heat strip), in a window exactly `rows` lines tall that scrolls
   to the last row with its header held. Every row is its own grid on the same
   column template, so the columns line up without a table's styling. At phone
   width the window scrolls sideways inside itself; the page never does. */
.entity-panel {
  --ep-row: 2.1rem;
  --ep-head: 2rem;
  --ep-label: 14rem;
  --ep-bar: minmax(9rem, 1fr);
  --ep-bar-min: 9rem;
  --ep-value: 7rem;
  --ep-cell: 0.95rem;
  --ep-gap: 2px;
  margin: 0 0 1.1rem;
}

.entity-panel.ep-unit-quarter {
  --ep-cell: 1.7rem;
}

.ep-scroll {
  max-height: calc(var(--ep-head) + var(--panel-rows, 10) * var(--ep-row) + 2px);
  overflow: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.ep-scroll:focus-visible {
  outline: 2px solid var(--brand-secondary);
  outline-offset: 1px;
}

.ep-row {
  display: grid;
  grid-template-columns: var(--ep-template);
  align-items: center;
  height: var(--ep-row);
  min-width: var(--ep-min);
  border-top: 1px solid var(--line-soft);
}

.ep-row.ep-head {
  position: sticky;
  top: 0;
  z-index: 2;
  height: var(--ep-head);
  border-top: 0;
  border-bottom: 1px solid var(--line);
  background: var(--surface-alt);
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.ep-cell {
  min-width: 0;
  padding: 0 0.5rem;
  font-size: 0.84rem;
  line-height: 1.2;
}

/* The label column holds still while the window scrolls sideways at phone
   width, so a row can always be read against its client. */
.ep-label {
  position: sticky;
  left: 0;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  background: var(--surface);
  border-right: 1px solid var(--line-soft);
}

.ep-head .ep-label {
  background: var(--surface-alt);
}

.ep-head .ep-cell {
  white-space: nowrap;
}

.ep-label .drill-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
  text-align: left;
}

.ep-value {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ep-value.ep-negative {
  color: var(--danger);
}

/* The diverging bar: two halves either side of a centre rule, the left one
   filled from the rule outwards to the left. Offboards in Gold and onboards in
   Midnight Green, the brand's first two series colours (charts.js). */
.ep-bar {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  height: 1rem;
  padding: 0 0.6rem;
}

.ep-half {
  display: flex;
  height: 100%;
}

.ep-half-left {
  justify-content: flex-end;
  border-right: 1px solid var(--ink-faint);
}

.ep-half-right {
  justify-content: flex-start;
}

.ep-fill {
  display: block;
  height: 100%;
}

.ep-fill-left {
  background: var(--brand-gold);
  border-radius: 2px 0 0 2px;
}

.ep-fill-right {
  background: var(--brand-midnight);
  border-radius: 0 2px 2px 0;
}

.ep-bar-head {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  padding: 0 0.6rem;
}

.ep-bar-head-left {
  text-align: right;
}

.ep-swatch {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  margin: 0 0.3rem;
  border-radius: 1px;
  vertical-align: -0.05rem;
}

.ep-swatch-left {
  background: var(--brand-gold);
}

.ep-swatch-right {
  background: var(--brand-midnight);
}

/* The heat strip: one cell per period, Midnight Green in five steps on one
   scale for the whole panel; a zero is a blank-ish cell. */
.ep-strip {
  display: flex;
  gap: var(--ep-gap);
  align-items: center;
}

.ep-period,
.ep-heat {
  flex: 0 0 var(--ep-cell);
  width: var(--ep-cell);
}

.ep-period {
  font-size: 0.68rem;
  font-weight: 600;
  text-align: center;
}

.ep-heat {
  height: 1.05rem;
  border-radius: 2px;
  background: var(--line-soft);
}

.ep-heat.ep-l1 {
  background: rgba(24, 89, 96, 0.16);
}

.ep-heat.ep-l2 {
  background: rgba(24, 89, 96, 0.32);
}

.ep-heat.ep-l3 {
  background: rgba(24, 89, 96, 0.52);
}

.ep-heat.ep-l4 {
  background: rgba(24, 89, 96, 0.74);
}

.ep-heat.ep-l5 {
  background: var(--brand-midnight);
}

.ep-heat.ep-open {
  outline: 1px dashed var(--ink-faint);
  outline-offset: -1px;
}

/* A new year starts here: a hairline before January, or before Q1. */
.ep-period.ep-year-start,
.ep-heat.ep-year-start {
  box-shadow: -2px 0 0 var(--surface), -3px 0 0 var(--line);
}

.ep-caption {
  margin: 0.35rem 0 0;
  font-size: 0.76rem;
  color: var(--ink-faint);
}

@media (max-width: 40rem) {
  .entity-panel {
    --ep-label: 9.5rem;
    --ep-value: 6rem;
  }
}

/* A section that draws a panel and no chart does not keep the empty chart
   hosts' margins between its header and the panel. */
.section-body:has(> .panel-host:not(:empty)) > .charts:empty {
  display: none;
}

/* ---------------------------------------- panel views, stacks, meters (§5) */

/* SPEC §5 "A panel above the table", views (Sept 26, 2026): a button per view
   above the window, and the view's legend under the buttons. */
.ep-views {
  margin: 0 0 0.45rem;
}

.ep-views .segment {
  width: auto;
  margin: 0;
  padding: 0.3rem 0.8rem;
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.3;
  box-shadow: none;
}

.ep-views .segment:first-child {
  border-left: 0;
}

.ep-views .segment:hover {
  background: var(--brand-tint);
  color: var(--brand-secondary-dark);
}

.ep-views .segment.is-current {
  background: var(--brand-primary);
  color: var(--brand-paper);
  font-weight: 600;
}

.ep-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.9rem;
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

.ep-key {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.ep-key .ep-swatch {
  margin: 0 0.3rem 0 0;
}

/* A two-sided bar with a value at each end: the fills leave room for the
   labels, and a side cut at its cap ends in a slanted break. */
.entity-panel.ep-labelled {
  --ep-bar-label: 3.6rem;
}

.ep-bar-label {
  flex: 0 0 var(--ep-bar-label, 0);
  font-size: 0.72rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ep-half-left .ep-bar-label {
  text-align: right;
  padding-right: 0.3rem;
}

.ep-half-right .ep-bar-label {
  padding-left: 0.3rem;
}

.entity-panel.ep-labelled .ep-half {
  align-items: center;
}

.ep-fill.ep-over {
  position: relative;
}

.ep-fill.ep-over::after {
  content: '';
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 3px;
  background: var(--surface);
  transform: skewX(-20deg);
}

.ep-fill-right.ep-over::after {
  right: 5px;
}

.ep-fill-left.ep-over::after {
  left: 5px;
}

.ep-bar.ep-bar-empty {
  display: flex;
  justify-content: center;
}

.ep-empty {
  font-size: 0.75rem;
  font-style: italic;
  color: var(--ink-faint);
}

/* A stack: the parts on one scale, the total after the bar. By position:
   Stone, Gold, Sand with a Stone edge, muted Emerald, Midnight Green (the
   Concept Complete layers: add-on cost, labor, platform, watched line, margin;
   licensing: cost, margin). */
.ep-stack {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.ep-stack-track {
  display: flex;
  flex: 1 1 auto;
  height: 1rem;
  min-width: 0;
}

.ep-seg {
  display: block;
  height: 100%;
}

.ep-seg-0,
.ep-swatch.ep-seg-0 {
  background: var(--brand-stone);
}

.ep-seg-1,
.ep-swatch.ep-seg-1 {
  background: var(--brand-gold);
}

.ep-seg-2,
.ep-swatch.ep-seg-2 {
  background: var(--brand-sand);
  box-shadow: inset 0 0 0 1px var(--brand-stone);
}

.ep-seg-3,
.ep-swatch.ep-seg-3 {
  background: var(--brand-emerald);
  opacity: 0.55;
}

.ep-seg-4,
.ep-swatch.ep-seg-4 {
  background: var(--brand-midnight);
}

/* Costs past revenue: no profit segment, and a muted danger edge. */
.ep-stack-track.ep-stack-loss {
  box-shadow: 3px 0 0 var(--danger);
}

.ep-stack-total {
  flex: 0 0 5.2rem;
  text-align: right;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.ep-stack-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.7rem;
  align-items: center;
}

/* A meter from 0 to its max, with a line at the all-client value. */
.ep-meter-track {
  position: relative;
  display: block;
  height: 1rem;
  background: var(--line-soft);
  border-radius: 2px;
}

.ep-meter-fill {
  display: block;
  height: 100%;
  background: var(--brand-midnight);
  border-radius: 2px 0 0 2px;
}

.ep-meter-fill.ep-meter-danger {
  background: var(--danger);
  opacity: 0.55;
}

.ep-meter-line {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  margin-left: -1px;
  background: var(--brand-ink);
}

.ep-swatch.ep-swatch-line {
  width: 2px;
  height: 0.85rem;
  background: var(--brand-ink);
  border-radius: 0;
}

/* Pico stretches a role="group" and its buttons to the full width; a view
   switcher and the Month | Quarter control are as wide as their words. */
.segmented[role='group'] {
  display: inline-flex;
  width: auto;
}

.segmented[role='group'] > .segment {
  flex: 0 0 auto;
}

/* A heading never runs into its neighbour; the full words are its title. */
.ep-head .ep-value,
.ep-bar-head-left,
.ep-bar-head-right {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A labelled two-sided bar needs room for a value at each end before the
   window scrolls sideways, and the view buttons wrap on a narrow screen. */
.entity-panel.ep-labelled {
  --ep-bar-min: 17rem;
}

.ep-views {
  flex-wrap: wrap;
  max-width: 100%;
}
