/* WeGro Fundraising Desk
 *
 * Brand colours read straight out of the logo file: green #00A950, orange
 * #F5831F. The brief was "related to the logo, but not too contrasty", which
 * turns into one rule applied everywhere:
 *
 *   SATURATED BRAND COLOUR STAYS UNDER ROUGHLY 10% OF ANY SCREEN.
 *
 * Green means "this is the primary action" or "this is confirmed". Orange
 * means "look at this" - a deadline inside three weeks, a missing document, an
 * overdue follow-up - and nothing else, so that when it appears it still
 * carries weight. They are never used as a pair; orange text on green, or the
 * reverse, appears nowhere.
 *
 * Everything else is a warm neutral ramp on paper. The tables are dense on
 * purpose: the job is comparing three hundred firms, and whitespace that looks
 * generous on one row costs you the ability to see thirty.
 */

:root {
  /* --- surfaces, warm rather than blue-grey ---------------------------- */
  --bg:        #faf9f6;
  --panel:     #ffffff;
  --panel-2:   #f5f3ee;
  --line:      #e5e2da;
  --line-soft: #efece5;

  /* --- ink ------------------------------------------------------------- */
  --ink:       #1b1c19;
  --ink-2:     #4a4a44;
  --muted:     #74736b;

  /* --- brand ----------------------------------------------------------- */
  --green:       #00a950;   /* the logo green, for small marks only */
  --green-deep:  #00713a;   /* text and fills that need to pass contrast */
  --green-mid:   #3eae73;
  --green-soft:  #e8f2ec;
  --green-line:  #bfe0cd;

  --orange:      #f5831f;   /* attention, never decoration */
  --orange-deep: #c2410c;
  --orange-soft: #fdf1e3;
  --orange-line: #f6d5b0;

  /* --- status ---------------------------------------------------------- */
  --bad:       #a12a1e;
  --bad-soft:  #fbeae7;
  --warn-ink:  #8a5a00;

  /* --- the shell ------------------------------------------------------- */
  --top-h:       52px;
  --nav-w:       236px;
  --nav-rail-w:  58px;

  --radius:    7px;
  --radius-sm: 5px;
  --shadow:    0 1px 2px rgba(28, 28, 26, .05);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

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

/* Green-deep against body ink is 2.8:1, and WCAG asks for 3:1 when colour is
   the only thing marking a link. The underline is the second signal; it is
   drawn in a pale green so a dense table does not turn into a fence. */
a { color: var(--green-deep); text-decoration: underline;
    text-decoration-color: var(--green-line); text-underline-offset: 2px; }
a:hover { text-decoration-color: currentColor; }
/* Things that are links only incidentally - buttons, pills, whole cards - opt
   out. They already look like controls. */
.btn, .linkbtn, .brand, .lane-pill, .sidebar a, .flowstep, .choose a,
.bcard-name, .card a, .topbar a { text-decoration: none; }

h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -.01em; }
h2 { font-size: 16px; margin: 0 0 10px; letter-spacing: -.005em; }
h3 { font-size: 13px; margin: 0 0 8px; text-transform: uppercase;
     letter-spacing: .06em; color: var(--muted); font-weight: 600; }

/* ---------------------------------------------------------------------- */
/* Chrome                                                                  */
/* ---------------------------------------------------------------------- */

.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 18px;
  padding: 0 20px; height: 52px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex; align-items: baseline; gap: 1px;
  font-weight: 800; font-size: 17px; letter-spacing: -.02em;
  color: var(--green-deep); text-decoration: none; white-space: nowrap;
  /* Without this the wordmark is the first thing flexbox squeezes, and
     "WEGRO Fundraising Desk" collapses into a broken-looking stack. */
  flex: 0 0 auto;
}
.brand .o { color: var(--orange); }
.brand small {
  font-weight: 500; font-size: 12px; color: var(--muted);
  margin-left: 8px; letter-spacing: 0;
}

/* Opens the drawer below 900px, where the sidebar is an overlay. Hidden above
   it, because there the sidebar is always on screen. */
.navbtn {
  display: none; background: none; border: 0; padding: 6px; cursor: pointer;
  color: var(--ink-2); border-radius: var(--radius-sm); line-height: 0;
}
.navbtn:hover { background: var(--panel-2); }

/* flex-shrink is what stops "sending is live" - the one thing on this bar
   that must never be missed - being the element that wraps at 800px. */
.topbar .right {
  display: flex; align-items: center; gap: 10px;
  margin-left: auto; flex: 0 0 auto;
}

.lane-pill {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; padding: 3px 9px; border-radius: 20px;
  background: var(--green-soft); color: var(--green-deep);
  border: 1px solid var(--green-line);
}
.lane-pill.grant { background: var(--orange-soft); color: var(--orange-deep);
                   border-color: var(--orange-line); }

.mode { font-size: 11px; color: var(--muted); text-transform: uppercase;
        letter-spacing: .06em; white-space: nowrap; }
.mode.live { color: #fff; background: var(--bad); padding: 3px 8px;
             border-radius: 20px; font-weight: 700; }

.avatar {
  position: relative;     /* anchors the .vh name inside it */
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--green-deep); color: #fff;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; letter-spacing: .02em;
}
.avatar.sm { width: 21px; height: 21px; font-size: 9px; }
.avatar.none { background: var(--line); color: var(--muted); }

.linkbtn {
  background: none; border: 0; padding: 6px 8px; cursor: pointer;
  color: var(--muted); font-size: 13px; font-family: inherit;
}
.linkbtn:hover { color: var(--ink); text-decoration: underline; }

/* The two flags: favourite (personal) and shortlist (the team's).
   They differ by SHAPE, not just colour - a star and a bookmark - because two
   controls that differ only in hue are two controls nobody can tell apart, and
   that is doubly true for anyone who cannot see the difference at all.

   Off is a grey outline, on is filled. Green means "this is set" here as it
   does everywhere else in the app; orange is reserved for attention and a
   bookmark is not an alert. */
.flag {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--muted); line-height: 1;
  /* A 16px icon in a 24px hit area, bought back with negative margin so a
     dense table row does not grow. */
  padding: 4px; margin: -4px;
  border-radius: var(--radius-sm);
}
.flag:hover        { color: var(--ink); background: var(--panel-2); }
.flag.on           { color: var(--green-deep); }
.flag.on:hover     { color: var(--green-deep); }
.flag:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 1px; }
.flag .ico         { flex: 0 0 auto; }

/* Both flags in one cell, and the cell must not stretch the row. */
.flags { white-space: nowrap; }
.flags .m0 { display: inline-block; }

/* On the firm page they are buttons with words beside the icon, so the
   negative margin above would pull them out of the button box. */
.btn.flag { padding: 5px 10px; margin: 0; }
/* Inside a table the same button was adding 12px to every row's height.
   Two hundred rows of that is a lot of scrolling for no information. */
/* Was an 18x20 target, under the 24x24 floor. Negative margin buys the hit
   area back out of the cell padding without adding a pixel of row height -
   which matters, because this button appears on all 364 rows. */
td .linkbtn {
  font-size: 14px; line-height: 1.3;
  padding: 6px 9px; margin: -6px -4px;
  min-width: 24px; min-height: 24px;
}

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

/* Sidebar down the left, everything else on the right, top bar across both.
   The bar spans the full width so the wordmark and the account controls stay
   exactly where they are while the sidebar folds underneath them.

   `minmax(0, 1fr)` rather than `1fr`: a grid column's default minimum is its
   content, so one wide table would otherwise push the whole page sideways
   instead of scrolling inside its own box. */
body.app {
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr);
  grid-template-rows: var(--top-h) 1fr auto;
  grid-template-areas:
    "top top"
    "nav main"
    "nav foot";
  min-height: 100vh;
}
/* The chooser is the one screen with no workspace, so it has no sidebar. */
body.app.no-nav {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "top" "main" "foot";
}

.topbar { grid-area: top; }
main     { grid-area: main; max-width: 1320px; width: 100%; margin: 0 auto;
           padding: 20px; }
footer   { grid-area: foot; max-width: 1320px; width: 100%;
           margin: 30px auto 40px; padding: 0 20px;
           color: var(--muted); font-size: 12px; }
/* Focused only by the skip link, which needs somewhere to land, not a ring. */
main:focus { outline: none; }

.page-head { display: flex; align-items: flex-end; justify-content: space-between;
             gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.page-head p { margin: 0; color: var(--muted); font-size: 13px; }
.crumbs { font-size: 12px; color: var(--muted); margin: 0 0 2px; }

/* --- the sidebar ------------------------------------------------------- */

.sidebar {
  grid-area: nav;
  position: sticky; top: var(--top-h); align-self: start;
  height: calc(100vh - var(--top-h));
  overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column;
  padding: 10px 8px 14px;
  background: var(--panel);
  border-right: 1px solid var(--line);
}

/* A native <details> per group. No JavaScript needed to fold one, and the
   keyboard and screen-reader behaviour comes with it. */
.navgroup > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 9px 10px 5px; cursor: pointer; user-select: none;
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
  border-radius: var(--radius-sm);
  list-style: none;
}
.navgroup > summary::-webkit-details-marker { display: none; }
.navgroup > summary:hover { background: var(--panel-2); color: var(--ink-2); }
.navgroup > summary .chev { flex: 0 0 auto; transition: transform .15s ease; }
.navgroup[open] > summary .chev { transform: rotate(180deg); }

.sidebar ul { list-style: none; margin: 0 0 4px; padding: 0; }
.sidebar a {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; margin: 1px 0;
  border-radius: var(--radius-sm);
  color: var(--ink-2); font-size: 14px; line-height: 1.25;
  white-space: nowrap; text-decoration: none;
}
.sidebar a:hover { background: var(--panel-2); color: var(--ink);
                   text-decoration: none; }
/* The inset rail matters: it means the current row is not signalled by a pale
   green wash alone, which is a 1.4:1 difference against the panel. */
.sidebar a.on {
  background: var(--green-soft); color: var(--green-deep); font-weight: 600;
  box-shadow: inset 2px 0 0 var(--green);
}
.sidebar .ico { flex: 0 0 18px; color: var(--muted); }
.sidebar a:hover .ico, .sidebar a.on .ico { color: inherit; }

.navfoot { margin-top: auto; padding-top: 6px;
           border-top: 1px solid var(--line-soft); }
.railtoggle { margin: 0; }
#rail-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 7px 10px; border-radius: var(--radius-sm); color: var(--muted);
}
#rail-toggle:hover { background: var(--panel-2); color: var(--ink);
                     text-decoration: none; }
#rail-toggle .ico { flex: 0 0 18px; transition: transform .15s ease; }

.navscrim { display: none; }

/* ---------------------------------------------------------------------- */
/* Layout                                                                  */
/* ---------------------------------------------------------------------- */

.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; margin-bottom: 16px;
  box-shadow: var(--shadow);
  /* A panel is a column: heading, then content. Without this, a floated or
     inline-block child could sit beside the heading and look like a collision. */
  display: flow-root;
}
.panel.tight { padding: 12px; }

/* Heading for a panel whose body is a full-bleed table. Replaces the inline
   `style="padding:4px 4px 8px"` that was repeated on six headings and drifted. */
.panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin: 0 0 10px; flex-wrap: wrap;
}
.panel-head h2 { margin: 0; }
.panel-head .note { font-size: 12px; color: var(--muted); }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.split-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
/* Cards reflow on their own rather than at two hard breakpoints. Four across
   on a wide screen, and at 900px they were being squeezed to the point that a
   six-figure number wrapped under its own label. */
.cards { display: grid; gap: 12px; margin-bottom: 16px;
         grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

.card {
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--green); border-radius: var(--radius);
  padding: 12px 14px;
}
.card.attention { border-left-color: var(--orange); }
.card.plain { border-left-color: var(--line); }
.card .n { font-size: 26px; font-weight: 700; letter-spacing: -.02em;
           line-height: 1.15; }
.card .k { font-size: 12px; color: var(--muted); }
.card .sub { font-size: 11px; color: var(--muted); margin-top: 2px; }
.card a { color: inherit; }

/* ---------------------------------------------------------------------- */
/* Tables                                                                  */
/* ---------------------------------------------------------------------- */

/* A table scrolls inside its own box, both ways.
 *
 * This used to be `overflow-x: auto` with the header stuck at `top: 52px` to
 * clear the topbar. That is the wrong mental model: `overflow` makes this
 * element the scroll container, so `top` is measured from the TOP OF THIS BOX,
 * not from the page. The header was being pushed 52px down over the first two
 * rows and sat there. Inside a scroll container the correct offset is always 0.
 */
.table-wrap {
  overflow: auto;
  /* Tall tables scroll internally so the header stays visible. Short ones are
     shorter than this and never get a second scrollbar. */
  max-height: min(72vh, 900px);
  border-radius: var(--radius);
  /* No `overscroll-behavior: contain` here. On the pipeline this table *is*
     the page, and blocking scroll chaining meant reaching the bottom of it
     stopped the page dead, with the pager below still out of reach. */
}

table { width: 100%; border-collapse: separate; border-spacing: 0;
        font-size: 13.5px; }
/* Scoped to `.table-wrap`, which is the element with `overflow`. Outside it
   the scroll container is the viewport, so the header sticks at y=0 - directly
   underneath the opaque top bar - and is invisible for the whole scroll. Every
   chart's "show the numbers" table is one of those. */
.table-wrap thead th { position: sticky; top: 0; z-index: 5; }
thead th {
  text-align: left; font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); font-weight: 600;
  padding: 8px 9px; background: var(--panel-2);
  white-space: nowrap;
  /* border-collapse: separate means a real border would scroll away with the
     cell. A shadow is painted by the sticky element itself and stays put. */
  box-shadow: inset 0 -1px 0 var(--line);
}
tbody td { padding: 7px 9px; border-bottom: 1px solid var(--line-soft);
           vertical-align: middle; }
/* No cell may push the table wider than it needs to be. Long thesis text and
   long unbroken URLs were stretching rows several screens across.
   `overflow-wrap` rather than `text-overflow: ellipsis`, which does nothing
   without `white-space: nowrap` and would clip wrapped text if it did. */
tbody td { max-width: 340px; overflow-wrap: anywhere; }
tbody td.nowrap { overflow-wrap: normal; }
tbody tr:hover { background: #fcfbf8; }
tbody tr.dim { opacity: .5; }
tbody tr.starred td:first-child { box-shadow: inset 3px 0 0 var(--orange); }

td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.strong { font-weight: 700; }
.nowrap { white-space: nowrap; }
.muted { color: var(--muted); }
.small { font-size: 12px; }
.right { text-align: right; }
/* A form that is only wrapping a single button, so it should not add a line
   box. This was `style="margin:0"` in seven templates and `style="display:
   inline;margin:0"` in two more, which is why star toggles were taller in one
   lane than the other. */
.m0 { margin: 0; display: inline; }

/* Readable by a screen reader, invisible on screen. For the meaning that
   currently lives only in a `title` attribute, which touch never shows and
   assistive tech does not reliably announce. */
.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

table.mini { font-size: 12px; }
table.mini th, table.mini td { padding: 3px 8px; }

.empty { padding: 34px 16px; text-align: center; color: var(--muted); }

/* ---------------------------------------------------------------------- */
/* Score, tier, criteria                                                    */
/* ---------------------------------------------------------------------- */

.score { font-weight: 700; font-variant-numeric: tabular-nums; }
.score.hi { color: var(--green-deep); }
.score.lo { color: var(--muted); }

.tier {
  display: inline-grid; place-items: center;
  width: 20px; height: 20px; border-radius: var(--radius-sm);
  font-size: 11px; font-weight: 800;
}
.tier.A { background: var(--green-deep); color: #fff; }
/* Was white on --green-mid, which is 2.8:1 - under the 4.5:1 floor, on an
   11px bold glyph that appears on every row of the pipeline. */
.tier.B { background: var(--green-soft); color: var(--green-deep);
          box-shadow: inset 0 0 0 1px var(--green-mid); }
.tier.C { background: var(--green-soft); color: var(--green-deep); }
.tier.D { background: var(--panel-2); color: var(--muted); }

/* Y / Partial / N / unknown. Unknown is a dashed outline rather than a
 * paler fill, because "nobody checked" is not "a small amount of yes". */
/* Centred by the grid rather than by a hand-tuned line-height, which was one
   pixel out once the 1px border was added and left every letter sitting high. */
.crit {
  display: inline-grid; place-items: center;
  min-width: 18px; height: 18px; border-radius: 4px;
  font-size: 10px; font-weight: 700; border: 1px solid transparent;
  vertical-align: middle;
}
.crit.Y { background: var(--green-deep); color: #fff; }
/* Same failure as .tier.B, seven times a row. Kept visibly distinct from
   .crit.Y by the ring rather than by a lighter text colour. */
.crit.Partial { background: var(--green-soft); color: var(--green-deep);
                border-color: var(--green-mid); }
.crit.N { background: var(--panel-2); color: var(--muted);
          border-color: var(--line); }
.crit.unknown { background: repeating-linear-gradient(
    45deg, #f2f0ea, #f2f0ea 3px, #e4e1d8 3px, #e4e1d8 6px);
  color: transparent; border: 1px dashed #cbc8bf; }

.crit-row { display: flex; gap: 3px; }
/* The criteria editor. Was a two-column table whose left cell was standing in
   for a label, which meant seven selects in a row and no names on any of them. */
.critgrid { display: grid; gap: 10px;
            grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.critgrid .field { margin: 0; }

/* ---------------------------------------------------------------------- */
/* Badges                                                                   */
/* ---------------------------------------------------------------------- */

.tag {
  display: inline-block; font-size: 10.5px; padding: 1px 7px;
  border-radius: 20px; background: var(--panel-2); color: var(--ink-2);
  border: 1px solid var(--line); white-space: nowrap;
  line-height: 1.65; vertical-align: middle;
}
.tag.ok   { background: var(--green-soft); color: var(--green-deep);
            border-color: var(--green-line); }
.tag.warn { background: var(--orange-soft); color: var(--orange-deep);
            border-color: var(--orange-line); }
.tag.bad  { background: var(--bad-soft); color: var(--bad); border-color: #f0cdc6; }
.tag.noev { background: repeating-linear-gradient(
    45deg, #f4f2ec, #f4f2ec 4px, #e8e5dc 4px, #e8e5dc 8px);
  color: var(--ink-2); border-style: dashed; }

.stage {
  display: inline-block; font-size: 11px; padding: 2px 8px;
  border-radius: 20px; background: var(--panel-2); color: var(--ink-2);
  border: 1px solid var(--line); white-space: nowrap;
}
.stage.active { background: var(--green-soft); color: var(--green-deep);
                border-color: var(--green-line); font-weight: 600; }
.stage.dead { opacity: .6; }

.conf { font-size: 10.5px; padding: 1px 6px; border-radius: 20px;
        border: 1px solid var(--line); background: var(--panel-2);
        color: var(--muted); }
.conf.verified_mx   { background: var(--green-soft); color: var(--green-deep);
                      border-color: var(--green-line); }
.conf.found_on_site { background: var(--orange-soft); color: var(--orange-deep);
                      border-color: var(--orange-line); }

.urgent { color: var(--orange-deep); font-weight: 700; }

/* ---------------------------------------------------------------------- */
/* Forms                                                                    */
/* ---------------------------------------------------------------------- */

label { font-size: 12px; color: var(--muted); display: block; margin-bottom: 3px; }

input[type=text], input[type=search], input[type=email], input[type=password],
input[type=url], input[type=number], input[type=date], select, textarea {
  font: inherit; font-size: 13.5px;
  padding: 6px 8px; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--panel);
  color: var(--ink); max-width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--green-mid); outline-offset: -1px;
  border-color: var(--green-mid);
}
textarea { width: 100%; resize: vertical; line-height: 1.5; }

.field { margin-bottom: 10px; }
.field input, .field select, .field textarea { width: 100%; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }

button, .btn {
  font: inherit; font-size: 13.5px; font-weight: 600;
  padding: 6px 13px; border-radius: var(--radius-sm);
  border: 1px solid var(--green-deep); background: var(--green-deep);
  color: #fff; cursor: pointer; white-space: nowrap;
  display: inline-block; text-decoration: none;
}
button:hover, .btn:hover { background: #005c2f; text-decoration: none; }
button:disabled { opacity: .45; cursor: not-allowed; }

/* Keyboard users need to see where they are. `:focus-visible` rather than
   `:focus` so a mouse click does not leave a ring behind. */
a:focus-visible, button:focus-visible, .btn:focus-visible,
summary:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--green-deep);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Jump straight past the navigation. Hidden until it is focused. */
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--green-deep); color: #fff; padding: 8px 14px;
  border-radius: 0 0 var(--radius-sm) 0; z-index: 100;
}
.skip:focus { left: 0; text-decoration: none; }

button.ghost, .btn.ghost {
  background: var(--panel); color: var(--ink-2); border-color: var(--line);
}
button.ghost:hover, .btn.ghost:hover { background: var(--panel-2); }

button.small, .btn.small { padding: 3px 9px; font-size: 12px; }

.filters {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end;
  padding: 12px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); margin-bottom: 12px;
}
.filters .f { display: flex; flex-direction: column; }
.filters label { margin-bottom: 2px; }
.filters .check { flex-direction: row; align-items: center; gap: 5px;
                  padding-bottom: 6px; }
.filters .check label { margin: 0; }
.filters .spacer { flex: 1; }

.inline { display: inline-flex; gap: 6px; align-items: center; }

/* One action and everything it needs on one line: which model, whether to
   ignore the cache, and the button. Used by every model call in the app. */
.airun { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px;
         margin-top: 12px; }
.airun .field { margin: 0; flex: 0 1 210px; }

/* One proposed CSS selector in the source inspector, with its sample rows. */
.candidate { border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
             padding: 10px 12px; margin-bottom: 8px; background: var(--panel-2); }
.candidate p { margin: 0 0 6px; }
.check { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px;
         color: var(--muted); white-space: nowrap; }
.check input { width: auto; margin: 0; }

.flash { padding: 8px 11px; border-radius: var(--radius-sm); font-size: 13px;
         margin: 8px 0; border: 1px solid var(--line); background: var(--panel-2); }
.flash.ok    { background: var(--green-soft); border-color: var(--green-line);
               color: var(--green-deep); }
.flash.warn  { background: var(--orange-soft); border-color: var(--orange-line);
               color: var(--orange-deep); }
.flash.error { background: var(--bad-soft); border-color: #f0cdc6; color: var(--bad); }

.pager { display: flex; gap: 10px; align-items: center; justify-content: center;
         padding: 14px; color: var(--muted); font-size: 13px; }

/* ---------------------------------------------------------------------- */
/* Charts                                                                   */
/* ---------------------------------------------------------------------- */

.chart-figure { margin: 0 0 6px; }
.chart-figure figcaption {
  font-size: 12px; font-weight: 600; color: var(--ink-2); margin-bottom: 8px;
}
/* `hidden` now the value gutter is measured rather than guessed: nothing is
   meant to be painted outside the viewBox, so anything that is, is a bug we
   would rather see clipped than have overlap the panel next to it. */
svg.chart { display: block; max-width: 100%; height: auto; overflow: hidden; }
svg.chart .c-label { font-size: 11.5px; fill: var(--ink-2); }
svg.chart .c-value { font-size: 11.5px; fill: var(--ink-2); font-weight: 600; }
/* White on the mid-green segment was 2.8:1 - the same failure as .tier.B, just
   moved inside the bar. Dark ink reads on every fill in the ramp. */
svg.chart .c-inbar { font-size: 10.5px; fill: #1B1C19; font-weight: 700; }
svg.chart .c-axis  { font-size: 10px; fill: var(--muted); }
/* A clickable bubble. The <a> is mouse-only by design - see the note in
   charts.worldmap() - so it needs a cursor and a hover state to look like the
   control it is, and nothing else. */
svg.chart .c-hit { cursor: pointer; }
svg.chart .c-bub { transition: fill-opacity .12s ease, stroke-width .12s ease; }
svg.chart .c-hit:hover .c-bub { fill-opacity: .85; stroke-width: 2.2; }

/* Country labels on the map. Smaller and heavier than a bar label: they sit
   over land rather than in a clear gutter, so they need the weight to hold. */
svg.chart .c-map {
  font-size: 10px; font-weight: 700; fill: var(--ink);
  paint-order: stroke; stroke: #faf9f6; stroke-width: 2.5px;
  stroke-linejoin: round;
}

.legend { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 7px;
          font-size: 11.5px; color: var(--ink-2); }
.legend .k { display: inline-flex; align-items: center; gap: 5px; }
.legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block;
            border: 1px solid rgba(0,0,0,.07); flex: 0 0 auto; }
/* The hatched "not researched" key.
 *
 * An SVG <pattern> can only be referenced from inside the same SVG document -
 * `background: url(#id)` on an HTML element resolves to nothing, so this swatch
 * was rendering blank and the key read as an empty box next to a label. CSS has
 * to draw its own stripes. */
.legend i.hatched {
  background: repeating-linear-gradient(
    45deg, #f2f0ea, #f2f0ea 2px, #cbc8bf 2px, #cbc8bf 4px);
  border-style: dashed; border-color: #cbc8bf;
}

.chart-data { margin-top: 6px; }
.chart-data summary { font-size: 11.5px; color: var(--muted); cursor: pointer; }
.chart-data table { margin-top: 6px; }

/* ---------------------------------------------------------------------- */
/* The flow strip                                                           */
/* ---------------------------------------------------------------------- */

/* Four steps across the top of each dashboard. The sidebar says where things
   are; this says what to do with them, which was the part people could not
   find. The step with nothing in it is the one wearing the orange rail. */
.flow {
  display: flex; align-items: stretch; flex-wrap: wrap; gap: 4px;
  margin-bottom: 16px;
}
.flowsep { align-self: center; color: var(--line); font-size: 18px; }

.flowstep {
  flex: 1 1 170px; display: flex; align-items: flex-start; gap: 9px;
  padding: 10px 12px; text-decoration: none;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.flowstep:hover { border-color: var(--green-line); text-decoration: none; }

.flowstep .i {
  flex: 0 0 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--panel-2); color: var(--muted);
  font-size: 11px; font-weight: 700;
}
.flowstep .t { display: flex; flex-direction: column; min-width: 0; }
.flowstep .t b { font-size: 13px; }
.flowstep .n { font-size: 17px; font-weight: 700; letter-spacing: -.01em;
               line-height: 1.2; }
.flowstep .h { font-size: 11px; color: var(--muted); }

.flowstep.done .i { background: var(--green-soft); color: var(--green-deep); }
.flowstep.up-next {
  border-color: var(--orange-line); background: var(--orange-soft);
  box-shadow: inset 3px 0 0 var(--orange);
}
.flowstep.up-next .i { background: var(--orange); color: #fff; }

/* ---------------------------------------------------------------------- */
/* The board                                                                */
/* ---------------------------------------------------------------------- */

/* Nine columns at 250px is wider than the 1320px content area, so the board
   scrolls sideways inside its own box rather than making the whole page do it.
   The -20px margin with matching padding lets the scroll run edge to edge
   while the first and last column still line up with everything else. */
.board {
  display: flex; gap: 12px; align-items: flex-start;
  overflow-x: auto; overscroll-behavior-x: contain;
  padding: 2px 20px 14px; margin: 0 -20px;
  scroll-padding: 20px;
}

.bcol {
  flex: 0 0 250px; display: flex; flex-direction: column;
  max-height: min(70vh, 780px);
  background: var(--panel-2); border: 1px solid var(--line);
  border-top: 3px solid var(--line); border-radius: var(--radius);
}
.bcol.acc-green { border-top-color: var(--green); }
.bcol.acc-grey  { border-top-color: #cbc8bf; }
.bcol.acc-slate { border-top-color: var(--line); }
/* A finished column is a resting place, not a step, so it recedes. The work
   is happening in the open ones. */
.bcol.kind-won  { border-top-color: var(--green-deep); }
.bcol.kind-lost { opacity: .82; }

.bcol-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; padding: 9px 11px 7px;
}
.bcol-head h2 {
  margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-2);
}
.bcol-head .n { font-size: 11px; color: var(--muted); }
.bcol-head .n.over { color: var(--bad); font-weight: 700; }
.bcol-note { margin: 0 11px 8px; font-size: 11.5px; color: var(--muted); }

/* The drop zone has to fill the column and keep a floor, or an empty column is
   a zero-height target you cannot drop into. That is the classic board bug,
   and it is a CSS one rather than a JavaScript one. */
.bcards {
  flex: 1 1 auto; min-height: 96px;
  list-style: none; margin: 0; padding: 0 8px 10px;
  overflow-y: auto;
}
.bcards.over { background: var(--green-soft); border-radius: var(--radius-sm); }

.bcol-empty {
  border: 1px dashed var(--line); border-radius: var(--radius-sm);
  padding: 14px 10px; text-align: center;
  color: var(--muted); font-size: 11.5px;
}

.bcard {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 9px 10px; margin-bottom: 8px;
  box-shadow: var(--shadow);
}
.bcard:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 2px; }
.bcard.dragging { opacity: .4; }
.bcard.pending  { opacity: .6; }
.bcard.late     { border-left: 3px solid var(--orange); }
/* Paused, with the record of how far it got left intact. The hatch is the one
   "nobody has checked yet" uses: both mean "not a live answer". */
.bcard.held {
  border-left: 3px solid transparent;
  border-image: repeating-linear-gradient(45deg, #cbc8bf, #cbc8bf 2px,
                #f2f0ea 2px, #f2f0ea 4px) 3;
}

.bcard-name {
  display: block; font-weight: 600; font-size: 13.5px; line-height: 1.3;
  color: var(--ink); text-decoration: none;
}
.bcard-name:hover { color: var(--green-deep); }

.bcard-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 5px;
              margin-top: 6px; }
.bcard-owner { margin-left: auto; }

.bcard-hold   { margin: 7px 0 0; font-size: 11.5px; color: var(--ink-2); }
.bcard-update { margin: 7px 0 0; font-size: 12px; color: var(--ink-2); }
.bcard-next   { margin: 6px 0 0; font-size: 11.5px; color: var(--ink-2); }
.bcard-next .k { color: var(--muted); text-transform: uppercase;
                 letter-spacing: .05em; font-size: 10px; margin-right: 3px; }

/* The last update, expandable in place. Collapsed by default: a board of open
   cards is a wall, and the one line on the face answers the question most of
   the time. Neutral ink throughout - orange means "look at this" everywhere
   else in the app, and a card having history is not an alert. */
.cardlog { margin: 7px 0 0; }
.cardlog > summary {
  cursor: pointer; list-style: none; display: block;
  border-radius: var(--radius-sm); padding: 1px 0;
}
.cardlog > summary::-webkit-details-marker { display: none; }
.cardlog > summary .bcard-update { margin: 0; display: inline; }
.cardlog > summary:hover .bcard-update { color: var(--ink); }
.cardlog > summary:focus-visible {
  outline: 2px solid var(--green-deep); outline-offset: 2px;
}
/* A caret, so it reads as openable without relying on hover to discover it. */
.cardlog > summary::after {
  content: "▾"; font-size: 9px; color: var(--muted); margin-left: 4px;
  display: inline-block; vertical-align: 1px;
}
.cardlog[open] > summary::after { transform: rotate(180deg); }

.bcard-update .when, .cardlog .when {
  color: var(--muted); font-size: 10.5px; margin-left: 4px; white-space: nowrap;
}
.cardlog-body {
  margin-top: 6px; padding: 7px 8px;
  background: var(--panel-2); border-radius: var(--radius-sm);
  font-size: 11.5px; color: var(--ink-2);
}
/* --muted is 4.76:1 on --panel and only 4.30:1 on --panel-2, so the same grey
   that passes on the face of the card fails inside this tinted box. The meta
   text steps up to --ink-2 (8.04:1) here and stays de-emphasised by size
   rather than by colour alone. */
.cardlog-body .when { color: var(--ink-2); }
.cardlog-standing { margin: 0 0 6px; }
.cardlog-standing .k {
  display: block; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; font-size: 10px;
}
.cardlog-body ul { list-style: none; margin: 0; padding: 0; }
.cardlog-body li {
  padding: 4px 0; border-top: 1px solid var(--line-soft);
}
.cardlog-body li:first-child { border-top: 0; }
.cardlog-body .what { display: block; color: var(--ink); }
.cardlog-body .said { display: block; margin-top: 2px; }
.cardlog-body .who  { display: block; margin-top: 2px; color: var(--ink-2);
                      font-size: 10.5px; }
.cardlog-body a { display: inline-block; margin-top: 6px; }

.dropreason { display: flex; gap: 5px; margin-top: 7px; }
.dropreason input { flex: 1 1 auto; min-width: 0; font-size: 11.5px;
                    padding: 3px 6px; }
.dropreason button { padding: 3px 8px; font-size: 11.5px; }

.cardmove { margin-top: 7px; }
.cardmove > summary {
  cursor: pointer; font-size: 11px; color: var(--muted);
  list-style: none; display: inline-block;
  padding: 2px 6px; border-radius: var(--radius-sm);
}
.cardmove > summary::-webkit-details-marker { display: none; }
.cardmove > summary:hover { background: var(--panel-2); color: var(--ink); }

/* `dnd` is set by app.js once dragging is actually available. Where it is, the
   Move control steps back to hover and keyboard focus rather than sitting on
   every card as a second interface. Opacity rather than display, so it is
   still in the tab order and still appears the moment it is focused. */
.dnd .bcard { cursor: grab; }
.dnd .bcard.dragging { cursor: grabbing; }
.dnd .cardmove > summary { opacity: 0; }
.dnd .bcard:hover .cardmove > summary,
.dnd .bcard:focus-within .cardmove > summary,
.dnd .cardmove[open] > summary { opacity: 1; }
.cardmove form { display: flex; gap: 5px; margin-top: 6px; }
.cardmove select { flex: 1 1 auto; min-width: 0; font-size: 12px; padding: 3px 5px; }
.cardmove button { padding: 3px 8px; font-size: 12px; }

kbd {
  font: 11px/1 Consolas, ui-monospace, monospace;
  padding: 2px 5px; border: 1px solid var(--line);
  border-bottom-width: 2px; border-radius: 4px; background: var(--panel);
}

/* ---------------------------------------------------------------------- */
/* Activity timeline                                                        */
/* ---------------------------------------------------------------------- */

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  position: relative; padding: 0 0 14px 18px;
  border-left: 2px solid var(--line-soft);
}
.timeline li:last-child { border-left-color: transparent; padding-bottom: 0; }
.timeline li::before {
  content: ""; position: absolute; left: -5px; top: 4px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--green-mid); border: 2px solid var(--panel);
}
.timeline .when { font-size: 11.5px; color: var(--muted); }
.timeline .what { font-size: 13.5px; }

/* ---------------------------------------------------------------------- */
/* Text dumps                                                               */
/* ---------------------------------------------------------------------- */

pre { font: 12.5px/1.55 Consolas, "SF Mono", ui-monospace, monospace;
      white-space: pre-wrap; word-break: break-word; margin: 0; }
pre.log { background: #1d1e1b; color: #d7d5cc; padding: 11px;
          border-radius: var(--radius-sm); max-height: 260px; overflow: auto; }
pre.reasons { background: var(--panel-2); padding: 11px;
              border-radius: var(--radius-sm); border: 1px solid var(--line-soft); }
pre.raw { background: var(--panel-2); padding: 11px; border-radius: var(--radius-sm);
          max-height: 320px; overflow: auto; color: var(--ink-2); }

.mono { font-family: Consolas, "SF Mono", ui-monospace, monospace; }

ul.plain { list-style: none; margin: 0; padding: 0; }
ul.plain li { padding: 3px 0; border-bottom: 1px solid var(--line-soft); }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px;
      font-size: 13px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }

/* ---------------------------------------------------------------------- */
/* The way in                                                               */
/* ---------------------------------------------------------------------- */

.gate { max-width: 380px; margin: 9vh auto; }
.gate .panel { padding: 26px; }
.gate h1 { text-align: center; margin-bottom: 4px; }
.gate p.lede { text-align: center; color: var(--muted); font-size: 13px;
               margin: 0 0 20px; }
.gate button { width: 100%; margin-top: 6px; padding: 9px; }

.choose { display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
          max-width: 760px; margin: 5vh auto; }
.choose a {
  display: block; padding: 26px; text-align: center; text-decoration: none;
  background: var(--panel); border: 1px solid var(--line);
  border-top: 3px solid var(--green); border-radius: var(--radius);
  color: var(--ink); box-shadow: var(--shadow);
}
.choose a:hover { border-color: var(--green-mid); text-decoration: none;
                  transform: translateY(-1px); }
.choose a.grants { border-top-color: var(--orange); }
.choose .big { font-size: 19px; font-weight: 700; margin-bottom: 4px; }
.choose .n { font-size: 30px; font-weight: 800; color: var(--green-deep);
             letter-spacing: -.02em; }
.choose a.grants .n { color: var(--orange-deep); }
.choose .k { font-size: 12px; color: var(--muted); }

/* ---------------------------------------------------------------------- */
/* Narrow screens                                                           */
/* ---------------------------------------------------------------------- */

/* The icon rail is a desktop idea. Below 900px the sidebar is already a
   drawer, so every rail rule is scoped here and simply does not apply there -
   which is cheaper than writing a second set of rules to undo it. */
@media (min-width: 901px) {
  body.app.nav-rail { --nav-w: var(--nav-rail-w); }

  body.nav-rail .sidebar { padding-left: 6px; padding-right: 6px; }
  body.nav-rail .sidebar .lbl,
  body.nav-rail .navgroup > summary .gt,
  body.nav-rail .navgroup > summary .chev { display: none; }

  /* Folding a group you cannot read the name of is not a useful thing to be
     able to do, so in rail mode the headings become dividers. The server
     renders every group open when the rail is on, so nothing is hidden. */
  body.nav-rail .navgroup > summary {
    pointer-events: none; justify-content: center; padding: 8px 0 6px;
  }
  body.nav-rail .navgroup > summary::after {
    content: ""; display: block; width: 20px; height: 1px;
    background: var(--line);
  }
  body.nav-rail .sidebar a,
  body.nav-rail #rail-toggle { justify-content: center; gap: 0; padding: 9px 0; }
  body.nav-rail #rail-toggle .ico { transform: rotate(180deg); }
}

/* Below this the sidebar cannot hold a column of its own without leaving the
   content too narrow to read, so it becomes a drawer over the top. */
@media (max-width: 900px) {
  body.app, body.app.nav-rail {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "top" "main" "foot";
  }
  .navbtn { display: inline-flex; }

  .sidebar {
    position: fixed; top: var(--top-h); left: 0; z-index: 40;
    width: 264px; max-width: 84vw;
    transform: translateX(-100%); transition: transform .18s ease;
    box-shadow: 0 10px 34px rgba(28, 28, 26, .18);
  }
  body.nav-open .sidebar { transform: none; }
  body.nav-open .navscrim {
    display: block; position: fixed; inset: var(--top-h) 0 0 0; z-index: 35;
    background: rgba(28, 28, 26, .3); border: 0; padding: 0; cursor: pointer;
  }
  /* An open drawer must not leave the page behind it scrolling under it. */
  body.nav-open { overflow: hidden; }
}

@media (max-width: 1000px) {
  /* .grid-2 collapses here too. It used to hold on until 760px while .split
     gave up at 1000, so between those widths a form was one column inside a
     panel that was still two - which read as a rendering fault. */
  .split, .split-3, .choose, .grid-2, .grid-3 { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .topbar { padding: 0 12px; gap: 10px; }
  .brand small { display: none; }
  main { padding: 12px; }
  .filters .f { flex: 1 1 160px; }
  .board { padding-left: 12px; padding-right: 12px; margin: 0 -12px; }
}

/* Somebody who has asked their system to stop animating things means it. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ---------------------------------------------------------------------------
   Document checklists (Stage 5). Two panels side by side: what the investor
   asked for on the left, what the data room holds on the right. You drag from
   right to left.

   Both columns scroll INDEPENDENTLY and the page does not, because the whole
   point is comparing two lists - if the page scrolled, the item you are
   matching would leave the screen while you looked for the document.
   --------------------------------------------------------------------------- */
.dd {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
@media (max-width: 900px) { .dd { grid-template-columns: minmax(0, 1fr); } }

.dd-col { display: flex; flex-direction: column; max-height: 74vh; }
.dd-col > .ddlist, .dd-col > .ddheld { overflow-y: auto; flex: 1 1 auto; }

.ddlist, .ddheld { list-style: none; margin: 0; padding: 0; }

.dditem {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 9px 10px;
  margin-bottom: 7px;
  background: var(--panel);
}
/* The left border carries the state, so the column can be read down its edge
   without stopping on each row. */
.dditem.pending        { border-left: 3px solid var(--line); }
.dditem.provided       { border-left: 3px solid var(--green-deep);
                         background: var(--green-soft); }
.dditem.not_applicable,
.dditem.unavailable    { border-left: 3px solid var(--orange); }

.dditem.over { background: var(--green-soft); border-color: var(--green-line); }

.ddhead { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.ddseq { color: var(--muted); font-size: 11px; min-width: 20px; }
.ddtext { flex: 1 1 auto; min-width: 0; }

.ddmatch {
  margin-top: 6px; padding-top: 6px;
  border-top: 1px dashed var(--green-line);
  display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap;
}
.ddfile { font-weight: 600; word-break: break-word; }

/* A stated reason is what the investor actually reads, so it is set apart
   rather than left looking like an internal note. */
.ddreason {
  margin-top: 6px; padding: 5px 8px;
  background: var(--orange-soft);
  border-radius: var(--radius-sm);
  font-size: 13px; color: var(--ink-2);
}

.ddedit { margin-top: 7px; }
.ddedit > summary {
  cursor: pointer; font-size: 12px; color: var(--muted);
  padding: 2px 0;
}
.ddedit > summary:hover { color: var(--ink); }
.ddpick { margin-top: 8px; }

.ddsearch { display: flex; gap: 8px; align-items: flex-end; margin-bottom: 8px; }
.ddsearch .field { flex: 1 1 auto; margin: 0; }

.ddoc {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 7px 9px; margin-bottom: 6px;
  display: flex; flex-direction: column; gap: 1px;
  cursor: grab;
}
.ddoc:hover  { border-color: var(--green-line); background: var(--panel-2); }
.ddoc:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 1px; }
.ddoc.dragging { opacity: .4; cursor: grabbing; }
.ddoc.suggested { border-color: var(--green-line); background: var(--green-soft); }

/* Progress. Bare div rather than <progress>, which cannot be styled
   consistently across browsers without more CSS than this is worth. */
.bar {
  height: 6px; background: var(--line-soft);
  border-radius: 999px; overflow: hidden;
}
.bar > span {
  display: block; height: 100%;
  background: var(--green-deep); border-radius: 999px;
}

.tag.pending        { background: var(--panel-2); color: var(--ink-2); }
.tag.provided       { background: var(--green-soft); color: var(--green-deep);
                      box-shadow: inset 0 0 0 1px var(--green-line); }
.tag.not_applicable,
.tag.unavailable    { background: var(--orange-soft); color: var(--orange-deep);
                      box-shadow: inset 0 0 0 1px var(--orange-line); }

.linkbtn.danger { color: var(--bad); }

/* The FAQ pack. Reads as a document rather than a table, because that is what
   it is - the thing an investor is sent before the first call. */
.faq-qa { padding: 10px 0; border-top: 1px solid var(--line-soft); }
.faq-qa:first-of-type { border-top: 0; }
.faq-qa h3 { margin: 0 0 4px; font-size: 15px; }
.faq-qa p { margin: 0 0 4px; max-width: 74ch; color: var(--ink-2); }

@media print {
  .topbar, .sidebar, .navscrim, .filters, .pager,
  button, .btn { display: none !important; }
  body.app { display: block; }
  .panel { break-inside: avoid; border-color: #ccc; box-shadow: none; }
}

/* ---------------------------------------------------------------------- */
/* The log panel                                                           */
/* ---------------------------------------------------------------------- */

/* The three fields on a card. A <dl> because that is what this is: three
   labelled values, not a list and not a table. */
.cardlog-fields { margin: 8px 0 0; font-size: 11.5px; }
.cardlog-fields dt {
  color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; font-size: 9.5px; margin-top: 6px;
}
.cardlog-fields dt:first-child { margin-top: 0; }
.cardlog-fields dd { margin: 1px 0 0; color: var(--ink-2); }
/* "Nobody has met them" must not render as an empty line - a blank reads as
   "nothing to report", and that is a different claim. Hatched, the same way
   an unresearched criterion is, because both mean "not an answer". */
.cardlog-fields .none { color: var(--muted); font-style: italic; }

.cardlog-actions {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-top: 8px; padding-top: 7px;
  border-top: 1px solid var(--line-soft);
}
.cardlog-edit, .cardlog-more {
  font-size: 11px; color: var(--green-deep);
  text-decoration-color: var(--green-line);
}
.cardlog-more { color: var(--muted); text-decoration-color: var(--line); }
.cardlog-edit:hover, .cardlog-more:hover {
  color: var(--green-deep); text-decoration-color: currentColor;
}

/* The slide-over. Only ever created by app.js; with JavaScript off the same
   markup is served as an ordinary page and none of this applies. */
.panel-scrim {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(27, 28, 25, .34);
  display: flex; justify-content: flex-end;
}
.slideover {
  position: relative;
  width: min(460px, 100%); height: 100%;
  background: var(--panel); border-left: 1px solid var(--line);
  box-shadow: -8px 0 24px rgba(27, 28, 25, .10);
  overflow-y: auto; padding: 18px 20px 28px;
  animation: slidein .16s ease-out;
}
@keyframes slidein { from { transform: translateX(14px); opacity: .6; } }
/* Respected globally elsewhere in this file; repeated here because an
   animation added later must not quietly opt out of it. */
@media (prefers-reduced-motion: reduce) {
  .slideover { animation: none; }
}
.slideover-x {
  position: absolute; top: 10px; right: 12px;
  background: none; border: 0; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--muted);
  padding: 4px 8px; border-radius: var(--radius-sm);
}
.slideover-x:hover { background: var(--panel-2); color: var(--ink); }
/* The page behind must not scroll under an open panel. */
body.panel-open { overflow: hidden; }

.logpanel-title { margin: 0 26px 14px 0; font-size: 17px; }
.logpanel-form .field { margin-bottom: 12px; }
.logpanel-form .hint,
.logpanel-history .hint {
  margin: 4px 0 0; font-size: 11.5px; color: var(--muted);
}
.logpanel-form .hint.urgent { color: var(--orange-deep); }

.quickdates { display: flex; gap: 5px; margin-top: 6px; flex-wrap: wrap; }
.quickdates button {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 20px; padding: 3px 10px; font-size: 11.5px;
  color: var(--ink-2); cursor: pointer; font-family: inherit;
}
.quickdates button:hover { background: var(--green-soft);
                           border-color: var(--green-line);
                           color: var(--green-deep); }

.logpanel-history { margin-top: 16px; border-top: 1px solid var(--line);
                    padding-top: 12px; }
.logpanel-history > summary { cursor: pointer; font-size: 12px;
                              color: var(--muted); }
.logpanel-history ul { list-style: none; margin: 10px 0 0; padding: 0;
                       font-size: 12px; }
.logpanel-history li { padding: 7px 0; border-top: 1px solid var(--line-soft); }
.logpanel-history li:first-child { border-top: 0; }
.logpanel-history .when { color: var(--ink-2); font-size: 10.5px;
                          margin-right: 6px; }
.logpanel-history .entry-head {
  display: flex; align-items: baseline; gap: 8px; justify-content: space-between;
}
.logpanel-history .chan {
  font-size: 10px; color: var(--ink-2); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: 20px; padding: 0 7px;
  white-space: nowrap; flex: 0 0 auto;
}
.logpanel-history .what { color: var(--ink); font-weight: 600; }
.logpanel-history .said { display: block; color: var(--ink-2); margin-top: 2px; }
.logpanel-history .who  { display: block; color: var(--ink-2);
                          font-size: 10.5px; margin-top: 2px; }

/* Per-row edit on the contacts table. <details> again, so it needs no script
   and a row that is not being edited costs one line. */
.rowedit > summary { cursor: pointer; font-size: 11.5px; color: var(--muted);
                     list-style: none; padding: 2px 6px;
                     border-radius: var(--radius-sm); }
.rowedit > summary::-webkit-details-marker { display: none; }
.rowedit > summary:hover { background: var(--panel-2); color: var(--ink); }
.rowedit form { margin-top: 8px; }
/* Destructive, and it says so. --bad is used nowhere else on this page. */
.btn.danger, button.danger { color: var(--bad); border-color: var(--bad); }
.btn.danger:hover, button.danger:hover { background: var(--bad-soft); }

/* Four across on the add form; collapses on a narrow screen like grid-3. */
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
          gap: 10px; }
.contact-row { padding-bottom: 4px; }
@media (max-width: 900px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .grid-4 { grid-template-columns: minmax(0, 1fr); }
}

/* Key tasks: several per firm, each with a deadline and a priority. */
.tasks { border: 0; padding: 0; margin: 0 0 12px; }
.tasks > legend { padding: 0; font-size: 13px; margin-bottom: 8px;
                  text-transform: uppercase; letter-spacing: .06em;
                  color: var(--muted); font-weight: 600; }
.task-row { padding: 8px 0; border-top: 1px solid var(--line-soft); }
.task-row:first-of-type { border-top: 0; }
.task-grid { display: grid; gap: 8px;
             grid-template-columns: minmax(0, 1fr) 140px 118px; }
.task-grid .field { margin: 0; }
.task-done { margin-top: 6px; font-size: 11.5px; color: var(--muted); }
@media (max-width: 520px) {
  .task-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Priority reads as a SHAPE first - triangle up, dot, triangle down - so it
   survives greyscale and colour blindness. Orange on high is the app's
   "look at this" and is the only place colour is doing any work. */
.pri.high { color: var(--orange-deep); }
.pri.mid  { color: var(--ink-2); }
.pri.low  { color: var(--muted); }
select.pri { font-family: inherit; }

.tasklist { list-style: none; margin: 0; padding: 0; }
.tasklist li { margin-top: 2px; }
.tasklist li:first-child { margin-top: 0; }
.tasklist .pri { margin-right: 3px; font-size: 9px; vertical-align: 1px; }

/* Task status. Symbol + word, never colour alone; the strike-through is a
   third signal on top, not the only one. */
.task-grid { grid-template-columns: 26px minmax(0, 1fr) 140px 132px; }
.task-seq { color: var(--muted); font-size: 11.5px; padding-top: 7px;
            text-align: right; font-variant-numeric: tabular-nums; }
.task-seq.new { color: var(--line); }
.task-foot { display: flex; align-items: center; gap: 10px; margin-top: 5px;
             min-height: 18px; }
.task-foot .hint, .task-foot .urgent { margin: 0; font-size: 11.5px; }
.linkbtn.danger { color: var(--bad); padding: 2px 6px; font-size: 11.5px; }
.linkbtn.danger:hover { background: var(--bad-soft); text-decoration: none; }

.stat.pending   { color: var(--ink-2); }
.stat.on_hold   { color: var(--warn-ink); }
.stat.completed { color: var(--green-deep); }
select.stat { font-family: inherit; }

/* Completed: struck through and stepped back, still readable. It is kept on
   purpose - "we did that" is worth as much later as "we still owe it". */
.task-row.done .task-seq,
.task-row.done input[type="text"] { text-decoration: line-through; }
.task-row.done { opacity: .72; }
.tasklist li.done .tasktext,
.tasklist li.done .task-seq { text-decoration: line-through; color: var(--muted); }
@media (max-width: 520px) {
  .task-grid { grid-template-columns: 26px minmax(0, 1fr); }
}

/* Takes an unwanted row back out of the form before anything is saved. Not
   the Delete above it: that removes a saved task, this is an undo for the
   + button. Hidden until a script can actually do it, and hidden while only
   one empty row is left - a form with nowhere to type is a dead end. */
.rowminus {
  background: none; border: 1px solid var(--line); cursor: pointer;
  color: var(--muted); border-radius: var(--radius-sm);
  width: 26px; height: 26px; line-height: 1; margin-top: 4px;
  font-size: 15px; font-family: inherit; padding: 0;
}
.rowminus:hover { background: var(--bad-soft); color: var(--bad);
                  border-color: var(--bad); }
.rowminus[hidden] { display: none; }

/* The blank rows carry a fifth column for that button; saved rows do not, so
   their Delete sits in the row footer instead. */
.task-row[data-blank] .task-grid {
  grid-template-columns: 26px minmax(0, 1fr) 140px 132px 26px;
}
@media (max-width: 520px) {
  .task-row[data-blank] .task-grid { grid-template-columns: 26px minmax(0, 1fr); }
}

/* --- the log panel, second pass ------------------------------------------ */

/* The task NAME is the field that matters; the date and the status were
   taking room it needed. Wider panel, narrower controls. */
.slideover { width: min(560px, 100%); }
.task-grid { grid-template-columns: 24px minmax(0, 1fr) 118px 104px; }
.task-row[data-blank] .task-grid {
  grid-template-columns: 24px minmax(0, 1fr) 118px 104px 24px;
}
.task-grid input[type="text"] { font-size: 14px; }
.rowminus { width: 24px; height: 24px; font-size: 14px; }
@media (max-width: 560px) {
  .task-grid,
  .task-row[data-blank] .task-grid { grid-template-columns: 24px minmax(0, 1fr); }
}

/* Completed tasks: their own block, nothing to edit, and a way back. */
.done-tasks { margin-top: 4px; border-top: 1px solid var(--line);
              padding-top: 10px; }
.donelist { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.donelist li {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  padding: 5px 0; border-top: 1px solid var(--line-soft); color: var(--muted);
}
.donelist li:first-child { border-top: 0; }
.donelist .tasktext { text-decoration: line-through; flex: 1 1 auto;
                      min-width: 0; }
.donelist .task-seq { text-decoration: line-through; padding: 0; }
.linkbtn.redo { color: var(--green-deep); padding: 2px 6px; font-size: 11.5px; }
.linkbtn.redo:hover { background: var(--green-soft); text-decoration: none; }
.tasklist.done-on-card { margin-top: 3px; }

/* Where the firm stands, at the top of "What happened". */
.nowin { margin: 0 0 12px; display: flex; align-items: center; gap: 7px; }
.nowin .k { color: var(--muted); text-transform: uppercase;
            letter-spacing: .05em; font-size: 10px; }

/* Log history: one partial, so one set of rules for the panel and the page. */
.loghist { list-style: none; margin: 8px 0 0; padding: 0; font-size: 12.5px; }
.loghist > li { padding: 9px 0; border-top: 1px solid var(--line-soft); }
.loghist > li:first-child { border-top: 0; }
.loghist-head { display: flex; gap: 8px; justify-content: space-between;
                align-items: baseline; }
.loghist-head .when { color: var(--ink); font-weight: 600; font-size: 12px; }
.loghist-head .who  { color: var(--muted); font-size: 11px; }
.loghist-state { margin: 6px 0 0; display: grid; gap: 2px 10px;
                 grid-template-columns: 96px minmax(0, 1fr); }
.loghist-state dt { color: var(--muted); font-size: 10.5px;
                    text-transform: uppercase; letter-spacing: .05em;
                    padding-top: 2px; }
.loghist-state dd { margin: 0; color: var(--ink-2); }
.loghist-state .none { color: var(--muted); font-style: italic; }
.loghist-tasks { list-style: none; margin: 0; padding: 0; }
.loghist-tasks li { display: flex; gap: 6px; flex-wrap: wrap;
                    align-items: baseline; }
.loghist-tasks li.done .tasktext { text-decoration: line-through;
                                   color: var(--muted); }
.loghist-tasks .stat { font-size: 10px; text-transform: uppercase;
                       letter-spacing: .04em; }
.loghist-said { margin: 6px 0 0; color: var(--ink-2); }
@media (max-width: 560px) {
  .loghist-state { grid-template-columns: minmax(0, 1fr); }
  .loghist-state dt { padding-top: 6px; }
}
