/* =============================================================================
   The application's whole design system. Hand-written, framework-free, no build
   step: Bootstrap was removed early because a CSS framework here is 200 kB of
   class names nothing uses, and that decision stands. What follows is design,
   not a framework -- a screenful of tokens and then the six or seven objects the
   product actually has.

   It is deliberately mostly ELEMENT selectors. Fragments arrive after first
   paint (a page of match rows swapped into a table body, a typeahead list
   swapped into a div), and an element selector styles whatever is put in front
   of it, whereas a class contract has to be remembered by every partial that
   ever renders a row. Where a class is used it names a thing, not a look.

   Colour comes from the company's design system, unchanged: the same paper /
   surface / ink / line ramp, the same petrol-teal accent, the same semantic
   ok / warn / crit, the same three-state dark mode. A product screen is not a
   landing page, so the metrics differ -- smaller base size, tighter radius, a
   shadow you can barely see -- but nothing here invents a colour.
   ============================================================================= */

/* -------------------------------------------------------------- self-hosted type
   Not a font CDN. This application renders a client's tenant data and the product
   promises EU-only sub-processors; a stylesheet link to a foreign CDN is a
   sub-processor that hands it every visitor's IP address. See wwwroot/fonts/README.

   Three weights across two families, and no third family for code -- the handful of
   genuine code strings (a recovery code, a request id) use whatever monospace the
   reader's system already has, which costs nothing and is the one place a local
   face is as good as a downloaded one. */
@font-face {
  font-family: "Newsreader";
  font-style: normal; font-weight: 500; font-display: swap;
  src: url("../fonts/newsreader-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Newsreader";
  font-style: normal; font-weight: 500; font-display: swap;
  src: url("../fonts/newsreader-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/plexsans-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/plexsans-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/plexsans-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/plexsans-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ------------------------------------------------------------------------ tokens */
:root {
  --paper:#F6F7F9; --surface:#FFFFFF; --surface-2:#FBFCFD;
  --ink:#16202E; --ink-2:#46536A; --muted:#67738A;
  --line:#E3E7ED; --line-strong:#D2D8E1;
  --accent:#0F5E7A; --accent-2:#0B4A61; --accent-tint:#E7F1F4;
  --ok:#197A56; --warn:#8A5300; --crit:#B4322B;
  --ok-bg:#E7F3ED; --warn-bg:#FAF0DE; --crit-bg:#F8E9E7; --accent-bg:#E7F1F4;

  /* What goes ON a filled accent or crit button. White is right on the light theme's
     deep petrol and deep red; on the dark theme the same two roles are a pale cyan and a
     pale salmon, and white on those is about 2.4:1 -- unreadable, and the commonest way a
     dark mode fails an audit while looking fine in a screenshot. */
  --on-fill:#FFFFFF;

  /* Flatter and tighter than the marketing sheet on purpose. A landing page can
     afford a 32-pixel shadow under one card; a screen with fifty rules on it turns
     the same shadow into fog. */
  --shadow:0 1px 2px rgba(20,32,46,.05);
  --radius:5px;

  --serif:"Newsreader",Georgia,"Times New Roman",serif;
  --sans:"Plex Sans",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;

  /* One rhythm, used everywhere. Vertical space between things is always one of
     these; nothing gets a hand-picked margin. */
  --s1:4px; --s2:8px; --s3:12px; --s4:18px; --s5:28px; --s6:44px; --s7:68px;
}
@media (prefers-color-scheme:dark) {
  :root:not([data-theme="light"]) {
    --paper:#0E141C; --surface:#131C27; --surface-2:#0F1822;
    --ink:#E8EDF4; --ink-2:#AEBAC9; --muted:#93A1B2;
    --line:#26313F; --line-strong:#33404F;
    --accent:#3EA7C6; --accent-2:#5FBBD6; --accent-tint:#132A33;
    --ok:#54BF93; --warn:#E0A64B; --crit:#E4796F;
    --ok-bg:#12271F; --warn-bg:#2A2214; --crit-bg:#2C1817; --accent-bg:#122831;
    --on-fill:#08121A;
    --shadow:0 1px 2px rgba(0,0,0,.35);
  }
}
:root[data-theme="dark"] {
  --paper:#0E141C; --surface:#131C27; --surface-2:#0F1822;
  --ink:#E8EDF4; --ink-2:#AEBAC9; --muted:#93A1B2;
  --line:#26313F; --line-strong:#33404F;
  --accent:#3EA7C6; --accent-2:#5FBBD6; --accent-tint:#132A33;
  --ok:#54BF93; --warn:#E0A64B; --crit:#E4796F;
  --ok-bg:#12271F; --warn-bg:#2A2214; --crit-bg:#2C1817; --accent-bg:#122831;
  --on-fill:#08121A;
  --shadow:0 1px 2px rgba(0,0,0,.35);
}

/* ------------------------------------------------------------------------- base */
*, *::before, *::after { box-sizing:border-box }

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

body {
  margin:0;
  /* The chrome footer sits on the bottom of the window on a short page and after the
     content on a long one -- an empty strip of paper below a rule reads as a broken
     page. */
  min-height:100vh; display:flex; flex-direction:column;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--sans);
  font-size:15px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
}

/* Headings are the serif, at one weight. Legislative titles are the serif too, and
   that is the whole typographic idea on these screens: the serif is text that came
   from the source register or names one of its documents, the sans is the interface
   talking. A reader can tell sourced material from our own words without being
   told which is which. */
h1, h2, h3 {
  font-family:var(--serif); font-weight:500; color:var(--ink);
  letter-spacing:-.01em; line-height:1.2; margin:0; text-wrap:balance;
}
/* A measure, not just a size. A dossier's own title is the whole untruncated string --
   nine lines of it on the worst record in the corpus -- and at full container width that
   is eighty characters a line, which nobody reads twice. 30em holds it near sixty. */
h1 { font-size:29px; max-width:30em }
h2 { font-size:22px; max-width:34em }
h3 { font-size:18px; max-width:40em }
h4 { font-family:var(--sans); font-weight:600; font-size:15px; margin:0 }

p { margin:0 }
main p { max-width:76ch }

a { color:var(--accent); text-decoration:none }
a:hover { text-decoration:underline; text-underline-offset:2px }

strong { font-weight:600 }
code { font-family:var(--mono); font-size:.92em }
::selection { background:var(--accent); color:var(--on-fill) }

/* One focus treatment for the whole application, on the element rather than on a
   list of components, so nothing new can arrive without it. */
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:3px }

/* --------------------------------------------------------------------- the shell */
/* Inline padding only, as longhand. <main> is itself a .shell and sets its own BLOCK
   padding; a shorthand here would win on specificity (a class beats an element) and
   silently zero it, which is exactly how a page ends up with its heading tucked under
   the header rule. */
/* width:100% is not redundant. <main> is a flex item of <body>, and an auto margin on
   the cross axis of a flex container suppresses the stretch -- the element then sizes to
   its content and centres, so a form-only page came out two-thirds width while a table
   page looked almost right. An explicit basis, clamped by max-width, restores it. */
.shell { width:100%; max-width:1180px; margin-inline:auto; padding-inline:var(--s5) }
@media (max-width:640px) { .shell { padding-inline:var(--s4) } }

body > header { border-bottom:1px solid var(--line); background:var(--surface) }
.topbar { display:flex; align-items:center; gap:var(--s5); height:58px }

/* The lockup stands on one line. The mark's waterline is a ground line, so the
   wordmark sits ON it: baseline alignment puts the drawing's bottom edge on the
   text baseline, and the shift then drops the empty strip below the waterline out
   of the way. 13.125% is (32 - 27.8) / 32 -- the gap between the waterline and the
   bottom of the 32-unit viewBox as a share of the mark's own height -- so it holds
   at any size the mark is ever set at. The island still dips below the line, which
   is right: it is below water, the way a descender is below the baseline. */
.brand {
  display:flex; align-items:baseline; gap:9px;
  font-family:var(--serif); font-size:20px; font-weight:500;
  color:var(--ink); letter-spacing:-.015em; white-space:nowrap;
}
.brand:hover { text-decoration:none; color:var(--accent) }
.brand .mk { width:24px; height:24px; flex:none; transform:translateY(13.125%) }

.sitenav { display:flex; align-items:center; gap:var(--s5); margin-left:var(--s3) }
.sitenav a {
  color:var(--ink-2); font-size:14px; font-weight:500; padding:2px 0;
  border-bottom:2px solid transparent;
}
.sitenav a:hover { color:var(--accent); text-decoration:none }
.sitenav a[aria-current="page"] { color:var(--ink); border-bottom-color:var(--accent) }

.topbar .who { margin-left:auto; display:flex; align-items:center; gap:var(--s4) }
.topbar .who .signed {
  font-size:13px; color:var(--ink-2); max-width:28ch;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
@media (max-width:720px) { .topbar .who .signed { display:none } }

.mode-switch {
  background:transparent; border:1px solid var(--line-strong); color:var(--ink-2);
  width:32px; height:32px; border-radius:var(--radius); cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center; padding:0;
}
.mode-switch:hover { border-color:var(--accent); color:var(--accent) }
.mode-switch svg { width:16px; height:16px }
.sun { display:none }
[data-theme="dark"] .sun { display:block } [data-theme="dark"] .moon { display:none }
@media (prefers-color-scheme:dark) {
  :root:not([data-theme="light"]) .sun { display:block }
  :root:not([data-theme="light"]) .moon { display:none }
}

main { display:block; padding-block:var(--s6) var(--s7) }
main > * + * { margin-top:var(--s4) }
main > h2 { margin-top:var(--s5) }

/* The page's own title block: back link, heading, one line of orientation. */
.pagehead { display:flex; flex-direction:column; gap:var(--s2) }
.pagehead .back {
  font-size:13.5px; color:var(--ink-2); font-weight:500;
  display:inline-flex; align-items:center; gap:8px; align-self:flex-start;
}
.pagehead .back::before {
  content:""; flex:none; width:6px; height:6px; border:1.5px solid currentColor;
  border-width:1.5px 0 0 1.5px; transform:rotate(-45deg); margin-left:1px;
}
.pagehead .back:hover { color:var(--accent) }
.pagehead .sub { color:var(--ink-2); font-size:15px; max-width:70ch }

/* ----------------------------------------------------------------------- footers
   Two of them, and they are not the same thing. The company line is chrome. The
   source attribution is a term of the CC BY 4.0 licence the data is used under --
   not a courtesy, and it does not get shrunk into the background: 13.5px, --ink-2
   rather than --muted, links in the accent, directly under the content it applies
   to rather than below the page furniture. */
main footer {
  border-top:1px solid var(--line);
  margin-top:var(--s6);
  padding-top:var(--s4);
  font-size:13.5px;
  color:var(--ink-2);
  line-height:1.6;
}
main footer p { max-width:84ch }
body > footer {
  margin-top:auto;
  border-top:1px solid var(--line); background:var(--surface);
  padding-block:var(--s4); font-size:13px; color:var(--ink-2);
}

/* ---------------------------------------------------------------------- controls */
button, .btn {
  font-family:var(--sans); font-size:14px; font-weight:600; line-height:1.2;
  display:inline-flex; align-items:center; justify-content:center; gap:.5em;
  padding:8px 14px; border-radius:var(--radius); cursor:pointer;
  border:1px solid var(--line-strong); background:var(--surface); color:var(--ink);
  transition:border-color .12s ease, background-color .12s ease, color .12s ease;
  white-space:nowrap;
}
button:hover, .btn:hover { border-color:var(--accent); color:var(--accent); text-decoration:none }

/* Filled is opt-in, not "whatever submits a form". Half the submit buttons in this
   product are destructive-ish or secondary -- archiving a topic, dismissing a match --
   and the one filled control on a screen should be the one the reader came to press. */
.btn--go, .btn--go:disabled {
  background:var(--accent); border-color:var(--accent); color:var(--on-fill);
}
.btn--go:hover { background:var(--accent-2); border-color:var(--accent-2); color:var(--on-fill) }
button:disabled { opacity:.5; cursor:default }

/* A button that is really a link: the "show more" frontier, the archive action. */
.btn--quiet {
  background:transparent; border-color:transparent; color:var(--accent);
  padding:6px 0; font-weight:600;
}
.btn--quiet:hover {
  background:transparent; border-color:transparent;
  text-decoration:underline; text-underline-offset:3px;
}

label { font-size:14px; font-weight:600; color:var(--ink) }

input:not([type="checkbox"]):not([type="radio"]), select, textarea {
  font-family:var(--sans); font-size:15px; color:var(--ink);
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--radius); padding:9px 11px; width:100%; max-width:36rem;
}
input:not([type="checkbox"]):not([type="radio"]):focus, select:focus, textarea:focus {
  border-color:var(--accent); outline:2px solid var(--accent); outline-offset:1px;
}
input::placeholder { color:var(--muted) }
input[type="checkbox"], input[type="radio"] { accent-color:var(--accent); margin-right:.5em }

fieldset {
  border:1px solid var(--line); border-radius:var(--radius);
  background:var(--surface); padding:var(--s4); margin:0;
}
legend {
  font-family:var(--sans); font-size:13.5px; font-weight:600; color:var(--ink);
  padding:0 var(--s2); max-width:72ch; line-height:1.45;
}
fieldset > * + * { margin-top:var(--s3) }

/* A form is a column with one rhythm, not a stack of paragraphs with browser
   margins. */
form { margin:0 }
main form > * + * { margin-top:var(--s4) }
.field { display:flex; flex-direction:column; gap:6px; align-items:flex-start }
/* Guidance, wherever it sits: under a field, under a legend, beside a grandfathered
   option. Same size and colour every time, so a reader learns to recognise it. */
.hint { font-size:13px; color:var(--ink-2); font-weight:400; max-width:76ch; display:block }

/* Validation summary. Empty on most renders, so it must collapse to nothing rather
   than leave a hole where a border used to be. */
.validation-summary-errors {
  border:1px solid var(--crit); border-left-width:3px; background:var(--crit-bg);
  color:var(--crit); border-radius:var(--radius); padding:var(--s3) var(--s4);
  font-size:14px; font-weight:500;
}
.validation-summary-errors ul { margin:0; padding-left:1.1em }
.validation-summary-valid { display:none }
.field-validation-error { color:var(--crit); font-size:13px; font-weight:500 }

/* ------------------------------------------------------------------------ tables
   The register. Every list in this product is a register of documents, so there is
   one table treatment and no second one: hairline rules, no fill, no zebra, and
   enough vertical padding that a title wrapping to six lines still reads as one
   entry rather than merging into its neighbour.

   table-layout:fixed is load-bearing. Auto layout lets a 700-character title
   negotiate the column widths, which on real data squeezes the date and action
   columns to nothing and re-flows the whole table every time a page of rows is
   swapped in. Fixed widths mean rows arriving after load land in the same grid the
   first page did. */
table {
  width:100%; border-collapse:collapse; table-layout:fixed;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius);
}
thead th {
  font-family:var(--sans); font-size:12px; font-weight:600; color:var(--ink-2);
  letter-spacing:.03em; text-align:left; padding:9px var(--s4);
  border-bottom:1px solid var(--line-strong); background:var(--surface-2);
  white-space:nowrap;
}
tbody td {
  padding:13px var(--s4); border-top:1px solid var(--line);
  vertical-align:top; color:var(--ink-2); font-size:14px;
}
tbody tr:first-child td { border-top:0 }
tbody tr:hover td { background:var(--surface-2) }
td.when, th.when {
  font-variant-numeric:tabular-nums; white-space:nowrap; width:120px; color:var(--ink-2);
}
td.num, th.num { font-variant-numeric:tabular-nums; white-space:nowrap; width:90px }
/* The action column comes in three shapes.

   .pair is the verdict: stacked, equal width, never side by side. Two buttons of unequal
   length in a row read as one button and an afterthought, and at this width "Not
   relevant" would have to be abbreviated into something a reader has to decode. Stacked,
   they are two peers and each is a full-width target.

   .inline is a row of secondary actions -- edit, archive -- which are not a choice
   between peers and should not take a line each.

   .narrow is not a control at all: it is one short value (a stage) that happens to sit
   at the end of the row. */
td.act, th.act { width:158px }
td.act.pair { display:flex; flex-direction:column; gap:6px }
td.act.pair > button { width:100% }
td.act.inline, th.act.inline { width:186px }
td.act.inline { display:flex; align-items:baseline; gap:16px; flex-wrap:nowrap }
td.act.inline form { margin:0 }
td.act.narrow, th.act.narrow { width:172px }

/* --------------------------------------------------------------------- the entry
   One matched bill. The title is the entry; everything else annotates it.

   Set in the serif at reading size, not in the sans at label size, because these
   are not labels -- the median is 196 characters of French legislative prose and
   the reader has to actually read one to decide. */
.entry .title {
  font-family:var(--serif); font-weight:500; font-size:16px; line-height:1.4;
  color:var(--ink);
  overflow-wrap:break-word; hyphens:auto;

  /* No truncation at a short fixed length, ever. The first sixty characters of a
     French amending title are boilerplate -- "Projet de loi portant modification de
     la loi modifiee du ..." -- so a short clip deletes exactly the part that
     identifies the bill and leaves twenty-five rows reading identically.

     Six lines is about 420 characters at this measure: past the 196-character
     median, past most of the 701-character 95th percentile, and it clips only the
     tail enumeration of amended laws, which is not what a triage decision turns on.
     The browser draws the ellipsis itself, and only when it really clipped. The
     untouched title is the heading of the dossier page, one click away, and the
     whole block is that link. */
  display:-webkit-box; -webkit-line-clamp:6; -webkit-box-orient:vertical;
  overflow:hidden;
}
.entry .title:hover { text-decoration:underline; text-underline-offset:3px }

/* Why this row is here, under the claim it supports rather than in a column of its
   own. It is a sentence of about a hundred characters ("keyword 'blanchiment' and
   sponsoring ministry Ministere des Finances"); a quarter-width column turns that
   into six words a line. */
.entry .evidence {
  display:flex; gap:8px; align-items:baseline;
  margin-top:7px; font-size:13px; line-height:1.45; max-width:80ch;
}
/* The tier marker: three grades of evidence as three weights of one shape.
   Filled square -- the topic's own directive was transposed, which is proof.
   Hollow square -- two independent signals agreed.
   A rule -- one signal only, which is a lead and not a finding. */
.entry .evidence::before {
  content:""; flex:none; width:8px; height:8px; margin-top:.42em; border-radius:2px;
  border:1.5px solid currentColor;
}
.ev--strong { color:var(--accent) }
.ev--strong::before { background:currentColor }
.ev--good { color:var(--ok) }
.ev--thin { color:var(--ink-2) }
.ev--weak { color:var(--muted) }
.ev--thin::before, .ev--weak::before {
  height:0; width:9px; border-width:0 0 1.5px; border-radius:0; margin-top:.62em;
}

/* ---------------------------------------------------------------- the rationale
   "What the bill says", one row at a time. The control is a quiet button rather
   than a link because it fetches rather than navigates, and it sits under the
   evidence line it elaborates. Nothing here is styled inline: these rows arrive
   after first paint and have to land looking like the ones the page rendered. */
.entry .disclose { margin-top:4px; font-size:13px; padding:2px 0 }
.entry .why:empty { display:none }
.why-panel {
  margin-top:var(--s3); padding:var(--s3) var(--s4);
  border-left:2px solid var(--line-strong); background:var(--surface-2);
  border-radius:0 var(--radius) var(--radius) 0;
  font-size:13.5px; line-height:1.5; color:var(--ink-2); max-width:80ch;
}
.why-panel h4 {
  font-family:var(--sans); font-size:12px; font-weight:600; letter-spacing:.04em;
  text-transform:uppercase; color:var(--muted); margin-top:var(--s3);
}
.why-purpose { color:var(--ink) }
.why-list { margin-top:6px; padding-left:1.1em; list-style:disc }
.why-list li { margin-top:3px }
.why-evidence { margin-top:6px; list-style:none; padding:0 }
.why-evidence > li { margin-top:var(--s3) }
/* The claim, then the words. The subject leads because that is what the row was
   decided on; the confidence and the code follow it as annotations rather than
   as competing headings. */
.why-evidence .cited { display:flex; gap:8px; flex-wrap:wrap; align-items:baseline }
.why-evidence .subject { font-weight:600; color:var(--ink) }
.why-evidence .conf, .why-evidence .code { font-size:12px; color:var(--muted) }
/* Set in the serif, because it is the bill's own French and the reader is meant to
   read it rather than scan it. */
.why-panel blockquote {
  font-family:var(--serif); font-size:14.5px; line-height:1.5; color:var(--ink);
  margin-top:5px; padding-left:var(--s3); border-left:2px solid var(--accent);
}
.why-panel .cite { margin-top:4px; font-size:12px; color:var(--muted) }
/* A passage we could not find in our own copy of the document. Deliberately NOT
   styled like the quotes above -- it is the absence of evidence, and it must not
   read as a quieter kind of it. */
.why-panel .unlocated { margin-top:5px; font-size:12.5px; font-style:italic; color:var(--muted) }

/* The row a review verdict swaps itself for. Quiet, not celebratory: it says the
   row moved, and that the count in the band heading is now one out of date. */
.verdict td {
  background:var(--surface-2); color:var(--ink-2); font-size:13.5px; font-style:italic;
}

/* The frontier row that fetches the next page. It lives inside the table body
   because its own response replaces it, so it has to look like part of the
   register rather than like something under it. */
.more td { padding:var(--s3) var(--s4); background:var(--surface-2) }

/* --------------------------------------------------------------------- the bands
   Matched / needs review / ministry hints are not three sections of equal weight;
   they are three grades of certainty, and the page has to say so before a reader
   has clicked anything. The count is the number that gets reported upward, so it
   is the largest thing in the heading. */
.band { margin-top:var(--s6) }
.band-head { display:flex; align-items:baseline; gap:var(--s3); flex-wrap:wrap }
.band-head h2 { font-size:21px }
.band-head .count {
  font-family:var(--serif); font-size:30px; line-height:1; color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.band-head .of { font-size:13px; color:var(--ink-2) }
.band > p { margin-top:var(--s2); color:var(--ink-2); font-size:14px; max-width:78ch }
.band > table, .band > details { margin-top:var(--s4) }
/* An empty list says what to do next rather than reporting a zero. */
.empty {
  border:1px dashed var(--line-strong); border-radius:var(--radius);
  padding:var(--s4); color:var(--ink-2); font-size:14px; background:var(--surface-2);
}
.band .empty { margin-top:var(--s4) }

/* The third band, closed. It is 96-97% of the review queue and it is a filter
   rather than evidence, so it is one click away instead of in the way -- and one
   click away rather than gone, because on the 46% of the corpus whose titles say
   only what they amend it is the only signal there is. */
details {
  border:1px solid var(--line); border-radius:var(--radius); background:var(--surface);
}
details > summary {
  cursor:pointer; padding:var(--s3) var(--s4); font-weight:600; font-size:14.5px;
  color:var(--ink); list-style:none; display:flex; align-items:center; gap:10px;
}
details > summary::-webkit-details-marker { display:none }
details > summary::before {
  content:""; flex:none; width:7px; height:7px; border:1.5px solid var(--ink-2);
  border-width:1.5px 1.5px 0 0; transform:rotate(45deg); margin-left:2px;
}
details[open] > summary::before { transform:rotate(135deg); margin-top:-3px }
details > summary:hover { color:var(--accent) }
details > summary:hover::before { border-color:var(--accent) }
details > summary .of { font-weight:400; color:var(--ink-2); font-size:13px }
details > p, details > .empty {
  margin:0 var(--s4) var(--s4); font-size:14px; color:var(--ink-2); max-width:78ch;
}
details > table { margin:0; border:0; border-top:1px solid var(--line); border-radius:0 }
details > table thead th:first-child { padding-left:var(--s4) }

/* -------------------------------------------------------------------- the notice
   A card the page uses to say something about itself: an archived topic, a profile
   carrying options that are no longer offered. Informational, so it borrows the
   accent rather than a warning colour. */
.notice {
  border:1px solid var(--line); border-left:3px solid var(--accent);
  background:var(--surface); border-radius:var(--radius);
  padding:var(--s4); font-size:14px; color:var(--ink-2);
}
.notice p { max-width:80ch }
.notice ul { margin:var(--s2) 0 0; padding-left:1.2em }
.notice li { margin:3px 0 }
.notice em { color:var(--warn); font-style:normal; font-weight:600 }

/* --------------------------------------------------------------------- the alarm
   Loud on purpose, and the only saturated thing on any screen it appears on. While
   one of these stands the fetch job sends nothing at all, and this banner is the
   only place the halt can be lifted -- so it gets the crit colour, a heavy left
   rule, and the acknowledge control as a filled button rather than a link. */
.alarm {
  border:1px solid var(--crit); border-left-width:4px; background:var(--crit-bg);
  border-radius:var(--radius); padding:var(--s4) var(--s5);
  color:var(--ink); box-shadow:var(--shadow);
}
.alarm > strong {
  display:flex; align-items:center; gap:9px;
  font-family:var(--sans); font-size:15px; font-weight:600; color:var(--crit);
}
.alarm > strong::before {
  content:""; flex:none; width:9px; height:9px; border-radius:50%; background:var(--crit);
}
.alarm p {
  margin:var(--s3) 0 0; font-size:13.5px; color:var(--ink);
  font-variant-numeric:tabular-nums; max-width:90ch;
}
.alarm form { margin-top:var(--s3) }
.alarm button {
  background:var(--crit); border-color:var(--crit); color:var(--on-fill);
}
.alarm button:hover {
  background:var(--crit); border-color:var(--crit); color:var(--on-fill); filter:brightness(.9);
}

/* -------------------------------------------------------------------- typeahead
   The three swap targets on the topic editor. They are empty on first paint and
   filled from the server afterwards, so everything here has to work on injected
   content: element rules under one wrapper class, not classes the partials would
   have to remember to emit. */
.suggest { margin-top:var(--s2) }
.suggest:empty { display:none }
.suggest ul {
  list-style:none; margin:0; padding:var(--s2);
  border:1px solid var(--line); border-radius:var(--radius);
  background:var(--surface-2); max-height:15rem; overflow-y:auto;
  display:flex; flex-direction:column; gap:2px;
}
.suggest li { font-size:14px; color:var(--ink-2); padding:3px 6px; border-radius:3px }
.suggest li:hover { background:var(--accent-tint) }
.suggest label { font-weight:400; font-size:14px; color:var(--ink-2); cursor:pointer }
.suggest > p {
  border:1px solid var(--warn); border-left-width:3px; background:var(--warn-bg);
  border-radius:var(--radius); padding:var(--s3); font-size:13.5px; color:var(--ink);
  display:flex; flex-direction:column; gap:var(--s1);
}

/* The directives already on the profile: a checkbox list, not a table. */
.picked { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:var(--s2) }
.picked li { font-size:14px; color:var(--ink-2) }
.picked label { font-weight:400; font-size:14px; color:var(--ink-2) }
.picked em { color:var(--warn); font-style:normal; font-weight:600 }

/* A column of checkboxes wide enough to read, but not one per line at full width. */
.choices {
  display:grid; grid-template-columns:repeat(auto-fill,minmax(20rem,1fr));
  gap:var(--s2) var(--s4);
}
.choices label {
  font-weight:400; font-size:14px; color:var(--ink-2);
  display:flex; align-items:flex-start;
}
.choices code, .picked code { font-size:12.5px; overflow-wrap:anywhere }
.choices label:hover { color:var(--ink) }

/* ----------------------------------------------------------------------- the gate
   Sign in, verify, accept an invite, reset a password. A narrow card centred on the
   paper, with the mark above it -- these are the only screens in the product with
   no navigation, because there is nowhere to navigate to yet. */
.gate { max-width:26rem; margin:0 auto; padding:var(--s6) 0 }
.gate > * + * { margin-top:var(--s4) }
.gate .card {
  background:var(--surface); border:1px solid var(--line);
  border-radius:8px; padding:var(--s5); box-shadow:var(--shadow);
}
.gate .card > * + * { margin-top:var(--s4) }
.gate form > * + * { margin-top:var(--s4) }
.gate h1 { font-size:24px }
.gate .field { width:100% }
.gate input:not([type="checkbox"]) { max-width:none }
.gate button[type="submit"] { width:100% }
.gate .lede { color:var(--ink-2); font-size:14.5px }
.gate .alt {
  border-top:1px solid var(--line); padding-top:var(--s4);
  font-size:13.5px; color:var(--ink-2);
}
.gate .alt > * + * { margin-top:var(--s3) }
.gate .choice { width:100% }
.gate .choice button { width:100%; justify-content:space-between; font-weight:500 }
.gate .choice button .role { color:var(--ink-2); font-weight:400; font-size:13px }

/* Recovery codes: the one place a monospace face earns its keep, because these get
   transcribed by hand and 0/O and 1/l have to be told apart. */
.codes {
  list-style:none; margin:0; padding:var(--s4);
  background:var(--surface-2); border:1px solid var(--line); border-radius:var(--radius);
  display:grid; grid-template-columns:repeat(auto-fill,minmax(11rem,1fr)); gap:var(--s2);
  font-family:var(--mono); font-size:14px; color:var(--ink);
}

/* ---------------------------------------------------------------------- timeline
   A dossier's phases. An ordered list is the right element -- these are in order and
   the order is the point -- so it stays one, with the marker replaced by a rule
   running between the entries. */
/* The documents a dossier holds. A plain list, deliberately not a timeline: these have no
   order in time, only an order of usefulness, and borrowing the timeline's rail would imply
   a sequence the register does not publish. */
.docs { list-style:none; margin:0 0 var(--s5); padding:0 }
.docs li { padding:var(--s2) 0; border-bottom:1px solid var(--line) }
.docs li:last-child { border-bottom:0 }
.docs a { font-weight:500 }
.docs .meta { margin-left:var(--s2) }

/* Archived topics, collapsed. The summary carries the count so the section says whether it
   is worth opening before it is opened. */
.archived { margin-top:var(--s5); border-top:1px solid var(--line); padding-top:var(--s3) }
.archived > summary { cursor:pointer; font-weight:500 }
.archived > summary .meta { margin-left:var(--s2) }
.archived table { margin-top:var(--s3) }

.timeline { list-style:none; margin:0; padding:0 0 0 var(--s4); position:relative }
.timeline::before {
  content:""; position:absolute; left:3px; top:8px; bottom:8px;
  width:1px; background:var(--line-strong);
}
.timeline li { position:relative; padding:0 0 var(--s4) var(--s2) }
.timeline li:last-child { padding-bottom:0 }
.timeline li::before {
  content:""; position:absolute; left:calc(-1 * var(--s4) + 1px); top:.45em;
  width:7px; height:7px; border-radius:50%;
  background:var(--paper); border:1.5px solid var(--accent);
}
.timeline strong {
  font-family:var(--serif); font-weight:500; font-size:16px; color:var(--ink);
}
/* The same clip the register applies to a title, at half the depth.

   An act page is the one screen that lists up to sixty bills at once, and a
   Luxembourg amending title carries its whole enumeration of amended laws in the
   same sentence: the 2004 AML law's own title runs past 1,300 characters. Six lines
   each, sixty times over, is a page nobody scans -- and scanning is the entire job
   of this list, since the reader arrived asking which of these moved.

   Three lines still clears the 196-character median outright. What it clips is the
   ", 2. la loi modifiee du ..." tail, which is exactly the part the act page already
   knows: the reader is ON the law those tails name. */
.timeline .title {
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical;
  overflow:hidden;
}
.timeline .meta {
  display:block; margin-top:2px;
  color:var(--ink-2); font-size:13px; font-variant-numeric:tabular-nums;
}

/* ----------------------------------------------------------------------- narrow */
@media (max-width:900px) {
  table { table-layout:auto }
  td.when, th.when, td.act, th.act, td.act.narrow, th.act.narrow, td.num, th.num { width:auto }
  .topbar { height:auto; padding-block:var(--s3); flex-wrap:wrap; gap:var(--s3) var(--s4) }
  .sitenav { margin-left:0; order:3; width:100%; gap:var(--s4) }
  h1 { font-size:24px }
  .band-head .count { font-size:25px }
  main { padding-block:var(--s5) var(--s6) }
}

/* On a phone the register stops being a table and becomes a list of entries.

   A 196-character French title cannot share a 380-pixel line with a date, a stage and
   two buttons; any layout that tries either scrolls the whole page sideways or squeezes
   the title into one word a line. The columns are not carrying much anyway -- a date
   reads as a date, "InParliament" reads as a stage, and the two buttons say what they
   do -- so the header row is dropped and each row is set as a block: the title, its
   evidence, then its annotations underneath. */
@media (max-width:640px) {
  table, tbody, tr, td { display:block; width:auto }
  thead { display:none }
  table { border-radius:var(--radius); overflow:hidden }
  tbody tr { padding:var(--s4); border-top:1px solid var(--line) }
  tbody tr:first-child { border-top:0 }
  tbody td, tbody tr:first-child td { padding:0; border:0 }
  tbody td + td { margin-top:var(--s3) }
  tbody tr:hover td { background:transparent }
  tbody tr:hover { background:var(--surface-2) }
  td.when, td.num, td.act.narrow { font-size:13px; color:var(--ink-2) }
  td.act.pair { flex-direction:row; flex-wrap:wrap; gap:var(--s2) }
  td.act.pair > button { width:auto; flex:1 1 auto }
  .more td { padding:0 }
  .entry .title { font-size:15.5px }
  .band-head { gap:var(--s2) }
  details > p, details > .empty { margin-inline:var(--s3) }
  .choices { grid-template-columns:1fr }
}

@media (prefers-reduced-motion:reduce) {
  *, *::before, *::after { transition:none !important; animation:none !important }
}

/* Print: the register is the deliverable. Drop the chrome and the clamp, keep the
   attribution -- a printed page carrying licensed data carries its licence notice
   with it. */
@media print {
  body > header, body > footer, .mode-switch, .more, .act { display:none }
  body { background:#fff }
  table { border-color:#999 }
  .entry .title, .timeline .title { display:block; overflow:visible }
}
