/* An analyst's working note on a disinformation outlet: what it always says,
   and what it is about to say. Everything here follows from that. The page
   reads as ruled paper rather than a dashboard, because a forecast that looks
   like an instrument gets trusted like one; figures sit in a fixed pitch so a
   share can be compared down a column; and rust marks only the one thing
   being claimed, the rise. */

:root {
  /* Typography. Self-hosted or system, never fetched: the page promises that
     nothing you type leaves the machine, and a webfont request from a
     third party would make that false before the first keystroke.
     --voice carries the prose, --data every figure that is read against
     another figure, --quote the evidence lifted from the corpus. */
  --voice: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system,
           "Segoe UI", Roboto, sans-serif;
  --data: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono",
          Menlo, Consolas, monospace;
  --quote: "Newsreader", Georgia, "Times New Roman", serif;

  --paper: #f7f6f3;
  --card: #fffefb;
  --ink: #1c1a17;
  --ink-soft: #5d5750;
  --ink-faint: #8a827a;
  --rule: #ded9d0;
  --rule-soft: #ebe7e0;
  --rise: #9a3412;
  --rise-soft: #f3e3db;
  --stone: #78716c;
  --stone-soft: #e5e1da;
  --caution: #8a5a08;
  --caution-bg: #fbf3e0;
  --caution-rule: #e8d4a8;

  /* EU standing: three quiet hues, kept well away from the rust accent. */
  --g-member: #1e4f6b;
  --g-member-bg: #e8f0f5;
  --g-member-rule: #b8d0de;
  --g-cand: #4a5320;
  --g-cand-bg: #f0f2e2;
  --g-cand-rule: #cdd4aa;
  --g-rapp: #4b4453;
  --g-rapp-bg: #efecf2;
  --g-rapp-rule: #cfc8d6;

  --step--1: 0.78rem;
  --step-0: 0.94rem;
  --step-1: 1.12rem;
  --step-2: 1.45rem;
  --step-3: 2.1rem;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #171614;
    --card: #201e1b;
    --ink: #f0ece5;
    --ink-soft: #b3aca3;
    --ink-faint: #837c73;
    --rule: #37332e;
    --rule-soft: #2a2724;
    --rise: #f0845c;
    --rise-soft: #3b241c;
    --stone: #a8a29a;
    --stone-soft: #322e2a;
    --caution: #e8bf72;
    --caution-bg: #2e2617;
    --caution-rule: #4d4026;
    --g-member: #8ec5e0;
    --g-member-bg: #1a2b34;
    --g-member-rule: #2f4d5c;
    --g-cand: #c2cd7e;
    --g-cand-bg: #262a15;
    --g-cand-rule: #454d27;
    --g-rapp: #c3b8cf;
    --g-rapp-bg: #262130;
    --g-rapp-rule: #423a52;
  }
}

:root[data-theme="dark"] {
  --paper: #171614;
  --card: #201e1b;
  --ink: #f0ece5;
  --ink-soft: #b3aca3;
  --ink-faint: #837c73;
  --rule: #37332e;
  --rule-soft: #2a2724;
  --rise: #f0845c;
  --rise-soft: #3b241c;
  --stone: #a8a29a;
  --stone-soft: #322e2a;
  --caution: #e8bf72;
  --caution-bg: #2e2617;
  --caution-rule: #4d4026;
  --g-member: #8ec5e0;
  --g-member-bg: #1a2b34;
  --g-member-rule: #2f4d5c;
  --g-cand: #c2cd7e;
  --g-cand-bg: #262a15;
  --g-cand-rule: #454d27;
  --g-rapp: #c3b8cf;
  --g-rapp-bg: #262130;
  --g-rapp-rule: #423a52;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--voice);
  font-size: var(--step-0);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  /* Frame labels run long ("Ukraine is corrupt, failing or illegitimate")
     and sub-domain names do not break at all. At 390px either one pushes a
     horizontal scrollbar across the whole page. */
  overflow-wrap: break-word;
}

.wrap {
  max-width: 62rem;
  margin: 0 auto;
  padding-inline: 20px;
  padding-block: 2.4rem 4rem;
}

/* ---- masthead ---- */
.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 1rem;
  padding-bottom: 0.9rem;
  border-bottom: 2px solid var(--ink);
}
h1 {
  font-family: var(--voice);
  font-size: var(--step-3);
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0;
  line-height: 1;
}
.masthead .sub {
  font-size: var(--step--1);
  color: var(--ink-soft);
  margin: 0;
  max-width: 34rem;
}
.stamp {
  margin-inline-start: auto;
  font-family: var(--data);
  font-size: 0.7rem;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  /* "table of 10 frames x 64 countries, built 2026-09-28" does not fit a
     390px screen, and nowrap pushed it 34px past the viewport edge, giving
     the whole page a horizontal scrollbar. It wraps below that width. */
  white-space: nowrap;
}
@media (max-width: 34rem) {
  .stamp { white-space: normal; margin-inline-start: 0; }
}

/* ---- controls ---- */
.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  /* Align on the inputs, not on the bottom of each field. Only the date
     field carries a hint line underneath, so flex-end pushed its input up by
     the height of that line and the two controls sat on different levels. */
  align-items: flex-start;
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--rule);
}
.field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  /* Reserve the hint's line on every field so a field with one and a field
     without still line up. min-block-size rather than padding: the hint is
     in normal flow now, so it has to be allowed to grow. */
  padding-bottom: 0.2rem;
}
.field label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  color: var(--ink-faint);
}
select, input[type="month"] {
  font-family: var(--voice);
  font-size: var(--step-0);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.48rem 0.6rem;
  min-width: 15rem;
  max-width: 100%;
}
input[type="month"] { min-width: 9rem; }
select:focus-visible, input:focus-visible {
  outline: 2px solid var(--rise);
  outline-offset: 1px;
}
/* The hint was absolutely positioned with nowrap, which was fine while it
   read "recorded, no effect on the ranking". Now that it reports which week
   is actually shown it runs long, and an out-of-flow nowrap line does not
   push anything: it slid under the coverage block beside it and the two
   overlapped. In flow, wrapping, it takes the room it needs. */
.field .hint {
  display: block;
  min-block-size: 1.15rem;
  max-inline-size: 22rem;
  font-size: 0.68rem;
  color: var(--ink-faint);
  font-style: italic;
  line-height: 1.35;
}
.coverage {
  font-family: var(--data);
  font-size: 0.72rem;
  color: var(--ink-soft);
  /* Clears the label row above, so the tag lines up with the inputs. */
  padding-top: 1.05rem;
  line-height: 1.7;
}
.coverage b { color: var(--ink); font-weight: 500; }

/* EU standing. Each group gets its own quiet hue — the rust accent stays
   reserved for the prediction itself, so a tag never competes with it. */
.tag {
  display: inline-block;
  font-family: var(--voice);
  font-size: 0.64rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  padding: 0.14rem 0.45rem;
  border-radius: 2px;
  border: 1px solid;
}
.tag-member {
  color: var(--g-member); border-color: var(--g-member-rule);
  background: var(--g-member-bg);
}
.tag-candidate {
  color: var(--g-cand); border-color: var(--g-cand-rule);
  background: var(--g-cand-bg);
}
.tag-rapprochement, .tag-institution {
  color: var(--g-rapp); border-color: var(--g-rapp-rule);
  background: var(--g-rapp-bg);
}
.tag-third, .tag-unclassified {
  color: var(--ink-soft); border-color: var(--rule);
  background: var(--rule-soft);
}
.group-note {
  font-size: var(--step--1);
  color: var(--ink-soft);
  margin: 0.9rem 0 0;
  max-width: 44rem;
  font-style: italic;
}

/* ---- notices ---- */
.notice {
  display: flex;
  gap: 0.7rem;
  background: var(--caution-bg);
  border: 1px solid var(--caution-rule);
  border-left: 3px solid var(--caution);
  border-radius: 2px;
  padding: 0.75rem 0.9rem;
  font-size: var(--step--1);
  color: var(--ink);
  margin-top: 1.5rem;
}
.notice .mark {
  font-family: var(--data);
  font-weight: 500;
  color: var(--caution);
  flex-shrink: 0;
}
.notice p { margin: 0; }
.notice p + p { margin-top: 0.35rem; color: var(--ink-soft); }
/* A qualification, not a warning: same shape, neutral weight. */
.notice-soft {
  background: var(--rule-soft);
  border-color: var(--rule);
  border-left-color: var(--stone);
}
.notice-soft .mark { color: var(--stone); }

/* ---- section heads ---- */
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.8rem;
  margin: 2.4rem 0 0.2rem;
}
.section-head h2 {
  font-family: var(--voice);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin: 0;
  color: var(--ink);
}
.section-head .note {
  font-size: 0.72rem;
  color: var(--ink-faint);
  margin: 0;
}
.rule-heavy { border-bottom: 1px solid var(--ink); margin-bottom: 0.2rem; }

/* ---- ranking ---- */
ol.ranking { list-style: none; margin: 0; padding: 0; }
ol.ranking > li {
  display: grid;
  grid-template-columns: 2.1rem 1fr auto;
  gap: 0.15rem 0.85rem;
  padding: 0.95rem 0;
  border-bottom: 1px solid var(--rule-soft);
  align-items: baseline;
}
.rank {
  font-family: var(--data);
  font-size: 0.82rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.claim {
  font-family: var(--quote);
  font-size: var(--step-1);
  line-height: 1.35;
  color: var(--ink);
  text-wrap: balance;
}
.prob {
  font-family: var(--data);
  font-size: var(--step-1);
  font-variant-numeric: tabular-nums;
  color: var(--rise);
  font-weight: 500;
  white-space: nowrap;
}
.evidence {
  grid-column: 2 / -1;
  font-size: var(--step--1);
  color: var(--ink-soft);
}
.evidence .delta {
  font-family: var(--data);
  font-size: 0.72rem;
  color: var(--ink-faint);
}
/* The rise bar: the prediction against this outlet's own habitual share,
   so "rises above its usual level" is visible instead of asserted. */
.gauge {
  grid-column: 2 / -1;
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  margin-top: 0.4rem;
  max-width: 30rem;
}
.gauge .track {
  position: relative;
  height: 7px;
  background: var(--stone-soft);
  border-radius: 1px;
}
.gauge .fill {
  position: absolute;
  inset-block: 0;
  left: 0;
  background: var(--rise);
  border-radius: 1px;
}
.gauge .usual {
  position: absolute;
  inset-block: -2px;
  width: 2px;
  background: var(--stone);
}
.gauge .legend {
  font-family: var(--data);
  font-size: 0.66rem;
  color: var(--ink-faint);
  display: flex;
  gap: 0.9rem;
}

/* ---- background block ---- */
.bg-list { display: flex; flex-direction: column; gap: 0.55rem; margin-top: 0.9rem; }
.bg-row {
  display: grid;
  grid-template-columns: 3.4rem 1fr;
  gap: 0.8rem;
  align-items: center;
}
.bg-row .pct {
  font-family: var(--data);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: right;
}
.bg-row .bar-wrap { display: flex; flex-direction: column; gap: 0.2rem; }
.bg-row .bar {
  height: 9px;
  background: var(--stone);
  border-radius: 1px;
  min-width: 1px;
}
.bg-row .name { font-size: var(--step--1); color: var(--ink-soft); }

/* A week carrying a handful of articles can show one frame at 40% on three
   documents. Marked rather than hidden: an analyst who asked for a specific
   date needs to be told the answer is thin, not shown nothing. */
.thin { color: var(--caution); }

/* The observed section answers about the past, the ranking about what is to
   come. The left rule is what keeps a reader from carrying one reading into
   the other. */
#observed { border-inline-start: 2px solid var(--rule); padding-inline-start: 0.9rem; }

/* ---- worth panel ---- */
.worth {
  margin-top: 2.6rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--card);
  padding: 1.1rem 1.2rem;
}
.worth h2 {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin: 0 0 0.7rem;
  font-weight: 600;
}
.tablewrap { overflow-x: auto; }
table { border-collapse: collapse; font-size: var(--step--1); width: 100%; }
th, td {
  text-align: right;
  padding: 0.3rem 0.7rem 0.3rem 0;
  font-variant-numeric: tabular-nums;
  font-family: var(--data);
  white-space: nowrap;
}
th:first-child, td:first-child {
  text-align: left;
  font-family: var(--voice);
}
thead th {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  font-weight: 600;
  border-bottom: 1px solid var(--rule);
}
tbody tr.lead td { color: var(--rise); }
.worth p {
  font-size: var(--step--1);
  color: var(--ink-soft);
  margin: 0.8rem 0 0;
  max-width: 48rem;
}
.worth p b { color: var(--ink); font-weight: 500; }

footer {
  margin-top: 2.4rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-size: 0.72rem;
  color: var(--ink-faint);
}
footer code {
  font-family: var(--data);
  color: var(--ink-soft);
}

/* Attribution, set apart from the technical note above it by a thin rule
   rather than a block of its own: the page is built from rules, not cards. */
.made {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.9rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--rule-soft);
  font-size: 0.72rem;
  color: var(--ink-soft);
}
.made .flag {
  /* The hairline keeps the white field legible on paper that is also
     near-white; without it the flag reads as two floating blue bars. */
  border: 1px solid var(--rule);
  border-radius: 1px;
  flex: none;
}
.made a {
  color: var(--ink);
  text-decoration-color: var(--rule);
  text-underline-offset: 2px;
}
.made a:hover { text-decoration-color: var(--rise); }

@media (max-width: 34rem) {
  ol.ranking > li { grid-template-columns: 1.6rem 1fr; }
  .prob { grid-column: 2; grid-row: 1; justify-self: end; }
  .claim { grid-column: 2; }
  select { min-width: 100%; }
  .field { width: 100%; }
}

@media (prefers-reduced-motion: no-preference) {
  .gauge .fill { transition: width 0.25s ease; }
  .bg-row .bar { transition: width 0.25s ease; }
}
