/* Seasats lab UI. Dark by default, light when the OS asks, unless the person picked a theme under
   My settings (core.js setTheme puts data-theme on <html>; changelog v1.240). Dense, engineer-facing.
   The dark scheme is black with neutral greys since changelog v1.121 (D, 2026-09-29: "use a
   black background instead of the blue background"); the accents are unchanged. */
:root {
  --bg: #000000; --bg2: #0e0e0e; --bg3: #1a1a1a; --line: #272727; --line2: #383838;
  --fg: #ededed; --fg2: #a9a9a9; --fg3: #7e7e7e;
  --accent: #38bdf8; --accent2: #0ea5e9; --ok: #34d399; --warn: #f59e0b; --err: #f87171;
  --info: #60a5fa; --purple: #a78bfa; --pink: #f472b6;
  --lime: #a3e635; --lime-ink: #000000;   /* the applet buttons until v1.199; a lab service's mark on the boat queue */
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif;
  --radius: 8px; --shadow: 0 6px 24px rgba(0,0,0,.35);
  --cat1:#38bdf8; --cat2:#f59e0b; --cat3:#34d399; --cat4:#a78bfa; --cat5:#f472b6; --cat6:#fb923c; --cat7:#60a5fa; --cat8:#94a3b8;
  /* Projects (changelog v1.159, design section 2): --proj is "a project" in general, cyan and
     apart from the link blue; --proj-h0..7 are the eight hues a top-level project takes
     (orange, yellow, brown, teal, indigo, violet, magenta, pink), a sub-project sharing its
     parent's. Both schemes are checked by tests/test_ui_palette.py: contrast against the
     surfaces, and CIEDE2000 of at least 10 between hues and from link, status, lime, --proj
     and --fg3. Elements take a hue through the .ph0-.ph7 classes, never a style object. */
  --proj: #22d3ee; --proj-ink: #000000;
  --proj-h0: #fb8c4a; --proj-h1: #fde047; --proj-h2: #c8a27c; --proj-h3: #00a896;
  --proj-h4: #818cf8; --proj-h5: #c4a1ff; --proj-h6: #f472d0; --proj-h7: #fda4af;
  --proj-none: var(--fg3);
  /* The boat queue's card (changelog v1.162): --proj-on is the ink on a solid hue bar (7.0:1 or
     more on every dark hue), --q-warn marks a run someone disturbed, --q-veil lightens the part
     of a running bar still ahead of now. tests/test_ui_palette.py checks the first two. */
  --proj-on: #000000; --q-warn: var(--warn); --q-veil: rgba(255,255,255,.38);
  --warn-ink: var(--warn);   /* text in the warning colour: the Low RAM light (v1.194) */
  /* Kinds (changelog v1.199, Projects Stage 2): a tool project (one of the seven, shared lab
     equipment) is blue, every other project green, as the outline, pill and text colour of its
     marks (.pk-tool and .pk-work set --pk); the small family-hue dot stays. tests/test_ui_palette.py
     holds both at 4.5:1 or more on --bg2 and 10 or more (CIEDE2000) from every reference colour,
     every hue and each other, in both schemes. On --bg3 (hover) the blue is about 4.2:1, so a
     hovered or selected row keeps --fg text on a --pk tint. */
  --kind-tool: #2f7cda; --kind-work: #34b53a;
  /* The proof label [claude-tested] (changelog v1.201, D: "How about making it purple?"): a pill's
     text and border, a bar's segment. tests/test_ui_palette.py holds it at 4.5:1 or more on --bg2
     and --bg3 (a pill's surface) and 10 or more (CIEDE2000) from every reference colour, both
     kind colours and every hue, in both schemes; the blues (--info, --kind-tool) are 25 or more
     away. --purple, the older and lighter mark, stays for the other pills. */
  --proof-tested: #c06cff;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --bg:#f4f6fa; --bg2:#ffffff; --bg3:#eef2f8; --line:#d7deea; --line2:#c3cddd;
    --fg:#0f172a; --fg2:#3b4b63; --fg3:#6b7a93; --shadow:0 6px 24px rgba(15,23,42,.10);
    --lime:#4d7c0f; --lime-ink:#ffffff;   /* a darker lime reads on white */
    --proj:#0e7490; --proj-ink:#ffffff;
    --proj-h0:#c2410c; --proj-h1:#a16207; --proj-h2:#78350f; --proj-h3:#0f766e;
    --proj-h4:#3730a3; --proj-h5:#7c3aed; --proj-h6:#a21caf; --proj-h7:#be185d;
    --proj-none: var(--fg3);
    /* white ink is 4.9:1 or more on every light hue; the dark --warn is 2.1:1 on white, so the
       disturbed mark takes a darker amber (3.19:1, 13.4 or more from every hue) */
    --proj-on:#ffffff; --q-warn:#d97706; --q-veil: rgba(0,0,0,.30);
    --warn-ink:#92400e;   /* amber text on white: 7.1:1 (the dark --warn is 2.1:1) */
    --kind-tool:#2563eb; --kind-work:#166534;   /* 5.2:1 and 7.1:1 on white */
    --proof-tested:#6a1990;   /* 9.8:1 on white; the light violet and magenta hues sit beside purple */
  }
}
/* Light picked under My settings: the same tokens as the block above (tests/test_ui_palette.py
   holds the two equal). Dark picked on a light computer keeps :root's. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg:#f4f6fa; --bg2:#ffffff; --bg3:#eef2f8; --line:#d7deea; --line2:#c3cddd;
  --fg:#0f172a; --fg2:#3b4b63; --fg3:#6b7a93; --shadow:0 6px 24px rgba(15,23,42,.10);
  --lime:#4d7c0f; --lime-ink:#ffffff;   /* a darker lime reads on white */
  --proj:#0e7490; --proj-ink:#ffffff;
  --proj-h0:#c2410c; --proj-h1:#a16207; --proj-h2:#78350f; --proj-h3:#0f766e;
  --proj-h4:#3730a3; --proj-h5:#7c3aed; --proj-h6:#a21caf; --proj-h7:#be185d;
  --proj-none: var(--fg3);
  /* white ink is 4.9:1 or more on every light hue; the dark --warn is 2.1:1 on white, so the
     disturbed mark takes a darker amber (3.19:1, 13.4 or more from every hue) */
  --proj-on:#ffffff; --q-warn:#d97706; --q-veil: rgba(0,0,0,.30);
  --warn-ink:#92400e;   /* amber text on white: 7.1:1 (the dark --warn is 2.1:1) */
  --kind-tool:#2563eb; --kind-work:#166534;   /* 5.2:1 and 7.1:1 on white */
  --proof-tested:#6a1990;   /* 9.8:1 on white; the light violet and magenta hues sit beside purple */
}
:root[data-theme="dark"] { color-scheme: dark; }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--fg); font: 13.5px/1.45 var(--sans); }
a { color: var(--accent); text-decoration: none; } a:hover { text-decoration: underline; }
code, pre, .mono { font-family: var(--mono); font-size: 12.5px; }
pre { margin: 0; white-space: pre-wrap; word-break: break-word; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: var(--bg3); border: 1px solid var(--line2); border-radius: 6px; padding: 5px 10px; cursor: pointer; }
button:hover { border-color: var(--accent); } button:disabled { opacity: .5; cursor: default; }
button.primary { background: var(--accent2); border-color: var(--accent2); color: #fff; }
button.danger { border-color: var(--err); color: var(--err); }
button.small { padding: 2px 8px; font-size: 12px; }
a.btn { display: inline-block; background: var(--bg3); border: 1px solid var(--line2); border-radius: 6px; padding: 5px 10px; text-decoration: none; color: inherit; cursor: pointer; white-space: nowrap; }
a.btn:hover { border-color: var(--accent); }
a.btn.primary { background: var(--accent2); border-color: var(--accent2); color: #fff; font-weight: 600; }
a.btn.small { padding: 2px 8px; font-size: 12px; }
a.btn.big { padding: 10px 18px; font-size: 15px; }
.pdfbar { display: flex; gap: 12px; align-items: center; padding: 12px 16px; border: 1px solid var(--accent2); border-radius: var(--radius); background: color-mix(in srgb, var(--accent2) 10%, transparent); margin-bottom: 12px; }
.steps li { margin: 6px 0; }
.steps li pre.small { font-size: 11px; max-height: 240px; overflow: auto; margin: 4px 0 0; }
.plan { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
input, select, textarea { background: var(--bg); border: 1px solid var(--line2); border-radius: 6px; padding: 5px 8px; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
textarea.code { font-family: var(--mono); font-size: 12.5px; width: 100%; min-height: 320px; tab-size: 4; }
label.field { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--fg2); }
label.field > input, label.field > select { min-width: 110px; }
label.check { display: inline-flex; gap: 6px; align-items: center; font-size: 12px; color: var(--fg2); }
.boot { padding: 40px; color: var(--fg3); }

/* layout (changelog v1.199): the top bar across the top, then three columns: the project tree
   (nav.ptree-side), the content (main.main) and the AI lab helper (aside.helper, engineers and
   up). The columns' widths are --tree-col and --helper-col, set by the classes main.js, the tree
   and the helper put on #app (.tree-closed, .tree-drawer, .helper-open, .helper-closed) and by
   the breakpoints below; the helper's own width is --helper-w (app.style, helper.js), and the
   docked tree's is --tree-w once the person drags its edge (app.style, projecttree.js, v1.201;
   unset, the defaults below). The top bar grows to fit its tabs (changelog v1.121): they wrap
   onto a second row instead of scrolling out of sight.
     1400 px and up    tree docked at 248 px; the open helper docks too
     901 to 1399 px    tree docked (220 px below 1100); the open helper floats over the content
                       from its 40 px rail on the right
     641 to 900 px     the tree is a 40 px rail that opens as an overlay; the helper as above
     640 px and below  no tree column: the top bar's Projects button opens it as a drawer; the
                       helper's rail stays on the right, so a 390 px phone keeps 350 px */
.app { display: grid; grid-template-rows: auto minmax(0, 1fr); grid-template-columns: var(--tree-col) minmax(0, 1fr) var(--helper-col); height: 100vh; --tree-col: var(--tree-w, 248px); --helper-col: 0px; }
.app.tree-closed { --tree-col: 40px; }
.app.helper-open { --helper-col: var(--helper-w, 380px); }
.app.helper-closed { --helper-col: 40px; }
.app > .boot { grid-column: 1 / -1; }
.topbar { grid-row: 1; grid-column: 1 / -1; display: flex; align-items: center; gap: 6px 14px; padding: 6px 14px; min-height: 48px; background: var(--bg2); border-bottom: 1px solid var(--line); }
.brand { display: flex; align-items: center; gap: 8px; font-weight: 600; letter-spacing: .2px; }
.brand svg { width: 22px; height: 22px; }
.brand small { color: var(--fg3); font-weight: 400; }
/* Every core tab stays in view (changelog v1.121: seventeen tabs no longer fit one row of an
   ordinary display, and the bar used to scroll the last ones away with no scrollbar). The tab
   list takes the room between the brand and the controls and wraps (two rows on a 1920 px
   display); below 1760 px, where that would be three, it has a full-width row of its own under
   them: one row down to about 1300 px, two below. */
.tabs { display: flex; flex-wrap: wrap; align-content: center; gap: 2px; flex: 1 1 0; min-width: 0; }
.tabs a { padding: 5px 9px; border-radius: 6px; color: var(--fg2); white-space: nowrap; }
/* the tabs and controls sit in .topmenu, a plain pass-through here and More's sheet on a phone (v1.280) */
.topmenu { display: contents; }
.topmenu > .controls { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; margin-left: auto; }
/* v1.289: the search box (find.js) sits right of the tabs, before the controls */
@media (min-width: 641px) {
  .topbar > .topsearch { order: 5; margin-left: auto; }
  .topmenu > .controls { order: 6; margin-left: 0; }
}
@media (max-width: 1760px) {
  .topbar { flex-wrap: wrap; }
  .topmenu > .tabs { order: 10; flex: 1 1 100%; }
}
.tabs a:hover { background: var(--bg3); text-decoration: none; }
.tabs a.active { background: var(--bg3); color: var(--fg); box-shadow: inset 0 -2px 0 var(--accent); }
.tabs a .badge { margin-left: 5px; }
/* An applet shown in the main tab bar (manifest tab_bar, changelog v1.65: the GPU tab).
   It looks like a core tab; switched off (admins only) it is struck through, as its row in the
   project tree is. */
.tabs a.applet-tab.off { color: var(--fg3); text-decoration: line-through; }
.tabs a.applet-tab.off:hover { color: var(--fg2); text-decoration: line-through; }
/* The project tree (changelog v1.199, projecttree.js): the head (search, + Project, All
   projects, fold to the rail), Starred, Tools and Projects, the foot. Only the body scrolls, so
   the head and the foot stay; a long list never widens the page. A row is the chevron button
   then the link: the kind as a 3 px bar in var(--pk), the title in --fg (blue text on --bg3 is
   about 4.2:1), the family-hue dot (a tool project, which has none, shows its kind's colour) and
   the star (no count since v1.201); the selected row takes a --pk tint. Docked, its right edge is
   the resize handle (v1.201), hidden on the rail and in the drawer. */
nav.ptree-side { grid-row: 2; grid-column: 1; position: relative; display: flex; min-width: 0; min-height: 0; background: var(--bg2); border-right: 1px solid var(--line); }
.ptree-panel:focus { outline: none; }
.ptree-panel { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.ptree-head { flex: none; display: flex; flex-direction: column; gap: 6px; padding: 10px 10px 8px; border-bottom: 1px solid var(--line); }
.ptree-head input.ptree-search { width: 100%; min-width: 0; }
/* a tree dragged narrow (v1.201) wraps the fold button under the links, still at the right */
.ptree-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 10px; font-size: 12.5px; min-width: 0; }
.ptree-actions a { color: var(--fg2); white-space: nowrap; }
.ptree-actions a:hover { color: var(--fg); }
.ptree-actions a.active { color: var(--fg); font-weight: 600; text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
.ptree-actions .spacer { flex: 1 1 auto; }
.ptree-actions button.ghost, .ptree-collapse { background: transparent; border-color: transparent; color: var(--fg2); padding: 0 6px; margin-left: auto; }
.ptree-actions button.ghost:hover { border-color: var(--line2); color: var(--fg); }
.ptree-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 4px 6px 10px; }
.ptree-count { padding: 6px 6px 2px; }
.ptree-group { margin-top: 6px; }
.ptree-gtitle, button.ptree-gfold { display: flex; align-items: center; gap: 6px; width: 100%; padding: 6px 6px 3px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--fg3); }
button.ptree-gfold { background: transparent; border: 0; border-radius: 4px; text-align: left; cursor: pointer; }
button.ptree-gfold:hover { color: var(--fg); background: var(--bg3); }
.ptree-chev { display: inline-block; width: 10px; }
ul.ptree-list, ul.ptree-kids { list-style: none; margin: 0; padding: 0; }
ul.ptree-kids { padding-left: 14px; }
ul.ptree-kids[hidden] { display: none; }
.ptree-row { display: flex; align-items: center; gap: 1px; min-width: 0; margin: 1px 0; }
button.ptree-fold { flex: none; width: 18px; height: 24px; padding: 0; border: 0; border-radius: 4px; background: transparent; color: var(--fg3); font-size: 11px; line-height: 1; }
button.ptree-fold:hover { color: var(--fg); background: var(--bg3); }
.ptree-nofold { flex: none; width: 18px; }
a.ptree-link { flex: 1 1 auto; display: flex; align-items: center; gap: 6px; min-width: 0; padding: 3px 6px 3px 7px; border-left: 3px solid var(--pk, var(--line2)); border-radius: 0 6px 6px 0; color: var(--fg); font-size: 13px; line-height: 18px; }
a.ptree-link:hover { text-decoration: none; background: color-mix(in srgb, var(--pk, var(--fg3)) 12%, var(--bg3)); }
a.ptree-link.active { background: color-mix(in srgb, var(--pk, var(--fg3)) 24%, transparent); font-weight: 600; }
a.ptree-link:focus-visible, button.ptree-fold:focus-visible, button.ptree-gfold:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ptree-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.ptree-link.off .ptree-title { color: var(--fg3); text-decoration: line-through; }
a.ptree-link .pstar { flex: none; color: var(--fg2); font-size: 11px; }
a.ptree-link.pk-tool .pdot.ph-none { background: var(--pk); }
li.ptree-item.context > .ptree-row a.ptree-link { opacity: .55; font-weight: 400; }
/* Changelog v1.204: a row's scheduled tasks (a clock and the count, its words on hover; only
   paused ones: hollow, a pause mark) and an inactive project (its title in --fg3, never struck
   through, which is "server part off", with a small "inactive" tag). The project page's head
   and the #/p table reuse them. */
.ptree-sched { flex: none; display: inline-flex; align-items: center; gap: 2px; padding: 0 5px 0 4px; border-radius: 999px; border: 1px solid transparent; background: var(--bg3); color: var(--fg2); font-size: 11px; line-height: 15px; font-variant-numeric: tabular-nums; cursor: default; }
.ptree-sched .ico { display: inline-flex; }
.ptree-sched.paused { background: transparent; border-color: var(--line2); color: var(--fg3); }
/* changelog v1.218: the tree's badge opens the project's Schedules tab */
.ptree-sched.link { cursor: pointer; }
.ptree-sched.link:hover { color: var(--fg); border-color: var(--line2); }
a.ptree-link.inactive .ptree-title { color: var(--fg3); }
.ptree-inactive { flex: none; padding: 0 5px; border-radius: 999px; border: 1px dashed var(--line2); color: var(--fg3); font-size: 10.5px; line-height: 14px; }
.ptree tr.inactive > td { color: var(--fg3); }
.ptree tr.inactive > td a { color: var(--fg2); }
/* Team channels P5: the Slack channels group. A row's dot says its state (live filled --ok; held
   filled --q-warn with a ring, so it is never colour alone; unbound hollow), an admin channel a
   small solid tag, its open requests an inbox badge like the clock's; the foot holds + Channel and
   All channels. The channel page reuses the dot in its head. */
a.ptree-link.ptree-chan { --pk: var(--line2); }
.ptree-cdot { flex: none; display: inline-block; width: 8px; height: 8px; border-radius: 50%; box-sizing: border-box; }
.ptree-cdot.live { background: var(--ok); }
.ptree-cdot.held { background: var(--q-warn); box-shadow: 0 0 0 2px color-mix(in srgb, var(--q-warn) 40%, transparent); }
.ptree-cdot.unbound { background: transparent; border: 1.5px solid var(--fg3); }
.ptree-tag { flex: none; padding: 0 5px; border-radius: 999px; border: 1px solid var(--line2); color: var(--fg3); font-size: 10.5px; line-height: 14px; }
.ptree-req { flex: none; display: inline-flex; align-items: center; gap: 2px; padding: 0 5px 0 4px; border-radius: 999px; background: var(--bg3); color: var(--fg2); font-size: 11px; line-height: 15px; font-variant-numeric: tabular-nums; cursor: default; }
.ptree-req .ico { display: inline-flex; }
.ptree-cfoot { display: flex; flex-wrap: wrap; gap: 2px 12px; padding: 4px 6px 2px 25px; font-size: 12.5px; }
.ptree-cfoot a { color: var(--fg2); white-space: nowrap; }
.ptree-cfoot a:hover { color: var(--fg); }
.ptree-cfoot a.active { color: var(--fg); font-weight: 600; text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
.chead h1 { margin-right: 4px; overflow-wrap: anywhere; }
/* a Slack name runs to 80 characters: the name and the identity wrap, never scroll the page */
.chead .row.tight > h1, .chead .row.tight > .mono { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }
.chead .ptree-cdot { width: 10px; height: 10px; }
.cnote { margin: 2px 0 4px; overflow-wrap: anywhere; }
.channel-tabs, .csub { flex-wrap: wrap; }
.cperm-group { border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; margin-bottom: 6px; background: var(--bg2); }
.cperm-group.on { border-color: var(--line2); }
.cperm-head > * { min-width: 0; }
ul.cperm-tools { list-style: none; margin: 6px 0 2px; padding: 0 0 0 26px; display: grid; gap: 4px; }
ul.cperm-tools[hidden] { display: none; }
li.cperm-tool { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
li.cperm-tool .mono, .cperm-never .mono { overflow-wrap: anywhere; }
.cperm-never { opacity: .6; }
.cperm-missing { margin: 4px 0 0 26px; }
.creq { margin-bottom: 8px; }
.creq-note { margin: 4px 0; padding: 4px 10px; border-left: 3px solid var(--line2); color: var(--fg2); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 12em; overflow-y: auto; }
.creq-form > input { min-width: 0; }
.climits { flex-wrap: wrap; }
.climit input { max-width: 100%; }
.phead .ptree-sched { font-size: 12px; line-height: 18px; padding: 0 7px 0 6px; }
a.phead-sched:hover { text-decoration: none; }
a.phead-sched:hover .ptree-sched { color: var(--fg); border-color: var(--line2); }
/* The resize handle (v1.201): 6 px over the tree's border (14 px for a finger), drawn on hover,
   focus and while dragging; touch-action none keeps a finger's drag from scrolling the page. */
.ptree-resize { position: absolute; top: 0; bottom: 0; right: -3px; width: 6px; z-index: 20; cursor: col-resize; touch-action: none; background: transparent; }
.ptree-resize:hover, .app.tree-resizing .ptree-resize { background: var(--line2); }
.ptree-resize:focus-visible { outline: none; background: var(--accent); }
@media (pointer: coarse) { .ptree-resize { right: -7px; width: 14px; } }
.app.tree-closed nav.ptree-side .ptree-resize { display: none; }
.app.tree-resizing, .app.tree-resizing * { cursor: col-resize; user-select: none; }
.ptree-foot { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; padding: 6px 10px 8px; border-top: 1px solid var(--line); font-size: 11.5px; color: var(--fg3); }
.ptree-foot a { color: var(--fg2); }
/* Folded to its rail (.tree-closed, or below 900 px): one button that opens it again. */
button.ptree-rail { display: none; width: 40px; height: 100%; border: 0; border-radius: 0; background: var(--bg2); color: var(--fg2); padding: 10px 0 0; align-items: flex-start; justify-content: center; }
button.ptree-rail:hover { color: var(--accent); }
.app.tree-closed nav.ptree-side .ptree-rail { display: flex; }
.app.tree-closed nav.ptree-side .ptree-panel { display: none; }
.ptree-scrim { display: none; position: fixed; left: 0; right: 0; bottom: 0; top: var(--topbar-h, 48px); background: rgba(0, 0, 0, .45); z-index: 40; }
button.tree-toggle { display: none; align-items: center; gap: 6px; }
button.tree-toggle .ico { display: inline-flex; }

/* Projects (changelog v1.159, docs/projects/design.md section 2). A hue reaches an element
   only through a class: .ph0-.ph7 set --ph from the palette (.ph-none: grey, no project), and
   every mark below paints with var(--ph). Sub-projects (.psub) keep their parent's hue and add
   a dotted ring; diagonal hatching is reserved for undeclared root work (Projects P6). */
.ph0 { --ph: var(--proj-h0); } .ph1 { --ph: var(--proj-h1); } .ph2 { --ph: var(--proj-h2); } .ph3 { --ph: var(--proj-h3); }
.ph4 { --ph: var(--proj-h4); } .ph5 { --ph: var(--proj-h5); } .ph6 { --ph: var(--proj-h6); } .ph7 { --ph: var(--proj-h7); }
.ph-none { --ph: var(--proj-none); }
/* Changelog v1.199: a project's kind. A mark's outline, pill and text take var(--pk). */
.pk-tool { --pk: var(--kind-tool); }
.pk-work { --pk: var(--kind-work); }
/* A tool project has no family hue: its dot is its kind's blue everywhere (the head, the #/p
   table, chips), as in the tree and the Used by pills, never the grey of no project. */
.ph-none.pk-tool { --ph: var(--kind-tool); }
.pdot { display: inline-block; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--ph, var(--proj-none)); vertical-align: middle; }
.pdot.psub { background: transparent; border: 2px dotted var(--ph, var(--proj-none)); width: 10px; height: 10px; }
/* Project pills: a project's Used by and Uses strips (.pusedby; .kitprojects on the older
   pages) and its sub-project strip. Scoped to those places so a chip elsewhere never takes the
   pill's look. Since v1.199 a pill takes its kind's colour (--pk: blue for a tool project, green
   for the others; --proj while the kind is unknown), and its dot the family's hue. */
.kitprojects a.proj, .pusedby a.proj, .pstrip a.proj { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 2px 9px; font-size: 12.5px; line-height: 18px; font-weight: 600; white-space: nowrap; color: var(--pk, var(--proj)); border: 1px solid var(--pk, var(--proj)); border-radius: 999px; background: color-mix(in srgb, var(--pk, var(--proj)) 8%, transparent); }
.kitprojects a.proj::before, .pusedby a.proj::before, .pstrip a.proj::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ph, var(--proj-none)); }
.kitprojects a.proj.pk-tool.ph-none::before, .pusedby a.proj.pk-tool.ph-none::before, .pstrip a.proj.pk-tool.ph-none::before { background: var(--pk); }
.kitprojects a.proj.psub::before, .pusedby a.proj.psub::before, .pstrip a.proj.psub::before { background: transparent; border: 2px dotted var(--ph, var(--proj-none)); width: 9px; height: 9px; box-sizing: border-box; }
.kitprojects a.proj > span, .pusedby a.proj > span, .pstrip a.proj > span { overflow: hidden; text-overflow: ellipsis; max-width: 22ch; }
.kitprojects a.proj:hover, .pusedby a.proj:hover, .pstrip a.proj:hover { text-decoration: none; background: color-mix(in srgb, var(--pk, var(--proj)) 20%, transparent); box-shadow: 0 0 0 1px var(--pk, var(--proj)); }
.kitprojects a.proj.active, .pusedby a.proj.active, .pstrip a.proj.active { background: color-mix(in srgb, var(--pk, var(--proj)) 30%, transparent); color: var(--fg); }
.kitprojects a.proj.archived, .pusedby a.proj.archived, .pstrip a.proj.archived { color: var(--fg3); border-color: var(--line2); background: transparent; text-decoration: line-through; }
.pusedby { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.pusedby .label { color: var(--fg2); font-size: 12.5px; font-weight: 600; }
/* A kind's pill (projects.js kindPill): blue "tool", green "experiment", "analysis", "watcher",
   "report"; on --bg2, where both colours read as text. */
.pill.kpill { color: var(--pk); border-color: var(--pk); background: var(--bg2); }
/* A row's project chip on Logs, Jobs, Audit and Reports: the tag pill plus the family's dot,
   the title in full. */
a.tag.pill.pchip { margin-right: 6px; border-color: var(--pk, var(--line2)); }
a.tag.pill.pchip::before { content: ''; display: inline-block; width: 7px; height: 7px; margin-right: 5px; border-radius: 50%; background: var(--ph, var(--proj-none)); vertical-align: 0; }
a.tag.pill.pchip.psub::before { background: transparent; border: 1.5px dotted var(--ph, var(--proj-none)); width: 8px; height: 8px; box-sizing: border-box; }
a.tag.pill.pchip:hover { text-decoration: none; border-color: var(--pk, var(--proj)); box-shadow: 0 0 0 1px var(--pk, var(--proj)); color: var(--fg); }
/* The project page head (tabs/projects.js) */
.phead { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.phead .crumb { flex: 1 1 100%; font-size: 12px; color: var(--fg3); }
h1.ptitle { overflow-wrap: anywhere; }
h1.ptitle.editable { cursor: text; border-bottom: 1px dashed var(--line2); }
h1.ptitle.editable:hover { border-bottom-color: var(--proj); }
input.ptitle-edit { font-size: 18px; font-weight: 600; min-width: min(28ch, 100%); max-width: 100%; }
.pswatches { display: inline-flex; gap: 4px; align-items: center; }
.pswatches button.sw { width: 18px; height: 18px; padding: 0; border-radius: 50%; background: var(--ph, var(--proj-none)); border: 2px solid transparent; }
.pswatches button.sw:hover { border-color: var(--fg2); }
.pswatches button.sw.on, .pswatches button.sw[aria-pressed="true"] { border-color: var(--fg); box-shadow: 0 0 0 1px var(--bg2) inset; }
.powners { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px; }
.pill.unconfirmed { color: var(--warn); border-style: dashed; border-color: color-mix(in srgb, var(--warn) 50%, transparent); }
/* Sub-project strip, the All projects tree, the come-play badge, a toolkit's strip */
.pstrip { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.ptree td:first-child { white-space: nowrap; }
.ptree td:first-child .pdot { margin-right: 6px; }
.ptree tr.sub td:first-child { padding-left: 26px; }
/* v1.199: beside the project tree a long title wraps, its dot hanging, so the table fits 1280 px
   instead of hiding its last columns behind a sideways scroll (live titles run to 58 characters). */
.ptree th:first-child { width: 26%; }
.ptree tr:not(.pwhy) > td:first-child { padding-left: 23px; text-indent: -15px; }
.ptree tr.sub:not(.pwhy) > td:first-child { padding-left: 41px; }
.ptree tr:not(.pwhy) > td:first-child > a { white-space: normal; }
.ptree td:first-child .pill { text-indent: 0; }
.ptree td.nowrap a.tag.pill.pchip { white-space: nowrap; }
/* Changelog v1.167: a project's Overview leads with its findings. Marks take the project's hue
   (.phN sets --ph); the shape says the kind, hollow while drafted; hit targets larger than marks. */
.pf-highlights { min-width: 260px; }
.pf-heads { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-bottom: 8px; }
.pf-head .pf-num, .pf-metric .pf-num { font-size: 26px; font-weight: 650; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--fg); }
.pf-head .pf-lab, .pf-metric .pf-lab { font-size: 12px; color: var(--fg2); }
.pf-latest { margin: 0 0 8px; padding-left: 18px; } .pf-latest li { margin: 3px 0; }
.pf-totals { margin-top: 4px; }
/* changelog v1.170: a project's state and its uses */
.ps-card { flex: 2 1 420px; } .ps-uses { flex: 1 1 300px; }
.ps-summary { font-weight: 600; margin-bottom: 6px; }
.ps-sec { margin: 6px 0; } .ps-sec ul { margin: 2px 0 0; padding-left: 18px; } .ps-sec li { margin: 2px 0; }
.ps-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg3); font-weight: 600; }
.ps-limits li { color: var(--fg); } .ps-limits .ps-label { color: color-mix(in srgb, #f59e0b 70%, var(--fg3)); }
.ps-when { margin-top: 6px; } .ps-when .warn { color: color-mix(in srgb, #f59e0b 80%, var(--fg)); }
.ps-facts { margin-top: 8px; } .ps-facts > summary { cursor: pointer; }
.ps-script { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; padding: 4px 0; border-top: 1px solid var(--line); }
.ps-script .ps-runs { margin-left: auto; }
.ps-link { padding: 4px 0; border-top: 1px solid var(--line); }
/* changelog v1.170b: proof labels */
.ps-sec li.lv { list-style: none; margin-left: -18px; }
.ps-level .pill { font-size: 10.5px; padding: 0 6px; text-transform: none; letter-spacing: 0; }
.ps-ev { margin-left: 6px; } .ps-ev .warn, .ps-flag { color: var(--warn); }
.ps-counts { font-weight: 400; text-transform: none; letter-spacing: 0; }
.tag.for { background: color-mix(in srgb, var(--lime) 18%, transparent); border: 1px dashed color-mix(in srgb, var(--lime) 60%, var(--line2)); margin-right: 4px; }
.pf-head.drafted .pf-num { color: var(--fg2); font-style: italic; }
.pf-unconfirmed { color: var(--fg3); font-style: italic; }
.pf-timeline { position: relative; width: 100%; height: 76px; }
.pf-axisline { position: absolute; left: 14px; right: 14px; top: 42px; height: 1px; background: var(--line2); }
.pf-tick { position: absolute; top: 38px; width: 1px; height: 9px; background: var(--line2); }
.pf-ticklab { position: absolute; top: 56px; transform: translateX(-50%); color: var(--fg3); font-size: 11px; white-space: nowrap; }
.pf-today { position: absolute; right: 14px; top: 0; color: var(--fg3); font-size: 11px; }
.pf-hit { position: absolute; width: 24px; height: 24px; margin-left: -12px; display: flex; align-items: center; justify-content: center; cursor: default; }
.pf-hit svg { overflow: visible; }
.pf-activity { width: 100%; height: 104px; display: block; }
.pf-weeklabs { display: grid; grid-template-columns: repeat(16, 1fr); gap: 0; color: var(--fg3); font-size: 11px; margin-top: 2px; }
.pf-weeklabs > span { white-space: nowrap; overflow: visible; }
.pf-axis { stroke: var(--line2); stroke-width: 1; }
.pf-mark { fill: var(--ph, var(--proj)); stroke: var(--bg2); stroke-width: 2; }
.pf-mark.hollow { fill: var(--bg2); stroke: var(--ph, var(--proj)); stroke-width: 2; stroke-dasharray: 2 2; }
.pf-ring { fill: none; stroke: var(--ph, var(--proj)); stroke-width: 1.5; }
.pf-target { fill: transparent; }
.pf-hit:hover .pf-mark { stroke: var(--fg); }
.pf-bar { fill: var(--ph, var(--proj)); }
.pf-week:hover .pf-bar { opacity: .8; }
.pf-legend { display: flex; flex-wrap: wrap; gap: 12px; margin: 2px 0 10px; }
.pf-legend-item { display: inline-flex; align-items: center; gap: 4px; }
.pf-legend-mark .pf-mark { fill: var(--fg2); } .pf-legend-mark .pf-mark.hollow { fill: transparent; stroke: var(--fg2); } .pf-legend-mark .pf-ring { stroke: var(--fg2); }
.pf-list { display: flex; flex-direction: column; }
.pf-row { display: grid; grid-template-columns: 92px 1fr auto; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line); align-items: start; }
.pf-row .pf-when { font-size: 12px; color: var(--fg2); display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.pf-row .pf-title { font-weight: 600; }
.pf-row .pf-summary { color: var(--fg2); margin-top: 2px; }
.pf-row .pf-evs { margin-top: 4px; }
.pf-row.drafted .pf-title { font-style: italic; }
.pf-drafted { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
/* changelog v1.218: how a finding was confirmed, or what it waits for; words carry it, colour helps */
.pf-status { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; }
.pf-badge { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border-radius: 999px; border: 1px solid var(--line2); color: var(--fg2); font-size: 11.5px; }
.pf-badge.self::before, .pf-badge.silence::before, .pf-badge.person::before { content: '\2713'; font-weight: 700; }
.pf-badge.self, .pf-badge.silence { color: color-mix(in srgb, var(--info) 80%, var(--fg)); border-color: color-mix(in srgb, var(--info) 45%, transparent); }
.pf-badge.person { color: color-mix(in srgb, var(--ok) 80%, var(--fg)); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.pf-badge.verdict, .pf-badge.held { color: color-mix(in srgb, var(--warn) 80%, var(--fg)); border-color: color-mix(in srgb, var(--warn) 50%, transparent); }
.pf-badge.check { border-style: dashed; }
.pf-acts { display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.pf-labok { color: color-mix(in srgb, var(--info) 75%, var(--fg2)); }
.pf-metric { text-align: right; min-width: 110px; }
@media (max-width: 640px) { .pf-row { grid-template-columns: 1fr; } .pf-metric { text-align: left; } }
/* Changelog v1.166: a tool project's panel on a project page (projects.panels) carries a mark in
   the tool projects' colour (lime until v1.199, --kind-tool since); + panel picks them. */
.subtabs a.subtab.kitpanel::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 2px; background: var(--kind-tool); margin-right: 6px; vertical-align: 1px; }
.subtabs a.subtab.addpanel { color: var(--fg3); font-size: 12px; }
.subtabs a.subtab.addpanel:hover { color: var(--fg); }
.kitfrom { margin: -2px 0 6px; }
/* changelog v1.169: a page's link to its Confluence page */
a.confl { font-size: 12.5px; font-weight: 600; padding: 1px 8px; border-radius: 999px; border: 1px solid color-mix(in srgb, #2684ff 60%, var(--line2)); color: #4c9aff; white-space: nowrap; }
a.confl:hover { text-decoration: none; background: color-mix(in srgb, #2684ff 14%, transparent); }
.confl.none { white-space: nowrap; }
/* A toolkit's Overview (changelog v1.167): what it can do, as tiles, each with what does it */
.kitcaps { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; }
.kitcap { border: 1px solid var(--line); border-left: 3px solid var(--kind-tool); border-radius: 8px; padding: 10px 12px; background: var(--bg2); display: flex; flex-direction: column; gap: 6px; }
.kitcap-title { font-weight: 650; }
.kitcap-via { display: flex; flex-wrap: wrap; gap: 4px; margin-top: auto; }
a.kitvia { font-size: 11.5px; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--line2); color: var(--fg2); white-space: nowrap; }
a.kitvia:hover { text-decoration: none; border-color: var(--fg3); color: var(--fg); }
a.kitvia.panel { border-color: color-mix(in srgb, var(--kind-tool) 60%, var(--line2)); }
a.kitvia.script::before { content: 'script '; color: var(--fg3); font-family: inherit; }
/* v1.199: beside the project tree the Tools card takes the larger share of its row, so its
   table (name, tier, calls, failed, last) fits at 1280 px instead of scrolling sideways. */
.row > .card.kittools { flex: 2 1 520px; }
.kitbar { position: relative; display: inline-flex; align-items: center; min-width: 96px; height: 16px; border-radius: 4px; background: var(--bg3); overflow: hidden; }
.kitbar-fill { position: absolute; left: 0; top: 0; bottom: 0; background: color-mix(in srgb, var(--kind-tool) 45%, transparent); border-radius: 4px; }
.kitbar-n { position: relative; padding: 0 6px; font-size: 11.5px; font-variant-numeric: tabular-nums; }
details.kitparts > summary { cursor: pointer; font-weight: 600; }
.row.tight.pf-used > span.muted { flex: 1 1 12em; min-width: 0; }
details.kitparts[open] > summary { margin-bottom: 8px; }
/* Changelog v1.164: stars, the project menu (a right click on any project pill or tree row),
   and the deep search's "found in" line under a matching row; a parent kept only for its
   matching sub-project is greyed. */
.pstar { font-size: 11px; line-height: 1; }
.ptree .pstar { margin-right: 4px; color: var(--fg2); }
button.pstar-btn { white-space: nowrap; }
button.pstar-btn.on { border-color: var(--proj); color: var(--proj); }
.pstarred { margin: 0 0 8px; }
.pmenu { position: fixed; z-index: 1000; min-width: 200px; padding: 4px; background: var(--bg2); border: 1px solid var(--line2); border-radius: var(--radius); box-shadow: var(--shadow); display: flex; flex-direction: column; }
.pmenu-head { padding: 4px 8px 6px; font-size: 12px; color: var(--fg3); border-bottom: 1px solid var(--line); margin-bottom: 4px; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pmenu-item { text-align: left; background: transparent; border: 0; border-radius: 4px; padding: 5px 8px; }
.pmenu-item:hover, .pmenu-item:focus { background: var(--bg3); outline: none; }
.pmenu-sep { border-top: 1px solid var(--line); margin: 4px 0; }
.pmenu-item.danger { color: var(--err); }
/* v1.289: a chat is held for its menu, so a long press selects no text and shows no callout */
.chatrow { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
@keyframes askring { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 70%, transparent); } 100% { box-shadow: 0 0 0 12px transparent; } }
.ask-ring { animation: askring .9s ease-out 2; }
@media (prefers-reduced-motion: reduce) { .ask-ring { animation: none; } }
.ptree tr.context td { opacity: .55; }
.ptree tr.pwhy td { padding-top: 0; border-top: 0; font-size: 12px; color: var(--fg2); white-space: normal; }
.ptree tr.pwhy.sub td { padding-left: 26px; }
.ptree tr.pwhy mark { background: color-mix(in srgb, var(--accent) 30%, transparent); color: inherit; border-radius: 2px; padding: 0 1px; }
.pwhy-hit b { font-weight: 600; color: var(--fg); }
.pbadge { display: inline-block; padding: 0 7px; border-radius: 999px; font-size: 11px; border: 1px solid var(--line2); color: var(--fg2); white-space: nowrap; }
.pbadge.come { color: var(--proj); border-color: color-mix(in srgb, var(--proj) 50%, transparent); background: color-mix(in srgb, var(--proj) 10%, transparent); }
.kitprojects { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.kitprojects .label { color: var(--fg2); font-size: 12.5px; font-weight: 600; }
/* The Overview's My projects and Come play with these (tabs/overview.js), side by side */
.pcards > .slot > .card { flex: 1 1 340px; }
.plist { display: flex; flex-direction: column; }
.prow { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.prow:last-child { border-bottom: 0; }
.prow.sub { padding-left: 18px; }
.prow .ptitle-link { font-weight: 600; }
.prow .pintro { flex: 1 1 100%; color: var(--fg2); }
/* The boat queue's live card (changelog v1.162 part c, queuecard.js; docs/projects/design.md
   section 8): the Overview, a project's Queue tab, Boat Sync's Projects on boats and the job page.
   HTML blocks, not SVG: each claim is a focusable button placed by left and width in percent of
   the window, its hue only through .ph0-.ph7 / .ph-none (--ph). A running change is solid with
   --proj-on ink, a veil over the part still ahead of now, dashed once past its estimate; steady
   is an outline over a 22% tint, quiet adds dots (pulls deferred); waiting is outlined with its
   position; parked is grey and dashed; a booking is lined; a service that yields has a lime
   outline; another project's run on a project page is outlined with --fg2 text (never opacity);
   no project is --bg3 with a --fg3 border; a sub-project's run has a dotted left edge; disturbed
   carries a --q-warn ring; undeclared root work is a hatched tick, the only diagonal hatching.
   At 640 px or less, or with [list], the timeline gives way to .qlist. */
.qcard { display: flex; flex-direction: column; gap: 8px; }
.qcard > h3 { flex-wrap: wrap; margin-bottom: 0; }
.qctl { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--fg2); }
.qseg { display: inline-flex; }
.qseg button { border-radius: 0; margin-left: -1px; }
.qseg button:first-child { border-radius: 6px 0 0 6px; margin-left: 0; }
.qseg button:last-child { border-radius: 0 6px 6px 0; }
.qseg button[aria-pressed="true"], .qctl button.qtoggle[aria-pressed="true"] { background: var(--accent2); border-color: var(--accent2); color: #fff; }
.qctl select.qpick { max-width: 14em; padding: 2px 6px; font-size: 12px; }
.qsr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.qstale { font-size: 12px; color: var(--q-warn); }
.qlead { font-size: 12.5px; color: var(--fg); }
ul.qsummary { margin: 0; padding-left: 18px; font-size: 12.5px; color: var(--fg2); }
ul.qsummary li { overflow-wrap: anywhere; }
.qtimeline { display: flex; flex-direction: column; gap: 2px; }
.qbody { position: relative; }
.qlanes { display: flex; flex-direction: column; gap: 2px; }
.qaxis, .qlane, .qgrow { display: grid; grid-template-columns: 160px minmax(0, 1fr); align-items: start; }
.qticks { position: relative; height: 18px; border-bottom: 1px solid var(--line); overflow: hidden; }
.qtick { position: absolute; top: 1px; transform: translateX(-50%); font-size: 11px; color: var(--fg3); white-space: nowrap; }
.qtick.qnowtick { color: var(--accent); font-weight: 600; }
.qhullrow { font-weight: 600; font-size: 12.5px; color: var(--fg); margin-top: 6px; }
.qlabel { font-size: 12px; color: var(--fg2); padding: 5px 8px 0 0; overflow-wrap: anywhere; }
.qlabel button.qfold { padding: 0 6px; font-size: 11px; }
.qtrack { position: relative; min-height: 28px; background: var(--bg); border: 1px solid var(--line); border-radius: 4px; overflow: hidden; }
.qmarks, .qblocks { position: absolute; inset: 0; }
.qmarks { pointer-events: none; }
.qnow { position: absolute; top: 0; bottom: 0; width: 0; border-left: 2px solid var(--accent); pointer-events: none; z-index: 4; }
.qblock { position: absolute; height: 22px; padding: 0 6px; border: 1.5px solid var(--ph, var(--proj-none)); border-radius: 4px; background: var(--bg2); color: var(--fg); font-size: 11.5px; line-height: 18px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; transition: left .4s ease, width .4s ease; }
.qblock > span { position: relative; z-index: 1; }
.qblock:hover { border-color: var(--accent); }
.qblock:focus-visible, .qblock.lit { outline: 2px solid var(--accent); outline-offset: 1px; z-index: 3; }
.qblock.run { background: var(--ph, var(--proj-none)); color: var(--proj-on); }
.qblock .qtail { position: absolute; top: 0; bottom: 0; right: 0; background: var(--q-veil); }
.qblock.m-steady .qtail, .qblock.m-quiet .qtail, .qblock.pnone .qtail, .qblock.other .qtail, .qblock.restricted .qtail { background: color-mix(in srgb, var(--fg) 7%, transparent); }
.qblock.run.overdue { border-style: dashed; border-color: var(--fg); }
.qblock.run.m-steady, .qblock.run.m-quiet { background: color-mix(in srgb, var(--ph, var(--proj-none)) 22%, var(--bg2)); color: var(--fg); border-width: 2px; }
.qblock.run.m-quiet { background-image: radial-gradient(var(--ph, var(--proj-none)) 1px, transparent 1.4px); background-size: 6px 6px; }
.qblock.wait.unk { border-style: dotted; }
.qblock.park { background: var(--bg3); border: 1.5px dashed var(--fg3); color: var(--fg2); }
.qblock.book { background-color: var(--bg2); background-image: repeating-linear-gradient(0deg, color-mix(in srgb, var(--ph, var(--proj-none)) 40%, transparent) 0 2px, transparent 2px 6px); color: var(--fg); border-width: 2px; }
.qblock.book.queued { border-style: dashed; }
.qblock.par { box-shadow: inset 3px 0 0 var(--fg), inset -3px 0 0 var(--fg); }
.qblock.dist { box-shadow: 0 0 0 2px var(--q-warn); }
.qblock.par.dist { box-shadow: inset 3px 0 0 var(--fg), inset -3px 0 0 var(--fg), 0 0 0 2px var(--q-warn); }
/* these three win over every state and mode above (.run.m-quiet is the most specific there) */
.qblock.other, .qblock.run.other, .qblock.run.m-steady.other, .qblock.run.m-quiet.other { background: var(--bg2); background-image: none; color: var(--fg2); }
.qblock.pnone, .qblock.run.pnone, .qblock.run.m-steady.pnone, .qblock.run.m-quiet.pnone, .qlease.pnone { background: var(--bg3); background-image: none; color: var(--fg); border-color: var(--fg3); }
.qblock.restricted, .qblock.run.restricted, .qblock.run.m-steady.restricted, .qblock.run.m-quiet.restricted { background: var(--bg3); background-image: none; color: var(--fg2); border-color: var(--line2); }
.qblock.qsvc, .qblock.pnone.qsvc { border-color: var(--lime); }
.qblock.psub { border-left-style: dotted; border-left-width: 3px; }
.qblock.qhid { display: none; }
.qblock.dragging { z-index: 5; transition: none; cursor: grabbing; }
.qbadge { margin-left: 5px; font-weight: 600; }
.qmark { position: absolute; top: 0; bottom: 0; width: 6px; margin-left: -3px; background: repeating-linear-gradient(45deg, var(--fg2) 0 2px, transparent 2px 4px); }
.qlink { position: absolute; border-left: 1px dashed var(--fg3); border-bottom: 1px dashed var(--fg3); }
.qgpu { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
.qlease { position: absolute; top: 2px; height: 22px; padding: 0 6px; border-radius: 4px; background: var(--ph, var(--proj-none)); color: var(--proj-on); font-size: 11.5px; line-height: 22px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qlease.wait { background: var(--bg2); color: var(--fg); border: 1.5px solid var(--ph, var(--proj-none)); line-height: 19px; }
.qworkers { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg2); white-space: nowrap; overflow: hidden; }
.qworkers .qwtext { overflow: hidden; text-overflow: ellipsis; }
.qslots { display: inline-flex; gap: 3px; flex: none; }
.qslot { width: 11px; height: 11px; border-radius: 3px; border: 1.5px solid var(--line2); }
.qslot.busy { background: var(--ph, var(--proj-none)); border-color: var(--ph, var(--proj-none)); }
.qdrawer { border-top: 1px solid var(--line); padding-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.qdrawer-body { display: flex; flex-direction: column; gap: 6px; }
.qdrawer .kv { font-size: 12.5px; }
.qdrawer .qdist { color: var(--fg); border-left: 3px solid var(--q-warn); padding-left: 6px; }
.qbook { flex-wrap: wrap; }
.qlist { display: none; flex-direction: column; gap: 8px; }
.qlist h4 { margin: 4px 0; font-size: 12.5px; }
.qparts { display: flex; flex-direction: column; gap: 6px; }
.qpart-name { font-size: 12px; color: var(--fg2); }
.qrows { display: flex; flex-direction: column; gap: 3px; }
.qli { display: flex; align-items: flex-start; gap: 6px; padding-left: 8px; border-left: 3px solid var(--ph, var(--proj-none)); }
.qli.other { border-left-style: dotted; }
.qrow { flex: 1 1 auto; min-width: 0; text-align: left; background: transparent; border: 0; padding: 2px 0; font-size: 12.5px; color: var(--fg); overflow-wrap: anywhere; }
.qli.holding .qrow { font-weight: 600; }
details.qmenu { flex: none; position: relative; }
details.qmenu > summary { list-style: none; padding: 0 8px; border: 1px solid var(--line2); border-radius: 6px; font-size: 12px; }
details.qmenu > summary::-webkit-details-marker { display: none; }
.qmenu-items { display: flex; flex-direction: column; gap: 4px; padding: 6px 0; }
.qcard.qlistmode .qtimeline, .qcard.qlistmode ul.qsummary { display: none; }
.qcard.qlistmode .qlist { display: flex; }
@media (prefers-reduced-motion: reduce) { .qblock { transition: none; } }
/* Add Project (projectnew.js): the explainer picture, the chat and the picker. SVG marks take
   their colours from these classes, never from var() in a presentation attribute. */
.pnew { display: flex; flex-direction: column; gap: 12px; }
.pnew .explainer { display: block; width: 100%; max-width: 720px; height: auto; }
.pnew .explainer text { fill: var(--fg); font-family: var(--sans); font-size: 11px; }
.ex-shelf { fill: var(--bg3); stroke: var(--line2); stroke-width: 1; }
.ex-kit { fill: var(--bg2); stroke: var(--kind-tool); stroke-width: 1.5; }
.pnew .explainer text.ex-kit-label, .ex-kit-label { fill: var(--kind-tool); font-weight: 600; }
.ex-card { fill: var(--bg2); stroke: var(--kind-work); stroke-width: 1.5; }
.ex-line { fill: none; stroke: var(--kind-work); stroke-width: 1.2; stroke-dasharray: 3 3; opacity: .8; }
.ex-dot { fill: var(--ph, var(--proj-none)); }
.pnew .explainer text.ex-caption { fill: var(--fg2); }
.pnew .picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: 10px; align-items: end; }
.pnew .picker label.field > input, .pnew .picker label.field > select, .pnew .picker label.field > textarea { width: 100%; min-width: 0; }
.pill.override { color: var(--purple); border-color: color-mix(in srgb, var(--purple) 45%, transparent); }
.subtabs { display: flex; gap: 2px; margin: 8px 0 12px; border-bottom: 1px solid var(--line); }
.subtabs a.subtab { padding: 6px 10px; color: var(--fg2); border-bottom: 2px solid transparent; margin-bottom: -1px; }
.subtabs a.subtab:hover { text-decoration: none; color: var(--fg); } .subtabs a.subtab.active { color: var(--fg); border-bottom-color: var(--accent); }
/* Changelog v1.164: the Settings tab's row. Tool projects carry their mark (lime until v1.199,
   --kind-tool since); System, the one sub-tab that is no tool project and whose fields show
   nowhere else, sits past a divider in a box of its own with "lab-wide, only here". */
.settings-nav { align-items: flex-end; flex-wrap: wrap; }
.settings-nav .navlabel { font-size: 11px; color: var(--fg3); text-transform: uppercase; letter-spacing: .04em; padding: 6px 6px 8px 0; }
.settings-nav a.subtab.kit::before { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 2px; background: var(--kind-tool); margin-right: 6px; vertical-align: 1px; }
.settings-nav a.subtab.kit.active { border-bottom-color: var(--kind-tool); }
.settings-nav a.subtab.part::before { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 2px; background: var(--kind-work); margin-right: 6px; vertical-align: 1px; }
.settings-nav a.subtab.part.active { border-bottom-color: var(--kind-work); }
.settings-nav .navsep { width: 1px; align-self: stretch; background: var(--line2); margin: 4px 10px; }
.settings-nav a.subtab.system { border: 1px dashed var(--fg3); border-bottom: 2px solid transparent; border-radius: 6px 6px 0 0; background: var(--bg3); color: var(--fg); font-weight: 600; }
.settings-nav a.subtab.system .note { color: var(--fg3); font-size: 11px; font-weight: 400; margin-left: 6px; }
.settings-nav a.subtab.system.active { border-color: var(--fg2); border-bottom: 2px solid var(--fg); }
/* System's head line (v1.164): the host facts wrap on a phone */
.syshead { flex-wrap: wrap; }
.syshead > span.muted { flex: 1 1 220px; min-width: 0; overflow-wrap: anywhere; }
/* the "Also matching:" line under a settings search box */
.setelse { margin: -4px 0 10px; }
.setelse a.tag { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 12px; border: 1px solid var(--line2); color: var(--fg); }
.setelse a.tag:hover { text-decoration: none; border-color: var(--accent); }
.setelse a.setelse-kit { border-color: color-mix(in srgb, var(--kind-tool) 60%, transparent); }
.setelse a.setelse-system { border-style: dashed; background: var(--bg3); }
.tag.applet { display: inline-block; padding: 0 6px; margin-right: 6px; border-radius: 4px; font-size: 11px; background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--fg); border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); }
.tag.applet:hover { text-decoration: none; border-color: var(--accent); }
.setting { padding: 8px 0; border-bottom: 1px solid var(--line); } .setting:last-of-type { border-bottom: none; }
.settings-search { width: 100%; max-width: 480px; }
.no-results ul { margin: 6px 0 0 18px; } .no-results li { margin: 2px 0; }
.setting-group { margin-bottom: 10px; }
/* Settings that inherit (changelog v1.161, Projects P4; settings_form.js, projectsettings.js): a
   toolkit's form in two sections, the fields projects may override (a --proj rule beside them)
   then the toolkit-wide ones; a project field's "overridden in N projects" line and its links;
   on a project's Settings tab the line saying where a value comes from, notes, the read-only
   rows and the sub-tab row with Add a toolkit. Tokens only, so both schemes follow; no amber
   "raised" mark (R14). */
.setsec { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; min-width: 0; }
.setsec > h2 { margin: 2px 0 0; font-size: 14px; font-weight: 600; color: var(--fg); }
.setsec > .hint { margin-top: -6px; }
.setsec > .setting-group { margin-bottom: 0; }
.setsec[data-scope="project"] { border-left: 2px solid var(--proj); padding-left: 10px; }
.setsrc { margin-top: 3px; font-size: 12px; color: var(--fg2); overflow-wrap: anywhere; }
.setsrc[data-level="project"] { color: var(--fg); }
.setuse { margin-top: 4px; font-size: 12px; }
.setuse-list { display: flex; flex-wrap: wrap; gap: 4px 12px; padding: 4px 0 0 14px; }
.setnotes { display: flex; flex-direction: column; gap: 4px; }
.setnote { margin-top: 3px; color: var(--fg2); overflow-wrap: anywhere; }
.setting.ro { padding: 6px 0; }
.setro { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; }
.setwrap, .row.tight > .setwrap { flex: 1 1 220px; min-width: 0; overflow-wrap: anywhere; }
.setval, .row.tight > .setval { flex: 0 1 auto; min-width: 0; margin-left: auto; text-align: right; overflow-wrap: anywhere; }
.setnav { align-items: flex-end; }
.setnav > select { margin: 0 0 4px; max-width: 100%; }
.small.ok { color: var(--ok); }
.spacer { flex: 1; }
.search { position: relative; }
.search input { width: 260px; padding-left: 28px; }
.search::before { content: "⌕"; position: absolute; left: 9px; top: 50%; transform: translateY(-50%); color: var(--fg3); font-size: 15px; pointer-events: none; }
.search kbd { position: absolute; right: 8px; top: 6px; font-size: 10px; color: var(--fg3); border: 1px solid var(--line2); border-radius: 4px; padding: 0 4px; }
.live { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--fg3); }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fg3); display: inline-block; }
.dot.on { background: var(--ok); box-shadow: 0 0 8px var(--ok); } .dot.off { background: var(--err); }
.dot.warn { background: var(--warn); }
/* changelog v1.194: the Low RAM light beside Live (main.js memChip) */
.memchip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--warn-ink); text-decoration: none; padding: 1px 8px; border: 1px solid color-mix(in srgb, var(--warn) 55%, transparent); border-radius: 999px; background: color-mix(in srgb, var(--warn) 10%, transparent); white-space: nowrap; }
.memchip:hover { background: color-mix(in srgb, var(--warn) 20%, transparent); }
.dot.blink { box-shadow: 0 0 8px var(--warn); animation: memblink 1.2s ease-in-out infinite; }
@keyframes memblink { 50% { opacity: .15; box-shadow: none; } }
@media (prefers-reduced-motion: reduce) { .dot.blink { animation: none; } }
@media (max-width: 640px) { .memchip .mempct { display: none; } }
.who { font-size: 12px; color: var(--fg2); } .who b { color: var(--fg); }
a.who:hover { text-decoration: none; } a.who:hover b { color: var(--accent); }
/* The time zone chip (changelog v1.44): PDT by default, UTC while switched. */
.tzchip { font-family: var(--mono); font-size: 11.5px; color: var(--fg2); min-width: 44px; }
.tzchip.override { border-color: var(--warn); color: var(--warn); }
/* My settings (changelog v1.44) */
.me-rules select { min-width: 150px; } .me-rules input[type=number] { width: 84px; }
.me-rules td { vertical-align: middle; }
.me-channel { display: flex; flex-direction: column; gap: 8px; }
.me-channel .row.tight > * { flex: 0 0 auto; }
.me-status { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.me-tz .preview { font-family: var(--mono); font-size: 13px; color: var(--fg); }
.pill.muted { color: var(--fg3); }
.main { grid-row: 2; grid-column: 2; min-width: 0; min-height: 0; overflow: auto; padding: 16px 18px 40px; }
.page { max-width: 1500px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; }
/* A toolkit overview draws its own .page inside the panel's .page, a column flexbox, where auto
   margins turn off stretch: capped at the panel, it no longer grows to its widest table and
   scrolls a phone sideways (v1.159). */
.page > .page { max-width: 100%; }
.row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start; }
.row > * { flex: 1 1 300px; }
.row.tight { gap: 8px; align-items: center; } .row.tight > * { flex: 0 0 auto; }
/* a page's title and its description beside it, and hints beside a control, wrap instead of
   running off (at any width since v1.303: Code's and Schedules' descriptions ran 1,100 px past
   a desktop window) */
.row.tight > h1, .row.tight > span.muted, .row.tight > .hint { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }
.grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.grid.wide { grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } @media (max-width: 1000px) { .two { grid-template-columns: 1fr; } }
.side { display: grid; grid-template-columns: 320px 1fr; gap: 12px; } @media (max-width: 1000px) { .side { grid-template-columns: 1fr; } }
.two > *, .side > * { min-width: 0; }   /* a cell holds wide content in, never widens the grid (v1.282) */

/* cards */
.card { background: var(--bg2); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; min-width: 0; }
.card h3 { margin: 0 0 8px; font-size: 13px; text-transform: uppercase; letter-spacing: .6px; color: var(--fg3); font-weight: 600; display: flex; align-items: center; gap: 8px; }
.card h3 .spacer { flex: 1; }
.card.flat { background: transparent; border-style: dashed; }
h1 { font-size: 18px; margin: 0; font-weight: 600; } h2 { font-size: 15px; margin: 0; font-weight: 600; }
.sub { color: var(--fg3); font-size: 12px; }
.muted { color: var(--fg3); } .small { font-size: 12px; } .right { text-align: right; } .nowrap { white-space: nowrap; }
.pill { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; border: 1px solid var(--line2); color: var(--fg2); background: var(--bg3); white-space: nowrap; }
.pill.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.pill.err { color: var(--err); border-color: color-mix(in srgb, var(--err) 40%, transparent); }
.pill.info { color: var(--info); border-color: color-mix(in srgb, var(--info) 40%, transparent); }
.pill.purple { color: var(--purple); }
.pill.tested { color: var(--proof-tested); border-color: color-mix(in srgb, var(--proof-tested) 45%, transparent); }   /* [claude-tested], v1.201 */
.badge { display: inline-block; min-width: 16px; padding: 0 5px; border-radius: 999px; font-size: 10.5px; background: var(--bg3); color: var(--fg2); text-align: center; border: 1px solid var(--line2); }
.badge.err { background: var(--err); color: #fff; border-color: var(--err); } .badge.warn { background: var(--warn); color: #000; border-color: var(--warn); }
.stat { display: flex; flex-direction: column; gap: 2px; }
.stat .v { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat .v.small { font-size: 16px; }
.stat .k { font-size: 11.5px; color: var(--fg3); text-transform: uppercase; letter-spacing: .5px; }
.stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; font-size: 12.5px; }
.kv dt { color: var(--fg3); } .kv dd { margin: 0; word-break: break-word; }
.banner { padding: 9px 14px; border-radius: var(--radius); border: 1px solid; display: flex; gap: 10px; align-items: center; }
.banner.warn { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.banner.err { border-color: var(--err); background: color-mix(in srgb, var(--err) 12%, transparent); }
.banner.info { border-color: var(--info); background: color-mix(in srgb, var(--info) 12%, transparent); }
.banner code { background: var(--bg); padding: 1px 6px; border-radius: 4px; }
.empty { color: var(--fg3); padding: 14px; text-align: center; border: 1px dashed var(--line); border-radius: var(--radius); }
.error { color: var(--err); }

/* tables */
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
th, td { padding: 5px 8px; text-align: left; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--fg3); font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px; position: sticky; top: 0; background: var(--bg2); z-index: 1; }
tr.click { cursor: pointer; } tr.click:hover td { background: var(--bg3); }
tr.sel td { background: color-mix(in srgb, var(--accent) 12%, transparent); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tablewrap { overflow: auto; max-height: 70vh; }
.tablewrap.short { max-height: 40vh; }

/* logs */
.log { font-family: var(--mono); font-size: 12px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 10px; overflow: auto; max-height: 60vh; }
.log.tall { max-height: 78vh; } .log.short { max-height: 30vh; }
.log .ln { display: grid; grid-template-columns: 62px 1fr; gap: 10px; padding: 1px 0; border-bottom: 1px dotted var(--line); }
.log .ln:last-child { border-bottom: 0; }
.log .t { color: var(--fg3); white-space: nowrap; }
.log .ln.warning .m { color: var(--warn); } .log .ln.error .m { color: var(--err); } .log .ln.debug .m { color: var(--fg3); }
.log mark { background: color-mix(in srgb, var(--warn) 45%, transparent); color: inherit; border-radius: 2px; }
.evt { display: grid; grid-template-columns: 74px 64px 1fr; gap: 10px; padding: 5px 0; border-bottom: 1px solid var(--line); font-size: 12.5px; align-items: baseline; }
.evt:last-child { border-bottom: 0; }
.evt .t { color: var(--fg3); font-family: var(--mono); font-size: 11.5px; white-space: nowrap; }
.evt .k { font-family: var(--mono); font-size: 11px; color: var(--fg3); word-break: break-all; }
.evt .m { word-break: break-word; }
.evt.warning .m { color: var(--warn); } .evt.error .m { color: var(--err); }
.evt .d { grid-column: 3; font-family: var(--mono); font-size: 11px; color: var(--fg3); white-space: pre-wrap; }
.lvl { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 6px; vertical-align: middle; }
.lvl.info { background: var(--info); } .lvl.warning { background: var(--warn); } .lvl.error { background: var(--err); } .lvl.debug { background: var(--fg3); }

/* progress */
.bar { height: 8px; background: var(--bg3); border-radius: 999px; overflow: hidden; border: 1px solid var(--line); }
.bar > i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent2), var(--accent)); transition: width .4s; }
.bar.warn > i { background: var(--warn); } .bar.err > i { background: var(--err); } .bar.ok > i { background: var(--ok); }
.bar.pulse > i { animation: pulse 1.4s infinite; } @keyframes pulse { 50% { opacity: .55; } }
/* loading() in core.js (changelog v1.120): what a tab shows until its first answer */
.loading { display: flex; align-items: center; gap: 10px; padding: 18px 14px; color: var(--fg2); border: 1px dashed var(--line); border-radius: var(--radius); }
.spinner { flex: 0 0 auto; width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line2); border-top-color: var(--accent); animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }
.spark { display: flex; align-items: flex-end; gap: 2px; height: 34px; }
.spark i { flex: 1; background: var(--accent); opacity: .8; min-width: 3px; border-radius: 2px 2px 0 0; }
.spark i:hover { opacity: 1; background: var(--warn); }
.meter { display: flex; height: 10px; border-radius: 999px; overflow: hidden; border: 1px solid var(--line); }
.meter i { display: block; height: 100%; }
.legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--fg2); }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }

/* git graph */
.gitgraph { overflow: auto; }
.gitgraph svg { display: block; min-width: 100%; }
.gitgraph text { font-family: var(--mono); font-size: 11.5px; fill: var(--fg); }
.gitgraph .meta { fill: var(--fg3); }
.gitgraph .ref { font-size: 10.5px; }
.gitgraph .ref rect { fill: var(--bg3); stroke: var(--line2); }
.gitgraph .ref.head rect { stroke: var(--accent); } .gitgraph .ref.origin rect { stroke: var(--warn); }
.gitgraph .ref.deployed rect { fill: var(--ok); stroke: var(--ok); } .gitgraph .ref.deployed text { fill: #04281c; font-weight: 700; }
.gitgraph .ref.running rect { fill: var(--accent); stroke: var(--accent); } .gitgraph .ref.running text { fill: #04212e; font-weight: 700; }
.gitgraph .ref.branch rect { stroke: var(--purple); }
.gitgraph .row:hover rect.bg { fill: var(--bg3); }
.gitgraph rect.bg { fill: transparent; }
.repo-head { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
.state { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }

/* images */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.tile { position: relative; background: var(--bg3); border: 1px solid var(--line); border-radius: 6px; overflow: hidden; cursor: pointer; aspect-ratio: 4/3; }
.tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tile .cap { position: absolute; left: 0; right: 0; bottom: 0; font-size: 10.5px; padding: 3px 6px; background: rgba(0,0,0,.6); color: #fff; display: flex; justify-content: space-between; gap: 4px; }
.tile .cap .pill { font-size: 10px; padding: 0 5px; }
.tile:hover { border-color: var(--accent); }
.imgview { position: relative; display: inline-block; max-width: 100%; }
.imgview img { max-width: 100%; max-height: 70vh; display: block; }
.imgview svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.imgview .ours { stroke: var(--warn); } .imgview .reference { stroke: var(--accent); } .imgview .human { stroke: var(--ok); }
.imgview rect { fill: none; stroke-width: 2; }
.imgview text { font-size: 12px; fill: #fff; paint-order: stroke; stroke: #000; stroke-width: 3px; }

/* misc */
.toasts { position: fixed; right: 14px; bottom: 14px; display: flex; flex-direction: column; gap: 8px; z-index: 50; max-width: 380px; }
.toast { background: var(--bg2); border: 1px solid var(--line2); border-left: 4px solid var(--info); border-radius: var(--radius); padding: 9px 12px; box-shadow: var(--shadow); font-size: 12.5px; }
.toast.warning { border-left-color: var(--warn); } .toast.error { border-left-color: var(--err); } .toast.ok { border-left-color: var(--ok); }
.toast .k { color: var(--fg3); font-family: var(--mono); font-size: 11px; }
.toast .acts { display: flex; gap: 6px; margin-top: 6px; }
/* changelog v1.272: the plan of access (accessplan.js) */
.access-plan .plan { border: 1px solid var(--line2); border-radius: var(--radius); margin-top: 6px; }
.access-plan .plan-head { padding: 8px 12px; border-bottom: 1px solid var(--line2); background: var(--bg2); flex-wrap: wrap; }
.access-plan .plan-summary { padding: 8px 12px; border-bottom: 1px solid var(--line2); }
.access-plan .plan-group { padding: 8px 12px; border-bottom: 1px solid var(--line2); display: flex; flex-direction: column; gap: 6px; }
.access-plan .plan-gh { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg3); font-weight: 600; }
.access-plan .plan-line { display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; gap: 8px; align-items: start; }
.access-plan .plan-what { min-width: 0; overflow-wrap: anywhere; }
.access-plan .plan-line.held { opacity: .55; }
.access-plan .plan-foot { padding: 8px 12px; flex-wrap: wrap; }
/* the refusal notice (refusalnotice.js, changelog v1.257): stays until an admin answers it, at
   the bottom right of main.main (sticky: left of the helper, and room of its own at the end) */
.refusal-notes { position: sticky; bottom: 12px; z-index: 20; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; margin-top: 12px; pointer-events: none; }
.refusal-notes:empty { display: none; }
.refusal-notes > * { pointer-events: auto; width: min(380px, 100%); box-sizing: border-box; }
.toast.refusal { border: 1px solid var(--warn); border-left: 4px solid var(--warn); display: flex; flex-direction: column; gap: 3px; }
.toast.refusal .acts { display: flex; gap: 6px; margin-top: 4px; flex-wrap: wrap; }
.toast.refusal .mono { overflow-wrap: anywhere; }
.pa-refused.open { border: 2px solid var(--warn); border-radius: var(--radius); padding: 6px 8px; }
.modal-bg { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 40; display: flex; align-items: flex-start; justify-content: center; padding-top: 8vh; }
.modal { background: var(--bg2); border: 1px solid var(--line2); border-radius: 10px; width: min(760px, 94vw); max-height: 80vh; overflow: auto; box-shadow: var(--shadow); }
.modal .head { padding: 10px 14px; border-bottom: 1px solid var(--line); display: flex; gap: 10px; align-items: center; }
.modal .head input { flex: 1; font-size: 15px; }
.modal .body { padding: 8px 14px 14px; }
.hit { display: grid; grid-template-columns: 1fr; padding: 6px 8px; border-radius: 6px; cursor: pointer; }
.hit:hover, .hit.sel { background: var(--bg3); }
.hit .t { font-weight: 600; } .hit .s { color: var(--fg3); font-size: 12px; font-family: var(--mono); }
.group-title { font-size: 11px; text-transform: uppercase; letter-spacing: .6px; color: var(--fg3); margin: 8px 0 3px; }
.login { display: grid; place-items: center; height: 100vh; }
.login form { background: var(--bg2); border: 1px solid var(--line); border-radius: 12px; padding: 26px 28px; width: 340px; display: flex; flex-direction: column; gap: 12px; box-shadow: var(--shadow); }
.login h1 { display: flex; align-items: center; gap: 10px; }
.login input { padding: 8px 10px; }
.login a.button { display: block; text-align: center; text-decoration: none; padding: 9px 12px; border-radius: 8px; border: 1px solid var(--accent2); background: var(--accent2); color: #fff; font-weight: 600; }
.login a.button:hover { filter: brightness(1.1); }
.toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
.toolbar .spacer { flex: 1; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { padding: 2px 9px; border-radius: 999px; border: 1px solid var(--line2); cursor: pointer; font-size: 12px; color: var(--fg2); background: var(--bg3); }
.chip.on { border-color: var(--accent); color: var(--fg); background: color-mix(in srgb, var(--accent) 18%, transparent); }
.proj-pick { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.md { line-height: 1.55; max-width: 900px; }
.md h1 { font-size: 20px; margin: 18px 0 8px; } .md h2 { font-size: 16px; margin: 18px 0 6px; border-bottom: 1px solid var(--line); padding-bottom: 4px; } .md h3 { font-size: 14px; margin: 14px 0 4px; }
.md pre { background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; overflow: auto; }
.md code { background: var(--bg3); padding: 0 4px; border-radius: 3px; } .md pre code { background: none; padding: 0; }
.md table { width: auto; margin: 8px 0; } .md th { position: static; }
.md blockquote { border-left: 3px solid var(--line2); margin: 8px 0; padding: 2px 12px; color: var(--fg2); }
.md ul, .md ol { padding-left: 22px; }
.copy { cursor: pointer; color: var(--fg3); } .copy:hover { color: var(--accent); }
.json { font-family: var(--mono); font-size: 12px; white-space: pre-wrap; word-break: break-word; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; max-height: 50vh; overflow: auto; }
.tree { font-family: var(--mono); font-size: 12.5px; }
.tree .n { padding: 3px 6px; border-radius: 4px; cursor: pointer; display: flex; justify-content: space-between; gap: 8px; }
.tree .n:hover, .tree .n.sel { background: var(--bg3); }
.tree .n .d { color: var(--fg3); font-family: var(--sans); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tree .h { color: var(--fg3); text-transform: uppercase; letter-spacing: .5px; font-size: 10.5px; margin: 8px 6px 2px; font-family: var(--sans); }
.term { background: #050505; color: #d7e0f0; font-family: var(--mono); font-size: 12.5px; border-radius: var(--radius); border: 1px solid var(--line); padding: 10px 12px; max-height: 60vh; overflow: auto; }
.term .cmd { color: var(--accent); } .term .err { color: var(--err); } .term .meta { color: var(--fg3); }
.term .entry { border-bottom: 1px dashed var(--line); padding: 6px 0; }
.svc { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.svc .s { border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; display: flex; flex-direction: column; gap: 3px; }
.svc .s .n { font-weight: 600; font-family: var(--mono); font-size: 12px; }
.hint { font-size: 12px; color: var(--fg3); }
/* A live tab is a fixed sequence of slots (changelog v1.36): a redraw refills the data
   slots and leaves a card with a form alone. `display: contents` keeps the page's gap. */
.slot { display: contents; }
.card.flash { animation: flash 2.4s ease-out 1; }
@keyframes flash { 0%, 60% { outline: 2px solid var(--accent); outline-offset: 2px; } 100% { outline: 2px solid transparent; outline-offset: 2px; } }
.prompt-card pre { background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; font-size: 12px; max-height: 260px; overflow: auto; }
details > summary { cursor: pointer; color: var(--fg2); }
.flash { animation: flash 1.2s; } @keyframes flash { 0% { background: color-mix(in srgb, var(--accent) 30%, transparent); } 100% { background: transparent; } }

/* Claude terminal tab (changelog v1.17). xterm.css is loaded by the tab itself. */
.term-wrap { background: #0a0a0a; border-radius: 8px; padding: 8px; height: calc(100vh - 190px - var(--topbar-extra, 0px)); min-height: 320px; }
.term-wrap .xterm { height: 100%; }
.term-status { display: flex; gap: 10px; align-items: center; margin: 6px 0; }
.term-status .dot { width: 8px; height: 8px; border-radius: 50%; background: #888; display: inline-block; }
.term-status .dot.live { background: #3fb950; }
.term-status .dot.dead { background: #f85149; }

/* Boat folders (changelog v1.26): the per-boat folder table and the setup dialog. */
.folders table { font-size: 12px; }
.folders tr[data-key] td:first-child { white-space: nowrap; }
.folders .pill.err { background: color-mix(in srgb, var(--err) 10%, transparent); }
.folders .pill.warn { background: color-mix(in srgb, var(--warn) 10%, transparent); }
.folders .hint { margin-top: 2px; }
.modal.wide { width: min(1040px, 96vw); max-height: 88vh; }
.modal .body.page { gap: 8px; }
.modal .body .plan .tablewrap { max-height: 30vh; }

/* AI lab helper sidebar (changelog v1.32): the shell's third column, on the right of the
   content since v1.199 (the project tree took the left): the panel with its resize handle on
   its left edge, or a thin rail when hidden. Below 1400 px the open panel floats over the
   content from the rail (--helper-float-w wide), and its handle with it. */
.helper { grid-row: 2; grid-column: 3; position: relative; display: flex; min-width: 0; min-height: 0; background: var(--bg2); border-left: 1px solid var(--line); --helper-float-w: min(var(--helper-w, 380px), calc(100vw - 88px)); }
.helper .rail { display: none; width: 40px; height: 100%; border: 0; border-radius: 0; background: var(--bg2); color: var(--fg2); padding: 10px 0 0; align-items: flex-start; justify-content: center; }
.helper .rail:hover { color: var(--accent); }
.helper .rail.unread::after { content: ''; position: absolute; top: 8px; left: 26px; width: 8px; height: 8px; border-radius: 50%; background: var(--warn); }
.app.helper-closed .helper .rail { display: flex; }
.app.helper-closed .helper .helper-panel, .app.helper-closed .helper .helper-resize { display: none; }
.helper-panel { display: flex; flex-direction: column; min-width: 0; min-height: 0; flex: 1; }
.helper-resize { flex: none; width: 5px; cursor: col-resize; background: transparent; } .helper-resize:hover { background: var(--line2); }
.helper-head { padding: 10px 12px 8px; border-bottom: 1px solid var(--line); }
.helper-head .brandline { display: flex; align-items: center; gap: 8px; min-width: 0; }
.helper-head .brandline .ico { color: var(--accent); display: inline-flex; }
.helper-head .brandline b { white-space: nowrap; }
.helper-head .sub { margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.helper-head .sub .title.editable { cursor: text; border-bottom: 1px dashed var(--line2); }
.helper-head button.ghost { background: transparent; border-color: transparent; color: var(--fg2); padding: 1px 6px; }
.helper-head button.ghost:hover { border-color: var(--line2); color: var(--fg); } .helper-head button.ghost.danger:hover { color: var(--err); }
.helper-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 10px 12px; min-height: 0; }
.helper-foot { border-top: 1px solid var(--line); padding: 8px 12px 10px; display: flex; flex-direction: column; gap: 6px; }
.helper-foot textarea { width: 100%; resize: none; min-height: 44px; max-height: 160px; }
.helper-intro p { margin: 0 0 8px; color: var(--fg2); }
.chatrow { padding: 7px 8px; border-radius: 6px; cursor: pointer; border: 1px solid transparent; }
.chatrow:hover { background: var(--bg3); } .chatrow.active { border-color: color-mix(in srgb, var(--info) 50%, transparent); }
.chatrow .t { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: flex; gap: 6px; align-items: center; }
.chatrow .s { color: var(--fg3); font-size: 11.5px; display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.chatrow .s .pill { font-size: 10px; padding: 0 5px; }
.msgs { display: flex; flex-direction: column; gap: 12px; }
.msg .meta { font-size: 11px; color: var(--fg3); margin-top: 3px; }
.msg.user { align-self: flex-end; max-width: 92%; text-align: right; }
.msg.user .bubble { display: inline-block; text-align: left; background: color-mix(in srgb, var(--accent2) 22%, var(--bg3)); border: 1px solid color-mix(in srgb, var(--accent2) 40%, transparent); border-radius: 10px 10px 2px 10px; padding: 7px 10px; white-space: pre-wrap; word-break: break-word; }
.msg.assistant { max-width: 100%; min-width: 0; }
.msg.assistant .text { font-size: 13px; overflow-wrap: anywhere; }
/* v1.32a: a wide table scrolls inside its message instead of running under the panel's edge. */
.msg.assistant .md { max-width: 100%; overflow-x: auto; }
.msg.assistant .md table { width: 100%; }
.msg.assistant .md td, .msg.assistant .md th { overflow-wrap: anywhere; white-space: normal; }
.msg.assistant .md p { margin: 0 0 8px; } .msg.assistant .md p:last-child { margin-bottom: 0; }
.msg.assistant .md pre { font-size: 11.5px; padding: 6px 8px; } .msg.assistant .md table { font-size: 12px; } .msg.assistant .md ul, .msg.assistant .md ol { padding-left: 18px; }
.msg.assistant .text.streaming { white-space: pre-wrap; word-break: break-word; }
.msg.assistant .text.streaming::after { content: '▍'; color: var(--accent); animation: pulse 1s infinite; }
.msg.assistant .thinking { display: flex; align-items: center; gap: 6px; color: var(--fg3); font-size: 12px; margin-top: 4px; }
.msg.assistant .thinking .dots { animation: pulse 1.2s infinite; color: var(--accent); }
.msg.error .bubble { color: var(--err); border: 1px solid color-mix(in srgb, var(--err) 40%, transparent); border-radius: 8px; padding: 6px 10px; font-size: 12.5px; background: color-mix(in srgb, var(--err) 8%, transparent); }
details.tool { margin: 4px 0; border: 1px solid var(--line); border-radius: 6px; background: var(--bg); font-size: 12px; }
details.tool summary { padding: 4px 8px; display: flex; align-items: center; gap: 7px; color: var(--fg2); list-style: none; }
details.tool summary::-webkit-details-marker { display: none; }
details.tool summary .n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--mono); font-size: 11.5px; }
details.tool .dot.wait { background: var(--warn); animation: pulse 1s infinite; }
details.tool .tool-body { padding: 0 8px 6px; display: flex; flex-direction: column; gap: 4px; }
details.tool pre { max-height: 180px; overflow: auto; background: var(--bg2); border: 1px solid var(--line); border-radius: 4px; padding: 4px 6px; }
details.tool pre.out { color: var(--fg2); }
.people { display: flex; flex-direction: column; gap: 4px; max-height: 40vh; overflow: auto; }
/* Below 1400 px the content keeps its width: the open helper floats over it from its rail, its
   panel from the top of the content's row, so it starts under the top bar whatever its height. */
@media (max-width: 1399px) {
  .app.helper-open { --helper-col: 40px; }
  .app.helper-open .helper .rail { display: flex; }
  .app.helper-open .helper .helper-panel { position: absolute; right: 40px; left: auto; top: 0; bottom: 0; width: var(--helper-float-w); z-index: 30; background: var(--bg2); border-left: 1px solid var(--line); box-shadow: var(--shadow); }
  /* the refusal notice (v1.257) stays left of the floating helper, as wide as helper.js makes it */
  .app.helper-open .refusal-notes { margin-right: min(var(--helper-w, 380px), calc(100vw - 88px)); }
  .app.helper-open .helper .helper-resize { position: absolute; top: 0; bottom: 0; right: calc(40px + var(--helper-float-w)); z-index: 31; }
}
@media (max-width: 1099px) {
  .app { --tree-col: var(--tree-w, 220px); }
}
/* 641 to 900 px: the tree is a 40 px rail; its button opens the tree over the content. */
@media (max-width: 900px) {
  .app, .app.tree-closed { --tree-col: 40px; }
  nav.ptree-side .ptree-rail { display: flex; }
  nav.ptree-side .ptree-panel, nav.ptree-side .ptree-resize { display: none; }
  .app.tree-drawer nav.ptree-side .ptree-panel { display: flex; position: fixed; left: 0; top: var(--topbar-h, 48px); bottom: 0; width: min(86vw, 320px); z-index: 41; background: var(--bg2); border-right: 1px solid var(--line); box-shadow: var(--shadow); }
  .app.tree-drawer .ptree-scrim { display: block; }
}

/* Boat Sync (changelog v1.104): the header, the sub-tabs and one compact row per boat. */
.sync-head h1 { margin: 0; }
.sync-stats { margin-bottom: 8px; }
.boat-list { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 6px; background: var(--bg); }
details.boat { border-bottom: 1px solid var(--line); }
details.boat:last-child { border-bottom: none; }
details.boat > summary { display: flex; align-items: center; gap: 8px; padding: 6px 10px; color: var(--fg); flex-wrap: wrap; }
details.boat > summary:hover { background: var(--bg2); }
details.boat[open] > summary { background: var(--bg2); }
details.boat .boat-name { min-width: 8.5em; }
details.boat .boat-hull { min-width: 4.5em; }
details.boat .boat-desc { flex: 1 1 12em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; text-align: right; }
details.boat .boat-body { padding: 6px 10px 10px 24px; }
.sync-head .spacer { flex: 1 1 auto; }
.sync-stats { margin: 0 0 10px; }
.sync-count { padding: 2px 8px; border: 1px solid var(--line); border-radius: 12px; font-size: 12.5px; color: var(--fg2); background: var(--bg); }
a.sync-count:hover { text-decoration: none; border-color: var(--accent); }
.sync-count b { color: var(--fg); }
.sync-count.warn { border-color: color-mix(in srgb, var(--warn) 55%, transparent); }
.sync-count.info { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.sync-count.err { border-color: var(--err); }
/* the Hulls and applets matrix: a cell's words wrap inside their column */
.tablewrap.hulls { max-height: none; }
.tablewrap.hulls td:first-child { white-space: nowrap; }
.tablewrap.hulls td .row.tight > span:not(.pill) { flex: 1 1 10em; min-width: 0; }

/* Find (changelog v1.286, find.js): the top bar's magnifier on every screen; a bar under the top
   bar (input, n of m, previous, next, close) with the best projects and Search all of the lab
   below it; every place found is tinted, the current one ringed. */
button.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; background: transparent; border-color: transparent; color: var(--fg2); }
button.icon-btn:hover { color: var(--fg); border-color: var(--line2); }
.findbar { position: fixed; z-index: 55; top: calc(var(--topbar-h, 48px) + 6px); right: max(12px, env(safe-area-inset-right, 0px)); width: min(460px, calc(100vw - 24px)); background: var(--bg2); border: 1px solid var(--line2); border-radius: 10px; box-shadow: var(--shadow); padding: 6px; display: flex; flex-direction: column; gap: 4px; }
.findbar-row { display: flex; align-items: center; gap: 4px; }
.findbar-row .find-input { flex: 1 1 auto; min-width: 0; }
.find-count { white-space: nowrap; padding: 0 4px; font-variant-numeric: tabular-nums; }
.find-sugg { display: flex; flex-direction: column; border-top: 1px solid var(--line); padding-top: 4px; max-height: 40vh; overflow-y: auto; }
button.find-sugg-row { display: block; text-align: left; background: transparent; border: 0; border-radius: 6px; padding: 7px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
button.find-sugg-row:hover, button.find-sugg-row:focus-visible { background: var(--bg3); }
button.find-sugg-row.find-all { color: var(--accent); }
.find-hit { background: color-mix(in srgb, var(--warn) 16%, transparent); border-radius: 3px; }
.find-now { outline: 2px solid var(--warn); outline-offset: 2px; background: color-mix(in srgb, var(--warn) 28%, transparent); }
@media (max-width: 640px) {
  .findbar { left: 0; right: 0; width: auto; top: var(--topbar-h, 52px); border-radius: 0; border-left: 0; border-right: 0; padding: 6px max(8px, env(safe-area-inset-right, 0px)) 8px max(8px, env(safe-area-inset-left, 0px)); }
  .findbar .find-step { width: 40px; height: 40px; }
}

/* Boats (changelog v1.286): Hulls and Boats in one list, a line per hull with its computers as
   chips (ok, warn, err, info = pulling, dashed = not registered yet), opening to each applet's
   line for the hull and each computer's own row. */
details.hull > summary { gap: 6px 10px; padding: 7px 10px; flex-wrap: nowrap; }
details.hull .hull-n { min-width: 4.5em; }
.hchips { display: inline-flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.hchip { display: inline-flex; align-items: center; padding: 0 7px; border-radius: 999px; border: 1px solid var(--line2); font-size: 11.5px; line-height: 18px; color: var(--fg2); white-space: nowrap; }
.hchip.ok { border-color: color-mix(in srgb, var(--ok) 60%, transparent); color: var(--fg); }
.hchip.warn { border-color: var(--warn); color: var(--warn-ink); }
.hchip.err { border-color: var(--err); color: var(--err); }
.hchip.info { border-color: var(--info); color: var(--info); }
.hchip.missing { border-style: dashed; color: var(--fg3); }
.hull-body { padding: 4px 10px 10px 16px; display: flex; flex-direction: column; gap: 6px; }
.hull-applets { display: flex; flex-direction: column; gap: 4px; padding-bottom: 6px; border-bottom: 1px dashed var(--line); }
.hull-applet { display: grid; grid-template-columns: minmax(6em, 9em) minmax(0, 1fr); gap: 8px; align-items: baseline; font-size: 12.5px; }
.hull-applet-name { color: var(--fg2); }
.hull-body details.boat { border: 1px solid var(--line); border-radius: 6px; }
/* v1.289: a hull's computers by what they are (EDDIE, Captain, Router), each its own block */
.hull-comp { display: flex; flex-direction: column; gap: 6px; padding: 8px 0; border-top: 1px solid var(--line); }
.hull-comp:first-child { border-top: 0; padding-top: 2px; }
.hull-comp-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.hull-comp-head .hchip { font-size: 12.5px; font-weight: 600; line-height: 22px; }
.hull-comp.missing .hull-comp-head b { color: var(--fg3); }
.hull-comp .hull-applets { border-bottom: 0; padding: 0 0 0 4px; }
.hull-comp details.boat > summary { font-size: 12.5px; color: var(--fg2); }
details.which-button > summary { cursor: pointer; color: var(--fg2); }
@media (max-width: 640px) {
  .hull-applet { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .hull-body { padding: 4px 6px 8px 8px; }
}

/* Reports (changelog v1.121): one section per applet, one block per PDF. */
.rep-sections { display: flex; flex-direction: column; gap: 14px; width: 100%; }
.rep-section h3 a.rep-applet-link { text-transform: none; letter-spacing: 0; font-weight: 400; }
.rep-section h3 .badge { margin-left: 2px; }
.rep-list { display: flex; flex-direction: column; }
.rep { padding: 10px 2px 12px; border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 4px; }
.rep:last-child { border-bottom: 0; padding-bottom: 2px; }
.rep-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rep-title { font-size: 14px; }
.rep-asked { color: var(--fg); }
.rep-about { color: var(--fg2); max-width: 110ch; }
.rep-ctx { color: var(--fg2); font-size: 12.5px; max-width: 110ch; white-space: pre-wrap; }
.rep-ctx b { color: var(--fg3); font-weight: 600; }
.rep-result summary, .rep-versions summary { font-size: 12px; color: var(--fg3); }
.rep-result > div { color: var(--fg2); margin: 4px 0 0 14px; max-width: 110ch; white-space: pre-wrap; }
.rep-versions ul { margin: 4px 0 0 18px; padding: 0; font-size: 12px; } .rep-versions li { margin: 3px 0; }
.rep-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 2px; }
.rep-file { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 46ch; }

/* Changelog v1.135: the Code tab (code sessions, tabs/code.js) */
.stack { display: flex; flex-direction: column; gap: 8px; }
.code-log { max-height: 62vh; overflow: auto; font-size: 13px; }
.code-line { padding: 4px 0; border-bottom: 1px solid var(--line); }
.code-line pre.inline { display: inline; font-family: var(--sans); }
.code-line.err { color: var(--err); }
.code-line.muted, .code-line.muted pre { color: var(--fg3); }
.code-line.warn { color: var(--warn); }
.code-line.ok { color: var(--ok); }
pre.diff { font-family: var(--mono); font-size: 12px; max-height: 70vh; overflow: auto; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; }

/* Settings, System, Channels (changelog v1.163, Projects P7b): the Bind dialog and the token
   panel that shows a bound channel's token once. Palette tokens only, so dark and light both
   follow the scheme; the token wraps rather than widening the page at phone width. */
.channels .row.tight > .hint { flex: 1 1 240px; min-width: 0; }
.channel-form { margin-top: 10px; padding: 10px 12px; border: 1px solid var(--line2); border-radius: var(--radius); background: var(--bg2); display: flex; flex-direction: column; gap: 8px; }
.channel-form h4, .channel-result h4 { margin: 4px 0 0; font-size: 13px; }
.channel-form .row.tight > label.field { flex: 1 1 160px; min-width: 0; }
.channel-form label.field > input, .channel-form label.field > select { min-width: 0; width: 100%; }
.channel-lookup-view { display: flex; flex-direction: column; gap: 6px; }
.channel-result { margin-top: 10px; padding: 12px; border: 1px solid var(--warn); border-radius: var(--radius); background: color-mix(in srgb, var(--warn) 6%, var(--bg2)); display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.channel-once { font-size: 12.5px; color: var(--fg); }
.channel-token-row > .channel-token { flex: 1 1 260px; min-width: 0; }
.channel-token { display: inline-block; max-width: 100%; padding: 6px 10px; border: 1px dashed var(--warn); border-radius: 6px; background: var(--bg); color: var(--fg); word-break: break-all; user-select: all; }
.channel-allow-text { width: 100%; font-family: var(--mono); font-size: 12px; resize: vertical; }
.channel-steps { font-size: 12.5px; overflow-wrap: anywhere; }
.channel-steps ol, .channel-steps ul { padding-left: 22px; margin: 4px 0; }
.channel-warnings ul, .channel-result .banner ul { margin: 0; padding-left: 18px; }
.pchannel { color: var(--fg2); }
.channel-result .row.tight > span { flex: 1 1 240px; min-width: 0; }
/* Settings' long lines beside a title or a button wrap instead of widening the page. */
.settings-head > span.muted, .models-head > span.muted { flex: 1 1 240px; min-width: 0; }

/* Phone width (changelog v1.159): one column at 390 px with nothing to scroll sideways; grid
   cells never ask for more than the screen. Changelog v1.280, the phone shell: the top bar is one
   52 px row (the logo, the page's name, search and the bell), a bottom bar takes Home, Projects,
   Ask, Boats and More, and what used to float or wrap opens as a sheet between the two bars, one
   at a time (main.js openSheet): More holds the tabs and controls (.topmenu), the bell the
   refusal notes, Projects the tree's drawer and Ask the AI lab helper, which has no rail here.
   Fields are 16 px so iPhone Safari does not zoom into them; the page is as tall as what shows
   (--vvh follows the keyboard, else 100dvh) and keeps clear of the notch and the home bar. */
.phone-only, button.icon-btn.phone-only, nav.bottomnav, .phone-title { display: none; }
@media (max-width: 640px) {
  .app { height: 100vh; height: var(--vvh, 100dvh); grid-template-rows: auto minmax(0, 1fr) auto; }
  .app, .app.tree-closed { --tree-col: 0px; }
  .app, .app.helper-open, .app.helper-closed { --helper-col: 0px; }
  .phone-only, button.icon-btn.phone-only { display: inline-flex; }
  /* !important: a component's own smaller size (.qpick, the code editors) would zoom the page too */
  input, select, textarea { font-size: 16px !important; }
  .topbar { flex-wrap: nowrap; gap: 6px; min-height: 52px; padding: calc(4px + env(safe-area-inset-top, 0px)) max(8px, env(safe-area-inset-right, 0px)) 4px max(10px, env(safe-area-inset-left, 0px)); }
  .brand > span, .brand > small { display: none; }
  .brand svg { width: 28px; height: 28px; }
  .phone-title { display: block; flex: 1 1 auto; min-width: 0; font-size: 16px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  button.icon-btn { width: 40px; height: 40px; padding: 0; align-items: center; justify-content: center; gap: 2px; background: transparent; border-color: transparent; color: var(--fg2); position: relative; }
  button.icon-btn[aria-expanded="true"] { color: var(--accent); border-color: var(--line2); }
  button.icon-btn.bell .badge { position: absolute; top: 2px; right: 0; background: var(--warn); border-color: var(--warn); color: #000; font-weight: 700; }
  /* More: the tabs as a list, then the zone, Live, who and sign out */
  .topmenu { display: none; }
  .app.more-open .topmenu { display: flex; flex-direction: column; gap: 16px; position: fixed; left: 0; right: 0; top: var(--topbar-h, 52px); bottom: var(--bottomnav-h, 64px); z-index: 45; overflow-y: auto; overscroll-behavior: contain; background: var(--bg2); padding: 10px max(12px, env(safe-area-inset-right, 0px)) 20px max(12px, env(safe-area-inset-left, 0px)); }
  .topmenu > .tabs { order: 0; flex: none; flex-direction: column; flex-wrap: nowrap; gap: 0; }
  .topmenu > .tabs a { display: flex; align-items: center; min-height: 46px; padding: 0 12px; font-size: 16px; border-radius: 8px; border-bottom: 1px solid var(--line); }
  .topmenu > .tabs a.active { box-shadow: inset 3px 0 0 var(--accent); }
  .topmenu > .controls { flex: none; flex-wrap: wrap; gap: 12px 16px; margin-left: 0; padding: 0 12px; }
  /* v1.289: the search box shares the row with the page's name and takes it over while typed in */
  .topbar > .topsearch { flex: 0 1 150px; min-width: 0; }
  .topbar > .topsearch input { width: 100%; }
  .topbar:has(.topsearch:focus-within) > .phone-title { display: none; }
  .topbar > .topsearch:focus-within { flex: 1 1 auto; }
  /* the bottom bar */
  nav.bottomnav { display: grid; grid-row: 3; grid-column: 1 / -1; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); z-index: 46; background: var(--bg2); border-top: 1px solid var(--line); padding: 0 env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px); }
  nav.bottomnav > a, nav.bottomnav > button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 56px; padding: 6px 2px; border: 0; border-radius: 0; background: transparent; color: var(--fg2); font-size: 11.5px; line-height: 1.1; text-decoration: none; }
  nav.bottomnav .ico { display: inline-flex; }
  nav.bottomnav > a.active, nav.bottomnav > button[aria-expanded="true"], .app.helper-open nav.bottomnav > button.ask { color: var(--accent); }
  /* an open sheet is what the bar marks, not the page under it */
  .app.more-open nav.bottomnav > a.active, .app.helper-open nav.bottomnav > a.active, .app.tree-drawer nav.bottomnav > a.active { color: var(--fg2); }
  nav.bottomnav > a:focus-visible, nav.bottomnav > button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .app.kbd-open nav.bottomnav { display: none; }
  /* Projects: the tree's drawer, as wide as the screen, above the bottom bar */
  nav.ptree-side { border-right: 0; }
  nav.ptree-side .ptree-rail { display: none; }
  .app.tree-drawer nav.ptree-side .ptree-panel { width: 100%; bottom: var(--bottomnav-h, 64px); border-right: 0; box-shadow: none; }
  .ptree-scrim { bottom: var(--bottomnav-h, 64px); }
  a.ptree-link { min-height: 40px; font-size: 15px; }
  .ptree-ago { flex: none; color: var(--fg3); font-size: 12.5px; padding-left: 4px; }
  button.ptree-fold, .ptree-nofold { width: 28px; height: 40px; }
  /* Ask: the helper as a sheet; no rail, no resize handle */
  .helper { border-left: 0; }   /* its column is 0 px wide here: a border would widen the page */
  .helper .rail, .app.helper-open .helper .rail, .app.helper-closed .helper .rail, .app.helper-open .helper .helper-resize { display: none; }
  .modal-bg { z-index: 60; }   /* a dialog opened from a sheet (the helper's Share) shows above it */
  .app.helper-open .helper .helper-panel { position: fixed; left: 0; right: 0; top: var(--topbar-h, 52px); bottom: var(--bottomnav-h, 64px); width: auto; z-index: 44; border-left: 0; box-shadow: none; padding: 0 env(safe-area-inset-right, 0px) 0 env(safe-area-inset-left, 0px); }
  .app.helper-open.kbd-open .helper .helper-panel { bottom: 0; }
  /* v1.289: the box to ask in stands out (Dylan: "highlight the search box more") */
  .helper-foot { border-top: 2px solid var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--bg2)); }
  .helper-foot textarea { border: 2px solid var(--accent); border-radius: 12px; padding: 10px 12px; background: var(--bg); }
  .helper-foot textarea::placeholder { color: var(--fg2); }
  .pmenu-item { padding: 11px 12px; }
  /* the bell: refusals, requests and reviews leave the bottom of the page for their own sheet */
  .refusal-notes, .app.helper-open .refusal-notes { display: none; margin: 0; }
  .app.notes-open .refusal-notes:not(:empty) { display: flex; position: fixed; left: 0; right: 0; top: var(--topbar-h, 52px); bottom: var(--bottomnav-h, 64px); z-index: 43; overflow-y: auto; align-items: stretch; padding: 12px max(12px, env(safe-area-inset-right, 0px)) 12px max(12px, env(safe-area-inset-left, 0px)); background: var(--bg); }
  .app.notes-open .refusal-notes > * { width: 100%; box-shadow: none; }
  .main { padding: 12px max(10px, env(safe-area-inset-right, 0px)) 32px max(10px, env(safe-area-inset-left, 0px)); }
  .toasts { left: 14px; max-width: none; bottom: calc(var(--bottomnav-h, 64px) + 10px); }
  .grid { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
  .grid.wide { grid-template-columns: repeat(auto-fill, minmax(min(420px, 100%), 1fr)); }
  .subtabs { flex-wrap: wrap; }
  a.tag.pill.pchip { white-space: normal; }
  /* the boat queue's card: a list per hull instead of the timeline, the workers on one line */
  .qcard .qtimeline, .qcard ul.qsummary { display: none; }
  .qcard .qlist { display: flex; }
  .qctl { flex: 1 1 100%; }
}
/* Changelog v1.282, the shared pieces at phone width: a core.table() is a list of cards (each cell
   with its column's label, the first cell the card's title), dialogs rise from the bottom, a row
   of sub-tabs scrolls sideways instead of wrapping into rows, a filter bar folds behind one
   Filters button (core.js filterFold), a page's summary goes under its list (.facets-after), and
   anything a finger presses is at least 40 px tall (34 for a small button). */
.filterfold-btn { display: none; }
.subtabs { flex-wrap: wrap; }
@media (max-width: 640px) {
  .tablewrap.cards { max-height: none; overflow: visible; }
  .tablewrap.cards > table, .tablewrap.cards > table > tbody, .tablewrap.cards > table > tbody > tr, .tablewrap.cards > table > tbody > tr > td { display: block; width: auto; }
  .tablewrap.cards > table > thead { display: none; }
  .tablewrap.cards > table > tbody > tr { border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 10px; margin-bottom: 8px; background: var(--bg); }
  .tablewrap.cards > table > tbody > tr > td { border: 0; padding: 2px 0; text-align: left; overflow-wrap: anywhere; min-width: 0; }
  .tablewrap.cards > table > tbody > tr > td[data-label] { display: grid; grid-template-columns: minmax(64px, 26%) minmax(0, 1fr); gap: 8px; align-items: baseline; justify-items: start; }
  .tablewrap.cards > table > tbody > tr > td[data-label]::before { content: attr(data-label); color: var(--fg3); font-size: 12px; text-transform: lowercase; }
  .tablewrap.cards > table > tbody > tr > td:first-child { display: block; font-weight: 600; font-size: 14px; padding-bottom: 4px; }
  .tablewrap.cards > table > tbody > tr > td:first-child::before { content: none; }
  .tablewrap.cards > table > tbody > tr > td:empty { display: none; }
  .modal-bg { align-items: flex-end; padding: 0; }
  .modal, .modal.wide { width: 100%; max-height: 92dvh; border-radius: 14px 14px 0 0; border-bottom: 0; padding-bottom: env(safe-area-inset-bottom, 0px); }
  .modal .body > .row.tight:last-child > button { flex: 1 1 0; }
  .subtabs { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; overscroll-behavior-x: contain; }
  .subtabs::-webkit-scrollbar { display: none; }
  .subtabs > * { flex: none; white-space: nowrap; }
  .subtabs a.subtab { padding: 10px 12px; }
  .filterfold-btn { display: inline-flex; align-items: center; }
  .filterfold:not(.open) { display: flex; align-items: center; gap: 8px; }
  .toolbar > label.field { min-width: 0; max-width: 100%; }
  label.field > select, label.field > input { max-width: 100%; }
  /* v1.303: a select in a card row (My settings' priorities) is no wider than its card; the git
     graph keeps its size and scrolls sideways in its box; an opened script comes before the Library */
  .tablewrap.cards > table > tbody > tr > td > select { max-width: 100%; }
  .gitgraph svg { width: 1100px; }
  .side.picked > :last-child { order: -1; }
  .filterfold:not(.open) > .toolbar > :not(.fold-keep) { display: none; }
  .filterfold.open > .filterfold-btn { margin-bottom: 8px; border-color: var(--accent); }
  /* v1.286: two fields to a row (Dylan: "it only needs to span half of the display") */
  .toolbar > label.field { flex: 1 1 calc(50% - 4px); min-width: calc(50% - 4px); }
  .toolbar > label.field > input, .toolbar > label.field > select { width: 100%; min-width: 0; }
  .facets-after { order: 1; }
  .confl.none { display: none; }
  .sync-head > h1, .sync-head > span.muted { display: none; }   /* the top bar names the page */   /* "Confluence page coming" says nothing a phone needs */
  /* v1.286: a project's head keeps its title, kind, star and Claim; Details opens the rest */
  [data-slot="head"]:not(.phead-open) .phead-extra { display: none; }
  button.phead-more { margin-left: auto; }
  .side { grid-template-columns: minmax(0, 1fr) !important; }   /* over the Boat logs pages' inline two columns */
  button, a.btn, select, input:not([type=checkbox]):not([type=radio]):not([type=range]) { min-height: 40px; }
  button.small, a.btn.small { min-height: 34px; padding: 4px 10px; }
  input[type=checkbox], input[type=radio] { width: 20px; height: 20px; }
  label.check { min-height: 34px; }
  details > summary { min-height: 32px; padding-top: 6px; padding-bottom: 6px; }
  .chip, a.tag.pill, a.pill { min-height: 30px; display: inline-flex; align-items: center; }
}
/* Changelog v1.190: a project's Overview for people (tabs/projects.js renderOverview): Needs you
   first, its numbers as pictures, questions for the AI lab helper, a head with its details folded */
.phead-details { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin-top: 6px; padding: 8px 10px; border: 1px dashed var(--line2); border-radius: var(--radius); }
.pa-card.waiting { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); }
.pa-list { display: flex; flex-direction: column; }
.pa-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-top: 1px solid var(--line); }
.pa-row:first-child { border-top: none; padding-top: 2px; }
.pa-what { flex: 1 1 auto; min-width: 0; }
.pa-title { font-weight: 600; overflow-wrap: anywhere; }
.pa-none { color: var(--fg2); } .pa-ok { color: var(--ok); font-weight: 700; }
.pask { margin-top: 8px; flex-wrap: wrap; }
.pg-card { flex: 1 1 300px; }
.pg-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.pg-tile.wide { grid-column: 1 / -1; }
.pg-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg3); font-weight: 600; }
.pg-value { font-size: 22px; font-weight: 650; font-variant-numeric: tabular-nums; line-height: 1.2; }
.pg-bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden; margin: 6px 0 4px; background: var(--bg3); }
.pg-seg { min-width: 4px; }
.pg-seg.ok, .pg-key.ok { background: var(--ok); } .pg-seg.tested, .pg-key.tested { background: var(--proof-tested); }
.pg-seg.muted, .pg-key.muted { background: var(--fg3); } .pg-seg.warn, .pg-key.warn { background: var(--warn); }
.pg-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; color: var(--fg2); }
.pg-key { display: inline-block; width: 9px; height: 9px; border-radius: 2px; vertical-align: 0; }
.pg-spark { display: block; margin-top: 4px; max-width: 100%; }
.pg-spark .pf-bar { fill: var(--ph, var(--accent)); }
.pabout > summary { cursor: pointer; color: var(--fg2); padding: 6px 0; }
details.pintro > summary { cursor: pointer; list-style: none; }
details.pintro > summary::-webkit-details-marker { display: none; }
.ps-more > summary { cursor: pointer; list-style: none; }
.ps-more > summary::-webkit-details-marker { display: none; }
.ps-more[open] > summary .ps-short { color: var(--fg2); }
.ps-full { margin: 4px 0 6px 0; color: var(--fg2); }
.ps-rest { margin-top: 6px; } .ps-rest > summary { cursor: pointer; color: var(--fg2); }
.ps-works ul { padding-left: 18px; }
.pg-value.small { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
/* Changelog v1.190: the Healer incidents panel for people (server/applets/datadog/ui/heal.js,
   fix.js): Needs you, the last 30 days as pictures, an incident's story and its one action */
.heal-filters button[aria-pressed="true"] { font-weight: 600; }
.datadog-heal-action.waiting { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); }
.heal-runs > summary, .heal-known > summary { cursor: pointer; color: var(--fg2); padding: 6px 0; }
.heal-more > summary, .heal-tech > summary, .heal-health > summary { cursor: pointer; color: var(--fg2); margin-top: 6px; }
.heal-charts { display: grid; grid-template-columns: minmax(0, 2fr) minmax(220px, 1fr); gap: 18px; align-items: start; }
@media (max-width: 720px) { .heal-charts { grid-template-columns: minmax(0, 1fr); } }
svg.heal-days { width: 100%; height: 80px; display: block; margin: 6px 0 2px; }
.hd-new { fill: var(--accent); } .hd-noise { fill: color-mix(in srgb, var(--fg3) 45%, transparent); }
.hc-legend { display: flex; gap: 12px; color: var(--fg2); }
.hc-key { display: inline-block; width: 9px; height: 9px; border-radius: 2px; vertical-align: 0; }
.hc-key.new { background: var(--accent); } .hc-key.noise { background: color-mix(in srgb, var(--fg3) 45%, transparent); }
.heal-funnel { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.hf-row { display: grid; grid-template-columns: 96px minmax(0, 1fr) 32px; gap: 8px; align-items: center; }
.hf-track { height: 10px; background: var(--bg3); border-radius: 5px; overflow: hidden; }
.hf-bar { display: block; height: 100%; background: var(--ok); border-radius: 5px; }
.hf-n { text-align: right; font-variant-numeric: tabular-nums; }
ol.heal-story { list-style: none; margin: 0; padding: 0 0 0 14px; border-left: 2px solid var(--line2); }
ol.heal-story > li { position: relative; padding: 6px 0 6px 10px; }
ol.heal-story > li::before { content: ''; position: absolute; left: -20px; top: 12px; width: 10px; height: 10px; border-radius: 50%; background: var(--bg2); border: 2px solid var(--line2); }
.hs-attempt > summary { cursor: pointer; }
.hs-body { margin: 6px 0 4px 2px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius); }
.hs-answer { margin-bottom: 6px; }
.hs-person b, .hs-caught b { font-weight: 600; }
.datadog-heal-answer textarea { width: 100%; min-height: 70px; }

/* A project's charts on its Overview (changelog v1.233; js/overviewcards.js). Two columns on a
   wide page, lanes and heatmaps across both; the plots stretch, the labels are HTML. Colours are
   the palette's: a state (--ok, --warn, --err, --info, --fg3) or a category (--cat1..8). */
.oc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 440px), 1fr)); grid-auto-flow: row dense; gap: 12px; }
.oc-grid > .card { margin: 0; min-width: 0; }
.oc-card.wide, .oc-runs { grid-column: 1 / -1; }
.oc-caption { color: var(--fg2); font-size: 12px; margin: -2px 0 8px; }
.oc-from { margin-top: 6px; }
.oc-ok { --oc: var(--ok); } .oc-warn { --oc: var(--warn); } .oc-err { --oc: var(--err); }
.oc-info { --oc: var(--info); } .oc-muted { --oc: var(--fg3); } .oc-target { --oc: var(--fg2); }
.oc-c1 { --oc: var(--cat1); } .oc-c2 { --oc: var(--cat2); } .oc-c3 { --oc: var(--cat3); } .oc-c4 { --oc: var(--cat4); }
.oc-c5 { --oc: var(--cat5); } .oc-c6 { --oc: var(--cat6); } .oc-c7 { --oc: var(--cat7); } .oc-c8 { --oc: var(--cat8); }
.oc-frame { display: grid; grid-template-columns: max-content 1fr; gap: 6px; }
.oc-ylabs { display: flex; flex-direction: column; justify-content: space-between; color: var(--fg3); font-size: 11px; text-align: right; min-width: 22px; }
.oc-plot { width: 100%; height: 150px; display: block; overflow: visible; }
.oc-axis { stroke: var(--line2); stroke-width: 1; }
.oc-ref { stroke: var(--oc); stroke-width: 1.5; stroke-dasharray: 5 4; }
.oc-line { fill: none; stroke: var(--oc); stroke-width: 2; stroke-linejoin: round; }
.oc-line.dashed { stroke-dasharray: 6 4; stroke-width: 1.5; opacity: .85; }
.oc-dot { stroke: var(--oc); stroke-width: 6; stroke-linecap: round; }
.oc-dot.hit { stroke: transparent; stroke-width: 10; }
.oc-dot:hover { stroke: var(--fg); }
.oc-bar { fill: var(--oc); }
.oc-bar:hover { opacity: .8; }
.oc-xlabs { display: flex; justify-content: space-between; color: var(--fg3); font-size: 11px; margin: 2px 0 0 28px; }
.oc-catlabs { display: grid; color: var(--fg3); font-size: 11px; margin: 2px 0 0 28px; }
.oc-catlabs > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; padding: 0 1px; }
.oc-catlabs.days > span { overflow: visible; text-overflow: clip; text-align: left; }
.oc-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 8px; font-size: 12px; color: var(--fg2); }
.oc-legend i { display: inline-block; width: 14px; height: 3px; border-radius: 2px; margin-right: 6px; vertical-align: middle; background: var(--oc); }
/* v1.327: a button card (chart: button) */
.oc-btnrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin-bottom: 8px; }
.oc-btnreports { margin-top: 6px; display: grid; gap: 4px; }
.oc-legend i.dashed { background: repeating-linear-gradient(90deg, var(--oc) 0 4px, transparent 4px 7px); }
.oc-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
.oc-tile { border: 1px solid var(--line); border-left: 4px solid var(--oc); border-radius: 6px; padding: 6px 8px;
  background: color-mix(in srgb, var(--oc) 9%, var(--bg2)); min-width: 0; }
.oc-hull { font-size: 11px; color: var(--fg3); }
.oc-tval { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-tnote { font-size: 11px; color: var(--fg2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-lanes { display: grid; gap: 2px; }
.oc-lanerow, .oc-lanefoot { display: grid; grid-template-columns: 92px 1fr; align-items: center; gap: 8px; }
.oc-lanelab { font-size: 12px; color: var(--fg2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; }
.oc-lane { width: 100%; height: 20px; display: block; }
.oc-span { fill: var(--oc); opacity: .85; }
.oc-span:hover { opacity: 1; }
.oc-dot.mark { stroke-width: 7; }
.oc-lanefoot .oc-xlabs { margin-left: 0; }
.oc-heatwrap { overflow-x: auto; }
.oc-heat { display: grid; gap: 2px; align-items: center; font-size: 11px; }
.oc-hcol { color: var(--fg3); white-space: nowrap; overflow: visible; }
.oc-hrow { color: var(--fg2); padding-right: 6px; text-align: right; white-space: nowrap; }
.oc-cell { display: block; height: 16px; border-radius: 2px; background: var(--oc, var(--bg3)); }
.oc-cell.none { background: var(--bg3); }
.oc-cell.count { background: color-mix(in srgb, var(--accent) calc(var(--oc-v, 0) * 100%), var(--bg3)); }
.oc-sched { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1.2fr) minmax(0, 2fr) max-content; gap: 10px; align-items: center; padding: 4px 0; }
.oc-sname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-ticks { display: flex; gap: 2px; }
.oc-ticks i { width: 9px; height: 14px; border-radius: 2px; background: var(--oc); }
.oc-holds { margin-top: 8px; display: grid; gap: 3px; }
@media (max-width: 640px) {
  .oc-sched { grid-template-columns: minmax(0, 1fr); gap: 2px; padding: 6px 0; }
  .oc-lanerow, .oc-lanefoot { grid-template-columns: 56px 1fr; }
}
/* v1.236: a heatmap with its numbers in the cells (an evaluation table) */
.oc-heat.values .oc-cell { height: auto; min-height: 20px; line-height: 20px; font-size: 11px; font-style: normal; text-align: center; color: var(--fg); overflow: hidden; }

/* Project portals (changelog v1.265, docs/portals.md): static/portal.html and js/portal.js, one
   project's own screen on its own host, under a slim top bar. */
.portal { min-height: 100vh; display: flex; flex-direction: column; }
.portal-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; padding: 8px 16px; min-height: 48px; background: var(--bg2); border-bottom: 1px solid var(--line); }
.portal-bar h1 { overflow-wrap: anywhere; }
.portal-main { flex: 1; width: 100%; max-width: 1500px; margin: 0 auto; padding: 16px; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; }
.portal-signin { max-width: 420px; margin: 12vh auto 0; display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
@media (max-width: 640px) { .portal-main { padding: 12px; } }
/* v1.267: the people picker (portalpeople.js) and a portal's default screen (portal.js) */
.portal-picklist { max-height: 320px; overflow-y: auto; border: 1px solid var(--line); border-radius: var(--radius); padding: 4px 8px; display: flex; flex-direction: column; }
.portal-pick { display: flex; align-items: center; gap: 8px; padding: 3px 0; flex-wrap: wrap; cursor: pointer; }
.portal-pick.muted { cursor: default; }
.portal-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
/* ?focus= deep links (changelog v1.270, core.js focusOn): the part a link points at, ringed. */
.focus-hit { animation: focus-hit 4s ease-out 1; border-radius: 6px; }
@keyframes focus-hit { 0%, 70% { outline: 3px solid var(--accent); outline-offset: 3px; background: color-mix(in srgb, var(--accent) 12%, transparent); } 100% { outline: 3px solid transparent; outline-offset: 3px; background: transparent; } }

/* v1.311 boat access lists: the checklist of every onboarded boat (boatgrid.js) on a team
   channel's and a project's Boats tab (dense tiles, a box per registered computer coloured by its
   level, a dashed outline while a change waits for Save, a caret per hull that spans the row when
   open), the hull chip pickers (projectboats.js hullPicker: the attach form, Boat Sync's root
   fleet and Grant several), and a project's boat cards side by side with their secondary lines
   folded. */
.bg-intro { margin: 0; }
.bg-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.bg-bar .bg-filter { width: 7em; min-width: 0; }
.bg-show { display: inline-flex; }
.bg-show > button { border-radius: 0; }
.bg-show > button:first-child { border-radius: 6px 0 0 6px; }
.bg-show > button:last-child { border-radius: 0 6px 6px 0; margin-left: -1px; }
.bg-count { font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0; font-weight: 400; }
.bg-edit { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
.bg-tickfield { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--fg2); }
/* 340px: a hull with a change or root chip keeps one line (3 columns at 1600, 2 at 1280) */
.bg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); gap: 4px 6px; }
.bg-tile { border: 1px solid var(--line); border-radius: 6px; background: var(--bg); min-width: 0; }
.bg-tile[open] { grid-column: 1 / -1; }
.bg-tile.pending { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); }
.bg-line { display: flex; align-items: center; gap: 5px; padding: 3px 6px; min-height: 30px; list-style: none; }
summary.bg-line::-webkit-details-marker { display: none; }
.bg-hullbox { display: inline-flex; align-items: center; gap: 4px; min-width: 2.9em; cursor: pointer; }
.bg-hullbox b { color: var(--fg); font-variant-numeric: tabular-nums; }
.bg-sim { font-size: 9.5px; color: var(--fg3); border: 1px dashed var(--line2); border-radius: 4px; padding: 0 2px; }
.bg-chips { display: inline-flex; flex-wrap: wrap; gap: 3px; min-width: 0; }
.bg-slot, .bg-chips > .bg-chip { min-width: 66px; }
.bg-chip { display: inline-flex; align-items: center; gap: 2px; padding: 0 5px 0 3px; box-sizing: border-box; border: 1px solid var(--line2); border-radius: 999px; font-size: 11px; line-height: 20px; color: var(--fg2); cursor: pointer; white-space: nowrap; }
.bg-chip input { margin: 0; }
.bg-chip.lv-read { border-color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--fg); }
.bg-chip.lv-change { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--fg); }
.bg-chip.lv-root { border-color: var(--err); background: color-mix(in srgb, var(--err) 16%, transparent); color: var(--fg); }
.bg-chip.pending { box-shadow: 0 0 0 2px var(--accent); }
.bg-chip.off { opacity: .55; }
.bg-chip.missing { border-style: dashed; color: var(--fg3); }
.bg-lv { font-weight: 600; font-size: 10px; }
.bg-mark { width: 7px; height: 7px; border-radius: 50%; background: var(--warn); flex: none; }
.bg-caret { margin-left: auto; padding: 0 0 0 2px; color: var(--fg3); }
.bg-caret::before { content: '\25B8'; }
.bg-tile[open] .bg-caret::before { content: '\25BE'; }
.bg-body { padding: 6px 8px 8px 28px; display: flex; flex-direction: column; gap: 8px; border-top: 1px dashed var(--line); }
.bg-comp { display: flex; flex-direction: column; gap: 3px; }
.bg-comphead { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
/* name, host and level in columns of one width, so the level selects line up */
.bg-comphead .bg-cname { min-width: 4.6em; }
.bg-comphead .bg-chost { min-width: 7.5em; }
.bg-comphead .bg-clevel { min-width: 11em; }
.bg-comphead .bg-set { flex: 1 1 16em; min-width: 0; overflow-wrap: anywhere; }
.bg-history { display: flex; flex-direction: column; gap: 2px; padding-left: 8px; border-left: 2px solid var(--line); }
.bg-fleetline { padding: 0; gap: 8px; flex-wrap: wrap; }
.bg-confirm { display: flex; flex-direction: column; gap: 8px; }
.bg-confirm h3 { margin: 0; font-size: 14px; }
.hull-picker { gap: 4px; }
.hull-picker .chip { min-width: 2.6em; text-align: center; font-variant-numeric: tabular-nums; }
.hull-picker .chip.missing { border-style: dashed; }
.hull-picker .chip.off:not(.on) { opacity: .6; }
.pb-projgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 8px; align-items: start; }
.pb-projgrid > :not(.pb-boat) { grid-column: 1 / -1; }
details.pb-more > summary { font-size: 12px; margin-top: 4px; }
details.pb-more[open] { display: flex; flex-direction: column; gap: 3px; }
@media (max-width: 640px) {
  .bg-grid { grid-template-columns: minmax(0, 1fr); }
  .bg-line { min-height: 40px; flex-wrap: wrap; }
  .bg-chip { min-height: 34px; padding: 0 6px 0 4px; font-size: 12px; }
  .bg-line { gap: 4px; }
  .bg-hullbox { min-height: 34px; }
  .bg-bar .bg-filter { flex: 1 1 5em; }
  .bg-edit { margin-left: 0; }
  .hull-picker .chip { min-height: 34px; }
  .bg-body { padding-left: 10px; }
}
/* v1.311 access: the Access tab (projectaccess.js, a project's and a team channel's) and the plan
   card (accessplan.js). One column no wider than it needs; one line per row with the rest behind
   a caret; the tool projects' Use boxes in a grid; production and credentials folded at the end. */
.page.pa-page, .page > .page.pa-page { max-width: 980px; margin-left: 0; }
.pa-head, .pa-headlines { display: flex; flex-direction: column; gap: 4px; }
.pa-mode { padding: 3px 10px; border-left: 3px solid var(--line2); border-radius: 4px; background: var(--bg2); color: var(--fg2); }
.pa-mode.warn { border-left-color: var(--warn); } .pa-mode.info { border-left-color: var(--info); }
.pa-boatline { overflow-wrap: anywhere; }
.pa-cards { display: flex; flex-direction: column; gap: 10px; }
.pa-cards > .card { padding: 10px 14px; }
.pa-cards .card h3 { margin-bottom: 6px; }
.pa-list { display: flex; flex-direction: column; gap: 4px; }
.pa-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.pa-refused.pa-line:not(.open) { padding: 2px 0; }
.pa-key { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
/* a caret row: the line, and what it hides under it */
.pa-item { border-top: 1px solid var(--line); }
.pa-item:first-child { border-top: none; }
.pa-item > summary, .pa-manual > summary, details.pa-fold > summary, details.pa-history > summary { list-style: none; }
.pa-item > summary::-webkit-details-marker, .pa-manual > summary::-webkit-details-marker, details.pa-fold > summary::-webkit-details-marker, details.pa-history > summary::-webkit-details-marker { display: none; }
.pa-item > summary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 5px 0; color: var(--fg); }
.pa-item > summary::before, .pa-manual > summary::before, details.pa-fold > summary::before, details.pa-history > summary::before { content: '\25B8'; display: inline-block; width: 1em; color: var(--fg3); transition: transform .15s; }
.pa-item[open] > summary::before, .pa-manual[open] > summary::before, details.pa-fold[open] > summary::before, details.pa-history[open] > summary::before { transform: rotate(90deg); }
.pa-more { display: flex; flex-direction: column; gap: 4px; padding: 0 0 8px 1.4em; }
details.pa-history > summary { padding: 1px 0; }
.pa-hbody { display: flex; flex-direction: column; gap: 2px; padding: 2px 0 4px 1em; }
/* the tool projects: Use boxes, two to four across */
.pa-tools-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px 14px; }
.pa-tool { min-width: 0; display: flex; flex-direction: column; gap: 1px; padding: 4px 6px; border-radius: 6px; border: 1px solid transparent; }
.pa-tool.held { background: var(--bg3); }
.pa-tool[data-asked] { border-color: var(--warn); }
.pa-use { font-size: 13px; color: var(--fg); }
.pa-tname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-brings { padding-left: 26px; overflow-wrap: anywhere; }
.pa-tool details.pa-history { padding-left: 22px; }
/* Add access: the question, the words, then the form by hand under its caret */
.pa-addcard .plan-ask { font-weight: 600; color: var(--fg); }
.pa-addcard textarea { min-height: 3.4em; }
.pa-manual { border-top: 1px solid var(--line); margin-top: 10px; padding-top: 6px; }
.pa-manual > summary { color: var(--fg2); padding: 2px 0; }
.pa-manual[open] > summary { margin-bottom: 8px; }
.pa-add { display: flex; flex-direction: column; gap: 8px; }
.pa-add .toolbar { align-items: flex-end; }
.pa-add label.field.pa-levelf { flex: 0 1 22em; min-width: 0; max-width: 100%; }
.pa-add label.field.pa-levelf > select { width: 100%; }
.pa-add label.field > select { max-width: 100%; }
.pa-reason, .cfolder-reason { width: 16em; max-width: 100%; }
.pa-manual > .hint, .pa-suggest { margin-top: 8px; }
.pa-pick { align-items: flex-start; }
/* production and credentials, folded to one line */
details.pa-fold > summary { display: flex; align-items: baseline; gap: 4px; }
.pa-ft { font-size: 13px; text-transform: uppercase; letter-spacing: .6px; color: var(--fg3); font-weight: 600; }
.pa-fline { font-size: 12.5px; }
details.pa-fold[open] > summary { margin-bottom: 8px; }
.pa-gh { margin-top: 4px; }
/* the channel's projects folder: one row */
.cfolder .formfoot, .cfolder-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.formfoot.cfolder-row > select { flex: 0 1 22em; min-width: 0; max-width: 100%; }
@media (max-width: 640px) {
  .page.pa-page, .page > .page.pa-page { max-width: 100%; }
  .pa-tools-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 8px; }
  .pa-brings { padding-left: 0; }
  .pa-tool details.pa-history { padding-left: 0; }
  .pa-reason, .cfolder-reason { width: auto; flex: 1 1 10em; }
  .pa-add label.field.pa-levelf { flex: 1 1 100%; }
}

/* v1.311 settings layout and optional reasons: two shared form classes (any page may use them),
   the channel Settings tab's cards side by side, and settings_form.js fields that are as wide as
   their value needs, never the card. */
/* .formgrid: label/input pairs in equal columns; long labels wrap, inputs line up and fill */
.formgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(11em, 100%), 1fr)); gap: 10px 16px; align-items: end; max-width: 64em; }
.formgrid > label.field { min-width: 0; }
.formgrid > label.field > input, .formgrid > label.field > select { width: 100%; min-width: 0; }
/* .formfoot: an optional reason (or one short control) and its buttons right after it */
.formfoot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.formfoot > input, .formfoot > select, .formfoot > label.field { flex: 1 1 12em; min-width: 0; max-width: min(20em, 100%); }
.formfoot > button, .formfoot > a.btn { flex: none; }
/* the channel Settings tab: Limits and Token side by side, neither across a wide screen */
.csettings { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.csettings > .card { min-width: 0; }
.csettings > .climits-card { flex: 1 1 34em; max-width: 52em; }
.csettings > .ctoken { flex: 1 1 22em; max-width: 36em; }
/* settings_form.js: a select or text box about 32em, a number 12em, a checkbox by its label */
.setting > label.field { align-items: flex-start; }
.setting > label.field > select, .setting > label.field > input[type=text] { width: min(100%, 32em); min-width: 0; }
.setting > label.field > input[type=number] { width: min(100%, 12em); min-width: 0; }
.setting > label.field:has(> input[type=checkbox]) { flex-direction: row-reverse; justify-content: flex-end; align-items: center; gap: 8px; }
.setting > label.field > input[type=checkbox] { min-width: 0; margin: 0; }
.setting > label.field > .host-int, .setting > label.field > .proj-pick { max-width: 100%; }
/* its group cards in columns where the page is wide enough; one column on a phone */
.settings-form, .settings-form > .setsec { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 30em), 1fr)); gap: 10px 14px; align-items: start; }
.settings-form > :not(.setting-group), .setsec > :not(.setting-group) { grid-column: 1 / -1; }
.settings-form .setting-group { margin-bottom: 0; }
.settings-form > .setsec { margin-bottom: 4px; }
@media (max-width: 640px) {
  .formgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .formfoot > input, .formfoot > select, .formfoot > label.field { max-width: 100%; }
}

/* v1.311 channel overview: a channel's Overview (tabs/channels.js overviewPanel) is a card grid,
   two columns on a desktop and one on a phone, newest first; Now spans the row. Job, report and
   project lines are one row each on fixed columns, so they line up from row to row (flex lines
   that wrap on a phone); the 14-day charts are short. */
.cov { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.cov > .card, .cov > .cov-side { margin: 0; min-width: 0; }
.cov > .cov-now { grid-column: 1 / -1; }
.cov-side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.cov-side > :last-child { flex: 1 1 auto; }
@media (max-width: 900px) { .cov { grid-template-columns: minmax(0, 1fr); } }
.cov .card h3 a { text-transform: none; letter-spacing: 0; font-weight: 400; }
.cov-list { display: flex; flex-direction: column; min-width: 0; }
.cov-row { display: grid; align-items: center; gap: 2px 8px; padding: 5px 0; border-bottom: 1px solid var(--line); font-size: 13px; min-width: 0; }
.cov-row:last-child { border-bottom: 0; }
.cov-row.cov-job { grid-template-columns: 8px minmax(0, 1fr) minmax(0, 6em) 3.5em 4.6em; }
.cov-row.cov-rep { grid-template-columns: minmax(0, 1fr) 4.5em minmax(0, 6em) 4.6em; }
.cov-row.cov-prj { grid-template-columns: minmax(0, 1fr) 8.5em 4.6em; }
.cov-row.cov-post { grid-template-columns: minmax(0, 1fr) auto 4.6em; }
.cov-row.archived .cov-name .proj { opacity: .7; }
.cov-what, .cov-who, .cov-files { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cov-proj, .cov-name { min-width: 0; display: flex; align-items: center; gap: 6px; overflow: hidden; }
.cov-proj .proj, .cov-name .proj { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; }
.cov-name .pill { flex: 0 0 auto; }
.cov-when { text-align: right; color: var(--fg3); font-size: 12px; white-space: nowrap; }
.cov-jobs { white-space: nowrap; text-align: right; }
.cov-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fg3); }
.cov-dot.ok { background: var(--ok); } .cov-dot.err { background: var(--err); } .cov-dot.warn { background: var(--warn); }
.cov-dot.info { background: var(--info); box-shadow: 0 0 6px var(--info); }
.cov-row > .bar { grid-column: 2 / -1; height: 6px; margin-top: 2px; }
.cov-note { grid-column: 2 / -1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cov-nowbody { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px 20px; }
.cov-running { flex: 1 1 420px; }
.cov-quiet { flex: 1 1 auto; padding: 2px 0; }
.cov-chips { display: flex; flex-wrap: wrap; gap: 6px; flex: 0 1 auto; max-width: 100%; }
.cov-err { flex: 1 1 100%; }
a.cov-chip { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--line2); background: var(--bg3); color: var(--fg); font-size: 12px; text-decoration: none; white-space: nowrap; }
a.cov-chip.warn { border-color: color-mix(in srgb, var(--warn) 60%, transparent); background: color-mix(in srgb, var(--warn) 10%, var(--bg2)); }
a.cov-chip.err { border-color: var(--err); background: color-mix(in srgb, var(--err) 12%, var(--bg2)); }
a.cov-chip:hover { border-color: var(--fg3); }
details.cov-more > summary { cursor: pointer; padding: 5px 0; }
.cov-charts { display: flex; flex-direction: column; gap: 10px; }
.cov-sub { font-size: 11.5px; color: var(--fg3); margin-bottom: 2px; }
.cov-charts .oc-plot { height: 76px; }
.cov-charts .oc-legend { margin-top: 4px; }
.cov-jobchart .oc-c1 { --oc: var(--accent); } .cov-jobchart .oc-c2 { --oc: var(--err); }
.cov-spendchart .oc-c1 { --oc: var(--cat4); }
.cov .cglance .stats { grid-template-columns: minmax(0, 1fr); gap: 0; }
.cov .cglance .stat { flex-direction: row-reverse; justify-content: space-between; align-items: baseline; gap: 12px; padding: 5px 0; border-bottom: 1px solid var(--line); }
.cov .cglance .stat:last-child { border-bottom: 0; }
.cov .cglance .stat .v { font-size: 13px; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.cov .cglance .stat .k { font-size: 12.5px; text-transform: none; letter-spacing: 0; color: var(--fg2); }
.cnote-text { font-size: 13px; overflow-wrap: anywhere; }
.cnote-form .row.tight > input[name="note"] { flex: 1 1 10em; min-width: 0; }
.cnote-form .hint { margin-top: 6px; }
@media (max-width: 640px) {
  .cov-row.cov-job, .cov-row.cov-rep, .cov-row.cov-prj { display: flex; flex-wrap: wrap; gap: 4px 8px; padding: 7px 0; }
  .cov-row .cov-what, .cov-row .cov-name { flex: 1 1 100%; white-space: normal; }
  .cov-row.cov-job .cov-what { flex-basis: calc(100% - 16px); }
  .cov-row .cov-proj { flex: 0 1 auto; }
  .cov-row .cov-when { margin-left: auto; }
  .cov-row > .bar, .cov-note { flex: 1 1 100%; }
  a.cov-chip { min-height: 36px; padding: 4px 12px; }
}

/* v1.311 project overviews (tabs/projects.js renderOverview, js/overviewcards.js mountRecent):
   Needs you as one slim line when nothing waits; the Now cards (Running now, Coming up, Recent
   reports, Warnings), a tool project's Used by and At a glance, Recent jobs beside Activity and
   the static cards share .oc-grid's columns, each cell's card filling its row; a server part's
   manifest cards behind a caret, its live hook cards up top (hidden while it draws none). */
.pa-card.slim { padding: 8px 14px; }
.pa-card.slim h3 { margin: 0; flex-wrap: wrap; gap: 4px 10px; }
.pa-card.slim .pa-none { margin-left: 10px; text-transform: none; letter-spacing: 0; font-weight: 400; font-size: 13px; }
.ov-cell, .ov-lead > [data-slot], .ov-pair > [data-slot], .ov-static > [data-slot] { display: flex; flex-direction: column; min-width: 0; }
.ov-cell > .card, .ov-lead > [data-slot] > .card, .ov-pair > [data-slot] > .card, .ov-static > [data-slot] > .card { flex: 1 1 auto; margin: 0; }
.page.ppart-live:empty { display: none; }
.ov-list { display: flex; flex-direction: column; }
.ov-row { display: flex; flex-direction: column; gap: 3px; padding: 7px 0; border-top: 1px solid var(--line); min-width: 0; }
.ov-row:first-child { border-top: none; padding-top: 0; }
.ov-line { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; min-width: 0; }
.ov-line > .spacer { flex: 1 1 0; }
.ov-name { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.ov-sub { min-width: 0; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ov-n { margin-left: 8px; }
.ov-kind { font-size: 10.5px; padding: 0 6px; }
.pstrip.ov-proj { display: inline-flex; min-width: 0; max-width: 100%; }
.ov-use { display: grid; grid-template-columns: minmax(0, 1fr) minmax(96px, 25%); gap: 10px; align-items: center; padding: 3px 0; }
.ov-use .kitbar { width: 100%; }
.ov-now .oc-sched { grid-template-columns: minmax(0, 1fr) max-content; gap: 4px 10px; }
.ov-now .oc-ticks { flex-wrap: wrap; }
.ov-now .oc-ticks i { width: 7px; }
@media (max-width: 640px) { .ov-now .oc-sched { grid-template-columns: minmax(0, 1fr); } }
.tablewrap.ov-jobs td { vertical-align: top; }
.tablewrap.ov-jobs td:first-child { width: 100%; }
details.card.kitfold > summary { cursor: pointer; list-style: none; }
details.card.kitfold > summary::-webkit-details-marker { display: none; }
details.card.kitfold > summary h3 { margin: 0; }
details.card.kitfold > summary h3::before { content: '\25B8'; font-size: 11px; color: var(--fg3); }
details.card.kitfold[open] > summary h3::before { content: '\25BE'; }
details.card.kitfold[open] > summary { margin-bottom: 8px; }
