/* ---------------------------------------------------------------------------
   The catalogue page: the table, the pager, and the band above them.

   Loaded only by `/van-ban`, through `PageMeta.styles`. Most of this file was moved out
   of panes.css on 2026-09-13 rather than written: the SPA drew this same table into
   `#detail` until the screen became a server-rendered page, and the rules that decided
   its column widths were measured against real rows. Re-deriving them would have been
   re-making the same three mistakes the comments below record.
   --------------------------------------------------------------------------- */

/* The band. `.dochero` in doc.css already carries the photograph, the wash and the grid
   column; everything here is what a list needs and a document does not. The h1 is not the
   law's own title — it is a label the site wrote — so it steps out of the serif that
   `.doc-page .dochero h1` sets and back into the sans the rest of the interface uses. */
.cat-hero h1{font-family:inherit!important;font-size:30px!important;max-width:none!important}
.cat-hero .lead{margin:0;color:var(--muted);font-size:15px;max-width:56ch;line-height:1.6}
@media (max-width:900px){.cat-hero h1{font-size:22px!important}}

/* The sidebar is a form, and `app.css:201` styles every bare `form` as a flex row — the
   rule was written for the search box, which is one. Left to it the sidebar laid its
   headings out *beside* their controls instead of above them: measured at 1440px, "Loại
   văn bản" sat at x=1120 with its radio list at x=1206, vertically centred against it.
   `.report-form` already had to make the same correction; this is that line, not a new
   idea. `gap:0` matters as much as the display — a 12px flex gap becomes a 12px row gap
   the moment the children stack. */
#catfilter-form{display:block;padding-bottom:0;gap:0}
/* The same white surface as `#filters` on the search screen and `.panel` beside it. Every
   other pane on the site carries the border-and-shadow pair, and a sidebar that does not
   reads as loose text rather than as a control. */
.catfilters{font-size:13px;background:var(--panel);border:1px solid var(--line);
  border-radius:12px;box-shadow:var(--card-shadow)}
.catfilters .quiet.small{margin:8px 0 0}
/* The "Bộ lọc" bar. A rule of its own rather than folded into `.catfilters h4` below: it is
   the one heading in the rail that names the whole sidebar rather than one filter, and the
   only one carrying a second control (the reset link) beside it. */
.catfilters-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding-bottom:14px;margin-bottom:6px;border-bottom:1px solid var(--line)}
.catfilters-head h3{margin:0;display:flex;align-items:center;gap:8px;
  font-size:15px;font-weight:600;color:var(--ink)}
.catfilters-head a{font-size:13px;color:var(--accent);text-decoration:none}
.catfilters-head a:hover{text-decoration:underline}
/* Every filter heading now carries an icon — the shape that names the field, at a glance,
   in a rail that used to be a column of identically bold labels with no other cue between
   them. `currentColor` is what lets one `<svg>` serve every heading and both themes: the
   icon takes the muted grey the label already had, and the accent red on the bar above. */
.catfilters h4{display:flex;align-items:center;gap:8px}
.catfilters h4 svg.ico,.catfilters-head svg.ico{flex:none;width:14px;height:14px}
.catfilters-head svg.ico{width:16px;height:16px;color:var(--accent)}
.catfilter-do{display:flex;align-items:center;gap:12px;margin-top:20px;
  padding-top:16px;border-top:1px solid var(--line)}
.catfilter-do a{font-size:13px;color:var(--muted)}
/* The disclosure that replaces the SPA's "Xem thêm N loại" button. A `<details>` works
   with no script, which a button cannot, so it is the right control on this page. */
.more-types summary{font-size:12px;color:var(--accent);cursor:pointer;list-style:none}
.more-types summary::-webkit-details-marker{display:none}
.more-types summary::before{content:"+ ";font-weight:600}
.more-types[open] summary::before{content:"− "}

/* The table is wider than a column of prose, so the page gives up the 860px measure
   `.doc-page main` sets for statutory text. Scoped by `:has()` rather than by a class on
   `main`, which the shared `page()` shell does not write. */
.doc-page main:has(#catalogue),.doc-page main:has(.catfilters){max-width:1560px}

/* ---- the filters stand on the left, as they do everywhere else ----
   `doc.css` puts `.rail` in the right-hand column, which is right for what a *document*
   page hangs there: properties and a table of contents are about the text beside them,
   and the text is what must not move. A catalogue's rail is not that. It is the control
   that decides what the table holds, and every other screen on this site puts that
   control on the left — the search screen's `#filters` pane, `/so-sanh`'s `.clayout`
   (250px, then the rows), and the home screen's "Duyệt theo danh mục". This page was the
   one that disagreed, and it disagreed with itself: `/van-ban?type=Luật` is reached from
   a rail on the left of the home screen and answered by one on the right.

   Written as an override rather than by giving the sidebar its own class, because the
   rail's other half — sticky, `max-height`, `overflow`, the flex column — is `doc.css`'s
   and is correct here. Only the column is wrong, so only the column is restated. Equal
   specificity to the rules it overrides; it wins because `page()` loads this file after
   `doc.css`, which is also why this cannot move into `app.css`.

   The two banners span both columns. Left in column 2 they would start at the table's
   edge, which reads as the page being indented rather than as a sidebar standing beside
   it. With both spanning, the panel is still the third row — the count `doc.css` records
   for `grid-row:3` and the reason the rail lines up with the table rather than the hero. */
@media (min-width:1120px){
  .doc-page main:has(.catfilters){grid-template-columns:316px minmax(0,1fr)}
  .doc-page main:has(.catfilters)>*{grid-column:2}
  .doc-page main:has(.catfilters)>.crumbs,
  .doc-page main:has(.catfilters)>.dochero{grid-column:1/-1}
  .doc-page main:has(.catfilters)>.rail{grid-column:1}
}

/* Below the grid, the sidebar is a block after the table — not a form at the top of the
   page with no card around it, which is what it was.
   `doc.css` dissolves `.rail` with `display:contents` under 1120px so a *document* page
   can order the rail's three children individually against the law. This rail has one
   child and nothing to order, and dissolving it cost two things at once: the box went
   with the `aside` — border, background, radius, padding, all of it — and the form,
   no longer a DOM child of `main`, stopped matching `.doc-page main>*{order:9}` and took
   the flex default of 0. Measured at 900px: 880px of radio buttons above the `h1`, so
   "Danh mục văn bản" began below the fold on a page whose own filters had pushed it
   there. Both undone by not dissolving it; `order:9` is restated because the element is
   now a flex item in its own right and the rule it needs is the one every other child of
   `main` already gets. */
@media (max-width:1119px){
  .doc-page main .catfilters{display:block;order:9}
}

/* The catalogue as a list of cards, replacing the fixed-width table on 2026-09-22. A table
   needed five columns measured against the corpus's longest value in each — "Thông tư liên
   tịch", "Ngưng hiệu lực một phần" — because a table's columns all compete for one row's
   height. A card does not: the title gets its own line, the meta line wraps on its own, and
   nothing here is declared `nowrap` to protect a column that no longer exists. */
.cat-list{display:flex;flex-direction:column;gap:12px}
.cat-card{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:16px 20px;background:var(--panel);border:1px solid var(--line);
  border-radius:12px;box-shadow:var(--card-shadow);text-decoration:none;color:inherit}
.cat-card:hover{border-color:var(--accent)}
.cat-card:hover .cat-chev{color:var(--accent)}
.cat-card-main{flex:1;min-width:0}
.cat-card-top{display:flex;align-items:center;gap:10px;margin-bottom:6px;min-width:0}
/* The type badge. `.effect`'s pill radius, not `.tbadge`'s 4px square from the home
   screen's result rows — this card already carries an `.effect` pill on its other end, and
   the two badges read as one family of "status about this document" only if they share a
   shape. `text-transform:uppercase` does the "LUẬT" styling rather than storing it that
   way: `TYPE_SHORT` also feeds the home screen's badge, lowercase there on purpose.

   `TYPE_SHORT` covers eleven of the corpus's twenty-nine types; the other eighteen —
   "Văn bản hành chính liên quan" among them — fall back to printing the type in full.
   Unshrinkable and `nowrap`, that badge was wider than the card whenever a reader filtered
   to one of those types, which is what changed the page's width from one "Loại văn bản"
   selection to the next. `min-width:0` lets it shrink below its own text; `text-overflow:
   ellipsis` gives the truncation somewhere to land rather than clipping mid-glyph; the
   full name is still one hover away in `title`. */
.cat-type{display:inline-block;min-width:0;max-width:100%;flex:0 1 auto;
  padding:2px 9px;border-radius:99px;background:var(--accent-soft);color:var(--accent);
  font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cat-num{flex:none;white-space:nowrap;color:var(--accent);font-weight:600;font-size:13px;
  font-variant-numeric:tabular-nums}
/* The gazette writes Trích yếu as a continuation of "Quyết định số N/… ", so 20.642 of the
   22.374 stored titles begin lowercase — and we store them verbatim, because a title is
   quotable text. Capitalising the first letter is a rendering decision, the same one
   `doc.css` and `panes.css` already make on their own h1s. `::first-letter` only ever
   matches a block container, which is why this sits on the `h3` and not on an inline `a`
   inside it — the whole card is already the link, so the title is plain text now. */
.cat-title{margin:0 0 8px;font-family:inherit;color:var(--head);font-size:16px;
  font-weight:600;line-height:1.4}
.cat-title::first-letter{text-transform:uppercase}
.cat-meta{display:flex;flex-wrap:wrap;column-gap:18px;row-gap:4px;
  font-size:13px;color:var(--muted)}
.cat-meta span{display:inline-flex;align-items:center;gap:6px}
.cat-meta svg{flex:none;width:14px;height:14px;opacity:.75}
/* The side column: the effect pill and the chevron that says the card is a link. Flex, not
   grid — the pill's width varies by state ("Còn hiệu lực" against "Ngưng hiệu lực một
   phần") and the chevron has to sit beside whichever one is showing, not at a fixed offset. */
.cat-card-side{display:flex;align-items:center;gap:12px;flex:none}
.cat-chev{color:var(--muted);font-size:20px;line-height:1}

/* The pager. One band under the table: where you are on the left, how much a page holds on
   the right — the two questions the control answers, kept apart. */
.pager-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;
  flex-wrap:wrap;margin-top:20px;padding-top:16px;border-top:1px solid var(--line)}
.pgnums{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.pgbtn{display:inline-flex;align-items:center;justify-content:center;
  min-width:32px;height:32px;padding:0 8px;border:1px solid var(--line);border-radius:8px;
  background:var(--panel);color:var(--ink);font:inherit;font-size:13px;
  font-variant-numeric:tabular-nums;cursor:pointer}
.pgbtn:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.pgbtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* The current page is a `span`: it carries `aria-current`, takes no click, and must not
   look like a control that is refusing one — so it is filled rather than dimmed. The
   disabled arrows at either end of the run are the dimmed ones. */
/* `--accent-solid`, not `--accent`: the second one lightens in dark mode so that it can
   carry *text* on a dark ground, and painting a filled chip with it put white on #e08a8a.
   A filled surface is what `--accent-solid` and `--on-accent` are for — see app.css. */
.pgbtn.on{background:var(--accent-solid);border-color:var(--accent-solid);
  color:var(--on-accent);font-weight:600}
.pgbtn:disabled{opacity:.4;cursor:default}
/* Every control here is an `<a>` now, not a `<button>`: the catalogue is a server-rendered
   page and turning a page is a navigation. So the underline has to be taken off, and the
   step arrow at either end of the run is a `<span class="off">` rather than a disabled
   button — there is no page to link to, and a link to nowhere is not a link. */
a.pgbtn{text-decoration:none}
.pgbtn.off{opacity:.4;cursor:default}
.pgap{padding:0 4px;color:var(--muted)}
/* A `<form>` of its own now, so it also has to undo the bare-form padding from app.css —
   its `display:flex` and `gap` it already declares for itself, and a class beats `form`. */
.pgsize{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--muted);
  padding-bottom:0}
.pgsize select{font:inherit;font-size:16px;padding:6px 8px;border:1px solid var(--line);
  border-radius:8px;background:var(--bg);color:var(--ink)}
/* On a phone the card's two flex children no longer fit side by side — measured at 400px,
   the meta line's dates were the first thing to wrap, and a card whose right column still
   claimed a third of the width left the title fewer characters than the số hiệu beside it.
   Stacked, the status pill moves to sit under the meta line instead of beside it, and the
   chevron is dropped: there is no second column left for it to mark as a link into. */
@media (max-width:640px){
  .cat-card{flex-direction:column;align-items:stretch;padding:14px 16px}
  .cat-card-side{justify-content:flex-start}
  .cat-chev{display:none}
  .pager-bar{justify-content:center}
}
