/* devdash — tokens taken from the validated reference palette.
   Dark steps are their own selected values, not an automatic flip, and are
   declared under BOTH the OS media query and the explicit theme stamp so a
   manual choice wins either way. */
:root {
  color-scheme: light;
  --plane:        #f9f9f7;
  --surface:      #fcfcfb;
  --ink:          #0b0b0b;
  --ink-2:        #52514e;
  --ink-muted:    #898781;
  --grid:         #e1e0d9;
  --axis:         #c3c2b7;
  --hairline:     rgba(11,11,11,0.10);
  --series-1:     #2a78d6;
  --series-2:     #eb6834;
  --series-3:     #1baf7a;
  --good:         #0ca30c;
  --warning:      #fab219;
  --serious:      #ec835a;
  --critical:     #d03b3b;
  --success-text: #006300;
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --plane: #0d0d0d; --surface: #1a1a19; --ink: #fff; --ink-2: #c3c2b7;
    --ink-muted: #898781; --grid: #2c2c2a; --axis: #383835;
    --hairline: rgba(255,255,255,0.10);
    --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70;
    --success-text: #0ca30c;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --plane: #0d0d0d; --surface: #1a1a19; --ink: #fff; --ink-2: #c3c2b7;
  --ink-muted: #898781; --grid: #2c2c2a; --axis: #383835;
  --hairline: rgba(255,255,255,0.10);
  --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70;
  --success-text: #0ca30c;
}

* { box-sizing: border-box; }
body {
  margin: 0; background: var(--plane); color: var(--ink);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}
body.centred { display: grid; place-items: center; min-height: 100vh; }
.card {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 10px; padding: 28px 32px; max-width: 34rem;
}
h1 { font-size: 1.35rem; margin: 0 0 .5rem; letter-spacing: -0.01em; }
p { color: var(--ink-2); margin: .4rem 0; }
.muted { color: var(--ink-muted); font-size: .85rem; }
a.btn {
  display: inline-block; margin-top: 1rem; padding: .6rem 1.1rem;
  background: var(--series-1); color: #fff; text-decoration: none;
  border-radius: 7px; font-weight: 600;
}

/* --- chrome --- */
header.bar {
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
  padding: 14px 22px; border-bottom: 1px solid var(--hairline);
  background: var(--surface); position: sticky; top: 0; z-index: 5;
}
header.bar h1 { margin: 0; font-size: 1.05rem; }
header.bar .spacer { flex: 1; }
header.bar .meta { color: var(--ink-muted); font-size: .82rem; }
header.bar button, header.bar a.plain {
  background: none; border: 1px solid var(--hairline); color: var(--ink-2);
  border-radius: 6px; padding: .3rem .7rem; font: inherit; font-size: .82rem;
  cursor: pointer; text-decoration: none;
}

main { padding: 22px; display: grid; gap: 18px;
       grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
section.panel {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 10px; padding: 18px 20px; min-width: 0;
}
section.panel.wide { grid-column: 1 / -1; }
section.panel > h2 {
  margin: 0 0 .9rem; font-size: .78rem; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-muted);
}

/* --- stat tiles: label, value, then a recessive sub-line --- */
.tiles { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.tile .label { font-size: .75rem; color: var(--ink-muted); }
.tile .value { font-size: 1.7rem; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
.tile .sub   { font-size: .78rem; color: var(--ink-2); }
/* A meter is a magnitude, so it gets one hue and a track — never a rainbow. */
.meter { height: 5px; border-radius: 3px; background: var(--grid); margin-top: 6px; overflow: hidden; }
.meter > i { display: block; height: 100%; background: var(--series-1); border-radius: 3px; }

/* --- status: colour NEVER carries the meaning alone; the dot ships with text --- */
.state { display: inline-flex; align-items: center; gap: .4rem; font-size: .85rem; }
.state::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%;
  background: var(--ink-muted); flex: none;
}
.state.good::before     { background: var(--good); }
.state.warning::before  { background: var(--warning); }
.state.serious::before  { background: var(--serious); }
.state.critical::before { background: var(--critical); }
.state.good     { color: var(--success-text); }
.state.critical { color: var(--critical); }

table { width: 100%; border-collapse: collapse; font-size: .85rem; }
th {
  text-align: left; font-weight: 600; color: var(--ink-muted);
  font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
  padding: 0 .6rem .4rem 0; border-bottom: 1px solid var(--grid);
}
td { padding: .42rem .6rem .42rem 0; border-bottom: 1px solid var(--grid); vertical-align: top; }
tr:last-child td { border-bottom: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.name { font-weight: 500; }

/* --- horizontal bars: one hue, every bar directly labelled, so identity is
       never colour-alone and the sub-3:1 contrast relief is satisfied --- */
.bars { display: grid; gap: 7px; }
/* The value column is a FIXED width, not `auto`. With `auto` the column took
   its width from the widest number in each ROW, so `263` left a wider track
   than `98,641` and the grey ends stepped in and out down the chart. A bar
   chart whose baseline-opposite end wanders is one you cannot read lengths
   off at a glance, which is the entire job of the form.
   5rem holds `1,234,567` in tabular figures with room to spare. */
.bar-row { display: grid; grid-template-columns: 8.5rem 1fr 5rem; gap: .7rem; align-items: center; }
.bar-row .lang { font-size: .82rem; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-row .track { background: var(--grid); border-radius: 0 4px 4px 0; height: 14px; }
.bar-row .track > i {
  display: block; height: 100%; background: var(--series-1);
  border-radius: 0 4px 4px 0; min-width: 2px;
}
.bar-row .n { font-size: .8rem; color: var(--ink-2); font-variant-numeric: tabular-nums;
              text-align: right; }

.chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.chip {
  border: 1px solid var(--hairline); border-radius: 999px;
  padding: .18rem .6rem; font-size: .78rem; color: var(--ink-2);
}
.err {
  border-left: 3px solid var(--critical); background: color-mix(in srgb, var(--critical) 7%, transparent);
  padding: .5rem .7rem; border-radius: 0 6px 6px 0; font-size: .84rem; color: var(--ink-2);
}
.note {
  border-left: 3px solid var(--warning); background: color-mix(in srgb, var(--warning) 10%, transparent);
  padding: .5rem .7rem; border-radius: 0 6px 6px 0; font-size: .84rem; color: var(--ink-2);
}
/* There is deliberately no height cap on a card. A panel renders at the
   height its content needs and the PAGE scrolls; a scrollbar inside a card
   hides content on a screen that had room to show it, and hides it in a
   place the reader has to discover. */
.stale { opacity: .45; transition: opacity .2s; }

/* Inline style attributes are blocked by the CSP (style-src self, no
   unsafe-inline), so spacing that used to ride on style="margin-top" lives
   here instead. */
section.panel h2.sep { margin-top: 1.2rem; }

/* --- tab navigation ------------------------------------------------------
   Real anchors with real hrefs, so middle-click and "open in new tab" behave.
   The active tab is marked by an underline AND aria-current, not by colour
   alone. */
nav.tabs {
  display: flex; gap: .15rem; padding: 0 22px; overflow-x: auto;
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  position: sticky; top: 49px; z-index: 4;
}
nav.tabs .tab {
  padding: .7rem .95rem; font-size: .88rem; color: var(--ink-2);
  text-decoration: none; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
nav.tabs .tab:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 4%, transparent); }
nav.tabs .tab.on { color: var(--ink); border-bottom-color: var(--series-1); font-weight: 600; }
main { padding: 22px; display: block; }
main > section.panel { max-width: 1100px; margin: 0 auto; }

/* --- dependency popovers -------------------------------------------------
   Hover reveals, click pins. Colour follows the owner's mapping (red blocked,
   yellow in-progress, grey ready) with green added for done — but every chip
   also spells the status out, so hue is never the only carrier. */
.dep-cell { white-space: nowrap; }
.deps { position: relative; display: inline-block; cursor: pointer; }
.deps:focus-visible { outline: 2px solid var(--series-1); outline-offset: 2px; border-radius: 4px; }
.deps-n {
  display: inline-block; min-width: 1.5rem; text-align: center;
  font-variant-numeric: tabular-nums; font-size: .8rem;
  border: 1px solid var(--hairline); border-radius: 999px; padding: .05rem .4rem;
  color: var(--ink-2); background: var(--plane);
}
.deps:hover .deps-n, .deps.open .deps-n { border-color: var(--series-1); color: var(--ink); }
.deps-none { color: var(--ink-muted); }
.deps .pop {
  display: none; position: absolute; z-index: 20; left: 0; top: calc(100% + 6px);
  min-width: 13rem; max-width: 22rem; padding: .6rem .7rem;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.18);
  white-space: normal;
}
.deps:hover .pop, .deps.open .pop { display: block; }
.deps .pop b {
  display: block; font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-muted); margin-bottom: .4rem; font-weight: 600;
}
.dep {
  display: inline-flex; align-items: baseline; gap: .35rem;
  border: 1px solid var(--hairline); border-left-width: 3px;
  border-radius: 4px; padding: .12rem .4rem; margin: 0 .25rem .25rem 0;
  font-size: .78rem; color: var(--ink);
}
.dep > i { font-style: normal; font-size: .68rem; color: var(--ink-muted); }
.dep.good     { border-left-color: var(--good); }
.dep.warning  { border-left-color: var(--warning); }
.dep.critical { border-left-color: var(--critical); }
.dep.idle     { border-left-color: var(--axis); }
/* A dependency naming a task that has no file yet: dashed, so it does not read
   as "ready" in colour or in greyscale. */
.dep.unknown { border-left-style: dashed; border-left-color: var(--ink-muted); }

/* --- progress bars -------------------------------------------------------
   Part-to-whole, so one stacked bar rather than several. Segments are separated
   by a 2px rule in the surface colour drawn INSIDE the segment (border-box), so
   the separation never distorts the proportion it is separating. */
.progs { display: grid; gap: 14px; margin: 0 0 1.2rem; }
.prog-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.prog-label { font-size: .85rem; color: var(--ink); font-weight: 500; }
.prog-pct { font-size: .85rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.prog-track {
  display: flex; height: 10px; margin-top: 5px;
  background: var(--grid); border-radius: 5px; overflow: hidden;
}
.prog-track .seg { display: block; height: 100%; box-sizing: border-box; min-width: 2px; }
.prog-track .seg + .seg { border-left: 2px solid var(--surface); }
.seg.good { background: var(--good); }
.seg.warning { background: var(--warning); }
.seg.critical { background: var(--critical); }
.seg.idle { background: var(--axis); }
.prog-legend { display: flex; flex-wrap: wrap; gap: .5rem 1rem; margin-top: .45rem; }
.prog-legend .key { display: inline-flex; align-items: center; gap: .35rem; font-size: .76rem; color: var(--ink-2); }
.prog-legend .key::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--axis); }
.prog-legend .key.good::before { background: var(--good); }
.prog-legend .key.warning::before { background: var(--warning); }
.prog-legend .key.critical::before { background: var(--critical); }

/* --- task links and the task page --------------------------------------- */
a.task-link, a.dep-link {
  color: var(--series-1); text-decoration: none; font-weight: 600;
}
a.task-link:hover, a.dep-link:hover { text-decoration: underline; }
a.dep-link {
  display: inline-block; border: 1px solid var(--hairline); border-radius: 999px;
  padding: .18rem .6rem; font-size: .78rem; font-weight: 500; margin: 0 .25rem .25rem 0;
}

/* Rendered task markdown. Constrained measure, because these files are long
   prose and a full-width line is unreadable. */
.md { max-width: 62rem; }
.md h2, .md h3, .md h4, .md h5, .md h6 {
  margin: 1.4rem 0 .5rem; line-height: 1.3; color: var(--ink);
  font-size: 1.05rem; text-transform: none; letter-spacing: 0;
}
.md h2 { font-size: 1.2rem; border-bottom: 1px solid var(--grid); padding-bottom: .3rem; }
.md p { margin: .6rem 0; color: var(--ink-2); }
.md ul, .md ol { margin: .6rem 0; padding-left: 1.4rem; color: var(--ink-2); }
.md li { margin: .25rem 0; }
.md code {
  background: var(--plane); border: 1px solid var(--hairline); border-radius: 4px;
  padding: .05rem .3rem; font-size: .85em;
}
.md pre {
  background: var(--plane); border: 1px solid var(--hairline); border-radius: 7px;
  padding: .8rem; overflow-x: auto;
}
.md pre code { background: none; border: 0; padding: 0; }
.md blockquote {
  margin: .7rem 0; padding: .4rem .8rem; border-left: 3px solid var(--series-1);
  background: color-mix(in srgb, var(--series-1) 6%, transparent);
  border-radius: 0 6px 6px 0; color: var(--ink-2);
}
.md table { margin: .8rem 0; }
.md hr { border: 0; border-top: 1px solid var(--grid); margin: 1.2rem 0; }
.md a { color: var(--series-1); }
/* Work that is named but has no task file. Given a texture rather than another
   colour: it reads as distinct from `ready` even in greyscale, in forced-colours
   mode, and for a reader who cannot separate the two greys. */
.seg.unknown {
  background: repeating-linear-gradient(45deg,
    var(--axis), var(--axis) 3px, var(--grid) 3px, var(--grid) 6px);
}
.prog-legend .key.unknown::before {
  background: repeating-linear-gradient(45deg,
    var(--axis), var(--axis) 2px, var(--grid) 2px, var(--grid) 4px);
}
