:root{
  --bg:#fbfaf8; --panel:#fff; --ink:#1c1a17; --muted:#6b6560; --line:#e5e0d8;
  /* What the red is allowed to mean: who this is (the wordmark), where you are (the open
     tab, the chosen facet, the article being read), what you can do (the filled button,
     a link, a hover, a focus ring), and what you have picked (the selected card). It was
     also doing four jobs that are none of those — numbering every khoản in the body,
     numbering every row of every table of contents, the số hiệu on every card, the số
     hiệu down the whole first column of two tables — so a page could be a third red and
     the reader had no way to tell the four decorative reds from the six that meant
     something. Those four are ink now. */
  --accent:#8a1c1c; --accent-soft:#fdf3f3; --mark:#fff2b8;
  --high:#1f6b3a; --medium:#8a5a00; --low:#8a1c1c;
  /* The filled button's own ground, and the ink that goes on it. It is a second token
     because `--accent` has to lighten in dark mode to carry text on a dark ground, and a
     pastel rose *as a button* reads as a disabled control — the one solid action on the
     screen looked switched off. Filled stays a saturated red in both themes: #b03a3a
     carries white at 5.98:1 and stands 3.06:1 clear of the dark ground, both above the
     thresholds, while the old pastel fill was 2.57:1 against its own white. */
  --accent-solid:#8a1c1c; --on-accent:#fff;
  /* Three families, one job each, named here so no rule can invent a fourth. Serif is
     the words of the law and the headings that belong to those words; sans is everything
     about *using* the page — navigation, filters, metadata, controls; mono is a citation
     string, which is copied rather than read. The stacks were written out eight times
     and had already drifted: one serif list was missing "Times New Roman", so two blocks
     of statutory text on the same page could land on two different faces. */
  /* Georgia is deliberately absent: on Windows it renders Vietnamese double-diacritic
     letters (ề, ấ, ...) with the tone mark floating detached above the base glyph. */
  --serif:"New York",ui-serif,"Times New Roman","Noto Serif",serif;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,monospace;

  /* ---- Added by the 2026-09-11 mockup pass ----------------------------------
     `--head` is the navy the mockup sets every heading and the hero title in. It is a
     third ink, not a fourth accent: red still means identity/place/action/choice, and a
     heading is none of those — which is exactly why the mockup could not leave headings
     red and had to give them a colour of their own.

     `--blue` is the document-type badge and the số hiệu that is a link. It is the one
     colour on the page that means "this is a document", and it is deliberately not red:
     rule 5 made số hiệu ink precisely so the page would stop being a third red, and a
     type badge is the same claim in a smaller box.

     `--t1…--t6` are category tints, and they are a role the design system did not have.
     A 40px filled icon square is not type: it carries no words, it is never the only
     signal (the name is beside it), and its job is to make six tiles distinguishable at
     a glance in a grid. Red appears among them as one of six rather than as the accent,
     so `--t6` is a brick red that is *not* `--accent` — two reds on one screen meaning
     two different things is the defect rule 5 exists to prevent, and the distance
     between #c0392b and #8a1c1c is what keeps them from being read as the same one.

     Every pair has a dark half below. The mockup is light-only; the theme toggle is a
     feature that already ships, and a token with no dark value is a block that goes
     invisible the moment a reader presses it. */
  --head:#16243f;
  --blue:#1f5fa8; --blue-soft:#e9f1fa;
  --warn:#a8760d; --warn-soft:#fdf4e0;
  /* Two shadows, not one: a hairline that separates a card from the ground at any size,
     and a wide soft one that gives it height. A single large shadow reads as a drop
     shadow from 2011; the pair reads as paper. */
  --card-shadow:0 1px 2px rgba(22,36,63,.05),0 6px 20px rgba(22,36,63,.05);
  --foot-bg:#141d33; --foot-ink:#eef1f7; --foot-muted:#8e9ab4; --foot-line:#28334f;
  --t1:#1f8a4c;--t1b:#e6f4ec; --t2:#c9700f;--t2b:#fbefe0; --t3:#2f6fb8;--t3b:#e9f1fa;
  --t4:#7f47b5;--t4b:#f1eaf9; --t5:#13807c;--t5b:#e2f3f2; --t6:#c0392b;--t6b:#fbeceb;
  /* The page ground as an RGB triple, for the scrim that is washed over a photograph.
     A triple rather than a colour because the wash needs the same ground at four
     opacities, and `rgba(var(--sky),.28)` is the only way to say that once.

     It lives here rather than in home.css, where it was written, because the banner is
     now painted on two surfaces: the home screen's search band and the document page's
     hero. A document page does not load home.css — the same fact that turned the theme
     toggle into a solid red square before `.themer` moved into this file. A token used
     by shared chrome belongs with the shared chrome. */
  --sky:251,250,248;
}
/* The dark palette is declared once and reached two ways: by the device setting, unless
   the reader has explicitly asked for light, and by their explicit choice of dark. Both
   selectors are needed — the media query alone cannot be overridden by a toggle, and the
   attribute alone would ignore a device that is already dark. `light` is not redeclared:
   the bare `:root` above is the light palette, so asking for light is asking for the
   default, and a second copy of it would be a second thing to keep in step. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]){--bg:#16150f;--panel:#1e1d17;--ink:#ece7dd;--muted:#9a938a;
        --line:#33302a;--accent:#e08a8a;--accent-soft:#2a1d1d;--mark:#4a3f14;
        --high:#6fbf8b;--medium:#d9a441;--accent-solid:#b03a3a;--on-accent:#fff;
        /* The navy cannot come across: a heading two steps off black is a heading nobody
           sees on a near-black ground. Dark's version of "quieter than the accent, louder
           than body text" is a cool tint of the ink, which is what this is. */
        --head:#e9edf4;
        --blue:#7fb0e0;--blue-soft:#1b2634;--warn:#d9a441;--warn-soft:#302713;
        --card-shadow:0 1px 2px rgba(0,0,0,.32),0 6px 20px rgba(0,0,0,.24);
        /* The footer is *darker* than the page here, not lighter. Inverting it — the
           light theme's trick — would make the footer the brightest band on a dark page
           and pull the eye to the least important thing on it. */
        --foot-bg:#100f0a;--foot-ink:#ece7dd;--foot-muted:#948d84;--foot-line:#2b2822;
        --t1:#63c48d;--t1b:#16291f; --t2:#e0a055;--t2b:#2c2218; --t3:#79aee2;--t3b:#1a2532;
        --t4:#b98ae0;--t4b:#261d31; --t5:#5cc0bb;--t5b:#13292a; --t6:#e5837a;--t6b:#2f1d1c;
        --sky:22,21,15;}
}
:root[data-theme=dark]{--bg:#16150f;--panel:#1e1d17;--ink:#ece7dd;--muted:#9a938a;
        --line:#33302a;--accent:#e08a8a;--accent-soft:#2a1d1d;--mark:#4a3f14;
        --high:#6fbf8b;--medium:#d9a441;--accent-solid:#b03a3a;--on-accent:#fff;
        /* The navy cannot come across: a heading two steps off black is a heading nobody
           sees on a near-black ground. Dark's version of "quieter than the accent, louder
           than body text" is a cool tint of the ink, which is what this is. */
        --head:#e9edf4;
        --blue:#7fb0e0;--blue-soft:#1b2634;--warn:#d9a441;--warn-soft:#302713;
        --card-shadow:0 1px 2px rgba(0,0,0,.32),0 6px 20px rgba(0,0,0,.24);
        /* The footer is *darker* than the page here, not lighter. Inverting it — the
           light theme's trick — would make the footer the brightest band on a dark page
           and pull the eye to the least important thing on it. */
        --foot-bg:#100f0a;--foot-ink:#ece7dd;--foot-muted:#948d84;--foot-line:#2b2822;
        --t1:#63c48d;--t1b:#16291f; --t2:#e0a055;--t2b:#2c2218; --t3:#79aee2;--t3b:#1a2532;
        --t4:#b98ae0;--t4b:#261d31; --t5:#5cc0bb;--t5b:#13292a; --t6:#e5837a;--t6b:#2f1d1c;
        --sky:22,21,15;}
/* Form controls and scrollbars are painted by the browser, not by these tokens; without
   this they stay light-on-light when the reader picks dark on a light device. */
:root{color-scheme:light}
:root[data-theme=dark]{color-scheme:dark}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){color-scheme:dark}}
/* The type scale: 12 · 13 · 14 · 15 · 17 · 20 · 24 · 34, and nothing in between.
   It replaced nineteen sizes, most of them half a pixel apart. 13 beside 13.5 is a
   difference no eye resolves, so no two things on the page stood on the same step and
   nothing read as more important than anything else. The floor is 12, not 10.5: Vietnamese
   hangs its tone marks above the letter and they are the first thing a small size loses. */
/* The spacing grid: multiples of 4, and below that only 1, 2 and 3 — which are not
   spacing at all but optical correction inside a pill or an inline chip, where 4px of
   padding would double the height of the thing.
   Everything from 4 up was on nineteen different values, thirteen of them off any grid
   (5, 6, 7, 9, 10, 11, 13, 14, 15, 18, 22, 26, 30, 34): a page whose gaps are 6, 7 and 9
   in three neighbouring rules has no rhythm to read, only noise a reader feels as
   untidiness without being able to name it. Halfway values were resolved by role rather
   than by rounding: a control's own padding goes up (10 → 12, so a button keeps a
   comfortable target), a container's padding comes down (18 → 16, 26 → 24), so the page
   gained air where a finger lands and lost none of its density.

   The radius scale: 8 for anything a reader operates — buttons, inputs, chips, tabs,
   facet rows; 12 for a surface — panel, card, pane, notice; 99 for a pill or a dot.
   That replaced ten values between 2 and 12, several of them one pixel apart, plus a
   `50%` doing the job of the pill. `mark` takes the pill too: a rounded cap is what a
   highlighter leaves, and a 2px corner on a highlight was a corner nobody could see. */
*{box-sizing:border-box}
/* `hidden` is a browser default, and a browser default loses to any author rule that
   sets `display` — no matter how weak. `.waiting{display:flex}` beat it, so the "đang
   soạn câu trả lời" indicator stayed on screen under the finished answer while the code
   that set `waiting.hidden = true` looked perfectly correct. Stated once here so the
   attribute means what every reader of the JS assumes it means. */
[hidden]{display:none!important}
/* The gutter is reserved whether or not the page scrolls, which is the other half of the
   header not moving between screens. `/so-sanh` is short enough to fit the window and the
   home screen is not, so a classic scrollbar appeared on one and not the other: measured
   at a 1600px window, the wordmark sat 7px further right on the short page purely because
   15px of scrollbar had gone. Where the platform draws overlay scrollbars — macOS by
   default — the gutter is zero and this declaration changes nothing. */
html{scrollbar-gutter:stable}
body{margin:0;background:var(--bg);color:var(--ink);
  font:15px/1.6 var(--sans)}
/* The footer sits on the bottom edge of the window on a page too short to scroll —
   `/so-sanh` before a comparison is picked, a short information page, an empty result
   list — instead of ending halfway down and leaving the page background below it. A
   column with a stated minimum height and an auto margin above the footer does it: the
   margin eats whatever height is left over, and on a page that already scrolls there is
   none left over, so nothing moves.

   The 48px that used to be the footer's own `margin-top` moves to the block above it,
   because an auto margin collapses to zero exactly when the page scrolls — the one case
   where that gap is the only thing separating the text from the dark band. `main.auth`
   states its own 64px and keeps it: it is more specific than this. */
body{min-height:100dvh;display:flex;flex-direction:column}
body>#home,body>main{margin-bottom:48px}
body>footer{margin-top:auto}
/* `body>header`, not `header`. A bare element selector here made every `<header>` on the
   site a pinned bar at `z-index:5` — and `<header>` is the correct tag for the head of an
   `<article>`, so `/so-sanh` had one per comparison row. Scrolling, each row's heading
   pinned itself over the top bar and drew its title across the search box (USER reported
   it 2026-09-20; `elementsFromPoint` at y=20 returned `span.cheadtitle` above
   `div.searchpill`). Four other files had the same silent bug: the admin queues, the
   feedback list, the payment queue and the newsletter queue all head their cards with
   `<header>`.

   The site's own bar is the one `<header>` that is a child of `<body>` — `chrome.ts`
   writes it there and so does every static page — so the relationship is what identifies
   it, not a class it would now have to carry. Same lesson as `input[type=search]` sizing
   the sidebar's field: an element selector is a claim about every element of that name. */
body>header{border-bottom:1px solid var(--line);background:var(--panel);
  position:sticky;top:0;z-index:5}
/* `margin-inline`, not `margin:0 auto`: this class is the site's one horizontal measure
   and has no opinion about the space above or below the block it is on. The shorthand
   had one — it zeroed the block margins too, and it is a class, so it silently beat
   `body>main{margin-bottom}` on every page whose `<main>` carries it. That put the
   footer's dark band flush against the last line of `/van-ban`. */
/* `width:100%`, not left to default `auto`: `<main class="wrap">` is a flex item of
   `body{display:flex;flex-direction:column}` above, and `margin-inline:auto` — the
   centering this class exists for — disqualifies a flex item from the stretch it would
   otherwise get on its cross axis (the spec stretches only an item whose cross-margins are
   not `auto`). Without a width, `main` fell back to shrink-to-fit, and a `display:grid`
   box being shrink-to-fit sizes its `fr` tracks off their content's max-content width
   instead of filling available space — so `/van-ban` with six short "Hiến pháp" rows drew
   a visibly narrower page than the same route holding 628 "Luật" rows. `width:100%` forces
   the stretch outcome the flexbox spec would have given it for free had the margin not
   been `auto`, and the max-width above still bounds it exactly as before. */
.wrap{width:100%;max-width:1180px;margin-inline:auto;padding:0 20px}
/* The top bar carries identity and navigation. There is no emblem here on purpose: doc
   54 principle 5 forbids dressing as an authority, and scales, a gavel or a flag are the
   most direct way to claim one we do not have. */
/* `14px` of vertical padding, not 8. The bar carried two status pills until 2026-09-20
   and they made it look full; with them gone a 8px bar read as a strip rather than as the
   site's own header. `doc.css` carries the same two numbers for the server-rendered
   header — change one and change the other, or the wordmark jumps when a reader crosses
   from the home screen into a document. */
.topbar{display:flex;align-items:center;gap:20px;max-width:1560px;margin:0 auto;
  padding:14px 16px;border-bottom:1px solid var(--line)}
/* Anchored to the brand, on every page, since 2026-09-20. The strip was centred here —
   `margin-inline:auto` — while the six server-rendered headers, which also carry a search
   box, left it beside the wordmark. Measured at 1600px, "Tra cứu" stood at x=643 on the
   home screen and at x=354 on `/so-sanh` and `/van-ban`: pressing a tab moved the tab
   itself 289px, which is the jump the owner reported on 2026-09-20. The brand was already
   at x=29 on both, so the wordmark was the only fixed thing in a bar that is supposed to
   be the fixed thing on the site.

   Beside the brand and not centred, because centring is the arrangement the home screen
   cannot share: the other bars have a search pill between the tabs and the right edge, so
   an auto margin each side centres the tabs on what is left of the row rather than on the
   row, and the two would still land at different x. `.topbar-end` keeps the one
   `margin-left:auto` in the row, so the right end stays pinned right. */
/* The wordmark: the initial reversed out of a red tile, then the rest of the name in the
   heading navy. One letter in a 22px box is the whole logo, and it earns its place by
   being the one fixed thing in the bar — the tagline is dropped at 640px and a wordmark
   on its own has nothing left to anchor the left edge at that width.
   Still no seal and no gavel: a letter in a square claims nothing. */
.brand-mark{display:flex;align-items:center;gap:8px;text-decoration:none;
  color:var(--head);font-size:15px;white-space:nowrap}
/* The mark, as a mask rather than as an `<svg>` in the markup.
   The wordmark is written out in thirteen places — two headers, seven footers and four
   more — and pasting six lines of path data into each is thirteen copies to keep in step.
   As a mask it is defined once, and `background:currentColor` is what makes it navy in a
   header and white on the footer's dark band without a second copy for either.
   On the glyph itself: doc 54 principle 5, third amendment (2026-09-20). It was a letter
   in a box until then, because a mark is an assertion of identity and a civic colonnade
   reads as a state one. The owner was shown that objection and chose the building. The
   footer disclaimer is what carries the disclaimer in words and may not be shrunk. */
:root{--mark-glyph:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.8 9.2 12 3.6l9.2 5.6'/%3E%3Cpath d='M5.4 9.8v8.4M9.8 9.8v8.4M14.2 9.8v8.4M18.6 9.8v8.4'/%3E%3Cpath d='M3.4 20.4h17.2'/%3E%3C/svg%3E")}
.brand-mark .mark{flex:0 0 auto;width:27px;height:27px;background:currentColor;
  -webkit-mask:var(--mark-glyph) center/contain no-repeat;
  mask:var(--mark-glyph) center/contain no-repeat}
/* `.1em` and not the old `.06em`: the tile puts a hard vertical edge against the first
   letter, and at the old tracking "ECHTIN" crowded it badly enough to read as a typo. */
.brand-mark strong{color:var(--head);font-size:19px;font-weight:700;letter-spacing:.08em}
.brand-mark .tag{color:var(--muted);font-size:13px;font-weight:400;margin-left:6px}
.tabs{display:flex;gap:4px;flex-wrap:wrap}
.tabs a,.tabs button{background:transparent;border:0;color:var(--muted);font:inherit;
  font-size:14px;padding:8px 12px;border-radius:8px;cursor:pointer;text-decoration:none}
.tabs a:hover,.tabs button:not([disabled]):hover{color:var(--ink);background:var(--accent-soft)}
/* The buttons are tabs too: three of the five entries are screens this script swaps in
   rather than pages the browser navigates to, and a strip that only ever lights its one
   anchor tells the reader they are somewhere they are not. */
/* A straight bar under the word, drawn as a pseudo-element. It was an inset box-shadow,
   which the tab's own 8px radius bent into a curve at both ends — at 14px that reads as a
   pill that failed to close rather than as an underline. Inset by the tab's padding so it
   sits under the word and not under the hit area. */
.tabs a,.tabs button{position:relative}
.tabs a.on,.tabs button.on{color:var(--accent);font-weight:600}
.tabs a.on::after,.tabs button.on::after{content:"";position:absolute;
  left:12px;right:12px;bottom:2px;height:2px;border-radius:2px;background:var(--accent)}
/* Present but inert, and labelled with why. Hiding them would misstate the product;
   enabling them would promise a screen with no API behind it. */
.tabs button[disabled]{opacity:.45;cursor:not-allowed}
.topbar-end{margin-left:auto;display:flex;gap:8px;align-items:center}
/* Moved out of home.css on 2026-09-11. It was there while the home screen was the only
   screen with a topbar; the document pages and the five static pages have one now, and
   they load app.css and doc.css but never home.css — so the toggle arrived on all six
   of them as a bare <button>, which the base rule paints as the page's one filled red
   action. A 44px red square sat where a 28px outline circle belonged.
   A single character in a quiet round button: it is chrome, and the bar already has
   two badges competing for the same corner. */
/* Theme switch. A single character in a quiet round button: it is chrome, and the topbar
   already has two badges competing for the same corner. */
/* No outline since 2026-09-20. With the two badges gone the toggle was the only ringed
   thing next to the sign-in pill, and two rings side by side read as two buttons of equal
   weight — which they are not. */
.themer{background:transparent;color:var(--muted);border:0;
  border-radius:10px;width:32px;height:32px;padding:0;font-size:15px;line-height:1;
  display:flex;align-items:center;justify-content:center}
.themer:hover{color:var(--accent);background:var(--accent-soft)}
/* Who you are, at the right edge.
   `order` rather than relying on the order the scripts happen to finish in: `themer.js`
   and `account-menu.js` both append to `.topbar-end`, one of them after a network round
   trip, so without this the theme toggle lands to the left or the right of the avatar
   depending on how fast the API answered. The badges keep the default 0 and stay first. */
/* The toggle first, then who you are: the supplied design puts the sign-in pill hard
   against the right edge, and it is the one control in this corner a reader acts on. */
.themer{order:1}
.acct,.signin{order:2}
/* Signed out. An outline pill rather than the filled red the bare `button` rule paints:
   the one filled action on a page is the thing that page is for, and on a page about a
   Nghị định that is not signing in. */
.signin{font-size:13.5px;border:1px solid var(--line);border-radius:10px;
  padding:7px 15px;color:var(--muted);text-decoration:none;
  display:inline-flex;align-items:center;gap:7px}
.signin svg{width:15px;height:15px;flex:0 0 auto}
.signin:hover{color:var(--accent);border-color:var(--accent)}
/* Signed in. The <details> is the positioning context for the panel it drops. */
.acct{position:relative}
.acct summary{display:flex;align-items:center;gap:7px;cursor:pointer;list-style:none;
  border:1px solid var(--line);border-radius:10px;padding:3px 10px 3px 3px;font-size:13px}
/* Safari draws its own triangle through a pseudo-element that `list-style:none` misses. */
.acct summary::-webkit-details-marker{display:none}
.acct summary:hover,.acct[open] summary{border-color:var(--accent)}
.acct-face{width:24px;height:24px;border-radius:99px;flex:0 0 auto;
  background:var(--accent-solid);color:var(--on-accent);
  display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600}
.acct-name{max-width:12ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-plan{font-size:11px;color:var(--muted);border-left:1px solid var(--line);
  padding-left:7px}
.acctmenu{position:absolute;right:0;top:calc(100% + 6px);z-index:60;min-width:210px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:6px;
  box-shadow:var(--card-shadow)}
/* The address is a label, not a destination — it is here so a reader on a shared machine
   can see *which* account is signed in without opening the account page. */
.acct-who{margin:0;padding:6px 10px 8px;font-size:12px;color:var(--muted);
  border-bottom:1px solid var(--line);overflow:hidden;text-overflow:ellipsis}
.acctmenu a,.acctmenu button{display:block;width:100%;text-align:left;font:inherit;
  font-size:13px;padding:8px 10px;border-radius:6px;text-decoration:none;color:var(--ink)}
.acctmenu a:hover,.acctmenu button:hover{background:var(--accent-soft);color:var(--accent)}
/* Both bare-element rules further down this file reach in here and have to be undone: the
   `form` rule makes it a flex row with 12px of padding, and the `button` rule paints it as
   the page's one filled red action. A red "Đăng xuất" in a menu of five quiet links reads
   as the thing the menu is for. */
.acctmenu form{display:block;padding:0;gap:0;margin:0}
.acctmenu button{background:transparent;border:0;color:var(--ink);cursor:pointer}
.searchband{max-width:1560px;margin:0 auto;padding:12px 16px 0}
/* The pills at the right edge. `gap` rather than a space between the glyph and the words
   so the icon stays put when the count grows a digit. */
.badge{display:inline-flex;align-items:center;gap:4px;font-size:12px;
  border:1px solid var(--line);border-radius:99px;padding:3px 10px;color:var(--muted)}
.badge svg{width:13px;height:13px;flex:0 0 auto}
form{display:flex;gap:12px;padding-bottom:12px;flex-wrap:wrap;align-items:center}
/* 16px on every field a reader types in: iOS Safari zooms the page when a field under 16px
   takes focus, and the body is 15px, so `font:inherit` alone is not enough. */
input[type=search],input[type=date]{font:inherit;font-size:16px;padding:12px;border:1px solid var(--line);
  border-radius:8px;background:var(--bg);color:var(--ink)}
input[type=search]{flex:1;min-width:260px}
input:focus{outline:2px solid var(--accent);outline-offset:-1px}
/* Glyph, field and action in one pill. They were three shapes in a row, and at that size
   the button read as a separate control that happened to sit next to the box — on the
   home screen, where there is nothing else on the page, a reader had no other cue that
   pressing it would act on what they had just typed. The focus ring moves to the pill for
   the same reason: a ring around the field alone drew a second rounded rectangle inside
   the first, which is the shape the pill exists to remove. */
/* On the radii in this file, because four rules below depend on it: the pill shape is
   for a badge, and a control a reader operates takes a small radius. `.hpick` already
   cited that rule; the search box, the sign-in button and the chips were breaking it, and
   the design supplied 2026-09-20 draws every one of them as a rounded rectangle and keeps
   the full pill for the one true badge on the screen — the kicker above the title.
   14px for a box, 10px for a control inside or beside one. */
/* The pill and its dropdown are one control and share one positioned box, so the flex
   sizing that used to live on the pill belongs here — the pill itself now just fills it. */
.searchbox{position:relative;flex:1 1 420px;min-width:0}
.searchpill{min-width:0;display:flex;align-items:center;gap:10px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:4px 4px 4px 16px}
.searchpill:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.searchpill .mag{flex:0 0 auto;display:flex;color:var(--accent)}
.searchpill .mag svg{width:17px;height:17px}
/* The border and the ground belong to the pill now, so the field inside has neither —
   including its own focus outline, which would otherwise be drawn 1px inside the pill's. */
.searchpill input[type=search]{flex:1 1 auto;min-width:0;border:0;background:transparent;
  border-radius:0;padding:8px 0}
.searchpill input[type=search]:focus{outline:0}
.searchpill button{flex:0 0 auto;border-radius:10px;padding:9px 20px}
.searchpill .arr{margin-left:4px}
/* The suggestion list. On the first screen and therefore in this file rather than in a
   lazy stylesheet: it is part of the search box, and rules arriving after the box is
   already being typed into would repaint it under the reader's hands.

   z-index above the header's 5, because the header is sticky and the list has to stand
   over the page it covers — in practice the home screen's first block. */
.sgbox{position:absolute;z-index:20;top:calc(100% + 6px);left:0;right:0;margin:0;
  padding:4px;list-style:none;max-height:min(60vh,420px);overflow-y:auto;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 12px 32px rgb(0 0 0/.14)}
/* One line each. The name is the part allowed to be cut: a row that wraps stops being a
   glanceable list of names and becomes a page. The chip keeps its width, because a
   truncated verdict is worse than no verdict at all. */
.sg-row{border-radius:8px;font-size:14px}
/* Pointing with a mouse and pointing with ↓ are one state, so they are painted as one
   rule. Hover had no rule at all, which meant a row the cursor was sitting on looked
   exactly like the seven it was not.

   The wash alone does not carry it. Measured on the shipped page: `--accent-soft` on the
   list's `--panel` ground is 1.09:1 — a contrast ratio of 1.0 is *the same colour*, so
   the selected row was correct in the DOM and invisible on the screen. `--accent-soft`
   is a focus-ring tint; it was never a selection surface.

   What actually says "this one" is the accent edge, which is what a selected result card
   already uses (`a.card[aria-selected=true]` in panes.css) — one vocabulary for "picked",
   two places that draw it. Inset rather than a real border so the row does not jump 3px
   sideways as the selection moves down it, and the name takes the accent and 600 as well:
   colour alone is not a signal a reader with low colour vision can act on, and weight is
   the one extra channel a single-line row has room for. */
.sg-row:hover,.sg-row.on{background:var(--accent-soft)}
/* Hover takes the accent on the name and nothing else; the selected row takes the edge
   and the weight as well. Two strengths of one idea, because a pointer resting on a row
   and the row ↓ has actually moved to are not the same claim — and if hover were drawn
   as strongly, a reader whose cursor happened to sit over the list would see two
   selections and have no way to know which Enter would take. */
.sg-row:hover .sg-name{color:var(--accent)}
.sg-row.on{box-shadow:inset 3px 0 0 var(--accent)}
.sg-row.on .sg-name{color:var(--accent);font-weight:600}
/* The anchor fills the row so the whole row is the click target and, more importantly, so
   the link carries a real href — a suggestion is navigation, and navigation that only
   exists as a JavaScript handler cannot be opened in a new tab or read by a crawler. */
.sg-row>a,.sg-row{display:flex;align-items:center;gap:8px}
.sg-row>a{flex:1 1 auto;min-width:0;padding:9px 12px;color:inherit;text-decoration:none}
.sg-search{padding:9px 12px;cursor:pointer}
.sg-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sg-hint{flex:0 0 auto;font-size:12px;color:var(--muted)}
.sg-chip{flex:0 0 auto;font-size:11px;border-radius:99px;padding:1px 8px;
  border:1px solid currentColor}
.sg-chip.low{color:var(--low)} .sg-chip.medium{color:var(--medium)}
.sg-chip.high{color:var(--high)} .sg-chip.none{color:var(--muted)}
/* The hand-off row, separated by a rule rather than by spacing: it is a different kind of
   thing from the rows above it — those name a document, this one runs a search. */
.sg-search{border-top:1px solid var(--line);border-radius:0 0 8px 8px;margin-top:4px}
.sg-search .sg-name{font-style:italic}
/* The one filled control on the screen, painted from the pair declared at the top: a
   fill that stays red in both themes and the ink that belongs on it. */
button{font:inherit;padding:12px 16px;border:0;border-radius:8px;background:var(--accent-solid);
  color:var(--on-accent);cursor:pointer}
button.ghost{background:transparent;color:var(--muted);border:1px solid var(--line);
  padding:4px 12px;font-size:13px}
button.ghost:hover{color:var(--ink);border-color:var(--accent)}
.chips{display:flex;gap:8px;flex-wrap:wrap;padding-bottom:16px}
mark{background:var(--mark);color:inherit;padding:0 1px;border-radius:99px}
/* The same border-and-shadow pair the home screen's blocks carry. It is one declaration
   because `.panel` is the surface of the document pages, the reader pane and every
   notice — so syncing the home screen's card treatment to the rest of the site is this
   line rather than a pass over three stylesheets. */
.panel{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:24px;
  box-shadow:var(--card-shadow)}
/* Not `--head`: this is the title of a legal instrument, which is the words of the law
   and takes the law's serif and the law's ink. The navy is for headings *about* the site
   — block heads, the info pages, the sidebar labels — and the two must not blur, because
   the whole point of the serif/sans split is that a reader can tell at a glance which of
   the two they are reading. */
.panel h2{margin:0 0 3px;font-size:20px;line-height:1.35}
.panel .doc{font-size:13px;color:var(--muted);margin:0 0 16px}
/* A division title can be a 90-word paragraph; it is context, not a heading. */
.meta .division{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;
  overflow:hidden;max-width:52ch}
label.field{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted)}
.conf{font-size:12px;border-radius:99px;padding:2px 8px;border:1px solid currentColor}
.conf.high{color:var(--high)} .conf.medium{color:var(--medium)} .conf.low{color:var(--low)}
.conf.none{color:var(--muted)}
/* The status line's one sentence rather than one more pill: an ambiguous số hiệu
   is the only thing there the reader has to act on. */
#status .warn{color:var(--medium)}
.quiet{color:var(--muted);font-size:14px}
.intro p{margin:12px 0;font-size:14px;line-height:1.65}
.intro code{background:var(--accent-soft);color:var(--accent);padding:1px 8px;border-radius:8px;
  font:13px/1.5 var(--mono)}
.hint{font-size:12px;color:var(--muted);align-self:center;margin-left:auto;
  order:99;white-space:nowrap}
table a{color:inherit;text-decoration:none}
table a:hover{color:var(--accent)}
tr:hover td{background:var(--accent-soft)}
details.diag,.notice details{margin-top:12px;font-size:13px;color:var(--muted)}
details summary{cursor:pointer}
details code{display:block;margin-top:8px;font:12px/1.5 var(--mono);
  word-break:break-word}
.disclaimer{margin:16px 0 0;padding-top:16px;border-top:1px solid var(--line);
  font-size:13px;color:var(--muted);line-height:1.55}
/* The footer is a dark band now rather than a hairline and some grey text. It is the
   one place on the site where inverting is worth the cost: it ends the page, it is the
   only block a reader scrolls *to* rather than through, and against a near-white page a
   rule-and-grey-text footer never reads as an end — it reads as the page running out.
   It carried a skyline watermark until 2026-09-11 — an SVG mask painted from
   `--foot-muted` in `footer::after` — and with it went `position:relative`,
   `overflow:hidden` and two `z-index:1`, none of which were about the footer: they placed
   it, clipped it, and kept the columns from being painted over by it. */
footer{background:var(--foot-bg);color:var(--foot-ink);padding:36px 0 0}
footer p{max-width:70ch;margin:0;font-size:13px;color:var(--foot-muted);line-height:1.6}
/* Five blocks now: who this is, three columns of links, and the subscription. Flex with
   stated bases rather than a five-column grid, because the five do not want equal
   widths — the brand carries a paragraph, a link column carries four words, and the
   subscription carries a form — and a grid would have to say so five times anyway.
*/
.footcols{max-width:1560px;margin:0 auto;padding:0 16px;display:flex;gap:28px 32px;
  align-items:flex-start;flex-wrap:wrap;justify-content:space-between}
.footbrand{flex:0 0 260px}
.footbrand p{margin:12px 0 0;font-size:13px;color:var(--foot-muted);line-height:1.6}
/* On the dark band the brand goes white: `--head` is a navy, and a navy wordmark on
   #141d33 is a wordmark nobody can find. */
footer .brand-mark,footer .brand-mark strong{color:var(--foot-ink)}
footer .brand-mark .tag{color:var(--foot-muted)}
/* No rule between the two columns any more (dropped 2026-09-26, after CNN's footer) — they
   are told apart by their own gap, not by a drawn divider. */
.footlinks{flex:0 0 auto;display:flex;gap:32px}
.footlinks>ul{flex:0 0 180px;min-width:0;margin:0;padding:0;list-style:none;
  display:grid;gap:12px;align-content:start}
.footlinks a{font-size:13px;color:var(--foot-muted);text-decoration:none}
.footlinks a:hover{color:var(--foot-ink)}
.foot-legal{max-width:70ch}

/* Back on 2026-09-20, after being removed on 09-14 for pointing at "#". They still point
   at "#": the owner asked for them knowing that. Quiet by construction — an outlined
   circle in the muted colour — so that three controls which do nothing yet do not read as
   the loudest thing in the band. */
.footsocial{flex:0 0 auto;margin:0;padding:0;list-style:none;display:flex;gap:10px}
.footsocial a{display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  border:1px solid var(--foot-line);color:var(--foot-muted)}
.footsocial a:hover{color:var(--foot-ink);border-color:var(--foot-ink)}
.footsocial svg{width:16px;height:16px}
/* The subscription column. The field and the button are one control visually — a single
   bordered box with the button filling its right end — because two separate rounded
   shapes at this size read as two unrelated things and the reader has to work out that
   the button belongs to the field. */
.footsub{flex:0 0 300px}
.footsub h2{margin:0 0 8px;font-size:13px;font-weight:600;color:var(--foot-ink)}
.footsub p{margin:0 0 12px;font-size:12px;line-height:1.6;color:var(--foot-muted)}
.subform{display:flex;padding:0;gap:0;border:1px solid var(--foot-line);border-radius:8px;
  background:rgba(255,255,255,.05);overflow:hidden;max-width:320px}
.subform input{flex:1 1 auto;min-width:0;background:transparent;border:0;
  color:var(--foot-ink);font:inherit;font-size:16px;padding:9px 12px}
.subform input::placeholder{color:var(--foot-muted)}
.subform input:focus{outline:2px solid var(--accent-solid);outline-offset:-2px}
.subform button{border-radius:0;padding:9px 16px;font-size:13px;white-space:nowrap}
/* The reply to a submission, in the column rather than in an alert(): the form is at the
   very bottom of a long page and a dialog would be the only part of the site that stops
   the page to say something. It is a live region so it is announced, not just painted. */
.subnote{margin:8px 0 0!important;font-size:12px}
/* A literal, not a token: every red this project has is tuned to carry on a *page*
   ground, and both of them — #8a1c1c light, #b03a3a dark — disappear on the footer's
   near-black. The footer is the one surface that needs a red of its own. */
.subnote.bad{color:#f0918a}
/* The closing bar *does* get a rule now, unlike before. The old reasoning — the footer
   already has a line separating it from the page, so a second one fences off nothing —
   stopped holding the moment the footer became a dark band: there is no longer a border
   at the top for it to be a second copy of, and without it the copyright floats in the
   band with nothing to say it is a different register from the columns above.
   It is drawn from `--foot-line` at full width rather than inside the padding, so it
   reads as the band's own edge and not as an underline under the last link column. */
.footnote{max-width:1560px;margin:28px auto 0;padding:14px 16px 20px;
  border-top:1px solid var(--foot-line);display:flex;gap:10px 24px;align-items:center;
  flex-wrap:wrap}
/* `max-width:none` is load-bearing: app.css caps every footer paragraph at 70ch, and a
   right-aligned line inside a 70ch box lands in the middle of a 1560px footer. */
.footnote p{margin:0;max-width:none;font-size:12px;color:var(--foot-muted)}
/* Terms and privacy sit here rather than in a link column, which is where a reader looks
   for them and what the supplied design does. They are on every page either way — the
   parity check in view_test.ts counts the whole footer, not one block of it. */
.footterms{display:flex;gap:16px;flex-wrap:wrap}
.footterms a{font-size:12px;color:var(--foot-muted);text-decoration:none}
.footterms a:hover{color:var(--foot-ink)}
/* What the site claims for its text, opposite whose site it is. This sentence used to
   open the paragraph under the brand; it reads better here, and what stayed behind is the
   disclaimer doc 00 requires at full size. */
/* `.footnote .verify`, not `.verify`: the rule above sets `margin:0` on every `p` in this
   bar and `.footnote p` outranks a lone class, so the `auto` that pushes this line to the
   right edge was being reset to zero and the sentence sat in the middle of the band. */
.footnote .verify{margin-left:auto;display:flex;align-items:center;gap:7px}
.verify svg{flex:0 0 auto;width:15px;height:15px}
/* Stacked, the brand goes back on top: the columns beside it are what it is a heading
   for, and a name that arrives after its own menu reads as a footnote. */
@media (max-width:1000px){
  .footcols{gap:28px}
  .footbrand{order:-1;flex:1 1 100%;max-width:70ch}
  .footsocial{margin-left:0}
}
@media (max-width:620px){
  .footlinks{flex-wrap:wrap;gap:24px 32px}
  .footlinks>ul{flex:1 1 140px}
  .footnote .verify{margin-left:0}
}
/* One unwrapped row at 430px squeezed the tabs to min-content: every label broke into a
   column of single words, and the badges pushed the page sideways. The bar wraps and the
   strip scrolls on its own axis — one line of tabs, swiped. */
@media (max-width:820px){
  .topbar{flex-wrap:wrap;gap:8px 16px}
  /* The strip is cut, not ended: the fade says the row keeps going under the thumb. */
  .tabs{order:3;flex:1 0 100%;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    mask-image:linear-gradient(90deg,#000 88%,transparent)}
  .tabs a,.tabs button{white-space:nowrap}
  .tabs::-webkit-scrollbar{display:none}
  .topbar-end{margin-left:auto}
}
/* The tagline goes first when the name shares a line with the badges. Written once as
   `.brand .tag`, which matches nothing here, so it had never once been hidden. */
@media (max-width:640px){.brand-mark .tag{display:none}}
/* On a phone the bar is the wordmark, two badges and this, and the name is what gives.
   The circle stays: it is what says somebody is signed in, and it is still the control
   that opens the menu — where the name and the address are written out in full. */
@media (max-width:640px){
  .acct-name,.acct-plan{display:none}
  .acct summary{padding:3px}
}
/* The pill keeps its shape at every width, and that is what these rules now protect.
   They used to read `#q{flex:1 0 100%}` + `#search-form button{flex:1 1 auto}`, which was
   right while the field and the button were siblings in the form's flex row — it dropped
   the button onto a second line under the box. With the two inside a 99px-radius pill the
   same rule wrapped the button *inside* the pill, where it was clipped out of sight: on a
   430px screen the home page had a search box and no way to press it, and the id selector
   is why `.searchpill input` never got a chance to prevent it.
   The arrow goes instead — it is punctuation on the verb, and the verb has to fit. */
@media (max-width:640px){
  .searchbox{flex:1 1 100%}
  .searchpill{gap:6px;padding-left:12px}
  .searchpill button{padding:9px 14px}
  .searchpill .arr{display:none}
  #search-form label.field{order:9;flex:1 0 100%;justify-content:center}
}
/* On the working screen the pill is one control in a toolbar rather than the subject of
   the page: unbounded at 1440px it ran the full width and left a metre of empty field
   between the glyph and the button. The home screen's own cap is narrower still. */
.searchband .searchbox{max-width:840px}
@media (max-width:900px){
  header{position:static}
  .hint{display:none}
  main{margin:16px auto}
  .panel{padding:16px}
}
table{border-collapse:collapse;width:100%;font-size:13px}
td{padding:8px;border-bottom:1px solid var(--line);vertical-align:top}
td:first-child{white-space:nowrap;font-weight:600}
/* The catalogue's own rules are in panes.css. Nothing on the first screen draws a
   catalogue — it is reached through `browse()`, which loads catalogue.js and panes.css in
   one promise — and this file is inside the 30 KB budget doc 54 sets for that screen. */

button[disabled]{opacity:.55;cursor:progress}

ul.evidence a{color:var(--accent)}

/* `.linkish` and `.small` stay: the home screen's block headings use the first for their
   "Xem tất cả →" and the counter block uses the second, and both draw before any pane
   exists. Everything else below moved to panes.css. */
.linkish{margin-left:auto;background:0;border:0;color:var(--accent);font:inherit;
  font-size:12px;text-transform:none;letter-spacing:0;cursor:pointer;padding:0;
  text-decoration:none}
/* Both of these are `<a href>` now rather than `<button>`, so the underline has to be
   taken off and put back on hover; the accent colour and the arrow carry the rest. */
.linkish:hover{text-decoration:underline}
.linkish[disabled]{color:var(--muted);opacity:.6;cursor:default}
.small{font-size:12px;line-height:1.5}

/* The filter facets, shared by the two sidebars that use them.
   `apps/web/public/panes/filters.js` draws one on the search screen and
   `packages/view/src/catalogue-filters.ts` renders the other into `/van-ban`. They are
   different programs — one narrows a list already on screen, the other builds a URL — but
   they are the same control to look at, so the rules live here, in the one stylesheet both
   the SPA and every server-rendered page load. Moved out of panes.css on 2026-09-13; a
   copy in each would have drifted the first time either was touched. */
#filters h4,.catfilters h4{margin:16px 0 8px;font-size:12px;color:var(--muted);
  font-weight:600}
#filters h4:first-child,.catfilters h4:first-child{margin-top:0}
ul.facets{list-style:none;margin:0;padding:0}
label.facet{display:flex;align-items:center;gap:8px;padding:4px 8px;border-radius:8px;
  font-size:13px;cursor:pointer}
label.facet:hover{background:var(--accent-soft)}
label.facet.on{color:var(--accent);font-weight:600}
label.facet.off{cursor:not-allowed;opacity:.5}
label.facet .name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
label.facet .count{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
/* `min-width:0` is the whole point of this line and it is not decoration.
   `input[type=search]` above carries `min-width:260px`, written for the query field in the
   band at the top of the page — a bare element selector, so it also dressed this one. The
   sidebar gives the field 195px, min-width beats width, and the field was laid out at 260:
   65px of overflow inside a pane whose `overflow-y:auto` makes overflow-x compute to
   `auto` as well. That is where the horizontal scrollbar under the filters came from, on
   both screens — measured at 260px in a 227px content box on 2026-09-15.

   Fixed here rather than by narrowing the rule above, because that rule cannot be narrowed
   to miss this field: `/van-ban` puts its copy inside a form, exactly like the band's. */
#filter-issuer{width:100%;min-width:0;font:inherit;font-size:13px;padding:8px;
  border:1px solid var(--line);border-radius:8px;background:var(--bg);color:var(--ink)}
.daterange{display:flex;align-items:center;gap:8px}
.daterange input{flex:1;min-width:0;font-size:16px;padding:8px}
.more-types{margin:4px 0 0 8px;display:inline-block}
