/* Shared page frame for the Ostrom dashboard sub-pages.

   Managed by ostrom/ostrom-dashboard-standards (assets/_subpage.css).
   Edit there, not here: the sync overwrites this file.

   The frame (width / padding / back-arrow) is identical in every dashboard so
   pages don't shift when navigating between them.

   THIS IS THE ONLY FILE IN THE PLATFORM THAT CONTAINS A HEX COLOUR. Pages use
   var(--token). Values follow the ostrom-brand-guidelines skill; when the skill
   moves, this file moves and every page follows for free. */

:root {
  /* Brand palette. Comments give the skill's name for each colour. */
  --bg:          #F0F7F7;  /* Teal 6 */
  --card:        #FFFFFF;
  --ink:         #00102B;  /* Black */
  --navy:        #17295A;  /* Navy */
  --muted:       #384150;  /* Grey Placeholder */
  --accent:      #00C2B2;  /* Teal 1 */
  --accent-mid:  #00A693;  /* Teal 05 */
  --accent-dk:   #007063;  /* Teal 025 */
  --border:      #DEEFEF;  /* Teal 5 */
  --grid:        #DEEFEF;  /* Teal 5, chart gridlines */
  --chip:        #F0F7F7;  /* Teal 6. Same value as --bg: a chip only reads on
                              white, so it belongs inside a panel or a card and
                              never directly on the page. */
  --good:        #00C14D;  /* Green */
  --bad:         #FB5C4F;  /* Red, UX negative only */
  --inactive:    #CCD1D9;  /* Mid Grey: a disabled control, or a bar with no data */

  /* Status messages: a surface, its border, and text that is legible on it.

     NOT BRAND COLOURS. These twelve values are the only ones in this file the
     ostrom-brand-guidelines skill does not define, and this is the only place
     a page may take a colour the skill has not blessed.

     Two things are missing from the brand and a dashboard cannot do without
     either. There is no amber, and the brand's Orange sits a shade away from
     its Red, too close for the two to carry different meanings -- so a
     red/amber/green scale has nowhere to get its middle band. And Green and
     Red are solid signal colours with no tint or ink to pair them with, so a
     message saying "this failed" has no surface to sit on.

     Every team solved both separately. Operations declared a warning token in
     three files independently; across the four repos the status colours had
     reached roughly thirty spellings, including seven different reds. The
     values below are the ones those pages most commonly used, drawn as three
     consistent ramps so the three states finally look related to each other.

     Karl to bless or replace them. When he does, this is the only place that
     changes, which is the entire reason they are here. */
  --good-bg:     #DCFCE7;  /* the surface a success message sits on */
  --good-line:   #A7F3D0;  /* its border */
  --good-ink:    #166534;  /* text on --good-bg */

  --bad-bg:      #FEF2F2;  /* the surface an error message sits on */
  --bad-line:    #FECACA;  /* its border */
  --bad-ink:     #B91C1C;  /* text on --bad-bg */

  --warn:        #F59E0B;  /* solid signal: the middle band of red/amber/green */
  --warn-bg:     #FEF3C7;  /* the surface a warning message sits on */
  --warn-line:   #FDE68A;  /* its border */
  --warn-ink:    #92400E;  /* text on --warn-bg */

  /* Categorical chart series, in the order the ostrom-chart skill defines, so
     a chart generated by the skill and a chart built into a dashboard match.
     Every value is a brand colour. _charts.js reads these and carries none. */
  --series-1: var(--accent);   /* Teal 1 */
  --series-2: var(--navy);     /* Navy */
  --series-3: var(--good);     /* Green */
  --series-4: var(--bad);      /* Red */
  --series-5: #7AEADB;         /* Teal 2 */
  --series-6: var(--muted);    /* Grey Placeholder */
  --series-7: #99E6E0;         /* Teal 3 */
  --series-8: #858E9B;         /* Dark Grey */

  /* Legacy aliases. Still used by many pages; do not use in new code.
     --teal-6 is a misnomer: it resolves to Teal 05, not Teal 6. */
  --page-bg: var(--bg);
  --teal:    var(--accent);
  --teal-6:  var(--accent-mid);
  --teal-5:  var(--border);
  --line:    var(--border);
}

* { box-sizing: border-box; }
body {
  margin: 0; min-height: 100vh; background: var(--bg); color: var(--ink);
  font: 14px/1.5 "Inter", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  padding: 32px 24px 56px;
}
main { max-width: 1180px; margin: 0 auto; }
a { color: var(--accent-dk); text-decoration: none; }
a:hover { text-decoration: underline; }
/* An anchor wrapping a whole tile is not an inline link. Underlining every word
   inside it on hover looks broken; the tile already signals hover with its
   border and lift. Covers the tile class names the four dashboards use. */
a.card:hover, a.team:hover, a.tile:hover, a.tool:hover { text-decoration: none; }
.back { font-size: 13px; font-weight: 700; color: var(--accent-dk); display: inline-block; margin-bottom: 10px; }
.eyebrow { color: var(--accent-dk); font-weight: 700; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; margin: 0 0 2px; }
h1 { font-size: 26px; font-weight: 800; color: var(--navy); margin: 0 0 2px; }
p.sub { color: var(--muted); margin: 0 0 24px; font-size: 13px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 18px 20px; }
/* Flex column so .card .arrow can pin to the bottom; harmless on cards without one. */
a.card { display: flex; flex-direction: column; color: var(--ink); transition: border-color .15s, transform .15s; }
a.card:hover { border-color: var(--accent); transform: translateY(-1px); }
.card .name { font-weight: 800; font-size: 16px; }
.card .desc { color: var(--muted); font-size: 13px; margin-top: 4px; }
.card .arrow { color: var(--accent-dk); font-weight: 700; margin-top: auto; padding-top: 8px; font-size: 13px; }
/* The label above a group of cards. Forty above and twelve below, so it reads
   as belonging to the section beneath it rather than floating between two.
   Twenty pages defined this themselves and fourteen of them left the top margin
   off, which put the label flush against the grid above. */
.section-label { font-size: 12px; font-weight: 700; text-transform: uppercase;
                 letter-spacing: .06em; color: var(--muted); margin: 40px 0 12px; }
.section-label:first-child { margin-top: 0; }
/* Status badges: not brand colours, pending a designed replacement. */
.badge { display: inline-block; font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 999px; background: var(--warn-bg); color: var(--warn-ink); margin-left: 8px; vertical-align: middle; }
.badge.live { background: var(--good-bg); color: var(--good-ink); }
.btn { background: var(--accent); color: #fff; border: 0; border-radius: 10px; padding: 10px 16px; font-weight: 700; cursor: pointer; font-family: inherit; font-size: 14px; }
.btn[disabled] { background: var(--inactive); cursor: not-allowed; }
.muted { color: var(--muted); font-size: 13px; }
footer { color: var(--muted); font-size: 12px; margin-top: 40px; }

/* Toast, for every page that calls S.toast() in _shared.js. It lives here
   rather than in each page because a page that forgets it does not fail
   loudly: the div has no styling, so the message lands as body text at the
   bottom of the document and looks like the page broke. Navy by default,
   red only for the error case, which S.toast marks with .err. */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  background: var(--navy); color: #fff; padding: 11px 18px; border-radius: 10px;
  font-size: 13px; box-shadow: 0 8px 24px rgba(0, 16, 43, .25); opacity: 0;
  pointer-events: none; transition: opacity .2s ease; max-width: 90vw; z-index: 50;
}
.toast.show { opacity: 1; }
.toast.err { background: var(--bad); }

/* Pagination, for long lists. Kept out of the pages so every table paginates
   the same way and the controls stay reachable on a phone. */
.pager { display: flex; align-items: center; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.pager .range { color: var(--muted); font-size: 12px; }
.pager .spacer { flex: 1 1 auto; }
.pager button {
  background: var(--card); color: var(--accent-dk); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 12px; font: inherit; font-size: 13px;
  font-weight: 700; cursor: pointer;
}
.pager button[disabled] { color: var(--muted); cursor: not-allowed; opacity: .55; }

/* ── Content surfaces ─────────────────────────────────────────────────────────
   The rules above say where a page starts and stops; these say what its content
   sits on. Every dashboard already had them under nine different names, which
   is how a chart in one repo ended up painted straight onto the page background
   while the same chart in another sat in a panel. Each declaration below is the
   variant that already appeared most often across the four repos, so adopting
   them moves as few pages as possible. */

/* The white surface content lives on. `.card` above is the navigation tile;
   this is its content-page counterpart, tighter because it usually wraps a
   chart rather than three lines of text. */
.panel { background: var(--card); border: 1px solid var(--border); border-radius: 16px; padding: 16px 14px 10px; }
.panel + .panel { margin-top: 14px; }
.panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.panel-title { font-size: 14px; font-weight: 800; color: var(--navy); margin: 0; }
.panel-note { color: var(--muted); font-size: 11px; letter-spacing: .04em; text-transform: uppercase; }

/* Chart box. Only position and spacing are shared; height is genuinely
   per-page, so pages keep setting it and nothing here overrides them. */
.chartwrap { position: relative; margin-top: 6px; }

.kpis { display: flex; flex-wrap: wrap; gap: 10px; margin: 12px 0 6px; }
/* White, not --chip: a KPI row usually sits straight on the page, where --chip
   is the same colour as the background and the tile disappears down to its
   hairline border. That is what made eleven product pages read as "still grey".
   Marketing has painted these white since the first version of the page. */
.kpi { background: var(--card); border: 1px solid var(--border); border-radius: 10px; flex: 1; min-width: 150px; padding: 8px 14px; }
.kpi .label { color: var(--muted); font-size: 11px; letter-spacing: .05em; text-transform: uppercase; }
.kpi .value { color: var(--navy); font-size: 20px; font-weight: 800; }

.filters { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 18px; border-bottom: 1px solid var(--border); padding-bottom: 10px; margin: 6px 0 2px; }
.fgroup { display: flex; flex-direction: column; }
.flabel { color: var(--muted); font-size: 11px; letter-spacing: .05em; text-transform: uppercase; margin-bottom: 6px; }

/* The caret is inline SVG because a background-image cannot reference a custom
   property; its fill is the one hex outside :root in this file. */
.sel {
  appearance: none; background: var(--card); border: 1px solid var(--border);
  border-radius: 8px; color: var(--ink); cursor: pointer; font: 500 13px/1 "Inter", sans-serif;
  padding: 9px 34px 9px 12px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath fill='%23384150' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}

/* Thirteen pages converged on this independently. `.btn` above is the same
   intent with a larger radius, kept for the pages already using it; new pages
   should pick one of the two rather than invent a third. */
.refresh {
  background: var(--accent); border: 1px solid var(--accent); border-radius: 8px;
  color: #fff; cursor: pointer; font: 600 13px/1 "Inter", sans-serif; padding: 9px 16px;
  transition: background .15s ease, opacity .15s ease;
}
.refresh:hover { background: var(--accent-dk); border-color: var(--accent-dk); }
.refresh:disabled { cursor: default; opacity: .55; }

/* Scoped to .panel so the styling and the rule "a table is never painted on the
   page background" are the same statement. */
.panel table { border-collapse: collapse; width: 100%; }
.panel th {
  color: var(--muted); font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; text-align: left; padding: 8px 10px;
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
.panel td { padding: 9px 10px; border-bottom: 1px solid var(--border); }
.panel tr:last-child td { border-bottom: 0; }

/* Mobile. Every page must work at <= 720px (see frontend-style.mdc).
   Wide content (charts, tables) goes in a .swipe; the .swipe-hint label shows
   only on small screens. A .swipe that is itself a grid or flex item needs
   min-width: 0, or the wide content stretches the page instead of scrolling
   inside the wrapper. */
.swipe { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
/* Legacy alias for .swipe, used by the operations schedule pages. */
.swipe-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
.swipe-hint { display: none; color: var(--muted); font-size: 11px; font-style: italic; margin: 10px 0 2px; }
@media (max-width: 720px) {
  body { padding: 18px 12px 40px; }
  h1 { font-size: 22px; }
  .swipe-hint { display: block; }
  /* Card grid to a single column: minmax(300px, 1fr) exceeds a ~296px content
     width on a 320px viewport and would otherwise overflow horizontally. */
  .grid { grid-template-columns: 1fr; }
  .panel { padding: 12px 10px 8px; border-radius: 12px; }
  /* Mobile rules for .filters, .kpi and .sel are deliberately absent until the
     pages stop defining those components themselves. A page that declares
     .filters { align-items: flex-end } and no flex-direction takes a shared
     flex-direction: column and becomes a hybrid neither side designed: it did
     that to operations' payments page, stacking a row that fitted and aligning
     the stack to the end. Add them once the migration removes the local copies. */
}
