/* Halcyon · the MSN-style front page (Mẫu A, captain 08/11 18:23: "đưa logo vào header giống msn, loại bỏ hero section,
   đảm bảo trang là bento-grid"; "các tin đều có kích thước giống nhau, a muốn rằng phải có những thẻ tin tức đáng chú ý
   có kích thước lớn hơn"; "a thấy card thời tiết của msn rất đẹp"). The approved mockup is
   plans/reports/trang-msn/mau-a2-msn-sat.html; this file ports it onto the site's tokens. It draws the website home and
   the extension's new tab (copied by extension/sync-site.py); the new tab keeps its own Google row above the panel.
   Every value comes from tokens.css (the --msn-* component tokens); the showcase is design/tokens.html. */

/* ---------- the top row: the weather and the day, the news search, "Tùy chỉnh" and the Google apps ---------- */
/* Captain, 10/11 14:48 and 14:55: the search at the top as on Edge, the weather and the day at the top left, the square
   9 dots at the top right (thanh-tren.js, menu-cong-cu.js). The corners keep equal columns, so the search stays centred. */
.msn-top { position: relative; padding: var(--top-pad) var(--msn-page-pad) 0; background: transparent; }
.msn-top-in {
  max-width: var(--msn-panel-max); margin-inline: auto;
  display: grid; grid-template-columns: minmax(var(--top-side), 1fr) minmax(0, var(--msn-search-max)) minmax(var(--top-side), 1fr); align-items: center;
  gap: var(--space-12); margin-bottom: var(--space-16);
}
.msn-top .news-search, .msn-top .web-search { grid-column: 2; grid-row: 1; width: 100%; position: relative; }
.msn-top .masthead-actions { grid-column: 3; grid-row: 1; justify-self: end; display: flex; align-items: center; gap: var(--space-8); }
.top-now {
  grid-column: 1; grid-row: 1; justify-self: start; min-width: 0; display: flex; align-items: center; gap: var(--space-16);
  color: var(--top-ink); text-shadow: var(--top-ink-shadow); font-size: var(--text-small); line-height: 1.25; white-space: nowrap;
}
.top-wx { display: inline-flex; align-items: center; gap: var(--space-6); font-weight: var(--weight-semibold); }
.top-wx-ic { width: var(--top-wx-icon); height: var(--top-wx-icon); flex: none; }
.top-temp { font-size: var(--text-sub); }
.top-date { font-weight: var(--weight-medium); }
[data-wx="off"] .top-wx { display: none; }
/* "Tùy chỉnh" and the 9 dots: square tiles with a small radius, never circles (captain, 10/11: "không nên bo tròn"). */
.msn-top .top-tile, .msn-top .tool-launcher-button {
  display: grid; place-items: center; width: var(--btn-h); height: var(--btn-h); padding: 0; border: 0; border-radius: var(--radius-8);
  background: var(--top-tile); color: var(--top-ink); cursor: pointer;
  transition: background-color var(--duration-150) ease, transform var(--duration-150) var(--ease-press);
}
.msn-top .top-tile .i { width: var(--top-icon); height: var(--top-icon); stroke-width: 2; }
.msn-top .top-tile:hover, .msn-top .top-tile[aria-expanded="true"],
.msn-top .tool-launcher-button:hover, .msn-top .tool-launcher-button[aria-expanded="true"] { background: var(--top-tile-on); color: var(--top-ink); }
.msn-top .top-tile:active, .msn-top .tool-launcher-button:active { transform: scale(0.96); }
.msn-top .top-tile:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
@media (min-width: 768px) and (max-width: 1099px) {
  .msn-top-in { grid-template-columns: minmax(var(--top-side-narrow), 1fr) minmax(0, var(--msn-search-max)) minmax(var(--top-side-narrow), 1fr); }
  .top-now { flex-direction: column; align-items: flex-start; gap: 0; }
}
.msn-top .ns-open { display: none; }
.msn-top .ns-field { display: flex; height: var(--msn-search-h); padding: 0 var(--space-4) 0 var(--space-16); }
.msn-top .ns-field input { height: 100%; font-size: var(--text-small); }
.msn-top .ns-results { left: 0; right: 0; width: auto; transform-origin: top center; }
.ns-go {
  flex: none; min-height: var(--btn-h); padding: 0 var(--space-24); border-radius: var(--radius-full);
  background: var(--color-accent-fill); color: var(--color-on-accent); font-size: var(--text-small); font-weight: var(--weight-bold);
  transition: background-color var(--duration-150) ease, color var(--duration-150) ease, transform var(--duration-150) var(--ease-press);
}
.ns-go:hover { background: var(--color-accent-fill-hover); color: var(--color-on-accent-hover); }
.ns-go:active { transform: scale(0.97); }

/* ---------- the panel and its header row ---------- */
/* No outline anywhere (captain, 08/11 21:08: "Có viền màu bao quanh nút bấm, thanh tìm kiếm, card ... Loại bỏ nó"): the
   panel parts from the page by its fill and its shadow, a card from the panel by its shadow (light) or its lighter fill
   (dark). The panel takes focus only from a script (a jump to the top), so it never shows a ring (feed.css). */
.feed-main.front.msn-panel {
  /* The outer width stops at --msn-panel-max and the panel is centred; the top row (.msn-top-in) stops at the same width. */
  max-width: var(--msn-panel-max); margin: 0 max(var(--msn-page-pad), calc((100% - var(--msn-panel-max)) / 2)) var(--space-48);
  padding: var(--msn-panel-pad);
  background: var(--color-panel-front); border: 0; border-radius: var(--msn-panel-r);
  box-shadow: var(--msn-shadow-panel);
}
.newsbar.msn-head {
  position: relative; top: auto; z-index: 5; display: flex; align-items: center; gap: var(--space-16);
  min-height: var(--msn-search-h); margin-bottom: var(--space-8); background: transparent;
}
.newsbar.msn-head::after { display: none; }
.msn-head .brand { flex: none; display: inline-flex; align-items: center; gap: var(--space-8); min-height: var(--btn-h); padding: 0 var(--space-6); border-radius: var(--radius-8); }
.msn-head .brand-tile { width: var(--msn-brand-tile); height: var(--msn-brand-tile); display: block; }
.msn-head .brand-name { font-size: var(--msn-brand-size); line-height: 1; font-weight: var(--weight-bold); letter-spacing: -0.055em; color: var(--color-ink); }
.msn-head .sections {
  --header-pill-inset: 0px; flex: 0 1 auto; gap: var(--msn-tight); padding: 0;
  -webkit-mask-image: none; mask-image: none;
}
.msn-head .sections .tab-pill { display: none; }
/* When the sections scroll sideways, the edge that still hides sections fades out (feed.js sets data-more), so the
   reader sees there is more to the right; a tab that is fully in view is never faded. */
.msn-head .sections[data-more="end"] { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--space-48)), transparent); mask-image: linear-gradient(to right, #000 calc(100% - var(--space-48)), transparent); }
.msn-head .sections[data-more="start"] { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - var(--space-48)), transparent); mask-image: linear-gradient(to left, #000 calc(100% - var(--space-48)), transparent); }
.msn-head .sections[data-more="both"] { -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--space-48), #000 calc(100% - var(--space-48)), transparent); mask-image: linear-gradient(to right, transparent, #000 var(--space-48), #000 calc(100% - var(--space-48)), transparent); }
.msn-head .filter-chip {
  --header-control-bg: transparent; position: relative; height: var(--btn-h); padding: 0 var(--space-12); border-radius: var(--radius-8);
  font-size: var(--text-small); font-weight: var(--weight-semibold); color: var(--color-ink-2);
  transition: background-color var(--duration-150) ease, color var(--duration-150) ease;
}
.msn-head .filter-chip::before { border-radius: var(--radius-8); inset: 0; }
.msn-head .filter-chip:hover:not([aria-pressed="true"]) { --header-control-bg: var(--color-surface); color: var(--color-ink); }   /* a white wash on the tinted panel */
.msn-head .filter-chip[aria-pressed="true"] { --header-control-bg: transparent; color: var(--color-ink); }
.msn-head .filter-chip[aria-pressed="true"]::after {
  content: ""; position: absolute; left: var(--space-12); right: var(--space-12); bottom: var(--space-4);
  height: var(--msn-tab-line); border-radius: var(--msn-tab-line); background: var(--color-accent-fill);
}
.head-actions { display: flex; align-items: center; gap: var(--space-8); margin-left: auto; flex: none; }
.head-actions .sort-switch { margin: 0; }
/* "Đáng đọc nhất / Mới nhất": the segmented control of "Giao diện" in Tùy chỉnh (below, .tc-seg shares its track and
   its chosen side), so the chosen order shows as a raised pill on a grey track (captain, 10/11 19:3x). The header row's
   pill inset is not defined here, so the old track (.sort-switch::before) never drew. */
.msn-head .sort-switch { --tab-pill-inset: 0px; --header-pill-inset: 0px; gap: var(--msn-tight); }
.msn-head .sort-switch::before { display: none; }
.msn-head .sort-btn { padding: 0 var(--space-12); border-radius: var(--seg-thumb-r); }
.msn-head .sort-btn::before { border-radius: var(--seg-thumb-r); }
.msn-head .sort-btn[aria-pressed="true"] { --header-control-bg: var(--color-seg-thumb); }
.msn-head .has-pill .sort-btn[aria-pressed="true"] { --header-control-bg: transparent; }
.msn-head .ed-link {
  --header-pill-inset: 0px; --header-control-bg: var(--color-accent-fill); gap: var(--space-6); min-height: var(--btn-h); padding: 0 var(--space-16);
  font-size: var(--text-small); font-weight: var(--weight-bold); transition: transform var(--duration-150) var(--ease-press);
}
.msn-head .ed-link:hover { --header-control-bg: var(--color-accent-fill-hover); }
.msn-head .ed-link:active { transform: scale(0.97); }
.msn-head .ed-link .i { width: var(--msn-fav); height: var(--msn-fav); }
/* On the new tab the news search joins the head as a magnifier that opens a field (sync-site.py moves it). */
.msn-head .news-search { position: relative; flex: none; width: auto; }
.msn-head .ns-field, .msn-head .ns-go { display: none; }
.msn-head .ns-open { display: inline-grid; }
.msn-head .news-search.open .ns-field {
  display: flex; position: absolute; right: 0; top: 50%; transform: translateY(-50%); z-index: 6;
  width: min(var(--ns-w), calc(100vw - 2 * var(--msn-page-pad) - 2 * var(--msn-panel-pad)));
}
.msn-head .news-search.open .ns-clear { display: inline-grid; }
.msn-head .news-search.open .ns-open { visibility: hidden; }

/* ---------- above the grid ---------- */
/* Nothing on every tab and in either order, so the grid (and the weather and calendar cards in it) starts at one place.
   Only a section without a tab of its own shows a line: its name and the way back. */
.front-meta { margin: 0; min-height: 0; }
.front-meta .filter-context { display: flex; align-items: center; gap: var(--space-12); min-height: var(--btn-h); margin: 0 var(--msn-tight) var(--space-8); }
.front-meta .filter-context[hidden] { display: none; }
.filter-context .filter-name { font-size: var(--text-body); font-weight: var(--weight-bold); color: var(--color-ink); }
.front-meta .filter-context .text-btn { min-height: var(--btn-h); margin: 0; }

/* ---------- the grid ---------- */
.msn-grid {
  --msn-row: var(--msn-rowh);
  display: grid; grid-template-columns: repeat(var(--msn-cols), minmax(0, 1fr));
  grid-auto-rows: minmax(var(--msn-row), auto); grid-auto-flow: row dense; gap: var(--msn-gap);
}
.msn-grid.is-front { grid-template-rows: var(--msn-row1); }
.msn-grid[hidden] { display: none; }
.msn-card {
  position: relative; min-width: 0; min-height: 0; overflow: hidden;
  background: var(--color-surface); border: 0; border-radius: var(--msn-card-r); box-shadow: var(--msn-shadow-rest);
}
.msn-lead, .nc-wide { grid-column: span 2; }
.nc-big { grid-column: span 2; grid-row: span 2; }
/* The weather and the calendar hold the same cells on every section, sort and redraw (captain, 08/11 19:50: "cố định vị
   trí"), stacked in the grid's last column (captain, 09/11: "2 thẻ cùng 1 cột. Thời tiết ở trên, lịch ở dưới"): the
   weather ends the first row, the calendar sits under it, at three, five and seven columns alike. The first row keeps
   its height on every section, so the two cards keep their size too; the lead, "Chuyện lớn" and the stories fill the
   columns to their left. */
.msn-grid:has(> .msn-wx) { grid-template-rows: var(--msn-row1); }
.msn-grid > .msn-wx { grid-area: 1 / -2; }
.msn-grid > .msn-cal { grid-area: 2 / -2; }
.msn-card:not(.msn-toplist):has(.story-link:focus-visible) { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* the story card */
.nc { display: flex; flex-direction: column; transition: box-shadow var(--duration-250) ease, transform var(--duration-250) var(--ease-flow); }
@media (hover: hover) and (pointer: fine) {
  .nc:hover { box-shadow: var(--msn-shadow-card); transform: translateY(calc(-1 * var(--msn-tight))); }
  .nc:hover .nc-img { transform: scale(1.03); }
  .nc:hover .story-link { color: var(--color-link); }
}
.nc:active { transform: scale(0.985); }
.nc-photo { position: relative; height: var(--msn-photo-h); flex: none; overflow: hidden; background: var(--color-fill); }
.msn-card .media { aspect-ratio: auto; }
.nc-img { width: 100%; height: 100%; object-fit: cover; object-position: var(--photo-focus); display: block; transition: transform var(--motion-count) var(--ease-flow); }
/* min-width: 0 lets the body shrink beside a wide card's picture: the meta line's no-wrap parts would otherwise push
   the body past the card's edge (measured 2026-11-10: 412 px of text in a 343 px card at 375 px, 326/288 at 320 px). */
.nc-body { display: flex; flex-direction: column; gap: var(--space-6); min-width: 0; min-height: 0; flex: 1; padding: var(--space-8) var(--space-12) var(--space-12); }
/* The source keeps every letter (captain, 10/11: "Anthropi…", "NVIDIA N…"): when the line is full the time wraps under
   it, and a name wider than the card wraps rather than being cut. */
.nc-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--msn-tight) var(--space-6); min-width: 0; font-size: var(--text-micro); line-height: 1.3; color: var(--color-ink-3); }
.nc-meta .st-mark:empty { display: none; }
.nc-who, .nc-when { display: inline-flex; align-items: center; gap: var(--space-6); min-width: 0; }
.nc-when { flex: none; white-space: nowrap; }
.nc-fav { flex: none; display: inline-grid; }
.nc-fav .av { width: var(--msn-fav); height: var(--msn-fav); }
.nc-src { min-width: 0; overflow-wrap: anywhere; font-weight: var(--weight-semibold); color: var(--color-ink-2); }
.nc-dot { flex: none; width: var(--msn-dot); height: var(--msn-dot); border-radius: var(--radius-full); background: var(--color-ink-3); }
.nc-meta time { flex: none; white-space: nowrap; }
/* On a story card the source has the first line to itself and the time sits under it, every card alike, so no line
   ever starts with a stray dot and no name is cut. The lead's slide keeps them on one line. */
.nc .nc-when { flex-basis: 100%; }
.nc .nc-dot { display: none; }
.nc .nc-meta .st-mark:not(:empty) + .nc-who { flex: 1 1 0; }
.nc-title {
  margin: 0; font-size: var(--msn-title); line-height: 1.4; font-weight: var(--weight-bold); letter-spacing: -0.015em; color: var(--color-ink);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-wrap: pretty;
}
.msn-card .story-link { display: inline; min-height: 0; color: inherit; }
.nc.is-read .nc-title { color: var(--color-ink-2); }
.nc-mt { display: flex; margin: 0; }
.nc-mt .mt { margin: 0; }
.nc-sum { margin: 0; font-size: var(--text-meta); line-height: 1.5; color: var(--color-ink-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.nc-kicker, .msn-lead .nc-kicker { display: inline-flex; align-items: center; gap: var(--space-6); font-size: var(--text-micro); font-weight: var(--weight-bold); letter-spacing: 0.02em; color: var(--color-ink); }
.nc-kicker::before { content: ""; width: var(--space-8); height: var(--space-8); border-radius: var(--radius-full); background: var(--color-accent-fill); }
.nc:not(.nc-big):not(.nc-wide) .nc-sum { display: none; }

/* without a picture: an ordinary card becomes a type card, a notable one turns ink */
.nc.no-photo .nc-body { padding: var(--space-12) var(--space-16) var(--space-16); gap: var(--space-8); }
.nc.no-photo .nc-title { font-size: var(--msn-title-text); line-height: 1.38; -webkit-line-clamp: 6; }
.nc.no-photo:not(.nc-big):not(.nc-wide) .nc-sum { display: -webkit-box; margin-top: auto; -webkit-line-clamp: 3; font-size: var(--text-micro); }
.nc.no-photo .nc-fav .av { width: var(--msn-fav-lg); height: var(--msn-fav-lg); }

.nc-big .nc-photo { flex: 1; height: auto; min-height: 0; }
.nc-big .nc-body { flex: none; padding: var(--space-12) var(--space-16) var(--space-16); gap: var(--space-8); }
.nc-big .nc-title { font-size: var(--msn-title-big); line-height: 1.3; letter-spacing: -0.025em; }
.nc-wide { flex-direction: row; }
.nc-wide .nc-photo { width: 50%; height: auto; }
.nc-wide .nc-body { padding: var(--space-16); gap: var(--space-8); }
.nc-wide .nc-title { font-size: var(--msn-title-wide); line-height: 1.35; -webkit-line-clamp: 4; }
.nc-wide .nc-sum { margin-top: auto; -webkit-line-clamp: 3; }
.nc-big.no-photo, .nc-wide.no-photo { background: var(--msn-ink-card); color: var(--msn-on-ink); }
.nc-big.no-photo .nc-body, .nc-wide.no-photo .nc-body { flex: 1; padding: var(--space-24); gap: var(--space-12); }
.nc-big.no-photo .nc-title { font-size: var(--msn-title-ink-big); line-height: 1.22; letter-spacing: -0.03em; -webkit-line-clamp: 7; }
.nc-wide.no-photo .nc-title { font-size: var(--msn-title-big); line-height: 1.3; -webkit-line-clamp: 4; }
.nc-big.no-photo .nc-sum { margin-top: auto; -webkit-line-clamp: 4; font-size: var(--text-small); }
.nc.no-photo:is(.nc-big, .nc-wide) :is(.nc-title, .nc-kicker) { color: var(--msn-on-ink); }
.nc.no-photo:is(.nc-big, .nc-wide) :is(.nc-sum, .nc-meta, .nc-src) { color: var(--msn-on-ink-2); }
.nc.no-photo:is(.nc-big, .nc-wide) .nc-dot { background: var(--msn-on-ink-2); }
@media (hover: hover) and (pointer: fine) {
  .nc.no-photo:is(.nc-big, .nc-wide):hover .story-link { color: var(--msn-on-ink); }
}

/* ---------- the lead carousel ---------- */
.msn-lead { background: var(--msn-ink-card); color: var(--msn-on-ink); }
.slide { position: absolute; inset: 0; opacity: 0; visibility: hidden; transition: opacity var(--duration-250) ease, visibility 0s linear var(--duration-250); }
.slide.is-active { opacity: 1; visibility: visible; transition: opacity var(--duration-250) ease; }
.slide-media { position: absolute; inset: 0; background: var(--msn-ink-card); }
.slide-media .ai-badge { top: var(--space-12); bottom: auto; right: var(--space-12); }
.slide-box {
  position: absolute; left: var(--space-12); right: var(--space-12); bottom: var(--space-12);
  display: flex; flex-direction: column; gap: var(--space-6); padding: var(--space-12) var(--space-16) var(--space-12);
  border-radius: var(--radius-8); background: var(--msn-slide-box);
}
.slide-title {
  margin: 0; font-size: var(--msn-slide-title); line-height: 1.3; font-weight: var(--weight-bold); letter-spacing: -0.025em; color: var(--msn-on-ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-wrap: pretty;
}
.slide .nc-kicker, .slide .nc-src { color: var(--msn-on-ink); }
.slide .nc-meta { color: var(--msn-on-ink-2); }
.slide .nc-dot { background: var(--msn-on-ink-2); }
.slide.no-photo .slide-box { inset: 0; justify-content: flex-end; border-radius: 0; padding: var(--space-24) var(--space-24) var(--space-64); background: transparent; }
.slide.no-photo .slide-title { font-size: var(--text-feature); -webkit-line-clamp: 4; }
@media (hover: hover) and (pointer: fine) { .slide .story-link:hover { text-decoration: underline; text-underline-offset: 0.15em; } }
/* The pager dots, one style for every row of them: the lead carousel's (one per story) and the weather card's (one per
   page). Straight on the picture with no chip behind them (captain, 10/11 15:52: "bỏ cái nền của mấy dấu chấm ... chỉ để
   mấy dấu chấm") and no ring around them (10/11 18:54: "các dấu chấm trên carousel thì có viền, bỏ viền đi. bảo đảm các
   dấu chấm trên carousel phải đồng bộ với nhau"): a soft shadow alone keeps them legible on a white photo and a dark one.
   Each dot is a 44 px tall button; the active one is a longer bar. */
.pager-dots { display: flex; }
.pager-dots button {
  height: var(--btn-h); padding: 0 var(--pager-dot-pad); border: 0; background: none; display: grid; place-items: center;
}
.pager-dots button::before {
  content: ""; width: var(--pager-dot); height: var(--pager-dot); border-radius: var(--radius-full); background: var(--pager-dot-fill);
  box-shadow: var(--pager-dot-shadow);
  transition: width var(--duration-250) var(--ease-flow), background-color var(--duration-250) ease;
}
.pager-dots button[aria-current="true"]::before { width: var(--pager-dot-on); background: var(--pager-dot-fill-on); }
.pager-dots button:focus-visible { outline: none; }
.pager-dots button:focus-visible::before { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
@media (hover: hover) and (pointer: fine) { .pager-dots button[aria-current="false"]:hover::before { background: var(--msn-on-ink-2); } }
/* The carousel's dots at the photo's top left. No prev/next buttons (owner, 09/11): a swipe or the arrow keys on the
   dots move the story. */
.msn-lead { touch-action: pan-y; }
.lead-dots { position: absolute; top: 0; left: var(--space-12); z-index: 3; padding-inline: var(--space-6); }

/* ---------- "Chuyện lớn": a numbered list ---------- */
.msn-toplist { display: flex; flex-direction: column; padding: var(--space-12) var(--space-12) var(--space-8); }
.msn-toplist h2 { display: flex; align-items: center; gap: var(--space-8); margin: 0 0 var(--space-4); font-size: var(--text-sub); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--color-ink); }
.msn-toplist h2::before { content: ""; width: var(--space-8); height: var(--space-8); border-radius: var(--radius-full); background: var(--color-accent-fill); }
.msn-toplist ol { display: flex; flex-direction: column; flex: 1; margin: 0; padding: 0; list-style: none; }
.msn-toplist li {
  position: relative; flex: 1; display: flex; gap: var(--space-12); min-height: var(--btn-h); padding: var(--space-8) var(--space-4);
  border-top: var(--msn-hair) solid var(--color-hair); border-radius: 0; transition: background-color var(--duration-150) ease;
}
.msn-toplist li:first-child { border-top: 0; }

.msn-toplist li > b { min-width: var(--space-16); font-size: var(--text-tile); line-height: 1.1; font-weight: var(--weight-bold); color: var(--color-ink); }
.top-text { display: flex; flex-direction: column; min-width: 0; }
.msn-toplist .top-title {
  font-size: var(--text-meta); line-height: 1.38; font-weight: var(--weight-semibold); color: var(--color-ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.msn-toplist .is-read .top-title { color: var(--color-ink-2); }
/* The source and the time share a line and the time never breaks; the "Translated" mark moves under them when the line
   is full, and the source gives way (ellipsis) only when it and the time alone overflow. */
.top-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--msn-tight) var(--space-4); min-width: 0; margin-top: var(--msn-dot); font-size: var(--text-micro); line-height: 1.35; white-space: nowrap; color: var(--color-ink-3); }
.top-meta .st-mark:empty { display: none; }
.top-who { display: flex; flex-wrap: wrap; flex: 1 1 0; gap: 0 var(--space-4); min-width: 0; }
.top-meta { flex-wrap: nowrap; }
.top-src { min-width: 0; overflow-wrap: anywhere; white-space: normal; }
.top-who > :not(.top-src), .top-meta > :not(.top-who) { flex: none; }
.top-meta .mt { margin: 0; }
/* From 1100px the list shares the first row's fixed height with the lead: a tighter rhythm keeps all four stories,
   each with a two-line headline and a two-line source line, inside the card. */
@media (max-width: 1099px) {
  .top-who { flex-wrap: wrap; }   /* the card grows with its rows here, so a long source name keeps every letter */
}
@media (min-width: 1100px) {
  .msn-toplist li { padding: var(--space-6) var(--space-4); }
  .msn-toplist .top-title { line-height: 1.3; }
  .top-meta { row-gap: 0; margin-top: 0; }
}

/* ---------- the weather: a sky photograph, a flat ink veil, frosted tiles; no ring inside (captain, 08/11 19:50) ---------- */
.msn-wx {
  container-type: inline-size;
  isolation: isolate; display: flex; flex-direction: column; gap: var(--space-8); padding: var(--space-8) var(--space-12);
  border: 0; color: var(--msn-on-ink); text-shadow: var(--msn-wx-shadow);
  background: var(--msn-wx-sky) url("anh/bau-troi.jpg") center / cover no-repeat;
}
.msn-wx::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--msn-wx-veil); }
.msn-wx .i { width: var(--msn-fav); height: var(--msn-fav); }
.msn-wx .i-sm { width: var(--space-16); height: var(--space-16); stroke-width: 2.4; }
.wx-head { display: flex; align-items: center; margin: 0 calc(-1 * var(--space-6)); }
.wx-city, .wx-more, .wx-outlook {
  display: inline-flex; align-items: center; gap: var(--space-6); min-height: var(--btn-h); border-radius: var(--radius-8);
  background: transparent; color: inherit; transition: background-color var(--duration-150) ease;
}
.wx-city { padding: 0 var(--space-8); font-size: var(--text-sub); font-weight: var(--weight-bold); }
.wx-more { flex: none; margin-left: auto; width: var(--btn-h); justify-content: center; }
.wx-more .i circle { fill: currentColor; }
.wx-city:hover, .wx-more:hover, .wx-outlook:hover { background: var(--msn-wx-hover); }
.wx-body { display: flex; flex-direction: column; gap: var(--space-8); flex: 1; min-height: 0; }
.wx-now { display: flex; align-items: center; gap: var(--space-6); min-height: var(--msn-search-h); }
.wx-now .wx-ic { width: var(--msn-wx-icon); height: var(--msn-wx-icon); flex: none; filter: drop-shadow(var(--msn-wx-shadow)); }
.wx-temp { display: flex; align-items: flex-start; margin: 0; font-size: var(--msn-wx-temp); line-height: 1; font-weight: var(--weight-medium); letter-spacing: -0.04em; }
.wx-temp small { margin: var(--space-4) 0 0 var(--msn-tight); font-size: var(--text-body); font-weight: var(--weight-semibold); letter-spacing: 0; }
.wx-outlook { margin-left: auto; max-width: 54%; gap: var(--msn-tight); padding: var(--msn-tight) 0 var(--msn-tight) var(--space-6); text-align: right; font-size: var(--text-micro); line-height: 1.35; font-weight: var(--weight-semibold); }
.wx-switch {
  display: flex; align-self: flex-start; border-radius: var(--radius-8); background: var(--msn-wx-pill);
  -webkit-backdrop-filter: blur(var(--msn-blur)); backdrop-filter: blur(var(--msn-blur));
}
.wx-switch button { position: relative; min-height: var(--btn-h); padding: 0 var(--space-12); border-radius: var(--radius-8); font-size: var(--text-micro); font-weight: var(--weight-semibold); }
.wx-switch button[aria-pressed="true"] { background: var(--msn-wx-tile-on); }
.wx-switch button[aria-pressed="true"]::after { content: ""; position: absolute; left: 50%; bottom: var(--space-4); width: var(--space-16); height: var(--msn-tab-line); margin-left: calc(-1 * var(--space-8)); border-radius: var(--msn-tab-line); background: var(--msn-on-ink); }
.wx-days { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-4); margin: 0; padding: 0; list-style: none; }
.wx-days li {
  display: flex; flex-direction: column; align-items: center; justify-content: space-between; gap: var(--msn-tight); min-width: 0; padding: var(--space-8) var(--msn-tight);
  border-radius: var(--radius-8); background: var(--msn-wx-tile);
  -webkit-backdrop-filter: blur(var(--msn-blur)) saturate(140%); backdrop-filter: blur(var(--msn-blur)) saturate(140%);
  font-size: var(--text-micro); font-weight: var(--weight-semibold); transition: opacity var(--duration-150) ease;
}
/* Today is lit by a white wash over the ink tile, so it reads lighter yet keeps white text at AA over a bright cloud. */
.wx-days li:first-child { background: linear-gradient(var(--msn-wx-tile-on), var(--msn-wx-tile-on)), var(--msn-wx-tile); }
.wx-days .wx-ic { width: var(--msn-wx-icon-sm); height: var(--msn-wx-icon-sm); }
.wx-hi { font-size: var(--text-sub); font-weight: var(--weight-bold); }
.wx-lo { font-size: var(--text-micro); font-weight: var(--weight-medium); }
.wx-days.is-swapping li { opacity: 0; }
.wx-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
/* The weather card's two page dots: the pager dots above, their first dot on the card's content edge. */
.wx-dots { margin-left: calc(-1 * var(--pager-dot-pad)); }
.msn-wx .pill {
  display: inline-flex; align-items: center; min-height: var(--btn-h); padding: 0 var(--space-16); border-radius: var(--radius-full);
  background: var(--msn-wx-pill); color: inherit;
  -webkit-backdrop-filter: blur(var(--msn-blur)); backdrop-filter: blur(var(--msn-blur));
  font-size: var(--text-micro); font-weight: var(--weight-semibold); white-space: nowrap;
  transition: background-color var(--duration-150) ease, transform var(--duration-150) var(--ease-press);
}
.msn-wx .pill:hover { background: var(--msn-wx-pill-hover); }
.msn-wx .pill:active { transform: scale(0.97); }
.wx-full-short { display: none; }
.wx-city { min-width: 0; }
#wx-city-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wx-skel { display: grid; gap: var(--space-8); flex: 1; }
.wx-skel i { display: block; border-radius: var(--radius-8); background: var(--msn-wx-tile); animation: msn-breathe 1.2s ease-in-out infinite alternate; }
.wx-skel i:first-child { height: var(--msn-search-h); }
.wx-error { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: var(--space-12); flex: 1; font-size: var(--text-small); font-weight: var(--weight-semibold); }
.wx-detail {
  position: absolute; inset: 0; z-index: 4; display: flex; flex-direction: column; gap: var(--space-12); padding: var(--space-8) var(--space-12) var(--space-12);
  background: var(--msn-wx-solid); -webkit-backdrop-filter: blur(var(--msn-blur)); backdrop-filter: blur(var(--msn-blur));
}
.wx-detail[hidden] { display: none; }
.wx-detail-top { display: flex; align-items: center; gap: var(--space-8); }
.wx-detail-h { margin: 0; font-size: var(--text-sub); font-weight: var(--weight-bold); }
.wx-stats { display: grid; gap: var(--space-4); margin: 0; }
.wx-stats div { display: flex; justify-content: space-between; gap: var(--space-12); padding: var(--space-8) var(--space-12); border-radius: var(--radius-8); background: var(--msn-wx-tile); font-size: var(--text-small); }
.wx-stats dt { font-weight: var(--weight-medium); }
.wx-stats dd { margin: 0; font-weight: var(--weight-bold); }
.wx-credit { margin-top: auto; font-size: var(--text-micro); }
.wx-credit a { text-decoration: underline; text-underline-offset: 0.15em; }
.wx-menu {
  position: absolute; z-index: 5; top: var(--msn-menu-top); min-width: var(--msn-wx-menu-w); max-height: var(--msn-menu-max-h); overflow: auto;
  margin: 0; padding: var(--space-6); border-radius: var(--radius-12); background: var(--color-surface); color: var(--color-ink); text-shadow: none;
  box-shadow: var(--shadow-sheet); transform-origin: top left; transition: opacity var(--duration-150) ease, transform var(--duration-150) var(--ease-flow);
}
.wx-menu.at-right { right: var(--space-8); transform-origin: top right; }
.wx-menu.at-left { left: var(--space-6); }
.wx-menu[data-closed] { opacity: 0; transform: scale(0.96); pointer-events: none; }
.wx-menu p { margin: var(--space-4) var(--space-12) var(--space-6); font-size: var(--text-micro); font-weight: var(--weight-semibold); color: var(--color-ink-3); }
.wx-menu button, .wx-menu a {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); width: 100%; min-height: var(--btn-h);
  padding: 0 var(--space-12); border-radius: var(--radius-8); text-align: left; font-size: var(--text-meta); font-weight: var(--weight-medium); color: var(--color-ink);
}
.wx-menu button:hover, .wx-menu a:hover { background: var(--color-fill); }
.wx-menu [aria-checked="true"] { font-weight: var(--weight-bold); }
.wx-menu [aria-checked="true"]::after { content: "✓"; }

/* ---------- the calendar: a page of a Vietnamese tear-off calendar (lịch bloc) ----------
   Captain, 08/11 21:08: "Đưa con giáp tháng hoặc ngày, làm nền cho card lịch. Thiết kế lại card lịch cho giống phong cách
   lịch phương đông". The coral band is the red head of a lịch bloc; the big day and its weekday fill the page's middle
   (coral on Sunday); the lunar half sits at the foot: the lunar day large in coral, its month, then the can chi of the
   day, the month and the year and the solar term. The day's animal is the page's art: the shipped illustration's
   silhouette in a coral wash (a seal), large and cut by the card's corner, behind the text. No border, no ring. */
.msn-cal { container-type: inline-size; isolation: isolate; display: flex; flex-direction: column; padding: 0 0 var(--space-16); }
.cal-art {
  position: absolute; z-index: -1; top: 22%; right: -12%; width: var(--msn-cal-art-w); aspect-ratio: 1;
  background: var(--color-art-wash);
  -webkit-mask: var(--cal-art) center / contain no-repeat; mask: var(--cal-art) center / contain no-repeat;
}
.cal-band {
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-8); margin: 0; padding: var(--space-8) var(--space-16);
  background: var(--color-accent-fill); color: var(--color-on-accent);
  font-size: var(--text-micro); line-height: 1.3; font-weight: var(--weight-bold); letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap;
}
/* The big day and its weekday take the height the row leaves over, centred in it, so the spare room sits around the
   date instead of opening a band above the lunar half. The day follows the card's width. */
.cal-hero { flex: 1 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-8) var(--space-16) 0; text-align: center; }
.msn-cal .cal-day { font-size: clamp(var(--msn-cal-day-phone), var(--msn-cal-day-fluid), var(--msn-cal-day)); font-weight: var(--weight-bold); line-height: 0.9; letter-spacing: -0.06em; color: var(--color-ink); }
.cal-week { margin-top: var(--space-6); font-size: var(--text-small); font-weight: var(--weight-bold); line-height: 1.3; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink); }
.cal-hero.is-sunday :is(.cal-day, .cal-week) { color: var(--color-accent); }
.cal-moon { display: flex; flex-direction: column; gap: var(--space-8); margin: var(--space-12) var(--space-16) 0; }
.cal-lunar { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: var(--space-8); align-items: end; margin: 0; }
.cal-lunar b { grid-row: 1 / 3; font-size: var(--msn-cal-moon); line-height: 0.9; font-weight: var(--weight-bold); letter-spacing: -0.04em; color: var(--color-accent); }
.cal-k { font-size: var(--text-micro); line-height: 1.3; font-weight: var(--weight-bold); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-2); }
.cal-lunar span:last-child { font-size: var(--text-sub); line-height: 1.25; font-weight: var(--weight-bold); color: var(--color-ink); }
.msn-cal .cal-canchi { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4) var(--space-8); margin: 0; padding: 0; list-style: none; }
.cal-canchi li { font-size: var(--text-micro); line-height: 1.35; color: var(--color-ink-2); }
.cal-canchi b { display: block; font-size: var(--text-meta); font-weight: var(--weight-bold); color: var(--color-ink); }
.msn-cal .cal-note { margin: var(--space-8) var(--space-16) 0; padding: 0; font-size: var(--text-micro); line-height: 1.35; font-weight: var(--weight-semibold); color: var(--color-ink-2); }
/* ---------- the next event: the cell left of the calendar ----------
   Owner, 09/11: "Đưa sự kiện sắp diễn ra lên phần đầu trang, đặt nó ở vị trí phù hợp." The calendar says what day it is;
   the cell beside it says what is coming, at every width: left of the calendar in the second row on a desktop and a
   tablet (on the first screen), beside it on a phone (before the first ordinary story). The days are printed large as
   on the calendar page, in ink, so the calendar's coral band stays the one loud colour of the pair. */
.msn-grid > .msn-ev { grid-area: 2 / -3; }
.msn-ev { container-type: inline-size; display: flex; flex-direction: column; gap: var(--space-12); padding: var(--space-12) var(--space-16) var(--space-16); }
.ev-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); }
.ev-head h2 { display: flex; align-items: center; gap: var(--space-8); margin: 0; font-size: var(--text-sub); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--color-ink); white-space: nowrap; }
.ev-head h2::before { content: ""; width: var(--space-8); height: var(--space-8); border-radius: var(--radius-full); background: var(--color-accent-fill); }
.ev-all {
  display: inline-flex; align-items: center; min-height: var(--btn-h); margin-block: calc(-1 * var(--space-12)); margin-right: calc(-1 * var(--space-8)); padding: 0 var(--space-8);
  border-radius: var(--radius-8); font-size: var(--text-meta); font-weight: var(--weight-semibold); color: var(--color-accent); white-space: nowrap;
}
/* "Hai mươi lăm" (captain, 10/11 ~21:05, choosing the mockup): the number is the card. The days left are its one large
   thing; under them a day ruler (today in ink, the wait, the event's own days in coral); then the name, the dates and
   place and the opening hour as one quiet caption; then the calendar buttons, the only other coral. The parts stack
   the same way at every width. */
.msn-ev { --ev-tick: color-mix(in srgb, var(--color-ink-3) 32%, transparent); --ev-tick-gap: calc(var(--space-6) / 2); --ev-tick-r: calc(var(--space-4) / 2); }
.ev-next { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.ev-count { display: flex; margin: 0; min-width: 0; }
.ev-count.cd, .ev-count.cd.is-on, .ev-count.cd.is-over { color: var(--color-ink); font-weight: var(--weight-bold); }
.ev-count .cd-face { display: flex; align-items: flex-end; gap: var(--space-8); min-width: 0; }
.ev-n { font-size: min(var(--num-count), 50cqi); line-height: 0.82; font-weight: var(--weight-bold); letter-spacing: -0.055em; margin-inline-start: -0.045em; }
.ev-n.is-long { font-size: min(var(--size-88), 38cqi); }
.ev-n.is-word { font-size: var(--num-md); line-height: 1.15; letter-spacing: -0.03em; margin-inline-start: 0; }
.ev-u { padding-bottom: 0.1em; font-size: var(--text-sub); line-height: 1.2; font-weight: var(--weight-semibold); color: var(--color-ink-2); white-space: nowrap; }
.ev-ruler { display: flex; flex-direction: column; gap: var(--space-6); margin-top: var(--space-16); }
.ev-ruler:empty { display: none; }
.ev-ticks { display: flex; gap: var(--ev-tick-gap); height: var(--space-12); }
.ev-ticks i { flex: 1; min-width: 0; border-radius: var(--ev-tick-r); background: var(--ev-tick); }
.ev-ticks .is-now { background: var(--color-ink); }
.ev-ticks .is-on { background: var(--color-accent-fill); }
.ev-ticks .is-done { background: var(--color-accent-wash-strong); }
.ev-legend { display: flex; justify-content: space-between; gap: var(--space-8); font-size: var(--text-micro); line-height: 1.35; font-weight: var(--weight-medium); color: var(--color-ink-3); white-space: nowrap; }
.ev-legend > :first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ev-legend b { flex: none; font-weight: var(--weight-semibold); color: var(--color-accent); }
.ev-live { color: var(--color-live); font-weight: var(--weight-semibold); }
.ev-link { display: flex; flex-direction: column; min-width: 0; margin-top: auto; padding-top: var(--space-12); color: inherit; }
.ev-name {
  font-size: var(--text-title); line-height: 1.3; font-weight: var(--weight-semibold); letter-spacing: -0.015em; color: var(--color-ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-wrap: pretty;
}
.ev-next.is-read .ev-name { color: var(--color-ink-2); }
.ev-meta { font-size: var(--text-meta); line-height: 1.5; color: var(--color-ink-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ev-note { font-size: var(--text-micro); line-height: 1.35; color: var(--color-ink-3); }
/* The calendar pair: Google is the card's one filled button, .ics a tonal one beside it. */
.msn-ev .calbtn { display: flex; gap: var(--space-8); margin-top: var(--space-12); border-radius: 0; background: none; overflow: visible; }
.msn-ev :is(.calbtn-g, .calbtn-ics) { min-height: var(--btn-h); border-radius: var(--radius-12); transition: transform var(--duration-150) ease-out, background-color var(--duration-150) ease; }
.msn-ev .calbtn-g { flex: 1; min-width: 0; background: var(--color-accent-fill); color: var(--color-on-accent); }
.msn-ev .calbtn-ics { min-width: calc(var(--btn-h) + var(--space-16)); background: var(--color-fill); color: var(--color-ink); box-shadow: none; }
.msn-ev .calbtn-g:active, .msn-ev .calbtn-ics:active { transform: scale(0.97); }
.msn-ev .calbtn-g:active { background: var(--color-accent-fill-hover); color: var(--color-on-accent); }
.msn-ev .calbtn-ics:active { background: var(--color-field-on); color: var(--color-ink); }
.msn-ev .calbtn :focus-visible { outline-offset: var(--focus-offset); border-radius: var(--radius-12); }
.msn-ev .calbtn-add { display: none; }
@container (min-width: 17rem) { .msn-ev .calbtn-add { display: inline; } }
.ev-stream { display: flex; flex-direction: column; gap: var(--space-4); min-height: var(--btn-h); padding: var(--space-8) var(--space-12); border-radius: var(--radius-8); background: var(--color-fill); color: inherit; transition: background-color var(--duration-150) ease; }
.ev-stream-k { font-size: var(--text-micro); line-height: 1.3; font-weight: var(--weight-bold); color: var(--color-ink-2); }
.ev-stream-k.is-live { color: var(--color-live); }
.ev-stream-t { font-size: var(--text-meta); line-height: 1.35; font-weight: var(--weight-semibold); color: var(--color-ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.msn-ev :is(.ev-link, .ev-stream, .ev-all):focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-8); }
@media (hover: hover) and (pointer: fine) {
  .ev-stream:hover { background: var(--color-field-on); }
  .ev-all:hover { background: var(--color-fill); }
  .msn-ev .calbtn-g:hover { background: var(--color-accent-fill-hover); color: var(--color-on-accent); }
  .msn-ev .calbtn-ics:hover { background: var(--color-field-on); color: var(--color-ink); }
}
@media (prefers-reduced-motion: reduce) {
  .msn-ev .calbtn-g:active, .msn-ev .calbtn-ics:active { transform: none; }
}
@container (max-width: 14rem) {
  .ev-name { font-size: var(--text-sub); }
  .msn-ev .calbtn-g .i { display: none; }
}
.msn-grid > .ev-empty { grid-column: 1 / -2; align-self: start; margin: 0; padding: var(--space-16) var(--space-4); background: none; box-shadow: none; font-size: var(--text-body); color: var(--color-ink-2); }

/* ---------- the two cards on a narrow cell (five columns near 1100 px, three near 768 px) ---------- */
@container (max-width: 14rem) {
  .wx-city { padding: 0 var(--space-6); font-size: var(--text-meta); }
  .wx-city > .i:first-child { display: none; }
  .wx-now { flex-wrap: wrap; row-gap: 0; }
  .wx-outlook { flex-basis: 100%; max-width: none; margin: 0 calc(-1 * var(--space-6)); padding: 0 var(--space-6); text-align: left; }
  .wx-days li { padding-block: var(--space-6); }
  .wx-full-long { display: none; }
  .wx-full-short { display: inline; }
  .cal-band, .cal-hero { padding-inline: var(--space-12); }
  .cal-moon { margin-inline: var(--space-12); }
  .msn-cal .cal-note { margin-inline: var(--space-12); }
  .cal-lunar span:last-child { font-size: var(--text-meta); }
}

/* ---------- the front page's tiles as widgets ---------- */
.msn-grid > .tile {
  min-width: 0; min-height: 0; gap: var(--space-12); padding: var(--space-16); overflow: auto; overscroll-behavior: contain;
  background: var(--color-surface); border: 0; border-radius: var(--msn-card-r); box-shadow: var(--msn-shadow-rest);
}
.msn-grid.is-front > .tile { grid-column: span 2; grid-row: span 2; }
/* "Vừa đăng" sits beside the lead in the first row (owner, 10/11: "mục 'Vừa đăng' nằm ở mãi dưới"; his rule of 10/10:
   "người dùng vào đọc tin thì luôn muốn xem tin mới trước chứ"), one row tall; "Chuyện lớn" opens the second row. */
.msn-grid.is-front > .tile-fresh { grid-row: span 1; }
.fresh-list .fresh-new { display: none; }
.fresh-list li[data-pinned]:not(.is-read) .fresh-new {
  display: inline-block; margin-right: var(--space-6); padding: 0 var(--space-6); border-radius: var(--radius-full);
  background: var(--color-accent-fill); color: var(--color-on-accent);
  font-size: var(--text-micro); font-weight: var(--weight-bold); line-height: 1.6; vertical-align: 0.08em;
}
.fresh-list li[data-pinned]:not(.is-read) .new-mark { display: none; }
.fresh-list li, .fresh-list .brief, .briefs li + li .brief { border-radius: 0; }
/* Only whole rows (feed.js, fitFreshTile): rows outside the page are left out, and a page's first row drops the rule
   it would draw against the row before it. A batch longer than the tile pages with "‹ 1/2 ›" in the head, the shelf's
   own quiet buttons; it is for every pointer, not only a mouse. */
.fresh-list > li[hidden] { display: none; }
.fresh-list > li[hidden] + li .brief { border-top-color: transparent; }
/* The buttons keep their 44px target but take no more height than the title, so the list starts where it did. */
.tile-fresh .fresh-pager { gap: var(--space-4); margin-block: calc(-1 * var(--space-12)); }
.fresh-pager[hidden] { display: none; }
.fresh-page { min-width: 3ch; font-size: var(--text-meta); font-weight: var(--weight-semibold); color: var(--color-ink-2); text-align: center; }
.fresh-list li.is-flash { animation: fresh-flash var(--fresh-flash) var(--ease-flow) both; }
@keyframes fresh-flash { from, 35% { background: var(--color-accent-wash-strong); } to { background: transparent; } }
.msn-grid:not(.is-front) > .tile { grid-column: 1 / -1; overflow: visible; }
/* "Sắp diễn ra" (#sap-toi): the list, or its one empty line (.ev-empty), takes the columns left of the weather and the
   calendar from the first row, so the view never opens on an empty band. */
.msn-grid:not(.is-front) > .tile-live { grid-column: 1 / -2; grid-row: span 2; align-self: start; }
:is(.msn-grid, .band-grid) > .tile .tile-title { font-size: var(--text-sub); font-weight: var(--weight-bold); letter-spacing: 0; color: var(--color-ink); }
:is(.msn-grid, .band-grid) > .tile .tile-note { font-size: var(--text-micro); }

/* ---------- the models and code band (captain, 10/11 15:19: "gom các thành phần giống nhau vào 1 chỗ") ---------- */
/* "Mô hình dẫn đầu", "Kho mã đáng lấy" and "Mô hình đáng thử" side by side across the grid, under one heading; each
   tile keeps the height a 2x2 tile had and scrolls inside it, as before. Narrower, two then one per row. */
.msn-grid > .tile-band { grid-column: 1 / -1; min-width: 0; }
.band-title { display: flex; align-items: center; gap: var(--space-8); margin: var(--space-4) 0 var(--space-12) var(--space-4); font-size: var(--text-title); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--color-ink); }
.band-title::before { content: ""; width: var(--space-8); height: var(--space-8); border-radius: var(--radius-full); background: var(--color-accent-fill); }
.band-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--band-tile-min)), 1fr)); gap: var(--msn-gap);
  grid-auto-rows: calc(var(--msn-row) * 2 + var(--msn-gap));
}
.band-grid > .tile {
  grid-column: auto; grid-row: auto; min-width: 0; min-height: 0; gap: var(--space-12); padding: var(--space-16); overflow: auto; overscroll-behavior: contain;
  background: var(--color-surface); border: 0; border-radius: var(--msn-card-r); box-shadow: var(--msn-shadow-rest);
}

/* ---------- the front page's five bands (captain, 10/11 17:51: "Duyệt, giao sửa") ----------
   Hôm nay · Điểm nhấn · Tin mới · Mô hình và mã nguồn · Tin khác, top to bottom, each under the same heading. Inside a
   band every card in a row has the band's height (grid-auto-rows) and its content fits that height: lists show whole
   rows (feed.js, fitBandLists, fitFreshTile), headlines are clamped by line. The spans below keep every row full at
   five, four and three columns; feed.js builds "Tin mới" and "Tin khác" from the same column count. A phone is one
   column. */
.msn-grid.is-front { display: flex; flex-direction: column; gap: var(--band-gap); }
.band { display: flex; flex-direction: column; min-width: 0; }
.band[hidden] { display: none; }
.band > .band-title { margin: 0 0 var(--space-12) var(--space-4); }
.band-cells {
  --band-row: var(--band-h-news);
  display: grid; grid-template-columns: repeat(var(--bento-cols), minmax(0, 1fr)); grid-auto-rows: var(--band-row);
  grid-auto-flow: row; gap: var(--msn-gap);
}
.band-today .band-cells, .band-focus .band-cells { --band-row: var(--band-h-top); }
.band-cells > * { min-width: 0; min-height: 0; }
.band-cells > .msn-lead, .band-cells > .nc-wide, .band-cells > .tile-fresh { grid-column: span 2; }
.band-cells > .tile {
  gap: var(--space-12); padding: var(--space-12) var(--space-16) var(--space-16); overflow: hidden;
  background: var(--color-surface); border: 0; border-radius: var(--msn-card-r); box-shadow: var(--msn-shadow-rest);
}

/* Labels and headlines (captain, 10/11: the card names read like the headlines). A card's name is a small label; a
   band's heading is the one larger heading; a story's headline is never set like either. */
.band :is(.tile .tile-title, .msn-toplist h2, .ev-head h2) {
  margin: 0; font-size: var(--text-micro); line-height: 1.3; font-weight: var(--weight-bold); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--color-ink-2);
}
.band :is(.msn-toplist h2, .ev-head h2)::before { display: none; }
.band .tile .tile-head { align-items: center; min-height: var(--space-24); }
.band .tile .tile-note { font-size: var(--text-micro); }

/* "Vừa đăng" fills its cell: whole rows (fitFreshTile), sharing the height the tile has, headlines up to three lines. */
.band #fresh-row { margin: 0; }
.band .tile-fresh .fresh-list { flex: 1; min-height: 0; grid-auto-rows: auto; align-content: stretch; }
.band .tile-fresh .fresh-list > li { display: flex; min-height: 0; }
.band .tile-fresh .brief { flex: 1; align-items: center; padding-block: var(--space-8); }
.band .tile-fresh .brief time { padding-top: 0; }
.band .tile-fresh .brief-h { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* "Chuyện lớn": the four stories share the card's height; a row that cannot fit whole is left out (fitBandLists). */
.band .msn-toplist { padding: var(--space-12) var(--space-12) var(--space-8); }
.band .msn-toplist h2 { margin: 0 0 var(--space-6) var(--space-4); }
.band .msn-toplist ol { min-height: 0; overflow: hidden; }
.band .msn-toplist li { min-height: 0; padding: var(--space-6) var(--space-4); }
.band :is(.arena-list, .repo-row, .model-list, .msn-toplist ol) > [hidden] { display: none !important; }

/* "Đáng chú ý": the double story card of the second band. */
.band-focus .nc-wide .nc-title { font-size: var(--msn-title-big); line-height: 1.3; letter-spacing: -0.02em; -webkit-line-clamp: 6; }
.band-focus .nc-wide .nc-sum { -webkit-line-clamp: 4; }

/* "Sắp diễn ra" in its band: a white card like its neighbours (the mockup the captain chose on 10/11 ~21:05 replaced
   the coral-washed ticket of 19:3x). With more events, or a stream, the card is dense: a smaller number, the ruler
   without its legend, no opening-hour line, and the next events as a short schedule at its foot. On a phone the card
   is as tall as it needs, so nothing is left out there. */
.band .msn-ev { padding: var(--space-12) var(--space-16) var(--space-16); }
.ev-more { display: flex; flex-direction: column; min-height: 0; margin: auto 0 calc(-1 * var(--space-8)); padding: var(--space-8) 0 0; list-style: none; }
.ev-more li { border-top: var(--msn-hair) solid var(--color-hair); }
.ev-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); min-height: var(--btn-h); padding-block: var(--space-6); color: inherit; }
.ev-row-text { display: flex; flex-direction: column; min-width: 0; }
.ev-row-t { font-size: var(--text-meta); font-weight: var(--weight-semibold); line-height: 1.35; color: var(--color-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ev-row-m { font-size: var(--text-micro); line-height: 1.35; color: var(--color-ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ev-row-d { flex: none; font-size: var(--text-micro); line-height: 1.35; white-space: nowrap; }
.ev-row-d.cd, .ev-row-d.cd.is-over { font-weight: var(--weight-semibold); color: var(--color-ink-2); }
.ev-row-d.cd.is-on { color: var(--color-live); }
.msn-ev .ev-row { --row-wash-x: 0px; --row-wash-y: 0px; }
.msn-ev .ev-row:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-8); }
@media (min-width: 768px) {
  .msn-ev.is-dense .ev-n:not(.is-word) { font-size: min(var(--num-count-dense), 36cqi); }
  .msn-ev.is-dense .ev-n.is-long { font-size: min(var(--size-56), 28cqi); }
  .msn-ev.is-dense .ev-u { font-size: var(--text-small); }
  .msn-ev.is-dense .ev-ruler { margin-top: var(--space-12); }
  .msn-ev.is-dense .ev-ticks { height: var(--space-8); }
  .msn-ev.is-dense :is(.ev-legend, .ev-note) { display: none; }
  .msn-ev.is-dense .ev-link { margin-top: 0; }
  .msn-ev.is-dense .ev-name { -webkit-line-clamp: 1; }
}

/* "Mô hình và mã nguồn": the tiles side by side, as many columns as tiles, one height. */
.band-lab .band-grid { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); grid-auto-rows: var(--band-h-lab); }
.band-lab .band-grid > .tile { container-type: inline-size; overflow: hidden; padding: var(--space-12) var(--space-16) var(--space-12); }
.band-lab :is(.arena-list, .repo-row, .model-list) { flex: 1 1 0; min-height: 0; overflow: hidden; }
.band-lab .tile-foot { margin-top: 0; }
.band-lab .tile-arena { min-height: 0; }
.band-lab .tile-models { align-self: stretch; }
.band-lab .tile-repos.has-area { grid-column: auto; }
/* One filter row in the tile (captain, 10/11: "Kho mã có 3 hàng bộ lọc"); the window, the totals and the work areas
   appear with the whole list when the reader opens it ("Mở rộng"). */
.band-lab:not(.is-open) .tile-repos :is(.seg-quiet, .area-chips, .repo-note, .repo-more) { display: none; }
.band-lab .repo-ctl { flex-wrap: nowrap; overflow: hidden; }
.band-lab.is-open .band-grid { grid-auto-rows: auto; }
.band-lab.is-open .repo-ctl { flex-wrap: wrap; }
.band-lab.is-open :is(.arena-list, .repo-row, .model-list) { flex: none; overflow: visible; }
.lab-open { margin-left: auto; }
/* A narrow tile (four or three columns) keeps the names and numbers and leaves out the preview pictures. */
@container (max-width: 24rem) {
  .band-lab .repo { grid-template-columns: minmax(0, 1fr); }
  .band-lab .repo-img { display: none; }
  .band-lab .model { grid-template-columns: minmax(0, 1fr); }
  .band-lab .model-img { display: none; }
}

/* "Tin khác": whole rows that load as the reader scrolls (feed.js, loadMoreFront), the older days under full-width
   headings set like the bands' own, so a heading never breaks a row. A group's last stories share their row as wider
   cards (span-3 and up; span 2 is the double card's own). */
.more-box { display: flex; flex-direction: column; gap: var(--msn-gap); min-width: 0; }
.more-box > .band-cells:empty { display: none; }
.more-box > .day-line.band-title {
  margin: calc(var(--band-gap) - var(--msn-gap)) 0 0 var(--space-4); padding: 0; line-height: 1.3;
  font-size: var(--text-title); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--color-ink);
}
.band-cells > .span-3 { grid-column: span 3; }
.band-cells > .span-4 { grid-column: span 4; }
.band-cells > .span-5 { grid-column: span 5; }

/* ---------- one row of any list: Vừa đăng, Chuyện lớn, Đang nóng, the band's lists, Sắp diễn ra ---------- */
/* One wash behind the whole row, the same for the pointer (only where there is one that hovers) and for the keyboard,
   which adds the focus ring around the wash. Defined once here; feed.js gives every list row the class. The wash is
   square, so it reads as one with the straight rules between the rows (captain, 10/11: "hover bo góc, đường kẻ thẳng"). */
.list-row { position: relative; isolation: isolate; outline: none; border-radius: 0; }
.list-row::before {
  content: ""; position: absolute; z-index: -1; inset: calc(-1 * var(--row-wash-y)) calc(-1 * var(--row-wash-x));
  border-radius: 0; background: transparent; pointer-events: none;
  transition: background-color var(--duration-150) ease;
}
@media (hover: hover) and (pointer: fine) { .list-row:hover::before { background: var(--row-wash); } }
.list-row:focus-visible, .list-row:has(:focus-visible), .list-row :focus-visible { outline: none; }
.list-row:focus-visible::before, .list-row:has(:focus-visible)::before { background: var(--row-wash); outline: var(--focus-ring); outline-offset: 0; }
/* Rows that carry their own padding and dividers wash inside their box. */
.msn-toplist li.list-row, .brief.list-row { --row-wash-x: 0px; --row-wash-y: 0px; }
.arena-go.list-row { --row-wash-y: var(--space-4); }

/* ---------- loading, more and the end ---------- */
.msn-sk { background: var(--color-fill); box-shadow: none; animation: msn-breathe 1.2s ease-in-out infinite alternate; }
#feed-skeleton .msn-lead { grid-column: span 2; }
@keyframes msn-breathe { from { opacity: 0.55; } to { opacity: 1; } }
.feed-sentinel { height: var(--msn-hair); }
.feed-status:empty { display: none; }
.loading-line { display: flex; align-items: center; justify-content: center; gap: var(--space-8); min-height: var(--btn-h); margin-top: var(--space-8); font-size: var(--text-micro); color: var(--color-ink-3); }
.spinner { width: var(--msn-spinner); height: var(--msn-spinner); border-radius: var(--radius-full); border: var(--msn-spinner-w) solid var(--color-hair); border-top-color: var(--color-ink-2); animation: msn-spin 700ms linear infinite; }
@keyframes msn-spin { to { transform: rotate(360deg); } }
/* The older days at the end of the stream: one section per day, its line then its own grid of the same columns and rows,
   filled in order (no dense packing), so a day's stories never rise above its line. The line is quiet: the day's name in
   small muted type, no rule, no count. */
.msn-days { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--msn-gap); }
.msn-day { display: flex; flex-direction: column; gap: var(--space-8); }
.msn-day-grid {
  display: grid; grid-template-columns: repeat(var(--msn-cols), minmax(0, 1fr));
  grid-auto-rows: minmax(var(--msn-row), auto); gap: var(--msn-gap);
}
.day-line {
  margin: var(--space-16) 0 0; padding: 0 var(--space-4);
  font-size: var(--text-meta); font-weight: var(--weight-semibold); letter-spacing: 0; line-height: 1.4; color: var(--color-ink-2);
}
/* The stream's end: no card, one quiet action. */
.feed-end { display: flex; justify-content: center; margin-top: var(--space-16); }
.feed-end[hidden] { display: none; }
.feed-end .text-btn { min-height: var(--btn-h); padding: 0 var(--space-16); font-size: var(--text-small); color: var(--color-ink-2); text-decoration: none; }
.feed-end .text-btn:hover { color: var(--color-ink); text-decoration: underline; }
.msn-panel .feed-empty { margin-top: var(--space-24); }
.msn-grid .seg-b { min-height: var(--btn-h); }

/* ---------- widths ---------- */
/* At most five columns at any width (captain, 10/11 17:51: seven columns were too dense); the panel stops at
   --msn-panel-max and the day's picture shows beside it. */
/* Three columns: the lead and the weather fill the first row, "Vừa đăng" and the calendar the second; the next event
   follows the stories in the page's order. */
@media (min-width: 700px) and (max-width: 1099px) {
  .msn-grid > .msn-ev { grid-area: auto; }
}
@media (min-width: 1100px) and (max-width: 1450px) {
  .newsbar.msn-head { gap: var(--space-8); }
  .msn-head .filter-chip { padding: 0 var(--space-8); }
  .msn-head .filter-chip[aria-pressed="true"]::after { left: var(--space-8); right: var(--space-8); }
}
/* The tabs fill this row, so the order is the one button that says the current order and switches it, as on a phone. */
@media (min-width: 1280px) and (max-width: 1365px) {
  .msn-head .sort-btn:not(.sort-btn-compact) { display: none; }
  .msn-head .sort-btn-compact { display: inline-flex; padding-inline: var(--space-8); }
  .msn-head .sort-switch .tab-pill { display: none; }
}
/* Narrower still, even that button would push the last tabs out of sight: the tabs take their own row, as under 1100px. */
@media (min-width: 1100px) and (max-width: 1279px) {
  .newsbar.msn-head { flex-wrap: wrap; }
  .msn-head .sections { order: 3; flex: 1 1 100%; overflow-x: auto; }
}
@media (max-width: 1099px) {
  :root { --msn-cols: 3; }
  .newsbar.msn-head { flex-wrap: wrap; }
  .msn-head .sections { order: 3; flex: 1 1 100%; overflow-x: auto; }
}
@media (max-width: 767px) {
  /* A phone: the weather and the day beside "Tùy chỉnh" and the 9 dots, the search on its own row under them. */
  .msn-top-in { grid-template-columns: minmax(0, 1fr) auto; row-gap: var(--space-8); }
  .top-now { grid-column: 1; grid-row: 1; flex-direction: column; align-items: flex-start; gap: 0; font-size: var(--text-meta); }
  .top-temp { font-size: var(--text-small); }
  .top-wx-ic { width: var(--space-16); height: var(--space-16); }
  .msn-top .masthead-actions { grid-column: 2; grid-row: 1; gap: var(--space-4); }
  .msn-top .news-search, .msn-top .web-search { grid-column: 1 / -1; grid-row: 2; }
  .msn-top .ns-field { display: flex; position: static; }
  .msn-top .news-search.open .ns-field { position: static; inset: auto; }
  .msn-top .news-search.open .ns-open { visibility: hidden; }
  .msn-top .ns-results { top: calc(100% + var(--space-4)); }
  /* The dock below carries "Bản tin" and "Tìm tin" (captain, 09/11: "có cái gì bỏ được nữa thì bỏ luôn"): the head
     drops the morning edition and the search keeps its field (results show as the reader types, the keyboard has its
     own search key). The footer keeps "Nguồn tin": the dock gave that place to the events (owner, 09/11). */
  .msn-head .ed-link, .msn-top .ns-go { display: none; }
}
@media (max-width: 699px) {
  :root { --msn-gap: var(--space-8); --msn-cols: 2; }
  .msn-top { padding: var(--space-8) var(--space-8) 0; }
  .msn-top-in { margin-bottom: var(--space-8); gap: var(--space-8); }
  .msn-top .ns-field { padding-left: var(--space-12); }
  .ns-go { padding: 0 var(--space-16); }
  .feed-main.front.msn-panel { margin: 0 var(--space-8) var(--space-32); padding: var(--space-8); border-radius: var(--radius-12); }
  .newsbar.msn-head { gap: var(--space-4); margin-bottom: var(--space-6); }
  .msn-head .brand-tile { width: var(--space-32); height: var(--space-32); }
  .msn-head .brand-name { font-size: var(--text-tile); }
  .msn-head .filter-chip { padding: 0 var(--space-8); font-size: var(--text-meta); }
  .msn-head .filter-chip[aria-pressed="true"]::after { left: var(--space-8); right: var(--space-8); }
  .front-meta .filter-context { margin-top: var(--space-4); }
  .msn-grid, .msn-grid.is-front, .msn-grid:has(> .msn-wx) { grid-template-rows: none; grid-auto-rows: auto; }
  /* On a phone the two cards come first in the grid's own order (after the lead on the front page). */
  .msn-grid > .msn-wx { grid-area: auto / 1 / auto / -1; }
  .msn-grid > .msn-cal, .msn-grid > .msn-ev { grid-area: auto; }
  .msn-ev { gap: var(--space-8); padding: var(--space-12); }
  /* "Sắp diễn ra" opens on its list, above the weather and the calendar. */
  .msn-grid:not(.is-front) > .tile-live, .msn-grid > .ev-empty { grid-column: 1 / -1; grid-row: auto; order: -1; }
  .nc { min-height: var(--msn-rowh-phone); }
  .nc-photo { height: var(--msn-photo-h-phone); }
  .nc-body { padding: var(--space-8) var(--space-8) var(--space-8); gap: var(--space-4); }
  /* Who said it matters more than when: on a half-width card the source keeps the whole first line and the time
     takes the line under it. */
  .nc:not(.nc-big):not(.nc-wide) .nc-meta { flex-wrap: wrap; row-gap: 0; }
  .nc:not(.nc-big):not(.nc-wide) .nc-dot { display: none; }
  .nc:not(.nc-big):not(.nc-wide) .nc-src { white-space: normal; overflow-wrap: anywhere; }
  .nc:not(.nc-big):not(.nc-wide) .nc-meta time { flex-basis: 100%; font-weight: var(--weight-medium); }
  .nc-title { font-size: var(--text-sub); line-height: 1.38; -webkit-line-clamp: 4; }
  .nc.no-photo .nc-body { padding: var(--space-12); gap: var(--space-8); }
  .nc.no-photo .nc-title { font-size: var(--text-sub); -webkit-line-clamp: 6; }
  .nc.no-photo:not(.nc-big):not(.nc-wide) .nc-sum { display: none; }
  .nc:not(.nc-big):not(.nc-wide) .nc-fav { display: none; }
  .msn-lead { grid-column: 1 / -1; height: var(--msn-lead-h-phone); }
  .slide-box { left: var(--space-8); right: var(--space-8); bottom: var(--space-8); padding: var(--space-8) var(--space-12) var(--space-12); }
  .lead-dots { left: var(--space-8); }
  /* The lead's headline is the page's most important sentence: on a phone it is never cut. */
  .slide-title { font-size: var(--text-title); display: block; -webkit-line-clamp: unset; overflow: visible; }
  .slide.no-photo .slide-title { font-size: var(--text-tile); }
  .msn-wx { grid-column: 1 / -1; min-height: var(--msn-wx-h-phone); padding: var(--space-8) var(--space-12); }
  .msn-toplist { grid-column: 1 / -1; }
  .msn-toplist li { flex: none; }
  .nc-big { grid-column: 1 / -1; grid-row: auto; height: var(--msn-big-h-phone); }
  .nc-big .nc-title { font-size: var(--text-title); }
  .nc-big .nc-sum { -webkit-line-clamp: 2; }
  .nc-wide { grid-column: 1 / -1; height: var(--msn-wide-h-phone); min-height: 0; }
  .nc-wide .nc-photo { width: 42%; }
  .nc-wide .nc-body { padding: var(--space-12); gap: var(--space-6); }
  .nc-wide .nc-title { font-size: var(--text-sub); -webkit-line-clamp: 5; }
  .nc-wide .nc-sum { display: none; }
  .nc-big.no-photo { height: auto; min-height: var(--msn-rowh-phone); }
  .nc-big.no-photo .nc-title { font-size: var(--text-feature); }
  .nc-wide.no-photo { height: auto; min-height: var(--msn-wide-h-phone); }
  .nc-wide.no-photo .nc-title { font-size: var(--text-title); }
  .nc-wide.no-photo .nc-sum { display: -webkit-box; -webkit-line-clamp: 3; }
  .msn-cal { min-height: var(--msn-rowh-phone); padding: 0 0 var(--space-12); }
  .msn-cal .cal-day { font-size: var(--msn-cal-day-phone); }
  .cal-week { margin-top: var(--space-4); font-size: var(--text-micro); }
  .cal-moon { margin-top: var(--space-8); }
  .cal-lunar b { font-size: var(--msn-cal-moon-phone); }
  .msn-cal .cal-note { display: none; }
  .msn-grid > .tile, .msn-grid.is-front > .tile { grid-column: 1 / -1; grid-row: auto; overflow: visible; }
  .band-grid { grid-auto-rows: auto; }
  .band-grid > .tile { overflow: visible; }
  .msn-sk { min-height: var(--msn-rowh-phone); }
  #feed-skeleton .msn-lead { grid-column: 1 / -1; min-height: var(--msn-lead-h-phone); }
  .msn-day-grid { grid-auto-rows: auto; }
  .day-line { margin-top: var(--space-8); }
}
@media (max-width: 370px) {
  :root { --msn-cols: 1; }
  .msn-lead, .msn-wx, .msn-toplist, .nc-big, .nc-wide { grid-column: 1; }
}

/* ---------- the front page's bands at each width (five, four, three columns; one on a phone) ---------- */
@media (min-width: 768px) {
  /* No "Vừa đăng" (nothing young enough): the lead takes its columns. No event coming: "Đáng chú ý" takes its column. */
  .band-today .band-cells:not(:has(> .tile-fresh)) > .msn-lead { grid-column: span calc(var(--bento-cols) - 1); }
  .band-focus .band-cells:not(:has(> .msn-ev)) > .nc-wide { grid-column: span 3; }
}
/* Four columns: Hôm nay = lead 2 · Vừa đăng 1 · weather 1; Điểm nhấn = four single cells, "Đáng chú ý" a tall card. */
@media (min-width: 1024px) and (max-width: 1439px) {
  :root { --bento-cols: 4; }
  .band-today .band-cells > .tile-fresh { grid-column: span 1; }
  .band-focus .band-cells > .nc-wide { grid-column: span 1; flex-direction: column; }
  .band-focus .band-cells > .nc-wide .nc-photo { width: auto; height: var(--msn-photo-h); }
  .band-focus .band-cells > .nc-wide .nc-title { font-size: var(--msn-title-text); -webkit-line-clamp: 4; }
  .band-focus .band-cells > .nc-wide .nc-sum { -webkit-line-clamp: 3; }
  .band-focus .band-cells:not(:has(> .msn-ev)) > .nc-wide { grid-column: span 2; flex-direction: row; }
  .band-focus .band-cells:not(:has(> .msn-ev)) > .nc-wide .nc-photo { width: 50%; height: auto; }
}
/* Three columns: the lead alone on the first row, then Vừa đăng 2 · weather 1; Chuyện lớn · event · calendar, then
   "Đáng chú ý" across the row. */
@media (min-width: 768px) and (max-width: 1023px) {
  :root { --bento-cols: 3; }
  .band-today .band-cells > .msn-lead { grid-column: 1 / -1; }
  .band-focus .band-cells > .nc-wide { grid-column: 1 / -1; order: 1; }
  .band-focus .band-cells:not(:has(> .msn-ev)) > .nc-wide { grid-column: span 1; order: 0; flex-direction: column; }
  .band-focus .band-cells:not(:has(> .msn-ev)) > .nc-wide .nc-photo { width: auto; height: var(--msn-photo-h); }
}
/* A phone: one column, news first and the widgets after it in each band. A story is a compact row (its picture beside
   the headline); a double story and "Đáng chú ý" are full-width picture cards. */
@media (max-width: 767px) {
  :root { --bento-cols: 1; --band-gap: var(--space-16); }
  .band-cells { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; gap: var(--space-8); }
  .band-cells > *, .band-cells > .msn-lead, .band-cells > .nc-wide, .band-cells > .tile-fresh { grid-column: 1 / -1; }
  .band > .band-title { margin: 0 0 var(--space-8) var(--space-4); font-size: var(--text-body); }
  .more-box { gap: var(--space-8); }
  .more-box > .day-line.band-title { margin-top: calc(var(--band-gap) - var(--space-8)); font-size: var(--text-body); }
  .band .msn-lead { height: var(--msn-lead-h-phone); }
  .band .msn-wx { min-height: var(--msn-wx-h-phone); }
  .band .msn-cal { min-height: var(--msn-rowh-phone); }
  .band .tile-fresh .fresh-list { grid-auto-rows: auto; }
  .band .msn-toplist ol { overflow: visible; }
  .band .msn-toplist li { flex: none; }
  .band .nc { min-height: 0; height: auto; }
  .band .nc:not(.nc-wide) { flex-direction: row; align-items: flex-start; }
  .band .nc:not(.nc-wide) .nc-photo {
    width: var(--bento-thumb-w); height: var(--bento-thumb-h); margin: var(--space-12) 0 var(--space-12) var(--space-12);
    border-radius: var(--radius-8);
  }
  .band .nc:not(.nc-wide) .nc-body { padding: var(--space-12); gap: var(--space-4); }
  .band .nc:not(.nc-wide) .nc-title { font-size: var(--text-sub); -webkit-line-clamp: 3; }
  .band .nc.no-photo:not(.nc-wide) .nc-sum { display: none; }
  .band .nc-wide { flex-direction: column; height: auto; min-height: 0; }
  .band .nc-wide .nc-photo { width: auto; height: auto; aspect-ratio: 16 / 9; }
  .band .nc-wide .nc-body { padding: var(--space-12); gap: var(--space-6); }
  .band .nc-wide .nc-title { font-size: var(--text-title); -webkit-line-clamp: 4; }
  .band .nc-wide .nc-sum { display: -webkit-box; -webkit-line-clamp: 2; }
  .band .nc-wide.no-photo .nc-body { padding: var(--space-16); }
  .band-lab .band-grid { grid-auto-flow: row; grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
  .band-lab .band-grid > .tile { overflow: visible; }
  .band-lab :is(.arena-list, .repo-row, .model-list) { flex: none; overflow: visible; }
  /* A phone's tiles grow with their rows, so a closed band keeps them short: three repositories, four models. */
  .band-lab:not(.is-open) .repo-row > :nth-child(n+4), .band-lab:not(.is-open) .model-list > :nth-child(n+5) { display: none; }
}
/* ---------- the day's picture behind the page (owner, 10/11: "còn về ảnh nền thì em làm như edge") ---------- */
/* From 768 px the day's 3D render fills the window behind the page, as on Edge's new tab, and stays put while the panel
   scrolls over it. Captain, 10/11 14:48: the search and
   the panel sit high (Edge: search near the top, panel right under it), and a veil lies between the picture and the
   content so the corners and the panel stand out; the corners' ink turns white on it. "Tùy chỉnh" (thanh-tren.js) can
   start the panel lower (data-layout part / head) or turn the picture off (data-nen="off": nothing is downloaded).
   nen.js picks the picture; under 768 px the layer is never drawn and nothing is downloaded. */
.nen { display: none; }
@media (min-width: 768px) {
  :root:not([data-nen="off"]) .nen { display: block; position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; background: var(--nen-mat); }
  .nen-img {
    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--nen-focus);
    opacity: 0; transition: opacity var(--motion-state) var(--ease-flow);
  }
  .nen.is-ready .nen-img { opacity: 1; }
  .nen.is-instant .nen-img { transition: none; }
  .nen::before { content: ""; position: absolute; inset: 0; z-index: 1; background: var(--nen-scrim); }
  /* No surface closes over the picture as the page scrolls (captain, 10/11 17:51): the picture stays in sight in the
     gutters beside the panel all the way down; only the scrim above keeps the top row readable. */
  .msn-top { display: flex; flex-direction: column; }
  .msn-top-in { width: 100%; }
  [data-layout="part"] .msn-top { min-height: var(--nen-fold); }
  [data-layout="head"] .msn-top { min-height: calc(100svh - var(--nen-peek)); }
  /* "Một phần" and "Đầu đề" (captain, 10/11 18:54: "nút tìm kiếm nó phải luôn nằm ở giữa mép trên và mép nội dung"): the
     top row fills the space above the panel, the corners stay where "Toàn trang" has them (centred on a search-high
     band at its top), and the search sits in its vertical middle, halfway between the window's top edge and the panel's
     (the row's top padding equals its bottom margin). */
  :is([data-layout="part"], [data-layout="head"]) .msn-top-in { flex: 1; grid-template-rows: var(--msn-search-h) 1fr; }
  :is([data-layout="part"], [data-layout="head"]) .msn-top :is(.news-search, .web-search) { grid-row: 1 / -1; align-self: center; }
  :root:not([data-nen="off"]) {
    --top-ink: var(--top-on-nen-ink); --top-ink-shadow: var(--top-on-nen-shadow);
    --top-tile: var(--top-on-nen-tile); --top-tile-on: var(--top-on-nen-tile-on);
  }
  :root:not([data-nen="off"]) .msn-top .top-tile, :root:not([data-nen="off"]) .msn-top .tool-launcher-button {
    -webkit-backdrop-filter: blur(var(--msn-blur)) saturate(1.4); backdrop-filter: blur(var(--msn-blur)) saturate(1.4);
  }
  .msn-top .ns-field {
    background: var(--nen-pill); box-shadow: var(--nen-pill-shadow);
    -webkit-backdrop-filter: blur(var(--msn-blur)) saturate(1.4); backdrop-filter: blur(var(--msn-blur)) saturate(1.4);
  }
  .msn-top .ns-field:hover, .msn-top .ns-field:focus-within { background: var(--nen-pill-on); }
}
@media (min-width: 768px) and (prefers-reduced-transparency: reduce) {
  .msn-top .ns-field { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--nen-pill-on); }
  :root:not([data-nen="off"]) .msn-top .top-tile, :root:not([data-nen="off"]) .msn-top .tool-launcher-button {
    -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--top-on-nen-tile-on);
  }
}

/* ---------- "Tùy chỉnh": a panel at the top right, grown out of its button (thanh-tren.js) ---------- */
/* Non-blocking, as on Edge: the page stays usable behind it; a pick applies at once. Groups part by their fill, never
   by a line; the chosen layout and theme take the coral wash. */
.tc-sheet {
  /* Under the top row, so its own button stays in sight and closes it again. */
  --tc-top: calc(var(--top-pad) + var(--btn-h) + var(--space-8));
  position: fixed; z-index: 80; top: var(--tc-top); right: var(--space-8);
  width: min(var(--tc-w), calc(100vw - 2 * var(--space-8))); max-height: calc(100dvh - var(--tc-top) - var(--space-8));
  overflow-y: auto; overscroll-behavior: contain; padding: var(--space-4) var(--space-12) var(--space-12);
  background: var(--color-panel); color: var(--color-ink); border-radius: var(--msn-panel-r); box-shadow: var(--tc-shadow);
  transform-origin: top right; opacity: 0; transform: translateY(calc(-1 * var(--space-4))) scale(0.98);
  transition: opacity var(--duration-150) ease, transform var(--duration-150) var(--ease-exit);
}
.tc-sheet.is-open { opacity: 1; transform: none; transition: opacity var(--motion-state) var(--ease-flow), transform var(--motion-state) var(--ease-flow); }
.tc-sheet[hidden] { display: none; }
.tc-sheet:focus { outline: none; }
.tc-top { display: flex; align-items: center; justify-content: space-between; min-height: var(--btn-h); margin-bottom: var(--space-4); }
.tc-top h2 { margin: 0; padding-left: var(--space-4); font-size: var(--text-title); font-weight: var(--weight-bold); letter-spacing: -0.01em; }
.tc-close { display: grid; place-items: center; width: var(--btn-h); height: var(--btn-h); border-radius: var(--radius-8); color: var(--color-ink-2); }
.tc-close:hover { background: var(--color-fill); color: var(--color-ink); }
.tc-close .i { width: var(--msn-fav); height: var(--msn-fav); }
.tc-group { margin: 0 0 var(--space-8); padding: var(--space-12); border: 0; border-radius: var(--radius-12); background: var(--color-canvas); min-width: 0; }
.tc-group legend { float: left; width: 100%; margin: 0 0 var(--space-8); padding: 0; font-size: var(--text-meta); font-weight: var(--weight-semibold); color: var(--color-ink-2); }
.tc-group legend + * { clear: both; }
.tc-layouts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-8); }
.tc-layout {
  display: grid; gap: var(--space-6); padding: var(--space-6) var(--space-6) var(--space-8); border-radius: var(--radius-12);
  background: var(--color-panel); text-align: center; cursor: pointer; font-size: var(--text-meta); font-weight: var(--weight-medium);
  transition: background-color var(--duration-150) ease, transform var(--duration-150) var(--ease-press);
}
.tc-layout:active { transform: scale(0.97); }
.tc-layout:has(input:checked) { background: var(--color-accent-wash-strong); font-weight: var(--weight-bold); }
.tc-layout:has(input:focus-visible), .tc-seg label:has(input:focus-visible) { outline: var(--focus-ring); outline-offset: var(--msn-tight); }
.tc-mini { position: relative; display: block; aspect-ratio: 16 / 10; border-radius: var(--radius-8); overflow: hidden; background: linear-gradient(160deg, var(--msn-wx-sky), var(--nen-mat)); }
.tc-mini b { position: absolute; top: 9%; left: 30%; right: 30%; height: 10%; border-radius: var(--radius-full); background: var(--brand-white); }
.tc-mini i { position: absolute; left: 9%; right: 9%; bottom: 0; top: 30%; border-radius: var(--msn-dot) var(--msn-dot) 0 0; background: var(--color-panel); }
.tc-mini-part i { top: 56%; }
.tc-mini-head i { top: 84%; }
.tc-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); min-height: var(--btn-h); font-size: var(--text-small); font-weight: var(--weight-medium); cursor: pointer; }
.tc-switch {
  -webkit-appearance: none; appearance: none; position: relative; flex: none; width: var(--tc-switch-w); height: var(--tc-switch-h); margin: 0;
  border-radius: var(--radius-full); background: var(--tc-switch-off); cursor: pointer; transition: background-color var(--duration-150) ease;
}
.tc-switch::before {
  content: ""; position: absolute; top: calc((var(--tc-switch-h) - var(--tc-knob)) / 2); left: calc((var(--tc-switch-h) - var(--tc-knob)) / 2);
  width: var(--tc-knob); height: var(--tc-knob); border-radius: var(--radius-full); background: var(--brand-white); box-shadow: var(--msn-shadow-rest);
  transition: transform var(--duration-150) var(--ease-press);
}
.tc-switch:checked { background: var(--color-accent-fill); }
.tc-switch:checked::before { transform: translateX(calc(var(--tc-switch-w) - var(--tc-switch-h))); }
.tc-switch:focus-visible { outline: var(--focus-ring); outline-offset: var(--msn-tight); }
/* The segmented control, one look wherever a choice of a few sides is shown: "Giao diện" here, the order in the
   panel's header row (.msn-head .sort-switch). A grey track; the chosen side a raised pill. */
.tc-seg, .msn-head .sort-switch { padding: var(--msn-tight); border-radius: var(--radius-8); background: var(--color-seg-track); }
.tc-seg label:has(input:checked), .msn-head .sort-switch .tab-pill, .msn-head .sort-btn-compact::before {
  background: var(--color-seg-thumb); box-shadow: var(--msn-shadow-rest); border-radius: var(--seg-thumb-r);
}
.tc-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--msn-tight); }
.tc-seg label { display: grid; place-items: center; min-height: var(--btn-h); border-radius: var(--seg-thumb-r); font-size: var(--text-small); font-weight: var(--weight-medium); color: var(--color-ink-2); cursor: pointer; transition: background-color var(--duration-150) ease, color var(--duration-150) ease; }
.tc-seg label:has(input:checked) { color: var(--color-ink); font-weight: var(--weight-bold); }
/* A phone draws no picture, so the layout and the picture switch have nothing to change there. */
@media (max-width: 767px) {
  .tc-wide { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .tc-sheet, .tc-sheet.is-open { transform: none; transition: opacity var(--duration-150) ease; }
  .tc-switch::before, .tc-layout { transition: none; }
  .tc-layout:active, .msn-top .top-tile:active, .msn-top .tool-launcher-button:active { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .nen-img { transition: none; }
  .fresh-list li.is-flash { animation: none; background: var(--color-accent-wash-strong); }
  .nc, .nc-img, .slide, .pager-dots button::before, .wx-days li, .wx-menu { transition-duration: 1ms !important; }
  .nc:hover, .nc:active { transform: none; }
  .nc:hover .nc-img { transform: none; }
  .msn-sk, .wx-skel i, .spinner { animation: none; }
}
@media (prefers-reduced-transparency: reduce) {
  .wx-days li, .wx-switch, .msn-wx .pill, .wx-detail { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--msn-wx-solid); }
}
