/* Review interface — Kapita Research brand system.
   Source of truth: ~/.claude/skills/kapita-research-tools/references/design-system.md
   ("Bloomberg Terminal meets Linear meets 2026" — sharp, geometric, data-forward.)

   Three deliberate departures from that document, all forced by what this is —
   an internal multi-page app, not a single-file public landing page:

   1. Inter is SELF-HOSTED, not loaded from Google Fonts. This app's CSP is
      `default-src 'self'` (main.py), so an external font request would be
      blocked outright. Self-hosting keeps the CSP strict and means the tool
      makes no external request at all. One variable file covers 400–900.
   2. The nav pill group is NOT absolutely centered. The design system centers
      it against a bare marketing banner; here it shares the bar with a signed-in
      user block, and absolute centering overlaps it below ~1100px.
   3. The logo links to "/" (this app's dashboard), not research.kapita.iq.
      Sending a reviewer off to the public site every time they click the
      wordmark would be hostile in a working tool.

   Everything else — tokens, banner treatment, buttons, fields, cards, badges,
   data-viz, rhythm — is lifted from the design system verbatim. */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/static/fonts/Inter-Variable.woff2') format('woff2-variations');
}

:root {
  /* Canonical brand values - design-system.md §1. Do not substitute. */
  --navy: #1A284A;
  --blue: #2352FF;
  --blue-deep: #1a43e0;      /* the documented hover for --blue */
  --sky: #79C8FF;
  --cream: #F4EEE0;
  --amber: #FAAD40;
  --red: #EC4136;
  --ink-black: #1B1B1C;
  --slate: #44474d;
  --slate-soft: #6b6f78;
  --line: #e7e2d6;
  --bg: #F4EEE0;
  --surface: #ffffff;
  --field-bg: #fbf9f4;
  --ghost-line: #c9d0e0;
  --shadow: 0 1px 2px rgba(26, 40, 74, .04), 0 8px 24px rgba(26, 40, 74, .06);
  --shadow-lift: 0 4px 12px rgba(26, 40, 74, .08), 0 16px 40px rgba(26, 40, 74, .10);
  --radius: 14px;

  /* Surfaces that were hard-coded hex until dark mode needed them to move.
     Named for what they do, not what colour they are. */
  --hover: #f1eee4;          /* nav pill, whoami, icon button */
  --row-hover: #faf8f2;      /* a table row under the cursor */
  --line-strong: #e9e3d6;    /* the badge dot, and anything needing more than --line */
  --field-locked: #f3f1ea;   /* a textarea you may read but not edit */
  --page-glow-1: rgba(121, 200, 255, .18);   /* sky, top right */
  --page-glow-2: rgba(35, 82, 255, .06);     /* blue, top left */
  /* Blue does two jobs and they want different lightnesses on a dark ground.
     As TEXT it has to clear the page behind it, which pushed --blue up to
     #6E90FF in dark. As a FILL under white text it has to stay dark enough
     for that text: white on #6E90FF measures 2.96:1, which fails AA outright.
     So the fill keeps the brand's own #2352FF in both themes - white on it is
     5.6:1 - and only the text colour moves. */
  --blue-fill: #2352FF;
  --blue-fill-hover: #1a43e0;

  /* Aliases kept so existing template markup didn't have to change. */
  --paper: var(--bg);
  --paper-raised: var(--surface);
  --ink: var(--navy);
  --muted: var(--slate);
  --faint: var(--slate-soft);
  --accent: var(--blue);
  --accent-ink: #ffffff;
  --accent-soft: rgba(35, 82, 255, 0.10);

  /* Status pills. Red is reserved for genuine alerts and negative results
     only, never decoration (design-system.md §1). */
  --good-bg: #E3F3EA; --good-fg: #157A44;
  --warn-bg: #FEF1DC; --warn-fg: #8A5A12;
  --bad-bg: #FDECEB;  --bad-fg: #C0332A;
  /* #6b6f78 measured 4.22:1 on its own pill background - under AA, and
     that predates dark mode by months. Nothing had ever measured it. */
  --muted-bg: #EFEBDE; --muted-fg: #63666e;
  --okwarn-bg: #E3F1FC; --okwarn-fg: #1B6FA8;
}

/* ---------- Dark ----------

   design-system.md ships a dark variant and says to build it ONLY on request.
   This was requested, so it exists now and is designed rather than derived:
   the earlier note here objected to an AUTOMATIC switch, and it was right to,
   because what it switched to was an off-brand navy page nobody had looked at.
   The objection was to shipping an unreviewed theme, not to honouring the
   reader's preference.

   Three states, two blocks, which is the whole trick:

     no attribute        - follow the operating system
     data-theme="light"  - light, even on a dark OS
     data-theme="dark"   - dark, even on a light OS

   So every colour is defined on bare `:root` and only REDEFINED here. A token
   whose only definition sits inside one of these blocks is a token that
   disappears in the other state.

   The palette is the brand's own, inverted rather than recoloured: the navy
   that carries text on cream becomes the ground, and the cream that was the
   ground becomes the text. Electric blue lifts to #6E90FF because #2352FF on a
   near-black ground measures 3.3:1 - fine as a button fill, too low for a
   link. Status pills keep their hue and swap their lightness, so a warning is
   still amber and a failure still red at a glance. */

/* `light dark` on bare root, not `dark`: with no attribute the page follows
   the operating system, and so must the form controls and scrollbars the
   browser paints itself. Saying `dark` here would have given a light-OS
   reader dark scrollbars on a light page. */
:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --navy: #E8ECF5;         /* the text colour, not the ground, in dark */
    --blue: #6E90FF;
    --blue-deep: #8AA6FF;    /* hover lifts rather than deepens on dark */
    --sky: #79C8FF;
    --slate: #C3CAD8;
    --slate-soft: #8E99AD;
    --line: #253150;
    --bg: #0C1220;
    --surface: #131C30;
    --field-bg: #0F1728;
    --ghost-line: #33415F;
    --hover: #1C2740;
    --row-hover: #172137;
    --line-strong: #33415F;
    --field-locked: #0D1524;
    --shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 8px 24px rgba(0, 0, 0, .45);
    --shadow-lift: 0 4px 12px rgba(0, 0, 0, .45), 0 16px 40px rgba(0, 0, 0, .55);
    --page-glow-1: rgba(121, 200, 255, .07);
    --page-glow-2: rgba(35, 82, 255, .10);
    --accent-soft: rgba(110, 144, 255, 0.16);
    --blue-fill: #2E5BFF;
    --blue-fill-hover: #4570FF;
    --good-bg: #10331F; --good-fg: #6EDB9C;
    --warn-bg: #37280C; --warn-fg: #F0B95C;
    --bad-bg:  #3A1512; --bad-fg:  #FF9086;
    --muted-bg: #1C2438; --muted-fg: #98A2B8;
    --okwarn-bg: #0F2A3D; --okwarn-fg: #7EC5F0;
  }
}

:root[data-theme="dark"] {
  --navy: #E8ECF5;
  --blue: #6E90FF;
  --blue-deep: #8AA6FF;
  --sky: #79C8FF;
  --slate: #C3CAD8;
  --slate-soft: #8E99AD;
  --line: #253150;
  --bg: #0C1220;
  --surface: #131C30;
  --field-bg: #0F1728;
  --ghost-line: #33415F;
  --hover: #1C2740;
  --row-hover: #172137;
  --line-strong: #33415F;
  --field-locked: #0D1524;
  --shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 8px 24px rgba(0, 0, 0, .45);
  --shadow-lift: 0 4px 12px rgba(0, 0, 0, .45), 0 16px 40px rgba(0, 0, 0, .55);
  --page-glow-1: rgba(121, 200, 255, .07);
  --page-glow-2: rgba(35, 82, 255, .10);
  --accent-soft: rgba(110, 144, 255, 0.16);
  --blue-fill: #2E5BFF;
  --blue-fill-hover: #4570FF;
  --good-bg: #10331F; --good-fg: #6EDB9C;
  --warn-bg: #37280C; --warn-fg: #F0B95C;
  --bad-bg:  #3A1512; --bad-fg:  #FF9086;
  --muted-bg: #1C2438; --muted-fg: #98A2B8;
  --okwarn-bg: #0F2A3D; --okwarn-fg: #7EC5F0;
}

/* The Kapita wordmark is a navy PNG on transparent, so on a dark ground it
   goes nearly invisible. Inverting the luminance keeps the mark's shape and
   spacing exactly and costs nothing at load time; a second white asset would
   be another file to keep in step for one page element. */
:root[data-theme="dark"] .brand-logo,
:root[data-theme="dark"] .login-logo { filter: invert(1) brightness(1.9) saturate(0); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo,
  :root:not([data-theme="light"]) .login-logo { filter: invert(1) brightness(1.9) saturate(0); }
}

/* Arabic falls back to the platform's Arabic UI face. Inter carries no Arabic
   glyphs, so without this the browser picks an arbitrary fallback and the
   interface loses its typographic identity the moment you switch language.
   A bundled Arabic webfont (IBM Plex Sans Arabic / Noto Sans Arabic) would be
   better and would match Kapita's Arabic print materials - it needs the font
   file added to /static/fonts and this stack updated, since the CSP forbids
   loading one from Google Fonts. */
[dir="rtl"] body,
[dir="rtl"] .btn,
[dir="rtl"] input,
[dir="rtl"] textarea,
[dir="rtl"] select {
  font-family: "Segoe UI", "Noto Sans Arabic", "Dubai", Tahoma, "Geeza Pro", 'Inter', sans-serif;
}
/* Arabic sits lower and needs more leading than Latin at the same size. */
[dir="rtl"] body { line-height: 1.75; }
[dir="rtl"] h1, [dir="rtl"] h2, [dir="rtl"] h3 { letter-spacing: 0; }

/* Numbers stay Western (123) and stay LTR inside Arabic text - the
   kapita-arabic-translator skill's Rule 1.2. */
[dir="rtl"] .mono, [dir="rtl"] .num, [dir="rtl"] .stat-n { direction: ltr; unicode-bidi: embed; }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  /* Layered radial glows over cream - sky top-right, faint blue top-left.
     This is what stops the page reading as flat beige. design-system.md §1. */
  background:
    radial-gradient(1200px 500px at 80% -10%, var(--page-glow-1), transparent 60%),
    radial-gradient(900px 480px at 0% 0%, var(--page-glow-2), transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--slate);
  font-family: 'Inter', system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Headings: heavy, tight, navy, top-left aligned. Never a serif. */
h1, h2, h3 {
  font-family: inherit;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--navy);
  text-align: start;
}

.mono { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.muted { color: var(--slate); }
.fine { font-size: 12.5px; }
.num { font-variant-numeric: tabular-nums; text-align: end; }

a { color: var(--blue); }
a:hover { color: var(--blue-deep); }

/* ---------- Banner / top nav (design-system.md §3) ---------- */

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 50;
}
.topbar-inner {
  /* 1560, not the 1180 the content column uses. This is the whole bug, and
     three earlier fixes missed it by treating the symptom.
     The three groups measure 342 + 673 + 353 px in English - 1,480 with the
     gaps and padding. On a 1900px laptop that fits the SCREEN with 400px to
     spare, and did not fit only because the bar was capped at the width of
     the article column beneath it. So the items were squeezed, the bar was
     cut off at the right, and the page scrolled sideways to reach `Sign out`.
     A banner is chrome; it does not have to line up with the prose. Given the
     width it needs, it takes one row and fits.
     Below that, `flex-wrap` and the media query put the nav on its own row -
     the same layout, one row lower. */
  max-width: 1560px; margin-inline: auto; padding: 14px 32px;
  display: flex; align-items: center; gap: 24px;
  flex-wrap: wrap; row-gap: 10px;
}
.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: var(--navy); white-space: nowrap; transition: opacity .15s; }
.brand:hover { opacity: .8; }
.brand-logo { height: 34px; width: auto; display: block; }
.brand-sub {
  color: var(--slate-soft); font-weight: 700; font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase;
  padding-inline-start: 12px; border-inline-start: 1px solid var(--line);
}

/* The pill group: white, hairline border, soft shadow, fully rounded. */
.topnav {
  display: flex; align-items: center; gap: 4px; margin-inline: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 99px; padding: 6px; box-shadow: var(--shadow);
}
.topnav a {
  text-decoration: none; color: var(--navy); font-size: 14.5px; font-weight: 600;
  padding: 9px 16px; border-radius: 99px; white-space: nowrap;
  transition: background .15s, color .15s;
}
.topnav a:hover { background: var(--hover); color: var(--blue); }
.topnav a.active { background: var(--blue-fill); color: #fff; }
.topnav a.active:hover { background: var(--blue-fill-hover); color: #fff; }

.topbar-user {
  display: flex; align-items: center; gap: 12px; font-size: 13px;
  color: var(--slate);
  /* Its own three items wrap too. Without this the group was `display: flex`
     with nothing allowed to move: at 375px its 353px of content had to fit in
     335px, and the only thing that could give was the text inside it - so
     `Sign out` broke into `Sign` / `out` against the page background, which
     is the bug as photographed. Wrapping `.topbar-inner` alone never reached
     this, because the squeeze happens one level down. */
  flex-wrap: wrap; row-gap: 8px; justify-content: flex-end;
}
.whoami {
  display: inline-flex; align-items: center; gap: 8px; font-weight: 600;
  color: var(--navy); text-decoration: none; padding: 5px 10px; border-radius: 99px;
  transition: background .15s;
}
.whoami:hover { background: var(--hover); color: var(--navy); }
/* The settings gear. An icon rather than a word because the bar is measured
   to 1,480px of content against a 1,560px box, and a sixth label would spend
   most of what is left. */
.icon-link {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 99px; color: var(--slate-soft);
  transition: background .15s, color .15s;
}
.icon-link svg { width: 17px; height: 17px; display: block; }
.icon-link:hover { background: var(--hover); color: var(--blue); }
.icon-link.active { background: var(--accent-soft); color: var(--blue); }

/* The theme switch is the same 30px icon button as the gear beside it. It is
   a form, not a link: it changes server-side state, and a GET that changes
   state is a GET a browser may prefetch. */
.theme-form { display: inline-flex; }
.theme-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border: none; border-radius: 99px;
  background: none; color: var(--slate-soft); cursor: pointer;
  transition: background .15s, color .15s;
}
.theme-btn svg { width: 17px; height: 17px; display: block; }
.theme-btn:hover { background: var(--hover); color: var(--blue); }

/* Which icon shows is a CSS question, not a template one: it has to agree
   with the palette in all three states, and in "system" only the browser
   knows which that is. The button offers the OPPOSITE of what is showing -
   a sun on a dark page, a moon on a light one. */
.theme-btn .icon-sun { display: none; }
.theme-btn .icon-moon { display: block; }
:root[data-theme="dark"] .theme-btn .icon-sun { display: block; }
:root[data-theme="dark"] .theme-btn .icon-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-btn .icon-sun { display: block; }
  :root:not([data-theme="light"]) .theme-btn .icon-moon { display: none; }
}
.role-tag {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  background: var(--accent-soft); color: var(--blue); padding: 3px 9px; border-radius: 99px;
}
/* `white-space: nowrap`: a two-word label is one label. Whatever squeezes it,
   the answer is for the row to wrap, never for `Sign out` to become two lines. */
.link-button { background: none; border: none; color: var(--slate-soft); cursor: pointer; font-size: 13px; font-weight: 600; padding: 0; font-family: inherit; white-space: nowrap; transition: color .15s; }
.link-button:hover { color: var(--blue); }

/* ---------- Language toggle ---------- */

.lang-form {
  display: inline-flex; align-items: center; gap: 0;
  background: var(--field-bg); border: 1px solid var(--line);
  border-radius: 99px; padding: 3px;
}
.lang-btn {
  font-family: inherit; font-size: 12px; font-weight: 700; cursor: pointer;
  border: none; background: none; color: var(--slate-soft);
  padding: 5px 12px; border-radius: 99px; transition: background .15s, color .15s;
}
.lang-btn:hover { color: var(--blue); }
.lang-active { background: var(--surface); color: var(--navy); box-shadow: var(--shadow); }
/* The Arabic option renders in Arabic ("العربية"), so it needs the Arabic
   face even while the interface is still in English. */
.lang-btn[lang="ar"] { font-family: "Segoe UI", "Noto Sans Arabic", Tahoma, sans-serif; font-size: 13px; }
/* Signed out there is no top bar to hang it on, so it floats above the card. */
.lang-floating { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-bottom: 16px; }

/* ---------- Page shell ---------- */

.page { max-width: 1180px; margin-inline: auto; padding: 48px 32px 96px; }
.page-narrow { max-width: 460px; padding-top: 72px; }

/* Hero two-tone: navy line, electric-blue accent line (design-system.md §2). */
.page-title { font-size: 34px; line-height: 1.15; margin: 0 0 8px; }
.page-title .accent { color: var(--blue); display: block; }
.page-lede { font-size: 15px; color: var(--slate-soft); margin: 0 0 40px; max-width: 70ch; }
.section-title { font-size: 21px; margin: 0; font-weight: 700; letter-spacing: -0.01em; }
.back-link { display: inline-block; margin-bottom: 16px; text-decoration: none; color: var(--slate-soft); font-size: 13px; font-weight: 600; }
.back-link:hover { color: var(--blue); }
/* Arrows come from CSS, not from the markup, so they can point the right way
   in each direction - a literal "←" glued into a template means "forward" once
   the page flips to RTL. */
.back-link::before { content: "\2190\00a0"; }
[dir="rtl"] .back-link::before { content: "\2192\00a0"; }
.go::after { content: "\00a0\2192"; }
[dir="rtl"] .go::after { content: "\00a0\2190"; }
.pager-prev::before { content: "\2190\00a0"; }
[dir="rtl"] .pager-prev::before { content: "\2192\00a0"; }
.pager-next::after { content: "\00a0\2192"; }
[dir="rtl"] .pager-next::after { content: "\00a0\2190"; }

/* Eyebrow badge with the sky dot (design-system.md §7). */
.badge {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: 99px;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow);
  font-size: 13px; font-weight: 600; color: var(--blue); margin-bottom: 20px;
}
.badge .dot-live { width: 7px; height: 7px; border-radius: 50%; background: var(--sky); box-shadow: 0 0 0 4px rgba(121, 200, 255, .25); }

/* ---------- Flash messages ---------- */

.flashes { margin-bottom: 24px; display: flex; flex-direction: column; gap: 8px; }
.flash { padding: 13px 18px; border-radius: 10px; font-size: 14px; font-weight: 500; box-shadow: var(--shadow); }
.flash-success { background: var(--good-bg); color: var(--good-fg); }
.flash-error { background: var(--bad-bg); color: var(--bad-fg); }
.flash-info { background: var(--surface); color: var(--slate); border-inline-start: 3px solid var(--blue); }

/* ---------- Cards (design-system.md §5) ---------- */

.card {
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 28px 32px;
}
.card-head {
  display: flex; align-items: center; gap: 12px;
  padding-bottom: 18px; margin-bottom: 24px; border-bottom: 1px solid var(--line);
}
.card-head .ic {
  width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--blue); flex-shrink: 0;
}
.card-head .ic svg { width: 18px; height: 18px; display: block; }
.card-head h2 { font-size: 21px; font-weight: 700; letter-spacing: -0.01em; margin: 0; }
.card-head .head-note { margin-inline-start: auto; font-size: 12.5px; color: var(--slate-soft); font-weight: 500; }

/* ---------- Stat cards ---------- */

/* Five cards in a fixed four-column grid left the fifth alone at one end.
   `auto-fit` with a minimum width lets the row settle at whatever count
   fits, so adding or removing a card never strands one. */
.stat-grid {
  display: grid; gap: 18px; margin-bottom: 56px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.stat-card {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 24px; text-decoration: none; color: inherit; display: block;
  transition: box-shadow .2s, transform .2s;
  position: relative; overflow: hidden;
}
/* Amber marks the key stat - as a rule above the number rather than as the
   number's own colour. design-system.md assigns amber to "key stats", but
   #FAAD40 on white measures 1.89:1 and even the brand's text-amber (#d9920f,
   from the data-viz scale) only reaches 2.6:1 - both under the 3.0 floor for
   large text. The numeral is navy (14.5:1) so it can actually be read; the
   amber still says "this is the number that matters". */
.stat-card::before {
  content: ""; position: absolute; inset-block-start: 0; inset-inline-start: 0;
  width: 44px; height: 3px; background: var(--amber);
}
.stat-card:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.stat-card:hover::before { width: 100%; transition: width .25s ease; }
.stat-n {
  font-size: 40px; font-weight: 900; font-variant-numeric: tabular-nums;
  color: var(--navy); display: block; line-height: 1;
  margin-block: 8px 10px; letter-spacing: -0.03em;
}
.stat-l { font-size: 13px; color: var(--navy); font-weight: 600; display: block; }
.stat-card .fine { display: block; margin-top: 6px; color: var(--slate-soft); }

/* ---------- Tables ---------- */

/* The card scrolls, never the page. A single long token in one cell - a record
   id, a URL - sets the table's minimum width, and with no scroll container the
   whole document goes wide: every page then scrolls sideways, and the sticky
   topbar, which is only as wide as the viewport, runs out of white partway
   across with the page background showing beyond it. This used to be true only
   below 700px, which is the one width where a long id is least likely. */
.table-wrap { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow); padding: 8px 24px 4px; overflow-x: auto; }
/* And break the token rather than scroll for it where a break is readable. */
.data-table td .mono, .data-table td a { overflow-wrap: anywhere; }
.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table th {
  text-align: start; font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--slate-soft); font-weight: 700; padding: 16px 14px 12px 0; border-bottom: 1px solid var(--line);
}
.data-table td { padding: 14px 14px 14px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tbody tr { transition: background .12s; }
.data-table tbody tr:hover { background: var(--row-hover); }
.item-title { color: var(--navy); text-decoration: none; font-weight: 600; }
.item-title:hover { color: var(--blue); }

/* ---------- Pills / badges ---------- */

.pill {
  display: inline-block; font-size: 11px; font-weight: 700; padding: 4px 11px; border-radius: 999px;
  letter-spacing: 0.02em; white-space: nowrap;
}
.pill-good { background: var(--good-bg); color: var(--good-fg); }
.pill-warn { background: var(--warn-bg); color: var(--warn-fg); }
.pill-bad { background: var(--bad-bg); color: var(--bad-fg); }
.pill-muted { background: var(--muted-bg); color: var(--muted-fg); }
.pill-ok-warn { background: var(--okwarn-bg); color: var(--okwarn-fg); }

/* Importance readout - navy filled, track in the cream hairline (§9). */
.dots { display: inline-flex; gap: 3px; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); display: inline-block; }
.dot-on { background: var(--navy); }

/* ---------- Buttons (design-system.md §4) ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1.5px solid transparent; background: transparent; color: var(--navy);
  padding: 13px 26px; border-radius: 10px; font-size: 15px; font-weight: 700;
  letter-spacing: 0.01em; cursor: pointer; text-decoration: none; font-family: inherit;
  transition: all .18s;
  /* A button is a label, not a paragraph. Inside a narrow table cell the
     flex layout below was shrinking these past their own text and breaking
     the word - "Open" rendered as "Ope / n". */
  white-space: nowrap;
}
.btn-sm { padding: 7px 15px; font-size: 12.5px; border-radius: 8px; }
.btn-primary { background: var(--blue-fill); color: #fff; }
.btn-primary:hover { background: var(--blue-fill-hover); color: #fff; transform: translateY(-1px); box-shadow: 0 8px 20px rgba(35, 82, 255, .28); }
.btn-ghost { background: transparent; border-color: var(--ghost-line); color: var(--navy); }
.btn-ghost:hover { border-color: var(--navy); background: var(--surface); color: var(--navy); }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.inline-form { display: inline; }
.row-actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
/* Never below their own content width: wrapping to a second line is fine,
   breaking a word in half is not. */
.row-actions > * { flex: 0 0 auto; }
/* `1%` is the standard way to ask a table for a column's natural width: the
   browser resolves it against the row and lands on the minimum that fits. */
.data-table td.row-actions { width: 1%; }

/* ---------- Form fields (design-system.md §6) ---------- */

.stack-form { display: flex; flex-direction: column; gap: 6px; margin-top: 20px; }
.stack-form label,
.draft-form label {
  font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--slate-soft); margin-top: 14px;
}
.stack-form input, textarea, .filter-row select {
  font-family: inherit; font-size: 15px; padding: 14px 16px; border: 1.5px solid var(--line);
  /* `--navy`, not `--ink-black`. Both are near-black in light and read the
     same there, but only --navy is a ROLE - "the colour text is" - and so
     only --navy moves in dark. --ink-black is a fixed brand ink, stayed
     #1B1B1C, and put 1.04:1 text into every input and textarea: typing into
     the draft editor produced nothing you could see. */
  border-radius: 10px; background: var(--field-bg); color: var(--navy); width: 100%;
  outline: none; transition: border-color .15s, background .15s, box-shadow .15s;
}
.stack-form input:focus, textarea:focus, .filter-row select:focus {
  border-color: var(--blue); background: var(--surface); box-shadow: 0 0 0 4px var(--accent-soft);
}
textarea[readonly] { background: var(--field-locked); color: var(--slate); }
.stack-form button { margin-top: 20px; }

/* Stated rather than left to the browser: the default selection blue is
   picked for a light page and hides light text on a dark one. */
::selection { background: var(--blue-fill); color: #fff; }

.draft-form { display: flex; flex-direction: column; gap: 4px; margin: 20px 0; }
.draft-form textarea { resize: vertical; line-height: 1.6; }
.draft-form button { margin-top: 20px; align-self: flex-start; }

.filter-row { margin-bottom: 20px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.filter-label { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--slate-soft); }
.filter-row select { width: auto; padding: 10px 14px; font-size: 14px; }

/* ---------- Tabs ---------- */

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 24px; flex-wrap: wrap; }
.tab {
  padding: 11px 18px; text-decoration: none; color: var(--slate); font-size: 14px; font-weight: 600;
  border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color .15s, border-color .15s;
}
.tab:hover { color: var(--blue); }
.tab-active { color: var(--blue); border-bottom-color: var(--blue); }

/* ---------- Pagination ---------- */

.list-count { margin: 0 0 12px; color: var(--slate-soft); }
.list-count b { color: var(--navy); font-variant-numeric: tabular-nums; }
.pager { display: flex; align-items: center; justify-content: center; gap: 18px; margin: 28px 0 4px; }

/* ---------- Article body ---------- */

.article-body-text {
  white-space: pre-wrap; line-height: 1.75; max-height: 32em; overflow-y: auto;
  padding: 12px 2px; font-size: 15px; color: var(--slate);
}
.article-body details > summary,
.approved-text > summary { cursor: pointer; font-weight: 700; color: var(--blue); padding: 10px 0; }

/* ---------- Detail pages ---------- */

.detail-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 28px; flex-wrap: wrap; }
.detail-section { margin-bottom: 32px; }
.detail-section .section-title { margin-bottom: 14px; }
.context-box {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  border-inline-start: 3px solid var(--blue); padding: 6px 24px;
}
.context-row { display: flex; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.context-row:last-child { border-bottom: none; }
.context-k {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--slate-soft); width: 180px; flex-shrink: 0; padding-top: 2px;
}
.source-links { margin: 20px 0; display: flex; flex-direction: column; gap: 8px; font-size: 13px; }
.action-row { display: flex; gap: 12px; margin: 28px 0; align-items: center; flex-wrap: wrap; }
.timeline { list-style: none; padding: 0; margin: 0; font-size: 13.5px; }
.timeline li { padding: 12px 0; border-bottom: 1px solid var(--line); }
.timeline li:last-child { border-bottom: none; }

/* ---------- Preview banner ---------- */

.demo-banner {
  background: var(--amber); color: var(--navy);
  padding: 9px 24px; font-size: 13px; font-weight: 600; text-align: center;
  border-bottom: 1px solid rgba(26, 40, 74, .18);
}
.demo-banner b { letter-spacing: .08em; margin-inline-end: 8px; }

/* ---------- Draft generation states ---------- */

.context-box.working { border-inline-start-color: var(--amber); }
.context-box.failed  { border-inline-start-color: var(--red); }
.context-box.working p, .context-box.failed p { margin: 10px 0; }

/* ---------- Login ---------- */

.login-wrap { display: flex; justify-content: center; }
.login-card {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-lift);
  padding: 44px 40px; width: 100%; max-width: 420px;
}
.login-logo { height: 36px; width: auto; margin-bottom: 28px; display: block; }
.kicker {
  font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--blue); margin: 0 0 12px;
}
.login-card h1 { font-size: 28px; margin: 0 0 6px; line-height: 1.15; }
.login-card > p.fine { color: var(--slate-soft); margin-top: 24px; }

.empty-state {
  color: var(--slate-soft); padding: 48px 32px; text-align: center;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
}

/* ---------- Settings ----------
   Forms rather than a dashboard: every control here changes what the pipeline
   does, so each one states its consequence next to it rather than in a help
   page nobody opens. Logical properties throughout - this page flips to RTL. */

.setting-form { margin-top: 4px; }

/* Running a cycle by hand: closed until asked for. Native <details>, because
   this interface carries no JavaScript and disclosure does not need any. */
.run-panel { margin-top: 18px; }
.run-summary { display: inline-flex; align-items: center; gap: 8px; list-style: none; cursor: pointer; }
.run-summary::-webkit-details-marker { display: none; }
/* Literal characters, deliberately. A CSS escape for these went into the
   file as a raw control byte and rendered as "[]be" on the button. */
.run-summary::after { content: "▾"; font-size: 11px; opacity: .8; }
.run-panel[open] > .run-summary::after { content: "▴"; }
.run-body {
  margin-top: 14px; padding: 16px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--field-bg);
}
.run-option {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  padding: 12px 14px; margin-bottom: 10px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
}
.run-option p { margin: 4px 0 0; }
.run-edit { display: block; }
.run-edit > summary { cursor: pointer; font-weight: 600; color: var(--blue); }
.run-edit[open] > summary { margin-bottom: 14px; }

/* A post's slides, stacked in the order they will be published. */
.slide-card { margin-bottom: 18px; }
.slide-number {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-inline-end: 8px;
  border-radius: 999px; background: var(--blue-fill); color: #fff;
  font-size: 13px; font-weight: 700;
}
/* The lead line carries the news; the body is the 40-90 words under it. Sized
   apart so a glance separates them the way the rendered slide will. */
.slide-lead { font-size: 16.5px; font-weight: 700; color: var(--navy); margin: 4px 0 10px; }
.slide-body { font-size: 14.5px; line-height: 1.85; margin: 0 0 14px; }

/* Picking which post a draft moves into. Titles are the whole point, so they
   are the button rather than a label beside one. */
.post-picker { list-style: none; padding: 0; margin: 0 0 16px; }
.post-picker li {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 0; border-bottom: 1px solid var(--line);
}
.post-picker li:last-child { border-bottom: none; }

/* Asking Stage 5 for the current week, on the weekly page. */
.weekly-run { margin-bottom: 28px; }
.weekly-run .inline-form { margin-top: 10px; }
/* The tail of a failed run's own output: a traceback, so it keeps its line
   breaks and scrolls sideways rather than stretching the card. */
.run-error {
  margin: 8px 0 0; padding: 10px 12px; max-height: 220px;
  overflow: auto; white-space: pre-wrap; word-break: break-word;
  background: var(--field-bg); border: 1px solid var(--line); border-radius: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Regenerating a draft: the one action here that spends money, so it is closed
   until asked for and opens onto a box for saying what was wrong with the
   draft on screen above it. Same native <details> as the run panel. */
.regen-box { margin: 8px 0 28px; }
.regen-box > summary {
  display: inline-flex; align-items: center; gap: 8px;
  list-style: none; cursor: pointer; font-weight: 700; color: var(--blue);
}
.regen-box > summary::-webkit-details-marker { display: none; }
/* Literal characters, deliberately - see .run-summary. */
.regen-box > summary::after { content: "▾"; font-size: 11px; opacity: .8; }
.regen-box[open] > summary::after { content: "▴"; }
.regen-box[open] > summary { margin-bottom: 12px; }
.regen-box .stack-form {
  margin-top: 0; padding: 16px; max-width: 620px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--field-bg);
}
.regen-box .stack-form button { align-self: flex-start; }

/* The hours box appears only when Custom is the choice. `:has()` on the group
   rather than a sibling selector, because each radio sits inside its own
   <label> and `~` cannot reach across that. Where `:has()` is unsupported the
   rule is simply ignored and the box stays visible, which is what it did
   before - a degradation, not a break. */
.window-group:not(:has(input[value="custom"]:checked)) .custom-hours,
.window-row:not(:has(option[value="custom"]:checked)) .custom-hours {
  display: none;
}
.custom-hours { display: inline-flex; align-items: center; gap: 8px; }
.field-group {
  border: 1px solid var(--line); border-radius: 12px;
  padding: 14px 16px; margin: 0 0 16px; background: var(--field-bg);
}
.field-group legend {
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--slate-soft); padding-inline: 6px;
}
.choice {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 6px 0; cursor: pointer; color: var(--navy); font-weight: 600;
}
.choice input[type="radio"] { accent-color: var(--blue); width: 16px; height: 16px; }
/* Indented under the "Choose which" radio it belongs to, so the relationship
   is visible without a line connecting them. */
.choice-grid {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 4px 0 10px; padding-inline-start: 26px;
}
.chip-check {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); border-radius: 99px;
  padding: 5px 12px; background: var(--surface); cursor: pointer; font-size: 13px;
}
.chip-check input { accent-color: var(--blue); }
.chip-check:hover { border-color: var(--ghost-line); }
.field-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.field-row:last-of-type { border-bottom: none; }
.field-row > label { min-width: 200px; font-weight: 600; color: var(--navy); }
.num-input, .text-input {
  border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px;
  background: var(--surface); font: inherit; font-size: 14px; color: var(--navy);
}
.num-input { width: 96px; }
.text-input { min-width: 200px; }
.num-input:focus, .text-input:focus, .field-row select:focus {
  outline: 2px solid var(--accent-soft); border-color: var(--blue);
}
.field-row select {
  border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px;
  background: var(--surface); font: inherit; font-size: 14px; color: var(--navy);
}
.setting-actions {
  display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 16px;
}
/* The source switch is the checkbox and its name as one target - a 3mm
   checkbox on its own is a poor thing to ask anyone to hit. */
.switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.switch input { accent-color: var(--blue); width: 16px; height: 16px; }
.switch input:disabled { cursor: not-allowed; }
.switch input:disabled + .mono { color: var(--slate-soft); text-decoration: line-through; }

/* ---------- Responsive ---------- */

/* Under the width where all three groups fit on one line, the nav takes its
   own row rather than pushing the page sideways. Measured against the real
   stylesheet, not guessed: 1,480px of content, with the slack a longer
   username needs. */
@media (max-width: 1560px) {
  .topnav {
    /* `flex: 0 0 100%`, not `width: 100%`: `margin-inline: auto` plus the
       default flex basis otherwise squeezes the pill group to its content. */
    order: 3; flex: 0 0 100%; margin-inline: 0;
    justify-content: center; gap: 4px;
  }
  /* Only here. On one row the nav's own auto margins centre it, and a second
     auto margin would take a share of the free space and pull it off centre. */
  .topbar-user { margin-inline-start: auto; }
}

@media (max-width: 900px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .page { padding: 32px 20px 64px; }
  .topbar-inner { padding: 12px 20px; }
}

@media (max-width: 700px) {
  /* The nav used to be `display: none` here with nothing replacing it, so
     below 700px a reviewer could only navigate by typing URLs - and the
     audience is explicitly non-technical (internal review M-19).
     No JavaScript, no hamburger, every destination one tap away. */
  .topnav {
    justify-content: space-between; gap: 2px; padding: 5px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
  }
  /* Tuned so all four destinations fit 375px without the pill group scrolling
     - measured, not guessed. */
  .topnav a { padding: 8px 9px; font-size: 12.5px; }
  .nav-long { display: none; }   /* "Approved & Publishing" -> "Approved" */
  .brand-sub { display: none; }
  .page-title { font-size: 27px; }
  .data-table { display: block; overflow-x: auto; }
  .context-row { flex-direction: column; gap: 4px; }
  .context-k { width: auto; }
  .table-wrap { padding-inline: 16px; }
}

/* The weekly analysis's citation list. Numbered because Stage 5 emits the ids
   in the order it used them, and that order is information. */
.weekly-cited { margin: 8px 0 0; padding-inline-start: 22px; }
.weekly-cited li { margin-bottom: 8px; line-height: 1.5; }
.weekly-cited code { font-size: 13px; color: var(--slate); }

/* ---------- The live-window switch ----------
   Above the cards on the dashboard and above the tabs in the inbox, because it
   changes what every number below it means. A segmented pill, following the
   `.badge` it sits under: the active half is FILLED rather than merely tinted,
   so the current view is legible at a glance and not inferred from a colour
   shift. Logical properties throughout - this page flips to RTL. */

.scope-switch { margin: 0 0 28px; }

.scope-seg {
  display: inline-flex; padding: 3px; border-radius: 99px;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow);
}
.scope-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 18px; border-radius: 99px; text-decoration: none; white-space: nowrap;
  font-size: 13px; font-weight: 600; color: var(--slate-soft);
  transition: background .15s, color .15s;
}
.scope-opt:hover { color: var(--blue); }

/* The active half carries THREE signals, not one: a filled background, heavier
   text, and a tick. One of them surviving is enough to answer "which view am I
   on" - and a colour fill alone does not answer it for a reader who cannot see
   the colour, or on a screen that renders it faintly. */
.scope-on, .scope-on:hover {
  background: var(--blue-fill); color: #ffffff; font-weight: 700;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .18);
}
.scope-on::before { content: "✓"; font-size: 12px; line-height: 1; }
.scope-note { margin: 10px 0 0; }
.scope-note b { color: var(--slate); font-weight: 600; font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .scope-seg { display: flex; }
  .scope-opt { flex: 1; text-align: center; padding-inline: 10px; }
}

/* ---------- Exception notice ----------
   For a state that should not exist: articles stuck before classification, a
   source that stopped answering. It appears only when there is something to
   say, so it is never wallpaper. Amber rather than red: the pipeline is
   running, something in it is not - and the warning tone already carries that
   meaning everywhere else on this page. Logical properties throughout; this
   page flips to RTL. */

.notice {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 16px 18px; margin: 0 0 24px;
  border-radius: 12px; background: var(--surface);
  border: 1px solid var(--line); border-inline-start: 3px solid var(--warn-fg);
  box-shadow: var(--shadow);
}
.notice-ic { flex: none; width: 22px; height: 22px; color: var(--warn-fg); margin-top: 1px; }
.notice-ic svg { width: 100%; height: 100%; display: block; }
.notice b { display: block; color: var(--slate); font-size: 15px; }
.notice p { margin: 6px 0 0; color: var(--slate-soft); }
.notice-link {
  display: inline-block; margin-top: 10px; font-size: 13px; font-weight: 600;
  color: var(--blue); text-decoration: none;
}
.notice-link:hover { text-decoration: underline; }
/* The link and the "Fix all" button sit on one line, baseline-aligned - the
   link keeps its own top margin, so the row zeroes it and owns the spacing. */
.notice-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 12px; }
.notice-actions .notice-link { margin-top: 0; }

/* The pipeline's own last run, above the per-source table it summarises. */
.cycle-line {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin: 14px 0 0; padding: 12px 14px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
}
.cycle-label {
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--slate-soft);
}
.cycle-line b { color: var(--navy); font-size: 15px; }
.cycle-detail { margin: 8px 0 0; }
/* Pushed to the far end of the row, so the reading (when did it last run)
   and the doing (run it again) do not compete for the same spot. */
.cycle-actions { margin-inline-start: auto; display: flex; gap: 8px; }
.cycle-running { display: flex; align-items: center; gap: 8px; color: var(--slate); }
.cycle-running .mono { color: var(--blue); }
.spinner {
  flex: none; width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--blue);
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* The page reloads itself every five seconds while a cycle runs, so the
   animation is decoration on top of that, not the thing reporting progress -
   and for anyone who has asked not to be moved at, it is no loss at all. */
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }

/* ---------- Other outlets on the same event (Stage 2.5) ----------
   A list, not a paragraph: the reviewer is checking names against a sourcing
   note, which is scanning, not reading. Logical properties - this page flips
   to RTL. */

.also-list { margin: 6px 0 0; padding-inline-start: 18px; }
.also-list li { margin: 3px 0; font-size: 13px; line-height: 1.5; }
.also-list .mono { color: var(--slate-soft); margin-inline-end: 6px; }
.also-list a { color: var(--blue); text-decoration: none; }
.also-list a:hover { text-decoration: underline; }

.also-box {
  margin: 0 0 16px; padding: 12px 14px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--line);
  border-inline-start: 3px solid var(--blue);
}
.also-box > b { font-size: 13px; color: var(--slate); }

/* ---------- The flag ----------
   The one signal saying a person has to read this story carefully, on the row
   where a reviewer scans headlines. Amber and lettered rather than a coloured
   dot: colour alone is not a signal to a reader who cannot distinguish it, and
   this is the marker that must never be missed.

   Its reason sits under the headline in full. `escalate_reason` names which of
   the three tests fired and why - a sentence, and useless in a tooltip nobody
   opens. Logical properties throughout; this page flips to RTL. */

.flag {
  display: inline-block; vertical-align: 2px; margin-inline-end: 8px;
  padding: 2px 8px; border-radius: 5px;
  background: var(--warn-bg); color: var(--warn-fg);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  white-space: nowrap;
}
/* The reason is NOT rendered in the queue. Measured: 93 of the first 100 rows
   are flagged, and a two-line reason under each headline took the table from
   9,200 pixels to 18,943 - nineteen screens of scrolling for a sentence that
   applies to most rows. It lives on the item page, where there is room, and on
   the badge's tooltip for a quick check. */

/* One story's other outlets, on the queue row. Quiet: it is context for a
   headline, not a warning - the flag beside it is the only thing on this row
   that should pull an eye. */
.outlets {
  display: inline-block; margin-inline-start: 8px;
  padding: 1px 7px; border-radius: 5px;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--slate-soft); font-size: 11px; font-weight: 600; white-space: nowrap;
}

/* --- The new-post fields ------------------------------------------------
   The sector row exists only for a sector digest, and the free-text box only
   when the reviewer picks "another sector". Both with `:has()` rather than
   script: this interface carries exactly one piece of JavaScript and its CSP
   has no script-src, so a second one would mean a new file and a policy
   change to hide a form row. `:has()` has been baseline in every browser
   since 2023.

   The fallback is not a broken form: without `:has()` support both rows
   simply stay visible, which is what the form did before this change. */
/* The partial is one flex CHILD of .stack-form, so without this its own
   contents collapse into a single block and lose the form's gap. */
.post-fields,
.post-fields .sector-row,
.post-fields .sector-new { display: flex; flex-direction: column; gap: 6px; }

.post-fields .sector-row,
.post-fields .sector-new { display: none; }

.post-fields:has(select[name="kind"] option[value="sector"]:checked) .sector-row,
.post-fields:has(select[name="sector"] option[value="__new__"]:checked) .sector-new {
  display: flex;
}

.post-fields .sector-row {
  border-inline-start: 2px solid var(--line);
  padding-inline-start: 14px;
  margin-top: 6px;
}

/* A `<select>` was never styled. `.stack-form input, textarea, .filter-row
   select` reads as three selectors, and only the third covers a select - so a
   select on any other form fell back to the browser's own control: half width,
   wrong font, wrong colours, unreadable on the dark theme. The old form had
   one and looked broken there too; this one has two.

   The native arrow goes with it, because it is drawn in the OS's colour and
   vanishes against a dark field. One SVG chevron replaces it, positioned from
   the physical left (both forms carrying it are RTL) with matching logical
   padding so the text never runs under it. Drawn as two CSS triangles first,
   which rendered a small garbled glyph rather than an arrow. */
.stack-form select,
.draft-form select {
  font-family: inherit; font-size: 15px; padding: 13px 16px;
  border: 1.5px solid var(--line); border-radius: 10px;
  background-color: var(--field-bg); color: var(--navy); width: 100%;
  outline: none; transition: border-color .15s, background-color .15s, box-shadow .15s;
  appearance: none;
  padding-inline-start: 40px;
  background-repeat: no-repeat;
  background-position: left 15px center;
  background-size: 11px 7px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'%3E%3Cpath d='M1 1l4.5 4.5L10 1' fill='none' stroke='%238C93A8' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.stack-form select:focus,
.draft-form select:focus {
  border-color: var(--blue); background-color: var(--surface);
  box-shadow: 0 0 0 4px var(--accent-soft);
}

/* The hint belongs under the label, not beside it. A label is 11px uppercase
   with 0.1em tracking, and the hint inherited all three - so a full sentence
   of Arabic rendered as spaced-out small caps running off the edge, which is
   what it did in the screenshot. */
.stack-form label,
.draft-form label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.stack-form label .fine,
.draft-form label .fine {
  text-transform: none; letter-spacing: normal; font-weight: 400;
  font-size: 12px; flex-basis: 100%;
}

/* --- The draft page's actions -------------------------------------------
   Two zones, because there are two kinds of action and they were previously
   four look-alike blocks stacked at the foot of the page.

   Zone 1 is the slide and the two ways to change it: Save, and Rewrite with
   AI. Both live under the text they change. Both are quiet - editing is the
   occasional case, not the point of the visit.

   Zone 2 is where the slide GOES, and it is the loud thing on the page,
   because filing the slide is why the reviewer opened it. */

.form-actions {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
}

/* Attached to the form above it rather than floating as a peer of the
   destination card: it is the second half of "change this text". */
.rewrite-box { margin-top: -4px; }

.destination {
  margin: 28px 0 8px; padding: 20px 22px;
  border: 1.5px solid var(--blue); border-radius: 14px;
  background: var(--accent-soft);
}
.dest-title {
  font-size: 15px; font-weight: 700; margin: 0 0 14px; color: var(--navy);
}
.dest-chips { display: flex; flex-wrap: wrap; gap: 10px; }

/* One chip per open post. Filled, not outlined: these are the buttons the
   page exists for, and an outline would put them at the same weight as Save. */
.btn-dest {
  background: var(--blue-fill); color: #fff; border-color: transparent;
  max-width: 100%; white-space: normal; text-align: start;
}
.btn-dest:hover { background: var(--blue-fill-hover); color: #fff; }
.btn-dest .dest-note { opacity: .72; font-size: 12px; font-weight: 500; }

/* Already in that post: shown, not hidden, so the reviewer can see where the
   slide has been filed - but inert, and it must not read as pressable. */
.btn-dest.is-in {
  background: transparent; color: var(--slate); border-color: var(--ghost-line);
  cursor: default;
}
.btn-dest.is-in:hover { background: transparent; color: var(--slate); transform: none; box-shadow: none; }

.sub-box { margin-top: 14px; }
.sub-box > summary { font-size: 12.5px; color: var(--slate-soft); cursor: pointer; }

/* The way back is an undo, so it gets no button weight at all - a link, set
   apart, at the end. */
.escape-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 22px 0 4px; padding-top: 16px; border-top: 1px solid var(--line);
}
.linkish {
  background: none; border: none; padding: 0; font: inherit; font-size: 13px;
  color: var(--slate); text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}
.linkish:hover { color: var(--blue); }
