/*
Theme Name: WellCareChina
Theme URI: https://wellcarechina.com/
Author: wellcarechina
Author URI: https://wellcarechina.com/
Description: WellCareChina (Chinese name: 入境医疗网) portal theme - informational portal for international patients looking up medical information in China. Visibility layer: design tokens, self-hosted icon set, homepage, credibility pages (methodology / corrections / editorial standards) and the services page. No third-party dependencies, no CDN.
Version: 0.72.4
Requires at least: 6.0
Requires PHP: 8.0
Tested up to: 7.1
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: wellcarechina
Tags: custom-menu, custom-logo, translation-ready
*/

/* Component styles only. Colour / spacing / radius / type values come from
   assets/css/tokens.css; fonts are declared in assets/css/fonts.css. Both are
   enqueued before this file (see wellcarechina_enqueue_assets()). */

/* ---------------------------------------------------------------- Base --- */

*,
*::before,
*::after {
	box-sizing: border-box;
}

body {
	margin: 0;
	color: var(--kl-ink);
	background: var(--kl-paper);
	font-family: var(--kl-font-sans);
	font-size: var(--kl-text-base);
	line-height: var(--kl-leading-body);
	-webkit-text-size-adjust: 100%;
}

a {
	color: var(--kl-accent);
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}

a:hover,
a:focus {
	color: var(--kl-accent-hover);
}

:focus-visible {
	outline: 2px solid var(--kl-accent);
	outline-offset: 2px;
}

h1,
h2,
h3,
h4 {
	margin: 0 0 var(--kl-space-3);
	line-height: var(--kl-leading-tight);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: -0.01em;
	overflow-wrap: anywhere;
	text-wrap: balance;
	hyphens: auto;
}

h1 {
	font-size: var(--kl-text-3xl);
}

h2 {
	font-size: var(--kl-text-xl);
}

h3 {
	font-size: var(--kl-text-lg);
}

img {
	max-width: 100%;
	height: auto;
	display: block;
}

hr {
	border: 0;
	border-top: 1px solid var(--kl-border);
	margin: var(--kl-space-6) 0;
}

/* --------------------------------------------------------- Primitives --- */

.kl-container {
	width: 100%;
	max-width: var(--kl-container);
	margin: 0 auto;
	padding: 0 var(--kl-space-5);
}

.kl-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
}

.kl-skip-link:focus {
	left: var(--kl-space-3);
	top: var(--kl-space-3);
	z-index: 100;
	padding: var(--kl-space-2) var(--kl-space-4);
	background: var(--kl-paper);
	border: 1px solid var(--kl-accent);
	border-radius: var(--kl-radius-input);
}

/* Icons are decoration; the label next to them carries the meaning. */
.kl-icon {
	width: 20px;
	height: 20px;
	flex: 0 0 auto;
	vertical-align: -3px;
}

.kl-icon--lg {
	width: 24px;
	height: 24px;
}

.kl-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

/* -------------------------------------------------------------- Header ---
   fix-007 T7 (ledger ui-008): one row on desktop, so the search box no longer
   wraps to a line of its own - the non-front header used to stand 196px tall
   (343px on mobile). */

.kl-header {
	border-bottom: 1px solid var(--kl-border);
	background: var(--kl-paper);
}

.kl-header__inner {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: var(--kl-space-5);
	padding-top: var(--kl-space-2);
	padding-bottom: var(--kl-space-2);
}

.kl-branding {
	flex: 0 0 auto;
}

.kl-branding__title {
	margin: 0;
	font-size: var(--kl-text-lg);
	font-weight: var(--kl-weight-semibold);
}

.kl-branding__title a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: inherit;
	text-decoration: none;
}

.kl-branding__tagline {
	margin: var(--kl-space-1) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* The menu is a plain row on desktop; the mobile disclosure is not rendered. */
.kl-nav {
	flex: 1 1 auto;
}

.kl-nav__details {
	display: none;
}

.kl-nav__list {
	display: flex;
	flex-wrap: wrap;
	/* dev-032: the English menu gained its eighth item (`Rankings`). At the
	   1200px container the row fits eight labels on two lines with a 16px
	   column gap; at the 24px gap it needed a third line and the non-front
	   header grew past the 120px the dev-024 contract allows. The row gap is
	   unchanged, and the <=900px mobile panel sets its own `gap: 0`.
	   dev-034: the menu gained its ninth item (`Insurance in China`) and the
	   column gap went 16px -> 4px, which is what keeps the nine labels inside
	   the dev-024 budget once the header's own gap is 4px on desktop
	   (see .kl-header__inner above). */
	gap: var(--kl-space-2) var(--kl-space-1);
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--kl-text-md);
}

.kl-nav__list a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--kl-ink);
	text-decoration: none;
}

/* ---------------------------------------------------- Language selector ---
   fix-007 T2: one conventional selector. The summary shows the current
   language's own name; the panel lists every configured language. It is a
   native `<details>`, so it opens with no JavaScript. */

.kl-lang {
	flex: 0 0 auto;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-lang__details {
	position: relative;
}

.kl-lang__toggle {
	display: inline-flex;
	align-items: center;
	gap: var(--kl-space-2);
	min-height: 44px;
	padding: 0 var(--kl-space-3);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper);
	color: var(--kl-slate);
	cursor: pointer;
	list-style: none;
	touch-action: manipulation;
}

/* Hide the native disclosure marker; the caret below replaces it. */
.kl-lang__toggle::-webkit-details-marker {
	display: none;
}

.kl-lang__toggle:hover,
.kl-lang__toggle:focus {
	color: var(--kl-ink);
}

.kl-lang__caret {
	width: 7px;
	height: 7px;
	margin-left: var(--kl-space-1);
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--kl-dur-fast) var(--kl-ease);
}

.kl-lang__details[open] .kl-lang__caret {
	transform: rotate(225deg);
}

.kl-lang__list {
	position: absolute;
	right: 0;
	top: calc(100% + var(--kl-space-1));
	z-index: 20;
	min-width: 200px;
	margin: 0;
	padding: var(--kl-space-2) 0;
	list-style: none;
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
	box-shadow: var(--kl-shadow-2);
}

.kl-lang__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--kl-space-4);
	min-height: 44px;
	padding: 0 var(--kl-space-4);
	color: var(--kl-ink);
	text-decoration: none;
}

.kl-lang__link:hover,
.kl-lang__link:focus {
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
}

.kl-lang__link[aria-current="true"] {
	font-weight: var(--kl-weight-semibold);
}

.kl-lang__code {
	color: var(--kl-slate);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-xs);
	text-transform: uppercase;
}

.kl-lang__toggle-code {
	display: none;
	color: var(--kl-slate);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
}

/* --------------------------------------------------- Chinese front page --- */

/* The Chinese landing page is text-only, so its hero uses one column instead
   of the English two-column (copy | photograph) grid. */
.kl-hero--zh .kl-hero__inner {
	grid-template-columns: minmax(0, 1fr);
}

.kl-hero--zh .kl-hero__text {
	max-width: var(--kl-measure);
}

.kl-chips--entries {
	gap: var(--kl-space-3);
}

.kl-zh-contact {
	margin-top: var(--kl-space-6);
}

/* ------------------------------------------------------------- Buttons --- */

.kl-btn {
	display: inline-flex;
	align-items: center;
	gap: var(--kl-space-2);
	padding: var(--kl-space-3) var(--kl-space-5);
	border: 1px solid var(--kl-accent);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent);
	color: var(--kl-paper);
	font-family: inherit;
	font-size: var(--kl-text-md);
	font-weight: var(--kl-weight-semibold);
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background-color var(--kl-dur-fast) var(--kl-ease), border-color var(--kl-dur-fast) var(--kl-ease);
}

.kl-btn:hover,
.kl-btn:focus {
	background: var(--kl-accent-hover);
	border-color: var(--kl-accent-hover);
	color: var(--kl-paper);
}

.kl-btn--ghost {
	background: transparent;
	border-color: var(--kl-border-strong);
	color: var(--kl-ink);
}

.kl-btn--ghost:hover,
.kl-btn--ghost:focus {
	background: var(--kl-accent-soft);
	border-color: var(--kl-accent);
	color: var(--kl-accent-hover);
}

/* A disabled button must still be readable and must not look clickable. */
.kl-btn[disabled],
.kl-btn[aria-disabled="true"] {
	background: var(--kl-disabled-bg);
	border-color: var(--kl-disabled-bg);
	color: var(--kl-disabled-ink);
	cursor: not-allowed;
}

.kl-btn[aria-disabled="true"]:hover {
	background: var(--kl-disabled-bg);
	border-color: var(--kl-disabled-bg);
	color: var(--kl-disabled-ink);
}

.kl-btn-note {
	display: block;
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* --------------------------------------------------------- Search form --- */

.kl-search-form {
	margin: 0;
}

.kl-search-form__label {
	display: block;
	margin-bottom: var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-search-form__row {
	display: flex;
	gap: var(--kl-space-2);
}

.kl-search-form__input {
	flex: 1 1 auto;
	min-width: 0;
	min-height: 44px;
	padding: var(--kl-space-3);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-input);
	background: var(--kl-paper);
	color: var(--kl-ink);
	font-family: inherit;
	font-size: var(--kl-text-md);
}

.kl-search-form__input:focus {
	border-color: var(--kl-accent);
	box-shadow: 0 0 0 3px var(--kl-accent-ring);
	outline: none;
}

.kl-search-form__submit {
	flex: 0 0 auto;
	min-height: 44px;
	padding: var(--kl-space-3) var(--kl-space-5);
	border: 1px solid var(--kl-accent);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent);
	color: var(--kl-paper);
	font-family: inherit;
	font-size: var(--kl-text-md);
	font-weight: var(--kl-weight-semibold);
	cursor: pointer;
}

.kl-search-form__submit:hover,
.kl-search-form__submit:focus {
	background: var(--kl-accent-hover);
	border-color: var(--kl-accent-hover);
}

.kl-search-form--hero .kl-search-form__input,
.kl-search-form--hero .kl-search-form__submit {
	padding-top: var(--kl-space-4);
	padding-bottom: var(--kl-space-4);
}

/* ---------------------------------------------------------------- Hero --- */

.kl-hero {
	padding: var(--kl-space-8) 0 var(--kl-space-7);
	background: var(--kl-navy);
	color: var(--kl-on-navy);
}

.kl-hero__inner {
	display: grid;
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
	gap: var(--kl-space-7);
	align-items: center;
}

.kl-hero__eyebrow {
	margin: 0 0 var(--kl-space-3);
	color: var(--kl-on-navy-muted);
	font-size: var(--kl-text-sm);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-hero__title {
	margin: 0 0 var(--kl-space-3);
	color: var(--kl-on-navy);
	font-size: var(--kl-text-4xl);
	letter-spacing: -0.02em;
}

.kl-hero__lede {
	max-width: 46ch;
	margin: 0 0 var(--kl-space-5);
	color: var(--kl-on-navy-muted);
	font-size: var(--kl-text-lg);
}

.kl-hero .kl-search-form {
	max-width: 560px;
}

/* dev-052 (ledger ui-034): the hero already caps its search row at 560px.
   The two in-page variants did not, so on /hospitals/ and the 404 page the
   field stretched to the full 1152px content box - the label sat at the left
   edge and the button about a thousand pixels away from it, and the row read
   as a full-width banner rather than a search control. Both now share the
   hero's cap. */
.kl-search-form--landing,
.kl-search-form--default {
	max-width: 560px;
}

.kl-hero .kl-search-form__label {
	color: var(--kl-on-navy-muted);
}

.kl-hero__chips {
	margin-top: var(--kl-space-4);
}

.kl-hero__chips-label {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-on-navy-muted);
	font-size: var(--kl-text-sm);
}

.kl-hero__media {
	margin: 0;
}

/* The frame carries the photograph only (fix-007 T1). It is a plain block, so
   the credit rendered below it can never become a flex sibling of the image -
   that flex row is what squeezed the credit into a 61px column beside the
   photograph (ledger ui-002). */
.kl-hero__media-frame {
	display: block;
}

/* Hero photograph: fills the right column, cropped to a stable 16:9 frame. */
.kl-hero__media-frame img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	border-radius: var(--kl-radius-card);
	box-shadow: var(--kl-shadow-2);
}

/* The credit line that used to sit under the image is gone (dev-082, user
   request): the hero figure is now the frame alone, so `.kl-hero__media-credit`
   has no rule and no template left to serve. */
@media (max-width: 900px) {
	.kl-hero__media-frame img {
		aspect-ratio: 4 / 3;
	}
}

/* ----------------------------------------- Hero focus news (dev-080) ---
   The hero's right column used to be one fixed photograph. It is now a
   focus-news carousel in the same 16:9 frame (4:3 under 900px, from
   `.kl-hero__media-frame img` above): a random draw of covered news items,
   each with its title, date and topic chips over a scrim at the foot of the
   image. dev-082 dropped the numbered dots and the always-visible pause
   button the user asked to remove; the one pause/continue control is painted
   only while the frame is hovered, focused or stopped.

   The first slide is the only one painted until hero-news.js marks the
   container `kl-focus-news--js`, so a reader with no JavaScript gets the first
   item in the frame and the controls (which would be dead) stay hidden. */

.kl-focus-news {
	position: relative;
	border-radius: var(--kl-radius-card);
	overflow: hidden;
}

.kl-focus-news__slide {
	position: relative;
	display: block;
}

/* No JavaScript yet: one slide, no controls. */
.kl-focus-news:not(.kl-focus-news--js) .kl-focus-news__slide:not(:first-child),
.kl-focus-news:not(.kl-focus-news--js) .kl-focus-news__controls {
	display: none;
}

/* JavaScript ready: slides stack inside the one frame, so its height never
   moves between slides. */
.kl-focus-news--js .kl-focus-news__slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--kl-dur-base) var(--kl-ease);
}

.kl-focus-news--js .kl-focus-news__slide.is-active {
	position: relative;
	opacity: 1;
	pointer-events: auto;
}

.kl-focus-news__img {
	margin: 0;
}

/* The words ride the foot of the photograph behind a navy scrim, so they stay
   legible whatever the image is. */
.kl-focus-news__body {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: var(--kl-space-6) var(--kl-space-4) var(--kl-space-4);
	background: linear-gradient(to top, rgba(11, 31, 51, 0.88), rgba(11, 31, 51, 0));
	color: var(--kl-on-navy);
}

.kl-focus-news__title {
	margin: 0;
	font-size: var(--kl-text-lg);
	line-height: var(--kl-leading-snug);
}

/* The headline is the slide's main tap target, so it clears the same 44px floor
   the chips already use (dev-024 / P7) - a one-line title would otherwise sit
   ~23px tall. */
.kl-focus-news__title a {
	display: flex;
	align-items: center;
	min-height: 44px;
	color: var(--kl-on-navy);
}

.kl-focus-news__meta {
	margin: var(--kl-space-1) 0 0;
	color: var(--kl-on-navy-muted);
	font-size: var(--kl-text-sm);
}

.kl-focus-news__body .kl-chips {
	margin: 0 0 var(--kl-space-2);
}

/* Chips sit on the photograph, so they take the hero's on-navy treatment
   (the same pairing as `.kl-hero .kl-chip` below). */
.kl-focus-news .kl-chip {
	border-color: rgba(255, 255, 255, 0.24);
	color: var(--kl-on-navy);
}

.kl-focus-news__controls {
	position: absolute;
	top: var(--kl-space-3);
	right: var(--kl-space-3);
	z-index: 2;
	display: flex;
	align-items: center;
	gap: var(--kl-space-2);
}

/* The control keeps a 24px visible mark inside a transparent 44px hit area,
   so the touch floor (dev-024: every clickable >= 44x44) is met without
   turning it into a large disc. It is painted only on hover, on focus inside
   the frame and while the rotation is stopped: the frame reads as a
   photograph until the reader reaches for the stop, but the stop is always
   there for a pointer, a keyboard and a screen reader (WCAG 2.2.2). */
.kl-focus-news__pause {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: var(--kl-radius-pill);
	background: radial-gradient(circle at center, var(--kl-on-navy-muted) 0, var(--kl-on-navy-muted) 12px, transparent 12px);
	color: var(--kl-navy);
	font-size: var(--kl-text-xs);
	line-height: 1;
	cursor: pointer;
	opacity: 0;
	transition: opacity var(--kl-dur-base) var(--kl-ease);
}

.kl-focus-news:hover .kl-focus-news__pause,
.kl-focus-news:focus-within .kl-focus-news__pause,
.kl-focus-news__pause:focus-visible,
.kl-focus-news__pause.is-paused {
	opacity: 1;
}

.kl-focus-news__pause:focus-visible {
	outline: 2px solid var(--kl-paper);
	outline-offset: 2px;
}

/* A touch screen has no hover, so the stop is painted there from the start. */
@media (hover: none) {
	.kl-focus-news__pause {
		opacity: 1;
	}
}

/* Pause glyph (two bars) becomes a play glyph (one triangle) once stopped. */
.kl-focus-news__pause::before {
	content: "";
	display: block;
	width: 10px;
	height: 12px;
	border-left: 3px solid currentColor;
	border-right: 3px solid currentColor;
}

.kl-focus-news__pause.is-paused::before {
	width: 0;
	height: 0;
	border-left: 9px solid currentColor;
	border-top: 6px solid transparent;
	border-bottom: 6px solid transparent;
	border-right: 0;
}

@media (prefers-reduced-motion: reduce) {
	.kl-focus-news__slide {
		transition: none;
	}
}

.kl-hero .kl-chip {
	border-color: rgba(255, 255, 255, 0.24);
	color: var(--kl-on-navy);
}

.kl-hero .kl-chip:hover,
.kl-hero .kl-chip:focus {
	background: rgba(255, 255, 255, 0.08);
	color: var(--kl-on-navy);
}

/* --------------------------------------------------------------- Chips --- */

.kl-chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-chips--nowrap {
	flex-wrap: nowrap;
	overflow: hidden;
}

/* Chip row with a clamped list plus an always-visible overflow counter. */
.kl-chip-row {
	display: flex;
	align-items: center;
	gap: var(--kl-space-2);
	min-width: 0;
}

.kl-chip-row > .kl-chips--nowrap {
	flex: 1 1 auto;
	min-width: 0;
}

.kl-card .kl-chip-row {
	margin: 0 0 var(--kl-space-3);
}

.kl-chip {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 var(--kl-space-3);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
}

.kl-chip:hover,
.kl-chip:focus {
	background: var(--kl-accent-soft);
	border-color: var(--kl-accent);
	color: var(--kl-accent-hover);
}

.kl-chip--more {
	color: var(--kl-slate);
	background: var(--kl-paper-alt);
	border-style: dashed;
}

.kl-chip--selected {
	background: var(--kl-accent);
	border-color: var(--kl-accent);
	color: var(--kl-paper);
}

/*
 * test-001 (B7): a wrapping chip list can carry one label longer than the
 * column - a hospital's full English alias ("Tongji Hospital, Tongji Medical
 * College, Huazhong University of Science and Technology") measured 533px in a
 * 342px row at 390 and pushed the document 167px sideways. A chip inside a
 * wrapping list now caps at its column and its own label wraps; the clamped
 * card rows (`.kl-chips--nowrap`, where the `+N` counter lives outside the
 * clip per known-issues #9) are untouched and keep their one-line chips, which
 * is what the dev-048 card rhythm relies on.
 */
.kl-chips:not(.kl-chips--nowrap) > li {
	max-width: 100%;
}

.kl-chips:not(.kl-chips--nowrap) > li > .kl-chip {
	max-width: 100%;
	padding-block: var(--kl-space-1);
	line-height: 1.35;
	text-align: left;
	white-space: normal;
	overflow-wrap: anywhere;
}

/* ------------------------------------- dev-078 hospital card chips ---
   The specialty cloud is the card's one variable-height block: every label is
   its own pill (one line, always whole) and the cloud wraps into full rows
   instead of clipping the row the way a non-interactive `+N` counter did
   (known-issues #9 keeps that pattern only where a consumer still needs it -
   the disease-card alias cloud and the detail-page alias lists). Two rows are
   the budget; when the list overruns them the script adds
   `data-kl-specialty-clamped`, the cloud takes the height of its third row and
   the last visible row fades under a mask against the card. Nothing is ever
   cut in half and nothing about the collapsed state depends on JavaScript
   beyond the class that expresses it. */
.kl-chips > li > .kl-chip {
	white-space: nowrap;
}

.kl-chip-cloud {
	margin: 0 0 var(--kl-space-3);
}

/* The card is a flex column, so the footnote that follows the cloud (or the
   title block when a record carries no specialty) is held to the bottom and
   the row's cards keep their footnotes on one line. */
.kl-card__foot {
	margin-top: auto;
}

/* ------------------------------------------------------------- Sections --- */

.kl-section {
	padding: var(--kl-space-8) 0;
}

.kl-section--alt {
	background: var(--kl-paper-alt);
}

.kl-section--tight {
	padding: var(--kl-space-7) 0;
}

.kl-section__head {
	max-width: 68ch;
	margin-bottom: var(--kl-space-6);
}

.kl-section__title {
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-2xl);
}

.kl-section__intro {
	margin: 0;
	color: var(--kl-slate);
}

/* The homepage line about admission timing (dev-035 T1). It sits in the
   services section head, under the intro, and reuses the page's own type
   tokens - the wording is elastic (no figure) and the hospital-confirms clause
   is part of the same sentence. */
.kl-section__note {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
}

/* The one-line travel-partner mention under the homepage services teaser
   (dev-011 T1); it links to /services/ rather than to the partner. */
.kl-section__foot-note {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* ----------------------------------------------------------- Trust bar --- */

.kl-trust {
	border-bottom: 1px solid var(--kl-border);
	background: var(--kl-paper-alt);
}

.kl-trust__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-5);
	margin: 0;
	padding: var(--kl-space-5) 0;
	list-style: none;
}

.kl-trust__item {
	display: flex;
	flex-direction: column;
	gap: var(--kl-space-1);
}

.kl-trust__value {
	color: var(--kl-ink);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-xl);
	font-variant-numeric: tabular-nums;
	line-height: 1.1;
}

.kl-trust__label {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-trust__sep {
	align-self: stretch;
	width: 1px;
	background: var(--kl-border-strong);
}

/* ------------------------------------------------------ Orientation band ---
   dev-075: the reading key between the hero and the worked example. It is a
   definition list - a term and its meaning - so it stays a list, not a row of
   cards. The columns share the trust bar's one-pixel rule language; on narrow
   screens the rules turn horizontal so the stack still reads as one band. */

.kl-orient {
	border-bottom: 1px solid var(--kl-border);
	background: var(--kl-paper);
}

.kl-orient__inner {
	padding-block: var(--kl-space-6);
}

.kl-orient__head {
	max-width: 68ch;
	margin-bottom: var(--kl-space-5);
}

.kl-orient__title {
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-2xl);
}

.kl-orient__intro {
	margin: 0;
	color: var(--kl-slate);
}

.kl-orient__list {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	margin: 0;
}

.kl-orient__item {
	padding: 0 var(--kl-space-6);
	border-left: 1px solid var(--kl-border);
}

.kl-orient__item:first-child {
	padding-left: 0;
	border-left: 0;
}

.kl-orient__item:last-child {
	padding-right: 0;
}

.kl-orient__term {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-ink);
	font-size: var(--kl-text-md);
	font-weight: var(--kl-weight-semibold);
	overflow-wrap: anywhere;
}

.kl-orient__body {
	max-width: 42ch;
	margin: 0;
	color: var(--kl-slate);
	overflow-wrap: anywhere;
}

.kl-orient__link {
	/* dev-082 (P7 fix): the orientation band's links were 22.1px tall - the only
	   homepage clickables under the 44px floor the site holds itself to (P7).
	   The hit area grows to 44px and the words stay optically where they
	   were, because the flex centring eats the space the old margin held. */
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-top: var(--kl-space-1);
	font-size: var(--kl-text-sm);
}

/* The band's closing entry to /guides/ (user, 2026-10-06). The homepage used
   to explain the guide library twice - the three facts above, then the
   "Understanding care in China" teaser between the trust bar and the
   categories - and the user read the second as the first said again. The
   teaser is gone; its one job, the way into the library, lands here as the
   band's own closing button.

   The button is the site's existing ghost button: the reader is being pointed
   at reading material, not asked for a contact detail, so it stays off the
   solid accent the header's Contact action owns. min-height keeps the same
   44px floor P7 holds every other clickable on this page to. */
.kl-orient__more {
	margin: var(--kl-space-6) 0 0;
}

.kl-orient__more-link {
	min-height: 44px;
}

@media (max-width: 900px) {
	.kl-orient__list {
		grid-template-columns: minmax(0, 1fr);
	}

	.kl-orient__item {
		padding: var(--kl-space-5) 0;
		border-left: 0;
		border-top: 1px solid var(--kl-border);
	}

	.kl-orient__item:first-child {
		padding-top: 0;
		border-top: 0;
	}

	.kl-orient__item:last-child {
		padding-bottom: 0;
	}
}

/* -------------------------------------------------------- Module cards --- */

.kl-modules {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: var(--kl-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-module {
	display: flex;
	flex-direction: column;
	height: 100%;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-module__icon {
	margin-bottom: var(--kl-space-3);
	color: var(--kl-accent);
}

.kl-module__title {
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-lg);
}

.kl-module__title a {
	color: inherit;
	text-decoration: none;
}

.kl-module__title a:hover,
.kl-module__title a:focus {
	color: var(--kl-accent-hover);
}

.kl-module__desc {
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
	font-size: var(--kl-text-base);
}

.kl-module__foot {
	margin-top: auto;
	color: var(--kl-slate);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- Two columns --- */

.kl-columns {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	gap: var(--kl-space-7);
}

.kl-columns__title {
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-xl);
}

.kl-news-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-news-list__item {
	padding: var(--kl-space-4) 0;
	border-bottom: 1px solid var(--kl-border);
}

.kl-news-list__item:first-child {
	padding-top: 0;
}

.kl-news-list__item a {
	font-weight: var(--kl-weight-semibold);
	text-decoration: none;
}

.kl-news-list__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2);
	margin: var(--kl-space-1) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-panel {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-panel + .kl-panel {
	margin-top: var(--kl-space-4);
}

.kl-panel__title {
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-lg);
}

/* ------------------------------------------------------- Evidence key --- */

.kl-levels {
	margin: 0;
}

.kl-level {
	display: flex;
	gap: var(--kl-space-3);
	padding: var(--kl-space-3) 0;
	border-bottom: 1px solid var(--kl-border);
}

.kl-level:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.kl-level__icon {
	color: var(--kl-slate);
}

.kl-level--a .kl-level__icon {
	color: var(--kl-level-a);
}

.kl-level--b .kl-level__icon {
	color: var(--kl-level-b);
}

.kl-level--c .kl-level__icon {
	color: var(--kl-level-c);
}

.kl-level__body {
	margin: 0;
}

.kl-level__name {
	display: block;
	font-weight: var(--kl-weight-semibold);
}

.kl-level__desc {
	display: block;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* ------------------------------------------------------- Service cards --- */

.kl-services {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--kl-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-service {
	display: flex;
	flex-direction: column;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-service__head {
	display: flex;
	align-items: flex-start;
	gap: var(--kl-space-3);
	margin-bottom: var(--kl-space-4);
}

.kl-service__icon {
	color: var(--kl-accent);
}

.kl-service__title {
	margin: 0;
	font-size: var(--kl-text-lg);
}

.kl-service__desc {
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
}

.kl-service__spec {
	margin: 0 0 var(--kl-space-4);
}

.kl-service__spec dt {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-semibold);
}

.kl-service__spec dd {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-base);
}

.kl-service__spec dd:last-child {
	margin-bottom: 0;
}

.kl-service__foot {
	margin-top: auto;
	padding-top: var(--kl-space-4);
	border-top: 1px solid var(--kl-border);
}

.kl-service__contact {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: var(--kl-space-3) 0 0;
	padding: 0;
	list-style: none;
	font-size: var(--kl-text-base);
}

.kl-service__contact a {
	display: inline-flex;
	align-items: center;
	gap: var(--kl-space-2);
}

/* --------------------------------------------------------------- Cards --- */

.kl-card-list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: var(--kl-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-card {
	display: flex;
	flex-direction: column;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-card__badge {
	align-self: flex-start;
	margin: 0 0 var(--kl-space-3);
	padding: var(--kl-space-1) var(--kl-space-3);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
	font-size: var(--kl-text-xs);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-card__title {
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-lg);
}

.kl-card__title a {
	color: inherit;
	text-decoration: none;
}

.kl-card__title a:hover,
.kl-card__title a:focus {
	color: var(--kl-accent-hover);
}

.kl-card__meta {
	margin: 0 0 var(--kl-space-3);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-card__chips {
	margin: 0 0 var(--kl-space-3);
}

.kl-card__excerpt {
	margin-top: auto;
	color: var(--kl-slate);
	font-size: var(--kl-text-base);
}

.kl-card__excerpt p {
	margin: 0;
}

.kl-card__foot {
	margin: var(--kl-space-3) 0 0;
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* -------------------------------------------------------- Single entry --- */

.kl-main {
	display: block;
}

.kl-single,
.kl-archive,
.kl-search-results {
	padding-top: var(--kl-space-7);
	padding-bottom: var(--kl-space-8);
}

.kl-entry {
	max-width: 820px;
}

.kl-entry__badge {
	display: inline-block;
	margin: 0 0 var(--kl-space-3);
	padding: var(--kl-space-1) var(--kl-space-3);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
	font-size: var(--kl-text-xs);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-entry__title {
	margin-bottom: var(--kl-space-3);
	font-size: var(--kl-text-3xl);
}

/* ------------------------------------------- English-first name (fix-003) ---
   The English name is a field, so it is rendered next to the Chinese title it
   belongs to: it leads on its own line, the Chinese original follows on a quiet
   second line. Both cards and single pages use the same two spans, so the pair
   cannot drift apart. Since fix-004 T3 each slot names its own language, so a
   record without an English name renders the Chinese name once, as the only
   child of the title - and that lone line stays at title size (the demotion
   below is for a quiet SECOND line). */

.kl-name-en {
	display: block;
}

.kl-name-zh {
	display: block;
	margin-top: var(--kl-space-1);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-regular);
	letter-spacing: normal;
}

.kl-name-zh:only-child {
	margin-top: 0;
	color: inherit;
	font-size: inherit;
	font-weight: inherit;
}

.kl-entry__icd {
	margin: var(--kl-space-6) 0 0;
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* dev-041: the procedure / project-code anchor line, printed directly under the
   ICD-10 line for a treatment line that carries no ICD-10 category of its own.
   It is a continuation of that line, so it takes no border and no top padding
   of its own. */
.kl-entry__procedure {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-entry__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2) var(--kl-space-5);
	margin: 0 0 var(--kl-space-5);
	color: var(--kl-slate);
	font-size: var(--kl-text-base);
}

.kl-entry__content {
	max-width: var(--kl-measure);
}

.kl-archive__header,
.kl-search-results__header {
	max-width: 68ch;
	margin-bottom: var(--kl-space-6);
}

.kl-archive__desc {
	color: var(--kl-slate);
}

.kl-search-results__scope {
	margin: 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-base);
}

/* ------------------------------------------------------- Source block --- */

.kl-source {
	max-width: 820px;
	margin-top: var(--kl-space-7);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-left: 4px solid var(--kl-slate);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-source--level-a {
	border-left-color: var(--kl-level-a);
}

.kl-source--level-b {
	border-left-color: var(--kl-level-b);
}

.kl-source--level-c {
	border-left-color: var(--kl-level-c);
}

.kl-source__title {
	display: flex;
	align-items: center;
	gap: var(--kl-space-2);
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-lg);
}

.kl-source--level-a .kl-source__title {
	color: var(--kl-level-a);
}

.kl-source--level-b .kl-source__title {
	color: var(--kl-level-b);
}

.kl-source--level-c .kl-source__title {
	color: var(--kl-level-c);
}

.kl-source__list {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: 0;
	font-size: var(--kl-text-base);
}

.kl-source__list dt {
	color: var(--kl-slate);
}

.kl-source__list dd {
	margin: 0;
	overflow-wrap: anywhere;
}

.kl-source__list dd:has(a) {
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
}

.kl-source__note {
	margin: var(--kl-space-4) 0 0;
	padding: var(--kl-space-3) var(--kl-space-4);
	border-radius: var(--kl-radius-input);
	background: var(--kl-note-bg);
	color: var(--kl-level-c);
	font-size: var(--kl-text-base);
}

/* ------------------------------------------------------- Field groups --- */

.kl-fields {
	max-width: 820px;
	margin-top: var(--kl-space-6);
}

.kl-fields__title {
	font-size: var(--kl-text-lg);
}

.kl-fields__list {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-base);
}

.kl-fields__list dt {
	color: var(--kl-slate);
}

.kl-fields__list dd {
	margin: 0;
	overflow-wrap: anywhere;
}

.kl-fields__note {
	margin: var(--kl-space-3) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* Link out of a field group to the full dataset (disease page blocks). */
.kl-fields__more {
	margin: var(--kl-space-4) 0 0;
	font-size: var(--kl-text-sm);
}

/* Lede sentence above the hospital-record table on a condition page (dev-005),
   and the specialty archive links below it. */
.kl-fields__lede {
	margin: var(--kl-space-3) 0 var(--kl-space-4);
	max-width: 68ch;
	color: var(--kl-ink);
}

.kl-fields__links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2) var(--kl-space-5);
	margin: var(--kl-space-3) 0 0;
	padding: 0;
	list-style: none;
	font-size: var(--kl-text-sm);
}

/* Level marker for dense contexts (tables, lists): a dot plus text, never a
   pill stack. */
.kl-level-tag {
	display: inline-flex;
	align-items: center;
	gap: var(--kl-space-2);
	white-space: nowrap;
}

.kl-level-tag::before {
	content: "";
	width: 8px;
	height: 8px;
	flex: 0 0 auto;
	border-radius: 50%;
	background: var(--kl-slate);
}

.kl-level-tag--a::before {
	background: var(--kl-level-a);
}

.kl-level-tag--b::before {
	background: var(--kl-level-b);
}

.kl-level-tag--c::before {
	background: var(--kl-level-c);
}

.kl-source-cell {
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
	overflow-wrap: anywhere;
}

/* -------------------------------------------------------------- Tables --- */

.kl-table-wrap {
	margin: 0;
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	overflow-x: auto;
}

.kl-table {
	width: 100%;
	min-width: 560px;
	border-collapse: collapse;
	font-size: var(--kl-text-base);
}

.kl-table th,
.kl-table td {
	padding: var(--kl-space-3) var(--kl-space-4);
	text-align: left;
	vertical-align: top;
	border-bottom: 1px solid var(--kl-border);
}

.kl-table th {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
	white-space: nowrap;
}

.kl-table tr:last-child td {
	border-bottom: 0;
}

.kl-table td.kl-num {
	font-family: var(--kl-font-mono);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/* --------------------------------------------------------- Policy pages --- */

.kl-policy {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 280px;
	gap: var(--kl-space-7);
	padding-top: var(--kl-space-7);
	padding-bottom: var(--kl-space-8);
	align-items: start;
}

.kl-policy__toc {
	position: sticky;
	top: var(--kl-space-5);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	font-size: var(--kl-text-base);
}

.kl-policy__toc-title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-base);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
	color: var(--kl-slate);
}

.kl-policy__toc ol {
	margin: 0;
	padding-left: var(--kl-space-5);
}

.kl-policy__toc li + li {
	margin-top: var(--kl-space-2);
}

/* dev-055 T1: `/insurance/` joins the two-column skeleton. Its scope / partner
   / direct-billing block is a direct child of the `.kl-policy` grid (it stays
   outside `.kl-prose`, so its own card styling is untouched), so it has to be
   pinned to the prose column - the grid's auto-placement would otherwise drop
   the first sibling into the 280px directory column. The column sizes it. */
.kl-policy > .kl-insurance__scope {
	grid-column: 1;
}

.kl-page-header {
	max-width: 68ch;
	padding-bottom: var(--kl-space-5);
	margin-bottom: var(--kl-space-5);
	border-bottom: 1px solid var(--kl-border);
}

.kl-page-header__lede {
	margin: var(--kl-space-3) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-lg);
}

.kl-page-header__stamp {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: var(--kl-space-4) 0 0;
	padding: 0;
	list-style: none;
	color: var(--kl-slate);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
}

/* dev-055 T2: on a prose page the header must read on the paragraph measure.
   The cap used to be 68ch, resolved against this block's inherited 15px
   (612px), while `.kl-prose p` resolves 72ch against its own 16px (691.2px) -
   one token, two pixel readings, and the lede and its rule were the narrow
   ones. Pinning the block's type size to the paragraph size makes
   `--kl-measure` resolve to one value here. Scoped to `.kl-prose` (the content
   pages), so a header outside the prose keeps the 68ch cap it was designed
   with (`/services/`, `/contact/`). */
.kl-prose > .kl-page-header {
	max-width: var(--kl-measure);
	font-size: var(--kl-text-md);
}

/* Privacy / Cookie pages (dev-012): the "last updated" line closes the prose. */
.kl-legal__updated {
	margin-top: var(--kl-space-6);
	padding-top: var(--kl-space-4);
	border-top: 1px solid var(--kl-border);
	color: var(--kl-slate);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
}

/* ---------------------------------------------------------------- Prose --- */

/* The reading measure applies to text, not to tables: a five-column log table
   squeezed into 72ch becomes a column of two-word lines. */
.kl-prose {
	max-width: none;
}

.kl-prose p,
.kl-prose li,
.kl-prose h2,
.kl-prose h3,
.kl-prose .kl-callout,
.kl-prose .kl-signature {
	max-width: var(--kl-measure);
}

.kl-prose h2 {
	margin-top: var(--kl-space-7);
	padding-top: var(--kl-space-2);
	font-size: var(--kl-text-2xl);
}

.kl-prose h3 {
	margin-top: var(--kl-space-5);
	font-size: var(--kl-text-lg);
}

.kl-prose p,
.kl-prose li {
	font-size: var(--kl-text-md);
}

.kl-prose p {
	margin: 0 0 var(--kl-space-4);
}

.kl-prose ul,
.kl-prose ol {
	margin: 0 0 var(--kl-space-4);
	padding-left: var(--kl-space-5);
}

.kl-prose li + li {
	margin-top: var(--kl-space-2);
}

.kl-prose code {
	font-family: var(--kl-font-mono);
	font-size: 0.9em;
}

.kl-prose .kl-table-wrap {
	margin: 0 0 var(--kl-space-5);
}

.kl-callout {
	margin: var(--kl-space-5) 0;
	padding: var(--kl-space-4) var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-left: 4px solid var(--kl-level-b);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-callout__title {
	display: flex;
	align-items: center;
	gap: var(--kl-space-2);
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-base);
	font-weight: var(--kl-weight-semibold);
	color: var(--kl-level-b);
}

.kl-callout p:last-child {
	margin-bottom: 0;
}

.kl-signature {
	margin: var(--kl-space-6) 0 0;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-signature dl {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: 0;
	font-size: var(--kl-text-base);
}

.kl-signature dt {
	color: var(--kl-slate);
}

.kl-signature dd {
	margin: 0;
}

/* ------------------------------------------------------------ Services --- */

/* The admission-timing block (dev-035 T1). It sits directly under the services
   page header and states the range and the expedited case once; the condition
   and the boundary stay ordinary paragraphs under it, so the qualifiers read as
   part of the statement rather than as fine print. The accent rule on the
   leading edge marks it as the page's answer to "how long does this take".
   Row width sits on the paragraphs, not on the box (known-issues #8). */

.kl-admission {
	margin: 0 0 var(--kl-space-6);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-left: 3px solid var(--kl-accent);
	border-radius: var(--kl-radius-card);
	background: var(--kl-accent-soft);
}

.kl-admission__title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-lg);
}

.kl-admission__headline {
	margin: 0;
	max-width: var(--kl-measure);
	color: var(--kl-ink);
	font-size: var(--kl-text-md);
}

.kl-admission__condition,
.kl-admission__boundary {
	margin: var(--kl-space-3) 0 0;
	max-width: var(--kl-measure);
	color: var(--kl-slate);
}

.kl-partner {
	margin-top: var(--kl-space-5);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-partner__head {
	display: flex;
	align-items: flex-start;
	gap: var(--kl-space-3);
	margin-bottom: var(--kl-space-3);
}

.kl-partner__title {
	margin: 0;
	font-size: var(--kl-text-lg);
}

.kl-partner__by {
	margin: var(--kl-space-1) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* The partner logo is the user-supplied file (no hotlink, no recolouring). It
   is shown on a white plate so the file's own white background reads as
   deliberate against the off-white card, and it carries the partner name as
   its alt text. */
.kl-partner__logo {
	margin: var(--kl-space-3) 0 0;
}

.kl-partner__logo img {
	display: block;
	width: 255px;
	height: auto;
	max-width: 100%;
	padding: var(--kl-space-2);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-input);
	background: var(--kl-paper);
	/* fix-008 T5 (ui-019): the logo used to stretch to the row's height, which
	   distorted it by ~11%. Contain keeps the artwork's own ratio on every row. */
	object-fit: contain;
	align-self: center;
}

/* --------------------------------------------------------- News coming soon --- */
/* fix-008 T4 (ui-015): the section is announced, not faked - the page names the
   six checks an item must pass before it can appear. */

.kl-news-coming {
	max-width: var(--kl-measure);
	margin: var(--kl-space-6) 0;
}

.kl-news-coming__lede {
	margin: 0 0 var(--kl-space-5);
	font-size: var(--kl-text-lg);
	color: var(--kl-slate);
}

.kl-news-coming__title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-xl);
}

.kl-news-coming__list {
	margin: 0 0 var(--kl-space-5);
	padding-left: var(--kl-space-5);
}

.kl-news-coming__list li {
	margin-bottom: var(--kl-space-2);
}

.kl-news-coming__note {
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
}

.kl-news-coming__links {
	margin: 0;
}

/* --------------------------------------------------------- News section ---
   dev-016: the news list and single pages. A card states the AI-assisted
   label, the date and the source name; the single page repeats them and adds
   the original-article button and the copyright block. Copy is verbatim from
   docs/文案-资讯栏目_v0.md. */

.kl-news-card__badge {
	align-self: flex-start;
	margin: 0 0 var(--kl-space-3);
	padding: var(--kl-space-1) var(--kl-space-3);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
	font-size: var(--kl-text-xs);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

/* The news wall's topic row (dev-049 B28). `wellcarechina_news_topic_chips()`
   prints nothing for an item that files under no topic, and an absent row is an
   absent 44px: on /news/ four of ten cards carry a topic and six do not, so the
   summaries started 44px apart and the row lost the one description line the
   wall is held to. Reserving the row's own height on the list - the
   `.kl-chips--topics` marker the helper always prints when it prints at all -
   holds every card's blocks on the same axis without inventing a placeholder
   chip for a fact the record does not state. A card with two topics grows past
   the floor on its own. */
.kl-chips--topics {
	min-height: 44px;
}

.kl-news-card__meta,
.kl-news-entry__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-1) var(--kl-space-4);
}

.kl-news-entry__ai {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-2) var(--kl-space-3);
	margin: var(--kl-space-4) 0 0;
}

.kl-news-entry__badge {
	display: inline-block;
	margin: 0;
	padding: var(--kl-space-1) var(--kl-space-3);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
	font-size: var(--kl-text-xs);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-news-entry__ai-note,
.kl-news-entry__rights {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-news-entry__original {
	margin: var(--kl-space-6) 0 0;
}

/* The original-article button is a primary action: it keeps a 44px touch
   height on every viewport (master §T2.4 / WCAG 2.5.8). */
.kl-news-entry__original-link {
	min-height: 44px;
}

.kl-news-entry__copyright {
	max-width: var(--kl-measure);
	margin: var(--kl-space-7) 0 0;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-left: 4px solid var(--kl-slate);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-news-entry__copyright-title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-lg);
}

.kl-news-entry__copyright p {
	margin: 0 0 var(--kl-space-3);
}

.kl-news-entry__copyright p:last-child {
	margin-bottom: 0;
}

.kl-news-entry__links {
	margin: var(--kl-space-6) 0 0;
}

.kl-partner__link {
	margin: var(--kl-space-3) 0 0;
}

/* "How to reach us" (dev-011 T2). The WhatsApp QR is live, labelled and
   linked to the same destination encoded in the image. */
.kl-contact {
	margin-top: var(--kl-space-6);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-contact__title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-lg);
}

.kl-contact__body p {
	margin: 0;
}

.kl-contact__body p + p {
	margin-top: var(--kl-space-2);
}

.kl-contact__qr {
	margin: var(--kl-space-4) 0 0;
}

.kl-contact__qr-label {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-semibold);
}

.kl-contact__qr img {
	display: block;
	width: 160px;
	height: auto;
	max-width: 100%;
}

.kl-declaration {
	margin-top: var(--kl-space-6);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	color: var(--kl-slate);
	font-size: var(--kl-text-base);
}

.kl-declaration p {
	margin: 0;
}

.kl-declaration p + p {
	margin-top: var(--kl-space-2);
}

/* -------------------------------------------------- Insurance guide (dev-034) ---
   The seventh block of /insurance/ (scope statement + partner + the
   direct-billing slot). It reuses the existing declaration, partner and
   empty-state shapes; only the outer spacing and the slot heading are new. */

.kl-insurance__scope {
	margin-top: var(--kl-space-6);
}

.kl-insurance__scope-title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-2xl);
}

.kl-insurance__scope .kl-declaration,
.kl-insurance__direct > p {
	max-width: var(--kl-measure);
}

.kl-insurance__direct {
	margin-top: var(--kl-space-5);
}

.kl-insurance__direct h3 {
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-lg);
}

/* The direct-billing list (dev-037). Each record is a card, so a long hospital
   name and its source line stay legible at 390px without a horizontal scroll;
   "inpatient only" is a pill because it is a restriction the entry carries, not
   a feature of it. Only new selectors here - the slot's existing rules and the
   shared tokens are untouched. */

.kl-insurance__direct-list {
	display: grid;
	gap: var(--kl-space-4);
	margin: var(--kl-space-4) 0 0;
	padding: 0;
	list-style: none;
}

.kl-insurance__record {
	margin: 0;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-insurance__record-name {
	margin: 0;
	font-size: var(--kl-text-md);
	font-weight: var(--kl-weight-semibold);
	line-height: var(--kl-leading-snug);
	overflow-wrap: anywhere;
}

.kl-insurance__record-meta {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-insurance__insurers {
	margin: var(--kl-space-3) 0 0;
	font-size: var(--kl-text-sm);
	overflow-wrap: anywhere;
}

.kl-insurance__inpatient {
	display: inline-block;
	margin: var(--kl-space-3) 0 0;
	padding: var(--kl-space-1) var(--kl-space-3);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-note-bg);
	color: var(--kl-ink);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-insurance__record-source {
	margin: var(--kl-space-3) 0 0;
	font-size: var(--kl-text-sm);
	overflow-wrap: anywhere;
}

.kl-insurance__direct-footer {
	margin: var(--kl-space-5) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* ------------------------------------------------------------- Utility --- */

.kl-empty {
	max-width: 68ch;
	margin: 0 0 var(--kl-space-4);
	padding: var(--kl-space-5);
	border: 1px dashed var(--kl-border-strong);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	color: var(--kl-slate);
}

.kl-empty--scoped {
	direction: ltr;
}

.kl-no-results {
	max-width: 68ch;
}

.kl-pagination,
.pagination {
	margin-top: var(--kl-space-6);
}

.kl-pagination .page-numbers,
.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	margin-right: var(--kl-space-2);
	padding: 0 var(--kl-space-2);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	color: var(--kl-ink);
	text-decoration: none;
}

.kl-pagination .page-numbers.current,
.pagination .page-numbers.current {
	background: var(--kl-accent);
	border-color: var(--kl-accent);
	color: var(--kl-paper);
}

.kl-post-nav {
	margin-top: var(--kl-space-6);
	padding-top: var(--kl-space-4);
	border-top: 1px solid var(--kl-border);
	font-size: var(--kl-text-base);
}

/* -------------------------------------------------------------- Footer --- */

.kl-footer {
	margin-top: var(--kl-space-8);
	padding: var(--kl-space-7) 0 var(--kl-space-6);
	background: var(--kl-navy);
	color: var(--kl-on-navy-muted);
	font-size: var(--kl-text-base);
}

.kl-footer a {
	color: var(--kl-on-navy);
}

.kl-footer__top {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-6);
	justify-content: space-between;
	padding-bottom: var(--kl-space-5);
	border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}

.kl-footer__brand {
	max-width: 40ch;
}

.kl-footer__brand-title {
	margin: 0;
	color: var(--kl-on-navy);
	font-size: var(--kl-text-lg);
	font-weight: var(--kl-weight-semibold);
}

.kl-footer__brand-note {
	margin: var(--kl-space-2) 0 0;
}

.kl-footer__nav-title {
	margin: 0 0 var(--kl-space-3);
	color: var(--kl-on-navy);
	font-size: var(--kl-text-sm);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-footer__list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-3) var(--kl-space-5);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-footer__disclaimer,
.kl-footer__note {
	max-width: 80ch;
	margin: var(--kl-space-4) 0 0;
}

.kl-footer__copy {
	margin: var(--kl-space-4) 0 0;
	font-size: var(--kl-text-sm);
}

/* -------------------------------------------------------------- Facets ---
   The directory filter bar (dev-010). Every facet value is an anchor, so the
   whole directory filters without JavaScript; the selected value keeps the
   shared chip's solid state and stays clickable to clear itself. */

.kl-facets {
	margin: 0 0 var(--kl-space-6);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-facets__group + .kl-facets__group {
	margin-top: var(--kl-space-4);
}

.kl-facets__title {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-chip--facet {
	gap: var(--kl-space-2);
}

.kl-chip__count {
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-variant-numeric: tabular-nums;
}

.kl-chip--selected .kl-chip__count {
	color: var(--kl-on-navy-muted);
}

.kl-facets__clear {
	margin: var(--kl-space-4) 0 0;
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
	font-size: var(--kl-text-sm);
}

.kl-facets__clear-link {
	color: var(--kl-accent-hover);
}

/* The grade block's one sentence: the published band is an administrative
   designation, not a quality judgement (dev-013).
   dev-105 (2026-10-08): promoted from `--kl-text-xs` to `--kl-text-sm` - this
   is a sentence to read, not a caps micro-label, and 12px measured below the
   site's own reading floor on every listing page. */
.kl-facets__note {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* dev-075: the grade block's orientation line, one paragraph under the note.
   It is the only text on a listing page exempted from the C7 "no ranking
   trace" scan, and check-directory C7 asserts it is present on every listing
   page before it strips it. */
.kl-facets__note--orient {
	margin-top: var(--kl-space-1);
}

.kl-archive__count {
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* -------------------------------------------------------- Touch targets ---
   fix-007 T7 (ledger ui-009): every element a visitor can tap is at least 44px
   tall. Block components take a min-height; inline links in prose grow their
   hit box with vertical padding, which does not change the line box. The only
   exceptions are the visually hidden elements (`.kl-skip-link`,
   `.kl-visually-hidden`), which are keyboard-only. */

.kl-btn,
.kl-nav__list a,
.kl-module__title a,
.kl-card__title a,
.kl-news-list__item a,
.kl-footer__list a,
.kl-panel a,
.kl-service__contact a,
.kl-branding__title a,
.kl-lang__toggle,
.kl-lang__link,
.kl-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

/* dev-105 (2026-10-08, pre-deploy sweep): the `Show all N …` folds share one
   disclosure component, but only the four contexts that grew one first carried
   the 44px floor. `/key-specialties/` measured 25.5px tall at 390 (79 folds),
   and the condition page's code table did too, while the same `.kl-fold__more`
   on `/hospitals/` measured 44px - the floor simply never reached the
   component. It lives here now. `min-height` + padding, not a flex display:
   a `<summary>` laid out with flex loses its own disclosure marker (measured
   before/after - the triangle disappeared), and that marker is the fold's only
   visible affordance. Padding alone (8px) keeps the marker and lets the
   min-height finish the job; the existing flex contexts are untouched, because
   min-height still wins there (25.5 + 16 < 44). */
.kl-fold__summary {
	min-height: 44px;
	padding-top: var(--kl-space-2);
	padding-bottom: var(--kl-space-2);
	cursor: pointer;
}

/* A card/module title stacks the English name over the Chinese one.
   dev-052 (ledger ui-033): the 44px hit-area group above hands this link
   `align-items: center`, so the stacked title was centred inside a
   full-width box. A short title landed in the middle of the card while every
   other line (meta, chips, excerpt, footer) stayed on the card's left edge,
   and a long title filled the box and read as left-aligned - one card grid
   could show both. `justify-content: center` had the same effect vertically:
   inside the 72px title box a one-line title sat lower than a two-line one,
   so titles on one row did not share a baseline. The box is now top-left
   aligned; `min-height: 72px` below still keeps the excerpt starting at the
   same y on every card in a row. */
.kl-module__title a,
.kl-card__title a {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-start;
	text-align: left;
}

.kl-main p > a,
.kl-main li > a {
	padding-top: var(--kl-space-4);
	padding-bottom: var(--kl-space-4);
}

/* ------------------------------------------------- City landing (dev-015) ---
   The L1 entrance of /hospitals/ (ledger ui-003 / ui-023). dev-015 T1 splits
   the page: the facet wall and the 730-row listing moved to /hospitals/all/,
   so the landing is the search box, the 12 curated city cards, ONE "Browse by
   province" fold and the "All hospitals" entry. Everything is a link or a
   native `<details>`, so the page needs no JavaScript at all. */

.kl-landing {
	margin: 0 0 var(--kl-space-7);
}

.kl-landing__title {
	margin: 0 0 var(--kl-space-2);
	font-size: var(--kl-text-xl);
}

.kl-landing__lede {
	max-width: 68ch;
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
	font-size: var(--kl-text-base);
}

/* The city cards: an equal-height grid (T4.1) whose columns step from four
   (desktop) to three to two, so the row height is the tallest card's height and
   a sparse record never leaves a short card beside a tall one. */
.kl-city-cards {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	grid-auto-rows: 1fr;
	gap: var(--kl-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (max-width: 1199px) {
	.kl-city-cards {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 899px) {
	.kl-city-cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 599px) {
	.kl-city-cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--kl-space-3);
	}
}

.kl-city-card {
	display: flex;
}

.kl-city-cards .kl-city-card__link {
	display: flex;
	flex-direction: column;
	width: 100%;
	height: 100%;
	min-height: 44px;
	padding: 0;
	overflow: hidden;
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
	color: inherit;
	text-decoration: none;
}

.kl-city-card__link:hover,
.kl-city-card__link:focus {
	border-color: var(--kl-border-strong);
}

.kl-city-card__img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	background: var(--kl-paper-alt);
}

/* The no-image fallback (T4.3): the card keeps a 16:10 band with a map pin, so
   a missing asset leaves no empty frame and the grid stays even. */
.kl-city-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 16 / 10;
	background: var(--kl-paper-alt);
	color: var(--kl-slate);
}

.kl-city-card__icon .kl-icon {
	width: 40px;
	height: 40px;
}

.kl-city-card__body {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: var(--kl-space-1);
	padding: var(--kl-space-4);
}

.kl-city-card__name {
	font-size: var(--kl-text-lg);
	font-weight: var(--kl-weight-semibold);
}

.kl-city-card__link:hover .kl-city-card__name,
.kl-city-card__link:focus .kl-city-card__name {
	color: var(--kl-accent-hover);
}

.kl-city-card__zh,
.kl-city-card__count {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* Push the count to the foot of the card so the three lines line up across a
   row of equal-height cards. */
.kl-city-card__body .kl-city-card__count {
	margin-top: auto;
}

/* One "Browse by province" fold (dev-015 T1): a single <details> whose summary
   is the section heading, opening a compact 3-column list of province links. */
.kl-provinces {
	display: block;
}

.kl-province {
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-input);
	background: var(--kl-paper);
}

.kl-province__summary {
	display: flex;
	align-items: center;
	gap: var(--kl-space-2);
	min-height: 44px;
	padding: var(--kl-space-2) var(--kl-space-3);
	cursor: pointer;
	list-style: none;
	font-size: var(--kl-text-md);
}

.kl-province--single .kl-province__summary {
	padding: var(--kl-space-3) var(--kl-space-4);
	font-size: var(--kl-text-xl);
}

.kl-province__summary::-webkit-details-marker {
	display: none;
}

.kl-province__summary::after {
	content: "";
	flex: 0 0 auto;
	width: 8px;
	height: 8px;
	margin-left: var(--kl-space-2);
	border-right: 2px solid var(--kl-slate);
	border-bottom: 2px solid var(--kl-slate);
	transform: rotate(45deg);
	transition: transform var(--kl-dur-fast) var(--kl-ease);
}

.kl-province[open] .kl-province__summary::after {
	transform: rotate(-135deg);
}

.kl-province__name {
	font-weight: var(--kl-weight-semibold);
}

.kl-province__summary .kl-province__count {
	margin-left: auto;
}

.kl-province__zh,
.kl-province__count {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-variant-numeric: tabular-nums;
}

.kl-province__list {
	margin: 0;
	padding: 0 0 var(--kl-space-2);
	list-style: none;
	border-top: 1px solid var(--kl-border);
}

.kl-province__list li {
	margin: 0;
}

.kl-provinces .kl-province__list a {
	display: flex;
	align-items: center;
	gap: var(--kl-space-2);
	min-height: 44px;
	padding: var(--kl-space-2) var(--kl-space-3);
	color: inherit;
	text-decoration: none;
	font-size: var(--kl-text-base);
}

.kl-province__list a:hover,
.kl-province__list a:focus {
	color: var(--kl-accent-hover);
	background: var(--kl-paper-alt);
}

.kl-province__list .kl-province__count {
	margin-left: auto;
}

/* The compact 3-column province list (T1.1); it steps to two columns, then
   one, as the viewport narrows. */
.kl-province__list--grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 0 var(--kl-space-4);
}

@media (max-width: 899px) {
	.kl-province__list--grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 599px) {
	.kl-province__list--grid {
		grid-template-columns: 1fr;
	}
}

.kl-landing__all {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-3);
	max-width: none;
	margin: var(--kl-space-6) 0 0;
}

.kl-landing__all-link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 var(--kl-space-5);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper);
	font-weight: var(--kl-weight-semibold);
}

.kl-landing__all-note {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-all-hospitals__title {
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-xl);
}

.kl-all-hospitals--preceded {
	margin-top: var(--kl-space-6);
	padding-top: var(--kl-space-6);
	border-top: 1px solid var(--kl-border);
}

.kl-all-hospitals {
	scroll-margin-top: var(--kl-space-6);
}

/* dev-105 (2026-10-08): the sort note is a sentence ("Sorted by province,
   then city, then hospital name."), so it reads at `--kl-text-sm` like the
   grade note above, not at the 12px caps-label size it inherited. */
.kl-archive__sort-note {
	margin: calc(-1 * var(--kl-space-3)) 0 var(--kl-space-5);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* The header line of a simplified result view (dev-015 T3): the filter in
   effect, the way back to the landing and one "Clear filter". */
.kl-archive__filter {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-1) var(--kl-space-3);
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-archive__filter-value {
	color: var(--kl-ink);
}

.kl-archive__filter .kl-archive__filter-change,
.kl-archive__filter .kl-facets__clear-link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

.kl-archive__filter .kl-facets__clear-link {
	margin-left: auto;
}

/* Equal-height hospital cards (ledger ui-013): every row takes the height of
   its tallest card, so a sparse record no longer leaves a one-line card beside
   a full one. Scoped to the hospital listing; the other archives are a later
   batch. */
.kl-archive--hospitals .kl-card-list {
	grid-auto-rows: 1fr;
	align-items: stretch;
}

/* --------------------------------------------- Hospital detail (dev-014) ---
   T3 puts the record in a wide main column with the key-facts / enquiry panel
   beside it, so the page no longer reads as one 544px strip (ledger ui-012),
   adds the breadcrumb, and grows the inline links a finger has to hit to 44px
   (ledger ui-013 / e2e-003). */

.kl-single--hospital .kl-entry {
	max-width: none;
}

.kl-breadcrumb {
	margin: 0 0 var(--kl-space-4);
}

.kl-breadcrumb__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0 var(--kl-space-1);
	margin: 0;
	padding: 0;
	list-style: none;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-breadcrumb__item + .kl-breadcrumb__item::before {
	content: "›";
	color: var(--kl-slate);
}

.kl-breadcrumb__item a,
.kl-breadcrumb__item [aria-current] {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

.kl-breadcrumb__item a {
	color: var(--kl-slate);
}

.kl-breadcrumb__item a:hover,
.kl-breadcrumb__item a:focus {
	color: var(--kl-accent-hover);
}

.kl-breadcrumb__item [aria-current] {
	color: var(--kl-ink);
}

.kl-entry__body {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: var(--kl-space-6) var(--kl-space-7);
	align-items: start;
	margin-top: var(--kl-space-5);
}

.kl-entry__main {
	min-width: 0;
}

.kl-entry__aside {
	display: flex;
	flex-direction: column;
	gap: var(--kl-space-5);
}

.kl-facts {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-facts__title,
.kl-cta__title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-lg);
}

.kl-facts__list {
	margin: 0;
}

.kl-facts__row + .kl-facts__row {
	margin-top: var(--kl-space-3);
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
}

.kl-facts__label {
	margin: 0 0 var(--kl-space-1);
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-facts__value {
	margin: 0;
	overflow-wrap: anywhere;
}

/* A link inside the panel (the hospital's own site) is a finger target too. */
.kl-facts__value a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

.kl-fact__source {
	display: block;
	margin-top: var(--kl-space-1);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-cta {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-cta__lede {
	margin: 0 0 var(--kl-space-3);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-cta .kl-btn-note {
	display: block;
	margin-top: var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* The layer line under the CTA (dev-020): the pilot-award evidence line on an
   A1 / A2 page, the "we have not verified" note on a B / C page. */
.kl-cta__evidence,
.kl-cta__note {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-cta__evidence a {
	overflow-wrap: anywhere;
}

/* Previous / next hospital: a finger target, not a sentence. */
.kl-single .post-navigation a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

/* The record's own links (the official site row, a row's source URL) sit in a
   `<dd>`, which the shared inline-link padding rule does not cover, so they get
   the 44px box here. Scoped to the hospital page: this batch does not touch the
   other single templates. */
.kl-single--hospital .kl-fields__list dd a,
.kl-single--hospital .kl-source__list a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

@media (max-width: 900px) {
	.kl-entry__body {
		grid-template-columns: minmax(0, 1fr);
	}

	/* A source link inside a table row is tapped, not read: give it a 44px box
	   on small screens only (the desktop inline-link size is exempt). */
	.kl-table .kl-source-cell a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: var(--kl-space-2);
	}
}

/* ------------------------------------------------------- Breakpoints --- */

@media (max-width: 900px) {
	/* Mobile header (fix-007 T7): at most two compact rows - the brand and the
	   menu button on the first, the language selector and the search on the
	   second. The menu itself overlays the page, so opening it never makes the
	   header taller. */
	.kl-header__inner {
		position: relative;
		flex-wrap: wrap;
		gap: var(--kl-space-2);
		padding-top: var(--kl-space-2);
		padding-bottom: var(--kl-space-2);
	}

	.kl-branding {
		order: 1;
		flex: 1 1 200px;
		min-width: 0;
	}

	/* The tagline is dropped on small screens so the brand and the menu button
	   share one row (the header height budget does not allow three rows). */
	.kl-branding__tagline {
		display: none;
	}

	.kl-nav__details {
		display: block;
		order: 2;
		flex: 0 0 auto;
	}

	.kl-lang {
		order: 3;
	}

	/* fix-019 (ledger ui-037): the panel hangs off one edge of the pill, so it
	   must never be wider than the axis it is anchored to - otherwise a long
	   language name (7 languages are planned) pushes it off the opposite edge.
	   The anchor itself is handled by the two bands below. */
	.kl-lang__list {
		max-width: calc(100vw - 2 * var(--kl-space-5));
	}

	.kl-nav__toggle {
		display: inline-flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		cursor: pointer;
		list-style: none;
		touch-action: manipulation;
	}

	.kl-nav__toggle::-webkit-details-marker {
		display: none;
	}

	/* The menu row ships hidden on mobile and is revealed by the opened
	   disclosure; it overlays the page so the header keeps its height. */
	.kl-nav {
		display: none;
	}

	.kl-nav__details[open] ~ .kl-nav {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 30;
		padding: var(--kl-space-3) var(--kl-space-5) var(--kl-space-4);
		background: var(--kl-paper);
		border-top: 1px solid var(--kl-border);
		box-shadow: var(--kl-shadow-2);
	}

	.kl-nav__list {
		flex-direction: column;
		gap: 0;
	}

	.kl-nav__list a {
		width: 100%;
	}
}

/* fix-033: phones below 480px keep one compact utility row. The menu loses
   its visible word (the accessible name stays on the native summary) and the
   language control shows its two-letter code instead of the full language
   name. Both controls remain 44px targets, so the brand and utilities now fit
   on one row instead of leaving the language pill alone on a second row. */
@media (max-width: 478px) {
	.kl-header__inner {
		flex-wrap: nowrap;
		gap: var(--kl-space-2);
		padding-inline: var(--kl-space-4);
	}

	.kl-branding {
		flex: 1 1 0;
	}

	.kl-header .kl-branding__logo {
		width: min(156px, 100%);
		height: auto;
	}

	.kl-nav__toggle {
		justify-content: center;
		width: 44px;
		padding: 0;
	}

	.kl-lang {
		order: 2;
	}

	.kl-nav__details {
		order: 3;
	}

	.kl-lang__toggle {
		gap: var(--kl-space-1);
		padding-inline: var(--kl-space-2);
		white-space: nowrap;
	}

	/* Visually hide the full control labels without removing them from the
	   summaries' accessible names. */
	.kl-nav__toggle-label,
	.kl-lang__toggle-label {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
	}

	.kl-lang__toggle-code {
		display: inline;
	}

	.kl-lang__list {
		right: 0;
		left: auto;
		top: calc(100% + var(--kl-space-1));
		width: max-content;
		min-width: 200px;
		max-width: calc(100vw - 2 * var(--kl-space-4));
	}
}

@media (max-width: 1024px) {
	.kl-modules {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.kl-policy {
		grid-template-columns: minmax(0, 1fr);
	}

	.kl-policy__toc {
		position: static;
	}
}

@media (max-width: 860px) {
	.kl-hero {
		padding: var(--kl-space-7) 0 var(--kl-space-6);
	}

	.kl-hero__inner {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--kl-space-6);
	}

	.kl-hero__title {
		font-size: var(--kl-text-3xl);
	}

	.kl-columns {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--kl-space-6);
	}

	.kl-services {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 700px) {
	.kl-section {
		padding: var(--kl-space-6) 0;
	}

	.kl-section--tight {
		padding: var(--kl-space-5) 0;
	}

	.kl-section__title {
		font-size: var(--kl-text-xl);
	}

	.kl-entry__title {
		font-size: var(--kl-text-2xl);
	}

	.kl-page-header h1 {
		font-size: var(--kl-text-2xl);
	}

	.kl-hero__title {
		font-size: var(--kl-text-2xl);
	}

	.kl-hero__lede {
		font-size: var(--kl-text-md);
	}

	.kl-trust__sep {
		display: none;
	}

	.kl-trust__list {
		gap: var(--kl-space-4) var(--kl-space-5);
	}

	.kl-source__list,
	.kl-fields__list,
	.kl-signature dl {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--kl-space-1);
	}

	.kl-source__list dt,
	.kl-fields__list dt {
		margin-top: var(--kl-space-2);
	}

	.kl-footer__top {
		gap: var(--kl-space-5);
	}
}

@media (max-width: 520px) {
	.kl-modules {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after,
	/* dev-025: `::backdrop` is a pseudo-element of the element, not of `*` or
	   `::before` / `::after`, so the selector list has to name it or the
	   selector sheet's backdrop fade would survive a reduced-motion request. */
	*::backdrop {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}
}

/* -------------------------------------------------- Why China (dev-017) --- */
/* The advantage pages (treatment volume / technology access / visas and
   entry). Charts are inline SVG drawn by inc/advantages.php: no JavaScript,
   no third-party resource, no new font. */

.kl-adv {
	padding-top: var(--kl-space-7);
}

.kl-adv__title {
	font-size: var(--kl-text-3xl);
}

.kl-adv__banner {
	margin: 0 0 var(--kl-space-7);
	padding: var(--kl-space-3) var(--kl-space-4);
	border: 1px solid var(--kl-border);
	border-left: 4px solid var(--kl-accent);
	border-radius: var(--kl-radius-input);
	background: var(--kl-accent-soft);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-adv__block {
	margin: 0 0 var(--kl-space-8);
}

.kl-adv__block-title {
	margin-bottom: var(--kl-space-4);
	padding-bottom: var(--kl-space-2);
	border-bottom: 1px solid var(--kl-border);
}

.kl-adv__block-note {
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* Charts: a fixed 720-unit drawing keeps the labels at their designed size;
   a narrower screen scrolls the chart instead of shrinking the type. */

.kl-adv__figure {
	margin: 0 0 var(--kl-space-5);
}

.kl-adv__chart-wrap {
	overflow-x: auto;
	padding-bottom: var(--kl-space-1);
}

.kl-adv__chart {
	display: block;
	width: 720px;
	max-width: none;
	height: auto;
}

.kl-adv__chart text {
	fill: var(--kl-ink);
	font-family: var(--kl-font-sans);
	font-size: 14px;
}

.kl-adv__bar-label {
	fill: var(--kl-slate);
}

.kl-adv__chart-value {
	font-weight: var(--kl-weight-semibold);
	font-variant-numeric: tabular-nums;
}

.kl-adv__bar {
	fill: var(--kl-accent);
}

.kl-adv__caption {
	margin-top: var(--kl-space-3);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* Data table: the metric and caliber columns carry the text, the value and
   as-of columns stay in the mono face so figures line up down the column. */

.kl-adv__table .kl-adv__metric,
.kl-adv__table .kl-adv__caliber {
	min-width: 180px;
}

/* dev-056: the `white-space: nowrap` that used to sit here was a defect, not a
   style. On `/why-china-visa-and-entry/` it made the browser size `Year or
   as-of` to 401px and squeeze `Caliber` into 182px, so every row of that page's
   longest table grew to ~280px and the page to 14,390px. The two short columns
   are free to wrap now; the mono face and the tabular figures stay, so a column
   still reads down. GLOBAL on purpose (裁定 01): the same tables on
   `/why-china-treatment-volume/` and `/why-china-technology-access/` carry the
   same defect and their typography improves with it - this is the batch's one
   global release, everything else is scoped to `.kl-adv--visa` below. */
.kl-adv__table .kl-adv__value,
.kl-adv__table .kl-adv__asof {
	font-family: var(--kl-font-mono);
	font-variant-numeric: tabular-nums;
}

/* Sources */

.kl-adv__sources {
	margin: 0 0 var(--kl-space-8);
}

.kl-adv__source-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-adv__source {
	padding: var(--kl-space-4) 0;
	border-bottom: 1px solid var(--kl-border);
}

.kl-adv__source-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-3);
	margin: 0 0 var(--kl-space-2);
}

.kl-adv__source-label {
	font-weight: var(--kl-weight-semibold);
}

.kl-adv__source-url {
	margin: 0;
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
	overflow-wrap: anywhere;
}

.kl-adv__source-url a {
	display: inline-block;
	min-height: 44px;
	padding: var(--kl-space-2) 0;
}

.kl-adv__source-meta {
	margin: var(--kl-space-1) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* What we cannot tell you */

.kl-adv__limits {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-left: 4px solid var(--kl-level-c);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-adv__limit-list {
	margin: 0;
	padding-left: var(--kl-space-5);
}

.kl-adv__limit + .kl-adv__limit {
	margin-top: var(--kl-space-3);
}

/* Cross-links to the other two pages */

.kl-adv__chips {
	margin-top: var(--kl-space-7);
	padding-top: var(--kl-space-5);
	border-top: 1px solid var(--kl-border);
}

@media (max-width: 900px) {
	.kl-adv__title {
		font-size: var(--kl-text-2xl);
	}

	.kl-adv__limits {
		padding: var(--kl-space-4);
	}
}

/* ------------------------------------ Advantage long page (dev-056) ---
   `/why-china-visa-and-entry/` measured 14,390px at 1440 across four
   six-column data tables whose rows averaged ~280px. The copy was not the
   cause: `white-space: nowrap` on `.kl-adv__asof` / `.kl-adv__value` made the
   browser size `Year or as-of` to 401px and squeeze `Caliber` to 182px, wrapping
   every long sentence into a narrow cell. That one declaration is released
   GLOBALLY at its own rule above (裁定 01); here the six shares are fixed, so a
   row follows its text instead of its longest single cell.

   Everything below is scoped to `.kl-adv--visa` - the class the visa branch of
   `wellcarechina_render_advantages_page()` prints - so the two sibling
   advantage pages keep the dev-017 rendering byte for byte.

   The tables keep `.kl-table-wrap`'s sideways scroll on a narrow screen rather
   than taking the `.kl-table--stack` card layout: the same rows become ~340px
   cards under that layout (390px page measured 25,831 against 12,263 with the
   scroll), which would break the batch's own 390 line. Measured before/after
   for both choices: docs/testing/dev-056/. */

.kl-adv--visa .kl-adv__table {
	table-layout: fixed;
	/* At least the content column wide, so the six shares below resolve to the
	   same widths at every viewport and a narrow screen scrolls the wrapper
	   instead of squeezing the caliber column (known-issues #8). */
	min-width: calc(var(--kl-container) - 2 * var(--kl-space-5));
}

.kl-adv--visa .kl-adv__table th:nth-child(1) { width: 16%; }
.kl-adv--visa .kl-adv__table th:nth-child(2) { width: 8%; }
.kl-adv--visa .kl-adv__table th:nth-child(3) { width: 9%; }
.kl-adv--visa .kl-adv__table th:nth-child(4) { width: 47%; }
.kl-adv--visa .kl-adv__table th:nth-child(5) { width: 7%; }
.kl-adv--visa .kl-adv__table th:nth-child(6) { width: 13%; }

.kl-adv--visa .kl-adv__table th,
.kl-adv--visa .kl-adv__table td {
	padding: var(--kl-space-2) var(--kl-space-3);
	line-height: 1.4;
}

/* The base header rule is `nowrap`, which is right for a wide column and wrong
   for a 9%-wide one: "YEAR OR AS-OF" is wider than its column and runs into
   "CALIBER". Let the header wrap to its column like the cells do. */
.kl-adv--visa .kl-adv__table th {
	white-space: normal;
}

/* The chart's caption is its `<h3>` (dev-056 T1): it sits above the drawing as
   a sub-heading, and the "On this page" list deliberately still carries `h2`
   only. */
.kl-adv--visa .kl-adv__subhead {
	margin: var(--kl-space-5) 0 var(--kl-space-2);
	font-size: var(--kl-text-lg);
}

.kl-adv--visa .kl-adv__block {
	margin-bottom: var(--kl-space-7);
}

.kl-adv--visa .kl-adv__block-title {
	margin-bottom: var(--kl-space-3);
}

.kl-adv--visa .kl-adv__figure {
	margin: 0 0 var(--kl-space-3);
}

.kl-adv--visa .kl-adv__caption {
	margin-top: var(--kl-space-1);
}

/* The prose measure, on the text elements only - the tables keep the grid
   width (known-issues #8). */
.kl-adv--visa .kl-page-header__lede,
.kl-adv--visa .kl-adv__banner,
.kl-adv--visa .kl-adv__block-note,
.kl-adv--visa .kl-adv__limit {
	max-width: var(--kl-measure);
}

/* The block's own explanatory sentence, and each rule / exception sentence in
   "What we cannot tell you", wear the site's callout (dev-056 T2). The limits
   box itself steps aside - its five sentences are the boxes now. */
.kl-adv--visa .kl-callout--note {
	border-left-color: var(--kl-accent);
}

.kl-adv--visa .kl-adv__limits {
	padding: 0;
	border: 0;
	background: none;
}

.kl-adv--visa .kl-adv__limit-list {
	padding-left: 0;
	list-style: none;
}

.kl-adv--visa .kl-adv__limits .kl-adv__limit.kl-callout {
	margin: 0;
	padding: var(--kl-space-3) var(--kl-space-4);
	border-left-color: var(--kl-level-c);
}

.kl-adv--visa .kl-adv__limits .kl-adv__limit + .kl-adv__limit {
	margin-top: var(--kl-space-3);
}

/* Sources: the entries are a dense reference list - the reference rhythm, not
   the card rhythm. */
.kl-adv--visa .kl-adv__source {
	padding: var(--kl-space-3) 0;
}

.kl-adv--visa .kl-adv__source-head {
	margin-bottom: var(--kl-space-1);
}

.kl-adv--visa .kl-adv__source-url {
	margin-bottom: 0;
}

/* The 44px hit box stays (ui-009); only the wrapper's own 8px padding goes, so
   a twenty-entry reference list loses 16px an entry. */
.kl-adv--visa .kl-adv__source-url a {
	padding: 0;
}

.kl-adv--visa .kl-adv__source-meta {
	margin-top: var(--kl-space-1);
}

/* dev-056 T3 (裁定 02-A): the source list's tail folds behind the site's own
   `.kl-fold` disclosure - the same `Show all N <noun>` summary sentence the hub
   and the condition pages print, with the count inside the label, and the same
   44px touch floor - so the page's largest single block stops being a 2,539px
   wall without dropping a citation. */
.kl-adv--visa .kl-adv__sources-more {
	margin-top: var(--kl-space-4);
}

.kl-adv--visa .kl-adv__sources-more .kl-fold__summary {
	display: flex;
	align-items: center;
	gap: var(--kl-space-3);
	min-height: 44px;
	cursor: pointer;
}

.kl-adv--visa .kl-adv__sources-more .kl-fold__label {
	font-weight: var(--kl-weight-semibold);
}

.kl-adv--visa .kl-adv__sources-more .kl-fold__body {
	margin-top: var(--kl-space-2);
}

/* ------------------------------ Advantage long page, technology (dev-057) ---
   `/why-china-technology-access/` measured 16,663px at 1440 and 32,261px at 390
   across four six-column tables (68 rows in all; the first table alone carries
   51) and a 20-entry source list. Two of the three blocks were layout, not
   content:

   - the tables had no fixed columns, so at 390 the browser collapsed them to
     their minimum width and the `Caliber` cell wrapped into a 180px column
     (its `min-width` floor) - the tallest row measured 571px, and the page grew
     to twice its desktop height. With the six shares fixed here the table keeps
     the content column's width at every viewport and the wrapper scrolls
     sideways instead (known-issues #8), so a row is the same height at 390 as at
     1440;
   - the source list is a dense reference block, the same case dev-056 folded on
     the visa page.

   The six shares are tuned for this page's own columns (institution names, the
   device-type string, the long policy caliber and the very long trial query
   URLs). Everything here is scoped to `.kl-adv--tech`, the class the technology
   branch of `wellcarechina_render_advantages_page()` prints, so the two sibling
   advantage pages keep the dev-017 rendering byte for byte. Measured shares and
   heights, before and after, with both the fold and the table choices:
   docs/testing/dev-057/. */

.kl-adv--tech .kl-adv__table {
	table-layout: fixed;
	/* At least the content column wide, so the shares resolve to the same widths
	   at every viewport and a narrow screen scrolls the wrapper instead of
	   squeezing the caliber column (known-issues #8). */
	min-width: calc(var(--kl-container) - 2 * var(--kl-space-5));
}

.kl-adv--tech .kl-adv__table th:nth-child(1) { width: 26%; }
.kl-adv--tech .kl-adv__table th:nth-child(2) { width: 16%; }
.kl-adv--tech .kl-adv__table th:nth-child(3) { width: 9%; }
.kl-adv--tech .kl-adv__table th:nth-child(4) { width: 25%; }
.kl-adv--tech .kl-adv__table th:nth-child(5) { width: 9%; }
.kl-adv--tech .kl-adv__table th:nth-child(6) { width: 15%; }

.kl-adv--tech .kl-adv__table th,
.kl-adv--tech .kl-adv__table td {
	padding: var(--kl-space-1) var(--kl-space-3);
	line-height: 1.35;
}

/* Same reason as the visa page: the base header rule is `nowrap`, which is wrong
   for a 9%-wide column - "YEAR OR AS-OF" would run into "CALIBER". */
.kl-adv--tech .kl-adv__table th {
	white-space: normal;
}

/* The chart's caption is its `<h3>` (dev-057 T1), the same shape as the visa
   page; "On this page" deliberately still lists only the `h2` entries. */
.kl-adv--tech .kl-adv__subhead {
	margin: var(--kl-space-5) 0 var(--kl-space-2);
	font-size: var(--kl-text-lg);
}

.kl-adv--tech .kl-adv__block {
	margin-bottom: var(--kl-space-7);
}

.kl-adv--tech .kl-adv__block-title {
	margin-bottom: var(--kl-space-3);
}

.kl-adv--tech .kl-adv__figure {
	margin: 0 0 var(--kl-space-3);
}

/* The prose measure applies to the text elements only - the tables keep the
   grid width (known-issues #8). */
.kl-adv--tech .kl-page-header__lede,
.kl-adv--tech .kl-adv__banner,
.kl-adv--tech .kl-adv__block-note,
.kl-adv--tech .kl-adv__limit {
	max-width: var(--kl-measure);
}

/* What we cannot tell you (dev-057 T2): the five rule / exception sentences wear
   the site's callout, so the licence scope, the provincial-management gap, the
   CAR-T gap and the trial-count caliber read as rules; the missing-row records
   stay plain list items and keep the limits box's own left rule. */
.kl-adv--tech .kl-adv__limits {
	padding: 0;
	border: 0;
	background: none;
}

.kl-adv--tech .kl-adv__limit-list {
	padding-left: 0;
	list-style: none;
}

.kl-adv--tech .kl-adv__limits .kl-adv__limit.kl-callout {
	margin: 0;
	padding: var(--kl-space-3) var(--kl-space-4);
	border-left-color: var(--kl-level-c);
}

.kl-adv--tech .kl-adv__limits .kl-adv__limit.kl-callout + .kl-adv__limit.kl-callout {
	margin-top: var(--kl-space-3);
}

.kl-adv--tech .kl-adv__limits .kl-adv__limit--missing {
	margin-top: var(--kl-space-3);
	padding-left: var(--kl-space-4);
	border-left: 4px solid var(--kl-level-c);
}

/* The first block's exhaustive centre list folds behind the same disclosure the
   sources use (dev-057 T3): the policy rows and the licence batches stay in
   view, the forty-two centres stay in the DOM, and the summary prints the
   table's own row count. */
.kl-adv--tech .kl-adv__table-more {
	margin-top: var(--kl-space-4);
}

.kl-adv--tech .kl-adv__table-more .kl-fold__summary {
	display: flex;
	align-items: center;
	gap: var(--kl-space-3);
	min-height: 44px;
	cursor: pointer;
}

.kl-adv--tech .kl-adv__table-more .kl-fold__label {
	font-weight: var(--kl-weight-semibold);
}

.kl-adv--tech .kl-adv__table-more .kl-fold__body {
	margin-top: var(--kl-space-2);
}

/* Sources: the same reference rhythm and fold the visa page uses (dev-056). */
.kl-adv--tech .kl-adv__source {
	padding: var(--kl-space-3) 0;
}

.kl-adv--tech .kl-adv__source-head {
	margin-bottom: var(--kl-space-1);
}

.kl-adv--tech .kl-adv__source-url {
	margin-bottom: 0;
}

.kl-adv--tech .kl-adv__source-url a {
	padding: 0;
}

.kl-adv--tech .kl-adv__source-meta {
	margin-top: var(--kl-space-1);
}

.kl-adv--tech .kl-adv__sources-more {
	margin-top: var(--kl-space-4);
}

.kl-adv--tech .kl-adv__sources-more .kl-fold__summary {
	display: flex;
	align-items: center;
	gap: var(--kl-space-3);
	min-height: 44px;
	cursor: pointer;
}

.kl-adv--tech .kl-adv__sources-more .kl-fold__label {
	font-weight: var(--kl-weight-semibold);
}

.kl-adv--tech .kl-adv__sources-more .kl-fold__body {
	margin-top: var(--kl-space-2);
}

/* ------------------------------------------- Content images (dev-018) --- */
/* The delivered cover images, shared by four surfaces (homepage module cards,
   service cards, news covers, policy page headers). The wrapper reserves the
   display ratio and the image is cropped into it; the intrinsic width/height
   on the <img> keeps the reserved box correct even before this sheet loads. */

.kl-module__media,
.kl-service__media,
.kl-news-card__media,
.kl-news-entry__media,
.kl-page__media {
	margin: 0 0 var(--kl-space-4);
	overflow: hidden;
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-module__media img,
.kl-service__media img,
.kl-news-card__media img,
.kl-news-entry__media img,
.kl-page__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.kl-module__media,
.kl-service__media {
	aspect-ratio: 16 / 10;
}

.kl-news-card__media,
.kl-news-entry__media {
	aspect-ratio: 16 / 9;
}

.kl-page__media {
	aspect-ratio: 21 / 9;
}

/* --------------------------------- Mobile interaction (dev-024) ---
   Ledger ui-024 (a 390px header search squeezed until its placeholder read
   "Disease n") and ui-025 (legal pages with no verifiable reading
   confirmation and no status feedback anywhere).
   Scope: prompts/dev/dev-024-mobile-interaction-master.md §四 - two new
   durations live in assets/css/tokens.css, and exactly four motions are added
   here: the card/list hover lift, the chip focus lift, the reading-gate
   progress bar and the header search reveal. Everything below is neutralised
   by the existing `prefers-reduced-motion: reduce` block (style.css, above). */

/* 1 - card / list row hover lift: the design system's "lift 2px", implemented.
   The hover media query keeps a stuck hover off touch devices. */

.kl-card {
	transition: transform var(--kl-dur-fast) var(--kl-ease);
}

@media (hover: hover) {
	.kl-card:hover {
		transform: translateY(-2px);
	}
}

/* 2 - a chip lifts 2px when it takes keyboard focus. */

.kl-chip {
	transition: transform var(--kl-dur-fast) var(--kl-ease);
}

.kl-chip:focus-visible {
	transform: translateY(-2px);
}

/* 3 - the reading confirmation gate (ledger ui-025). Front-end only: no
   request, no cookie, no storage. It sits at the end of the prose in normal
   flow - never a fixed overlay over the text. */

.kl-reading-gate {
	margin-top: var(--kl-space-6);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-reading-gate__note {
	margin: 0;
	color: var(--kl-ink);
}

.kl-reading-gate__caption {
	margin: var(--kl-space-3) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* The progress row only exists once the script is running: a browser without
   JavaScript never shows a "0%" it cannot update (the button below it stays
   enabled there, which is the progressive-enhancement contract). */

.kl-reading-gate__progress {
	display: none;
	margin-top: var(--kl-space-3);
}

.kl-reading-gate--active .kl-reading-gate__progress {
	display: block;
}

.kl-reading-gate__track {
	display: block;
	height: 6px;
	border-radius: var(--kl-radius-pill);
	background: var(--kl-disabled-bg);
	overflow: hidden;
}

.kl-reading-gate__fill {
	display: block;
	width: 0;
	height: 100%;
	background: var(--kl-accent);
	transition: width var(--kl-dur-base) linear;
}

.kl-reading-gate__value {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-variant-numeric: tabular-nums;
}

.kl-reading-gate__confirm {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	margin-top: var(--kl-space-4);
	padding: 0 var(--kl-space-5);
	border: 1px solid var(--kl-accent);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent);
	color: var(--kl-paper);
	font-family: inherit;
	font-size: var(--kl-text-md);
	font-weight: var(--kl-weight-semibold);
	cursor: pointer;
	transition: background-color var(--kl-dur-slow) var(--kl-ease), border-color var(--kl-dur-slow) var(--kl-ease), color var(--kl-dur-slow) var(--kl-ease);
}

.kl-reading-gate__confirm:disabled {
	border-color: var(--kl-border-strong);
	background: var(--kl-disabled-bg);
	color: var(--kl-disabled-ink);
	cursor: not-allowed;
}

.kl-reading-gate__confirm.is-confirmed {
	border-color: var(--kl-accent);
	background: var(--kl-paper);
	color: var(--kl-accent-hover);
}

/* --------------------------------------- Condition evidence (dev-022) ---
   The shortlist, its evidence card and the clinical-study list on a condition
   page, plus the same card on a hospital page (spec
   docs/design/疾病页医院短名单与临床试验_v1_20260928.md §3 / §4.2).

   Two rules the whole component follows:
   1. everything a visitor can tap keeps the 44px touch height (fix-007 T7):
      block links take a min-height, inline links in a sentence grow their hit
      box with vertical padding, which does not change the line box;
   2. a quoted source URL wraps anywhere (`overflow-wrap: anywhere`), so a long
      registry or ministry URL can never push the page sideways at 390px.
   No transition is added here, so the prefers-reduced-motion contract that
   covers the rest of the site is untouched. */

.kl-evidence__disclosure {
	display: inline-flex;
	align-items: center;
	margin: var(--kl-space-3) 0 0;
	padding: var(--kl-space-1) var(--kl-space-3);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper-alt);
	color: var(--kl-ink);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-semibold);
}

.kl-evidence__method {
	margin-top: var(--kl-space-4);
}

.kl-evidence__method-summary,
.kl-evidence__extended-summary,
.kl-trials__more .kl-fold__summary {
	display: flex;
	align-items: center;
	gap: var(--kl-space-3);
	min-height: 44px;
	cursor: pointer;
}

.kl-evidence__method-summary .kl-fold__label,
.kl-trials__more .kl-fold__label {
	font-weight: var(--kl-weight-semibold);
}

.kl-evidence__extended-summary .kl-fold__count {
	margin-left: auto;
	color: var(--kl-slate);
}

.kl-evidence__rule {
	max-width: 68ch;
	margin: 0 0 var(--kl-space-3);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-evidence__state {
	margin: var(--kl-space-4) 0 0;
	font-weight: var(--kl-weight-semibold);
}

.kl-evidence__list {
	display: grid;
	gap: var(--kl-space-4);
	margin: var(--kl-space-4) 0 0;
	padding: 0;
	list-style: none;
}

.kl-evidence-card {
	padding: var(--kl-space-4) var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-evidence-card__disease {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-accent-hover);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-evidence-card__name {
	margin: 0;
	font-size: var(--kl-text-lg);
}

.kl-evidence-card__name a {
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: 44px;
}

.kl-evidence-card__meta {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-evidence-card__badge {
	display: inline-flex;
	align-items: center;
	padding: 0 var(--kl-space-2);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
	font-size: var(--kl-text-xs);
}

.kl-evidence-card__group {
	margin-top: var(--kl-space-4);
}

.kl-evidence-card__label {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-evidence-card__items {
	display: grid;
	gap: var(--kl-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-evidence-card__rank,
.kl-evidence-card__claim,
.kl-evidence-card__platform,
.kl-evidence-card__paper {
	display: grid;
	gap: var(--kl-space-1);
	font-size: var(--kl-text-base);
}

.kl-evidence-card__item a {
	padding: var(--kl-space-3) 0;
	color: var(--kl-accent-hover);
}

.kl-evidence-card__journal {
	color: var(--kl-slate);
}

.kl-evidence-card__more,
.kl-evidence-card__note,
.kl-evidence-card__secondary {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-evidence__source {
	display: block;
	min-width: 0;
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-xs);
	overflow-wrap: anywhere;
}

.kl-evidence__source a {
	display: inline-block;
	min-height: 44px;
	padding: var(--kl-space-2) 0;
	color: var(--kl-accent-hover);
}

/* The clinical-study list (§4.2). */

.kl-trials__list {
	display: grid;
	gap: var(--kl-space-4);
	margin: var(--kl-space-4) 0 0;
	padding: 0;
	list-style: none;
}

.kl-trials__item {
	padding: var(--kl-space-4) var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-trials__study {
	display: grid;
	gap: var(--kl-space-1);
	margin: 0;
}

.kl-trials__field {
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-trials__fields {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: var(--kl-space-3) 0 0;
	font-size: var(--kl-text-base);
}

.kl-trials__fields dt {
	color: var(--kl-slate);
}

.kl-trials__fields dd {
	margin: 0;
	overflow-wrap: anywhere;
}

.kl-trials__fields dd a {
	display: inline-block;
	min-height: 44px;
	padding: var(--kl-space-2) 0;
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
	color: var(--kl-accent-hover);
}

@media (max-width: 480px) {
	.kl-trials__fields {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.kl-trials__fields dt {
		margin-top: var(--kl-space-3);
	}
}

/* ----------------------------- Mobile selector + standing bar (dev-025) ---
   Three pieces, one scope (prompts/dev/dev-025-mobile-selector-master.md §四):

   1. the bottom selector - the mobile shell of the EXISTING city / specialty
      facets on /hospitals/all/ and the specialty archive. It produces the URL
      the chips already produce (see wellcarechina_render_hospital_facet_sheets()
      in inc/hospital-directory.php), and it exists only from 900px down, so the
      desktop directory form is byte-for-byte the one it was;
   2. the standing contact bar on /services/, 900px down, pure CSS;
   3. the card layout the `.kl-table--stack` marker has been waiting for
      (ledger ui-020: a condition-page table that scrolled sideways on a phone).

   Two motions only, both on the dev-024 durations and the one easing curve, and
   the existing `prefers-reduced-motion: reduce` block above collapses them. */

/* 1 - the bottom selector. The triggers are hidden until the script has run
   (`html.kl-sheet-ready`, added by assets/js/filter-sheet.js), and hidden again
   from 901px up: without the script there is no pressable control with nothing
   behind it, and on a desktop there is no extra control at all. */

.kl-sheet-triggers,
.kl-sheet-open {
	display: none;
}

@media (max-width: 900px) {
	.kl-sheet-ready .kl-sheet-triggers {
		display: flex;
		flex-wrap: wrap;
		gap: var(--kl-space-2);
		margin: 0 0 var(--kl-space-4);
	}

	.kl-sheet-ready .kl-sheet-open:not([hidden]) {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		min-height: 44px;
		padding: 0 var(--kl-space-5);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		font-family: inherit;
		font-size: var(--kl-text-md);
		font-weight: var(--kl-weight-semibold);
		cursor: pointer;
	}

	.kl-sheet-ready .kl-sheet-open:not([hidden]):hover,
	.kl-sheet-ready .kl-sheet-open:not([hidden]):focus {
		border-color: var(--kl-accent);
		background: var(--kl-accent-soft);
		color: var(--kl-accent-hover);
	}

	/* The sheet itself is the native modal <dialog>: the backdrop, the Escape
	   key, the focus trap and the focus return are the browser's, not a rebuilt
	   overlay. It only grows its own look while it is open. */

	.kl-sheet[open] {
		display: block;
		position: fixed;
		inset: auto 0 0 0;
		width: 100%;
		max-width: none;
		max-height: 80vh;
		margin: 0;
		padding: 0;
		border: 0;
		border-radius: var(--kl-radius-card) var(--kl-radius-card) 0 0;
		background: var(--kl-paper);
		box-shadow: var(--kl-shadow-2);
		animation: kl-sheet-in var(--kl-dur-base) var(--kl-ease) both;
	}

	.kl-sheet::backdrop {
		background: var(--kl-scrim);
		animation: kl-sheet-backdrop var(--kl-dur-fast) linear both;
	}

	.kl-sheet__head {
		display: flex;
		align-items: center;
		gap: var(--kl-space-2);
		padding: var(--kl-space-3) var(--kl-space-4);
		border-bottom: 1px solid var(--kl-border);
	}

	.kl-sheet__title {
		flex: 1 1 auto;
		min-width: 0;
		margin: 0;
		font-size: var(--kl-text-md);
		text-align: center;
	}

	.kl-sheet__cancel,
	.kl-sheet__confirm {
		flex: 0 0 auto;
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		font-family: inherit;
		font-size: var(--kl-text-md);
		cursor: pointer;
	}

	.kl-sheet__confirm {
		border-color: var(--kl-accent);
		background: var(--kl-accent);
		color: var(--kl-paper);
		font-weight: var(--kl-weight-semibold);
	}

	/* Nothing is chosen yet: the Confirm control says so instead of looking
	   ready and doing nothing. */
	.kl-sheet__confirm:disabled {
		border-color: var(--kl-border-strong);
		background: var(--kl-disabled-bg);
		color: var(--kl-disabled-ink);
		cursor: not-allowed;
	}

	.kl-sheet__body {
		max-height: calc(80vh - 72px);
		overflow-y: auto;
		padding: var(--kl-space-3) var(--kl-space-4) var(--kl-space-5);
	}

	.kl-sheet__search {
		width: 100%;
		min-height: 44px;
		margin: 0 0 var(--kl-space-2);
		padding: 0 var(--kl-space-3);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-input);
		background: var(--kl-paper);
		color: var(--kl-ink);
		font-family: inherit;
		font-size: var(--kl-text-md);
	}

	.kl-sheet__list {
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.kl-sheet__item {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: var(--kl-space-3);
		min-height: 44px;
		padding: var(--kl-space-2) var(--kl-space-1);
		border-bottom: 1px solid var(--kl-border);
		color: inherit;
		text-decoration: none;
	}

	.kl-sheet__item:hover,
	.kl-sheet__item:focus {
		color: var(--kl-accent-hover);
	}

	.kl-sheet__item.is-selected {
		background: var(--kl-accent-soft);
		color: var(--kl-accent-hover);
		font-weight: var(--kl-weight-semibold);
	}

	.kl-sheet__count {
		color: var(--kl-slate);
		font-variant-numeric: tabular-nums;
	}

	/* No `display` here on purpose: the script hides this line with the
	   `hidden` attribute, and an author `display` would override it. */
	.kl-sheet__empty {
		margin: var(--kl-space-3) 0 0;
		color: var(--kl-slate);
	}

	@keyframes kl-sheet-in {
		from {
			transform: translateY(8px);
			opacity: 0;
		}

		to {
			transform: translateY(0);
			opacity: 1;
		}
	}

	@keyframes kl-sheet-backdrop {
		from {
			opacity: 0;
		}

		to {
			opacity: 1;
		}
	}
}

/* 2 - the standing action bar on /services/. It is fixed to the bottom of the
   window, and the footer reserves its height, so the last lines of the page
   (and every footer link) stay reachable. The bar carries one action: the
   address the page and the footer already use. */

.kl-action-bar {
	display: none;
}

@media (max-width: 900px) {
	.kl-action-bar {
		position: fixed;
		right: 0;
		bottom: 0;
		left: 0;
		z-index: 20;
		display: flex;
		align-items: center;
		gap: var(--kl-space-3);
		min-height: var(--kl-space-8);
		padding: var(--kl-space-2) var(--kl-space-4);
		padding-bottom: calc(var(--kl-space-2) + env(safe-area-inset-bottom, 0px));
		border-top: 1px solid var(--kl-border-strong);
		background: var(--kl-paper);
		box-shadow: var(--kl-shadow-2);
		animation: kl-action-bar-in var(--kl-dur-base) var(--kl-ease) both;
	}

	.kl-action-bar__summary {
		flex: 1 1 auto;
		min-width: 0;
		margin: 0;
		overflow: hidden;
		color: var(--kl-slate);
		font-size: var(--kl-text-sm);
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.kl-action-bar__cta {
		flex: 0 0 auto;
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding: 0 var(--kl-space-5);
		border: 1px solid var(--kl-accent);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-accent);
		color: var(--kl-paper);
		font-weight: var(--kl-weight-semibold);
		text-decoration: none;
	}

	.kl-action-bar__cta:hover,
	.kl-action-bar__cta:focus {
		border-color: var(--kl-accent-hover);
		background: var(--kl-accent-hover);
		color: var(--kl-paper);
	}

	/* The reserved space: bar height (--kl-space-8) plus the page's own foot
	   padding. Scoped with :has() to the page that renders the bar, so no other
	   template pays for it. */
	body:has(.kl-action-bar) .kl-footer {
		padding-bottom: calc(var(--kl-space-8) + var(--kl-space-4) + env(safe-area-inset-bottom, 0px));
	}

	@keyframes kl-action-bar-in {
		from {
			transform: translateY(8px);
			opacity: 0;
		}

		to {
			transform: translateY(0);
			opacity: 1;
		}
	}
}

/* 3 - ui-020: the card layout for `.kl-table--stack` on a narrow screen. The
   marker (the class plus one `data-label` per cell) has been in the three
   condition-page tables since fix-008 but had no stylesheet rule, so the table
   kept its 560px floor and scrolled sideways inside its wrapper (measured at
   390x844: 587 / 629 / 560 against a 340px wrapper). Each row becomes a block
   and each cell prints its own column name, so the wrapper no longer scrolls.

   The header row is visually hidden rather than removed: the table keeps its
   headers for assistive technology, and nothing about the desktop form
   changes - every rule here lives inside the 640px query. */

@media (max-width: 640px) {
	.kl-table--stack {
		display: block;
		min-width: 0;
	}

	.kl-table--stack thead {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
		border: 0;
	}

	.kl-table--stack tbody,
	.kl-table--stack tr,
	.kl-table--stack td {
		display: block;
		width: auto;
	}

	.kl-table--stack tr {
		padding: var(--kl-space-3) 0;
		border-bottom: 1px solid var(--kl-border);
	}

	.kl-table--stack tr:last-child {
		padding-bottom: 0;
		border-bottom: 0;
	}

	.kl-table--stack td {
		padding: var(--kl-space-1) var(--kl-space-4);
		border-bottom: 0;
	}

	.kl-table--stack td::before {
		content: attr(data-label);
		display: block;
		margin-bottom: var(--kl-space-1);
		color: var(--kl-slate);
		font-size: var(--kl-text-xs);
		font-weight: var(--kl-weight-semibold);
		letter-spacing: var(--kl-tracking-caps);
		text-transform: uppercase;
	}

	/* dev-059 T1: the listings' own card labels. The hub tables no longer carry
	   a `data-label` on every cell (the key-specialty board alone had 6,522 of
	   them); the column name comes from the custom properties the region prints
	   once (`--kl-stack-*`, inc/rankings-hub.php) and the cell's own column, so
	   the text is written once and cannot drift from the table's `<th>`. The
	   visible label text is unchanged - P31 / dev-059-report.md carry the
	   before-and-after read of `getComputedStyle(td, '::before').content`. */
	#fudan-general .kl-hub__table td:nth-child(1)::before { content: var(--kl-stack-general-0, ""); }
	#fudan-general .kl-hub__table td:nth-child(2)::before { content: var(--kl-stack-general-1, ""); }

	#fudan-specialty .kl-hub__table td:nth-child(1)::before { content: var(--kl-stack-specialty-0, ""); }
	#fudan-specialty .kl-hub__table td:nth-child(2)::before { content: var(--kl-stack-specialty-1, ""); }
	#fudan-specialty .kl-hub__table td:nth-child(3)::before { content: var(--kl-stack-specialty-2, ""); }
	#fudan-specialty .kl-hub__table td:nth-child(4)::before { content: var(--kl-stack-specialty-3, ""); }

	#national-key-specialties .kl-hub__table td:nth-child(1)::before { content: var(--kl-stack-key-0, ""); }
	#national-key-specialties .kl-hub__table td:nth-child(2)::before { content: var(--kl-stack-key-1, ""); }
	#national-key-specialties .kl-hub__table td:nth-child(3)::before { content: var(--kl-stack-key-2, ""); }

	/* The "grouped by specialty" view lists the hospital first, so its first
	   column is named Hospital, not Specialty (the other two columns match).
	   It is keyed off `.kl-hub__alt` rather than a board id because dev-059 T2
	   moved that view into its own section on /key-specialties/. */
	.kl-hub__alt .kl-hub__table td:nth-child(1)::before { content: var(--kl-stack-key_specialty-0, ""); }
	.kl-hub__alt .kl-hub__table td:nth-child(2)::before { content: var(--kl-stack-key_specialty-1, ""); }
	.kl-hub__alt .kl-hub__table td:nth-child(3)::before { content: var(--kl-stack-key_specialty-2, ""); }

	#research-platforms .kl-hub__table td:nth-child(1)::before { content: var(--kl-stack-platform-0, ""); }
	#research-platforms .kl-hub__table td:nth-child(2)::before { content: var(--kl-stack-platform-1, ""); }
	#research-platforms .kl-hub__table td:nth-child(3)::before { content: var(--kl-stack-platform-2, ""); }
	#research-platforms .kl-hub__table td:nth-child(4)::before { content: var(--kl-stack-platform-3, ""); }

	/* In a card the value wraps: the desktop `nowrap` on a numeric cell exists
	   to keep a column aligned, which no longer applies. */
	.kl-table--stack td.kl-num {
		white-space: normal;
	}

	/* A link in a card is a finger target, the same as everywhere else on the
	   site (fix-007 T7). The card gives a hospital name the full cell width, so
	   the name sits on one line and the anchor's own box is only a line tall;
	   the hit box is therefore grown here. Scoped to the card layout, so the
	   desktop table keeps its inline link size. */
	.kl-table--stack td a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
}

/* ------------------------------- Condition page data display (dev-027) ---
   Three pieces, one scope (prompts/dev/dev-027-condition-data-master.md §四):

   1. `.kl-facts` - the key-figure band under the identity. Four published
      figures, each tile a link into the section that carries its source. The
      figures are read from the same records those sections read, so a tile
      cannot state a number the section below contradicts;
   2. `.kl-range` - the interval bar inside the cost table's range cell. Every
      priced row of the condition is drawn on one scale, and the bar is a
      second reading of the figures printed above it (it is `aria-hidden`);
   3. `.kl-figure` - the five-year survival card. The page's one big number,
      with the confidence interval under it and the qualifiers below.

   The chart language is the one inc/advantages.php already uses: bars in the
   single accent, labels in slate, figures in IBM Plex Mono with tabular
   numerals, a caption under the graphic. Composition rules follow the site's
   own checklist (docs/design/设计方向_v0.md §10.5): tokens only, one accent,
   three radii, border instead of shadow, hover limited to colour plus the 2px
   lift, and no new motion - the site-wide `prefers-reduced-motion` block above
   already collapses these transitions. */

.kl-facts {
	margin: var(--kl-space-6) 0;
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-facts__head {
	max-width: 68ch;
	margin-bottom: var(--kl-space-5);
}

.kl-facts__title {
	margin: 0;
	font-size: var(--kl-text-lg);
}

.kl-facts__lede {
	margin: var(--kl-space-2) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-facts__list {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--kl-space-3);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* One tile is one link, so the finger target is the whole tile (44px floor). */
.kl-fact__link {
	display: flex;
	flex-direction: column;
	gap: var(--kl-space-2);
	box-sizing: border-box;
	width: 100%;
	height: 100%;
	min-height: 44px;
	padding: var(--kl-space-4);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-input);
	background: var(--kl-paper);
	color: var(--kl-ink);
	text-decoration: none;
	transition: border-color var(--kl-dur-fast) var(--kl-ease), transform var(--kl-dur-fast) var(--kl-ease);
}

.kl-fact__link:hover,
.kl-fact__link:focus {
	border-color: var(--kl-accent-ring);
	transform: translateY(-2px);
}

.kl-fact__label {
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

/* The figure is the tile's focal point and the accent is the site's link
   colour - the two jobs meet here, and the value is the link. */
.kl-fact__value {
	color: var(--kl-accent-hover);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-3xl);
	font-variant-numeric: tabular-nums;
	font-weight: var(--kl-weight-semibold);
	line-height: var(--kl-leading-tight);
}

.kl-fact__note {
	margin-top: auto;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	line-height: var(--kl-leading-snug);
}

/* The cost cell: the published figures first, the bar as their second reading. */
.kl-cost__figure {
	display: block;
	font-size: var(--kl-text-md);
	font-weight: var(--kl-weight-semibold);
}

.kl-range {
	display: block;
	position: relative;
	width: 100%;
	height: 6px;
	margin-top: var(--kl-space-2);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-border);
	overflow: hidden;
}

/* Geometry (left / width) is written inline by the renderer, because it is
   data, not styling: it comes from the two published figures of the row. The
   floor keeps an interval whose ends are equal visible; the figures above the
   bar remain the measurement. */
.kl-range__bar {
	position: absolute;
	top: 0;
	bottom: 0;
	min-width: 6px;
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent);
}

.kl-cost__scale {
	max-width: 68ch;
}

/* The one billing basis every range shares (dev-027 T6): it used to be a
   column that repeated the same words on every row. */
.kl-cost__caliber {
	max-width: 68ch;
}

/* The survival card. */
.kl-figure__card {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-figure__head {
	display: flex;
	flex-direction: column;
	gap: var(--kl-space-1);
	margin: 0;
	padding-bottom: var(--kl-space-4);
	border-bottom: 1px solid var(--kl-border);
}

.kl-figure__label {
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-figure__value {
	color: var(--kl-accent-hover);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-4xl);
	font-variant-numeric: tabular-nums;
	font-weight: var(--kl-weight-semibold);
	line-height: var(--kl-leading-tight);
}

/* A record whose source published no percentage keeps the shared empty-state
   word, at a size that reads as a statement and not as a measurement. */
.kl-figure__value--gap {
	color: var(--kl-slate);
	font-family: var(--kl-font-sans);
	font-size: var(--kl-text-xl);
}

.kl-figure__ci {
	color: var(--kl-slate);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-sm);
}

.kl-figure__list {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: var(--kl-space-2) var(--kl-space-4);
	margin: var(--kl-space-4) 0 0;
	font-size: var(--kl-text-base);
}

.kl-figure__list dt {
	color: var(--kl-slate);
}

.kl-figure__list dd {
	margin: 0;
	overflow-wrap: anywhere;
}

@media (max-width: 900px) {
	.kl-facts__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Narrow screens get the tiles as rows rather than a shrunken grid: the label
   and the figure on one line, the qualifier underneath, so four figures fit
   above the fold without a 4-column squeeze. */
@media (max-width: 640px) {
	.kl-facts {
		padding: var(--kl-space-4);
	}

	.kl-facts__list {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--kl-space-2);
	}

	.kl-fact__link {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		gap: var(--kl-space-1) var(--kl-space-4);
		align-items: baseline;
		padding: var(--kl-space-3) var(--kl-space-4);
	}

	.kl-fact__value {
		font-size: var(--kl-text-2xl);
		justify-self: end;
	}

	.kl-fact__note {
		margin-top: 0;
		grid-column: 1 / -1;
	}

	.kl-figure__value {
		font-size: var(--kl-text-3xl);
	}

	.kl-figure__list {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.kl-figure__list dt {
		margin-top: var(--kl-space-3);
	}
}

/* --------------------------------------------------------- Lead form ---
   The /contact/ form (dev-019 T2). Native controls only, because the page has
   to work with JavaScript off: every affordance here is an element the browser
   already knows how to submit. Styling follows the checklist the rest of the
   sheet follows (docs/design/设计方向_v0.md §10.5): tokens only, no new colour,
   border instead of shadow, one accent.

   The result of a submission is a sentence, never a colour on its own: the
   three states share one box and differ by background and border weight, and
   the idle state renders nothing at all. */

.kl-lead {
	margin: 0 0 var(--kl-space-6);
}

/* The honeypot (inc/lead-form.php). Off screen for a visitor, present for a
   script that fills every field it can find. `display: none` is deliberately
   avoided - that is the one thing the scripts this catches do skip. */
.kl-lead__trap {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	margin: 0;
	overflow: hidden;
}

.kl-lead__field {
	max-width: var(--kl-measure);
	margin: 0 0 var(--kl-space-4);
}

.kl-lead__label {
	display: block;
	margin-bottom: var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-lead__required {
	margin-left: var(--kl-space-2);
	color: var(--kl-ink);
	font-size: var(--kl-text-xs);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-lead__input {
	box-sizing: border-box;
	width: 100%;
	min-height: 44px;
	padding: var(--kl-space-3);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-input);
	background: var(--kl-paper);
	color: var(--kl-ink);
	font-family: inherit;
	font-size: var(--kl-text-md);
}

.kl-lead__input:focus {
	border-color: var(--kl-accent);
	box-shadow: 0 0 0 3px var(--kl-accent-ring);
	outline: none;
}

.kl-lead__textarea {
	min-height: calc(var(--kl-space-8) * 2);
	resize: vertical;
}

/* The consent sentence is long, so the box sits beside it rather than above it:
   the reader sees the whole statement and the control it belongs to at once. */
.kl-lead__consent {
	display: flex;
	gap: var(--kl-space-3);
	align-items: flex-start;
	max-width: var(--kl-measure);
	font-size: var(--kl-text-md);
	line-height: var(--kl-leading-body);
}

.kl-lead__consent input {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	margin: var(--kl-space-1) 0 0;
	accent-color: var(--kl-accent);
}

.kl-lead__actions {
	max-width: var(--kl-measure);
	margin: var(--kl-space-5) 0 0;
}

.kl-lead__status {
	max-width: var(--kl-measure);
	margin: 0 0 var(--kl-space-5);
	padding: 0;
	border-left: 4px solid transparent;
}

/* No submission yet: the box exists for assistive technology but prints
   nothing, so the form starts with no status line at all. */
.kl-lead__status--idle {
	display: none;
}

.kl-lead__status--ok,
.kl-lead__status--note,
.kl-lead__status--error {
	padding: var(--kl-space-3) var(--kl-space-4);
	border-radius: var(--kl-radius-input);
	background: var(--kl-paper-alt);
	border-left-color: var(--kl-ink);
}

.kl-lead__status--ok {
	background: var(--kl-accent-soft);
	border-left-color: var(--kl-accent);
}

.kl-lead__status--note {
	background: var(--kl-note-bg);
}

.kl-lead__status--error {
	font-weight: var(--kl-weight-semibold);
}

/* The voluntary-records notice, shown after a submission was accepted. */
.kl-lead__records {
	max-width: var(--kl-measure);
	margin: var(--kl-space-4) 0 0;
	padding: var(--kl-space-4);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	font-size: var(--kl-text-md);
}

/* The form entry on the disease, hospital and services pages. A link, sized as
   a finger target on narrow screens like every other in-page link. */
.kl-lead-entry {
	max-width: var(--kl-measure);
	margin: var(--kl-space-3) 0 0;
}

@media (max-width: 640px) {
	.kl-lead-entry a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
}

/* -------------------------------------------- 4 - the hospital page (dev-031) ---
   The re-ordered hospital detail page (docs/design/医院详情页重设计_v1_20260929.md
   §3). Everything here reuses the tokens and the tile language the condition
   page's key-figure band already established - one accent, 8pt spacing, borders
   instead of shadows, tabular figures - so the two detail pages read as one
   site. No colour, no font and no icon is introduced. */

/* The at-a-glance tile states a figure rather than opening a section, so it
   keeps the tile's look and drops the link's affordances. */
.kl-fact__link--static {
	cursor: default;
}

.kl-fact__link--static:hover,
.kl-fact__link--static:focus {
	border-color: var(--kl-border);
	transform: none;
}

/* A label that rests on something (the hospital's own published name) carries
   the ground it rests on, quieter than the label itself. */
.kl-entry__meta-note {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* One card per published listing, each with its own heading and its own table. */
.kl-rankings__block + .kl-rankings__block {
	margin-top: var(--kl-space-6);
}

.kl-rankings__title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-md);
}

/* The hospital's key-facts panel is a vertical list. The condition page's
   key-figure band shares the class name and lays its tiles out on a grid, and
   that rule reaches the panel too - measured at 1280px: the panel's `dl` came
   out as four 58.5px columns, so "Shanghai 上海市" was cut into three lines.
   The panel restates the layout it was built with; the band is untouched. */
.kl-single--hospital .kl-entry__aside .kl-facts__list {
	display: block;
}

.kl-single--hospital .kl-entry__aside .kl-facts__title {
	margin: 0 0 var(--kl-space-3);
}

/* -------------------------- Hospitals hub + rankings (dev-046) ---
   `dev-032`'s `/rankings/` page is retired: its four published lists are now the
   `Rankings & accreditation` region of the `/hospitals/` hub, and a hospital
   page gained a city banner, an action row and a same-city card row. The old
   page shell (`.kl-rankings-hub`, `.kl-hub__section`, `.kl-hub__subtitle`) is
   gone; the pieces the region still uses are kept below, and the boards, the
   distribution bars and the folded rows are new. Every rule reuses the existing
   tokens and the `.kl-table--stack` language, so a wide row turns into a card at
   390 instead of scrolling sideways. */

.kl-hub__hero {
	padding: var(--kl-space-6) 0 var(--kl-space-5);
}

.kl-hub__hero-lede {
	max-width: var(--kl-measure);
	margin: 0 0 var(--kl-space-5);
	color: var(--kl-slate);
	font-size: var(--kl-text-lg);
}

.kl-hub__stats {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2) var(--kl-space-3);
	margin: var(--kl-space-5) 0 0;
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-hub__toc {
	margin: var(--kl-space-5) 0 var(--kl-space-6);
	padding-top: var(--kl-space-4);
	border-top: 1px solid var(--kl-border);
}

.kl-hub__toc-title {
	margin: 0 0 var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-hub__caliber {
	margin: 0 0 var(--kl-space-4);
}

.kl-hub__count {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-regular);
}

.kl-hub__browse {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-3) var(--kl-space-5);
	margin: var(--kl-space-5) 0 0;
}

.kl-hospitals__rankings {
	margin-top: var(--kl-space-8);
	padding-top: var(--kl-space-6);
	border-top: 1px solid var(--kl-border);
}

.kl-hospitals__rankings-title {
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-2xl);
}

.kl-hub__boundary {
	margin-bottom: var(--kl-space-5);
}

.kl-hub__kpi {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: var(--kl-space-4);
	margin: 0 0 var(--kl-space-6);
	padding: 0;
	list-style: none;
}

.kl-hub__kpi-item {
	display: flex;
	flex-direction: column;
	gap: var(--kl-space-1);
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-hub__kpi-value {
	font-size: var(--kl-text-2xl);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: -0.01em;
}

.kl-hub__kpi-label {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-hub__board {
	margin-top: var(--kl-space-7);
	padding: var(--kl-space-6) var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-hub__board-title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-xl);
}

.kl-hub__board-lede {
	max-width: var(--kl-measure);
	margin: 0 0 var(--kl-space-4);
	color: var(--kl-slate);
}

.kl-hub__bars {
	display: grid;
	gap: var(--kl-space-1);
	margin: 0 0 var(--kl-space-6);
	padding: 0;
	list-style: none;
}

.kl-hub__bar {
	display: grid;
	grid-template-columns: minmax(110px, 220px) minmax(0, 1fr) 56px;
	align-items: center;
	gap: var(--kl-space-3);
	font-size: var(--kl-text-sm);
}

.kl-hub__bar-label {
	overflow: hidden;
	color: var(--kl-slate);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.kl-hub__bar-track {
	display: block;
	height: 8px;
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper);
}

.kl-hub__bar-fill {
	display: block;
	height: 100%;
	border-radius: var(--kl-radius-pill);
	background: var(--kl-accent);
}

.kl-hub__bar-value {
	text-align: right;
}

.kl-hub__group + .kl-hub__group {
	margin-top: var(--kl-space-6);
	padding-top: var(--kl-space-5);
	border-top: 1px solid var(--kl-border);
}

.kl-hub__group-title {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--kl-space-2) var(--kl-space-3);
	margin: 0 0 var(--kl-space-3);
}

/* A grouped listing's heading is a link to the record it names, so it is a
   control rather than an inline link and holds the 44px floor. */
.kl-hub__group-title a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

.kl-hub__source {
	white-space: nowrap;
}

/* The two controls in the region that are not inline links inside a table cell
   still hold the 44px touch floor the rest of the site keeps (ui-009): the
   source link of a board's caliber list, and every `Show all N` fold. The fold
   rule mirrors the one the condition page's study fold already carries
   (`.kl-trials__more .kl-fold__summary`). */
.kl-hub__caliber a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

.kl-hospitals__rankings .kl-fold__summary {
	display: flex;
	align-items: center;
	gap: var(--kl-space-3);
	min-height: 44px;
	cursor: pointer;
}

/* dev-046 裁定 01 (step 2): on a phone the published lists stack into cards
   (`.kl-table--stack`, dev-025's layout), and every link inside a stacked cell
   holds the 44px floor - the same rule the condition-page tables carry
   (dev-025-01). The desktop keeps its dense rows and exempts these links in the
   touch-target assertion instead. */
@media (max-width: 640px) {
	.kl-hub__rows td a,
	.kl-hub__rows td .kl-hub__source {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
}

.kl-hub__more {
	margin-top: var(--kl-space-3);
}

/* dev-048 T1: the board's own group fold and its distribution fold. Both sit
   under the content that stays visible and reuse the region's `.kl-fold`
   summary (which already carries the 44px touch floor, line 4603). */
.kl-hub__board-more {
	margin-top: var(--kl-space-6);
}

.kl-hub__bars-more {
	margin-top: var(--kl-space-3);
}

.kl-hub__alt {
	margin-top: var(--kl-space-6);
}

.kl-hub__how {
	margin-top: var(--kl-space-8);
	padding-top: var(--kl-space-6);
	border-top: 1px solid var(--kl-border);
}

.kl-hub__how p {
	max-width: var(--kl-measure);
}

/* The hospital page's three new blocks (dev-046). */

.kl-hosp-banner {
	position: relative;
	margin: 0 0 var(--kl-space-5);
	overflow: hidden;
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-hosp-banner__img {
	display: block;
	width: 100%;
	height: 150px;
	object-fit: cover;
}

.kl-hosp-banner__label {
	position: absolute;
	left: var(--kl-space-4);
	bottom: var(--kl-space-4);
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--kl-space-1) var(--kl-space-3);
	min-height: 44px;
	padding: var(--kl-space-2) var(--kl-space-4);
	border-radius: var(--kl-radius-pill);
	background: rgba(0, 0, 0, 0.62);
	color: #fff;
	text-decoration: none;
}

.kl-hosp-banner__city {
	font-weight: var(--kl-weight-semibold);
}

.kl-hosp-banner__count {
	font-size: var(--kl-text-sm);
}

.kl-hosp-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-3) var(--kl-space-4);
	margin: 0 0 var(--kl-space-5);
}

.kl-hosp-actions .kl-btn {
	min-height: 44px;
}

.kl-hosp-actions__city {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--kl-accent);
	font-weight: var(--kl-weight-semibold);
}

.kl-hosp-nearby__list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: var(--kl-space-4);
	margin: 0 0 var(--kl-space-4);
	padding: 0;
	list-style: none;
}

.kl-hosp-nearby__link {
	display: flex;
	flex-direction: column;
	min-height: 44px;
	overflow: hidden;
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	color: inherit;
	text-decoration: none;
}

.kl-hosp-nearby__img {
	display: block;
	width: 100%;
	height: 96px;
	object-fit: cover;
}

.kl-hosp-nearby__body {
	display: flex;
	flex-direction: column;
	gap: var(--kl-space-1);
	padding: var(--kl-space-4);
}

.kl-hosp-nearby__name {
	font-weight: var(--kl-weight-semibold);
}

.kl-hosp-nearby__grade {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-entry__meta--chips {
	gap: var(--kl-space-2);
}

/* One chip is a long label plus the ground it rests on ("University-affiliated
   (from the hospital's own published name)"), and the shared `.kl-chip`
   `white-space: nowrap` kept it from shrinking: at 390px the chip measured
   383px inside a 342px row and pushed the whole document 17px sideways
   (dev-046 B7). The chip now caps at its column and wraps inside it; the 44px
   touch height (`ui-009`) is unchanged. */
.kl-entry__meta-item.kl-chip {
	max-width: 100%;
	white-space: normal;
}

/* The ground gets its own line on a narrow screen, so the label keeps the
   chip's first line to itself. */
@media (max-width: 640px) {
	.kl-entry__meta-note {
		display: block;
	}
}

/* The rail sticks to the top while the record scrolls past it (dev-046): the
   left column used to sit beside a much taller rail, which left a block of
   white space under a thin record's two lines. */
.kl-single--hospital .kl-entry__aside {
	position: sticky;
	top: var(--kl-space-6);
	align-self: start;
	max-height: calc(100vh - var(--kl-space-8));
	overflow-y: auto;
}

/* ------------------------------------------- Guides (dev-033) --- */
/* The /guides/ archive and its detail pages. The homepage teaser these rules
   were first written for (`.kl-guides__*`, between the trust bar and the
   category cards) was withdrawn by the user on 2026-10-06 - the reading-key
   band's closing button is the homepage's one entrance to the library now -
   and its rules left with it. The figure rules mirror the dev-018
   content-image block so the surfaces crop the same way; no new design token
   is introduced. */

.kl-guide-card__media {
	margin: 0 0 var(--kl-space-4);
	overflow: hidden;
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	aspect-ratio: 16 / 9;
}

.kl-guide-entry__media {
	margin: 0 0 var(--kl-space-5);
	overflow: hidden;
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	aspect-ratio: 16 / 9;
}

.kl-guide-card__media img,
.kl-guide-entry__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.kl-guide-entry__boundary {
	margin-top: var(--kl-space-6);
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-guide-entry__note {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-archive__foot {
	margin-top: var(--kl-space-6);
}

/* The "Outcomes and care quality" card (dev-039). It carries the same card
   language as the survival figure so a reader meets one shape; only new
   selectors are added. */
.kl-outcomes__card {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper);
}

.kl-outcomes__value {
	margin: 0;
	padding-bottom: var(--kl-space-4);
	border-bottom: 1px solid var(--kl-border);
	color: var(--kl-accent-hover);
	font-family: var(--kl-font-mono);
	font-size: var(--kl-text-2xl);
	font-variant-numeric: tabular-nums;
	font-weight: var(--kl-weight-semibold);
	line-height: var(--kl-leading-tight);
	overflow-wrap: anywhere;
}

.kl-outcomes__target {
	margin: var(--kl-space-4) 0 0;
	color: var(--kl-ink);
	font-size: var(--kl-text-base);
}

.kl-outcomes__sources {
	margin: var(--kl-space-4) 0 0;
	padding: 0;
	list-style: none;
	font-size: var(--kl-text-sm);
}

.kl-outcomes__source + .kl-outcomes__source {
	margin-top: var(--kl-space-1);
}

.kl-outcomes__note {
	margin: var(--kl-space-3) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* --------------------------------------------- Grouped header (dev-045) ---
   The English primary menu is five top-level controls: `Home` plus four groups
   (Find treatment / Plan your trip / Why China / About). A group is a native
   `<details>`; its `<summary>` is the toggle and the panel is the next sibling.
   On desktop the panel is revealed by `:hover` / `:focus-within`, so the whole
   navigation works with JavaScript switched off. At <= 900px the same
   `<details>` is the mobile accordion inside `.kl-nav__details`.

   Header budget (master §三 T5): <= 88px on every desktop step. Three rules buy
   it - the brand tagline leaves the row below 1280px, the search collapses to
   the 44x44 toggle dev-024 gave phones across 901-1279px, and the row keeps its
   4px gap (already set at > 900px for the nine-item menu this batch replaces).
   Everything below is additive: no existing selector is changed or removed. */

.kl-nav__item {
	display: flex;
	align-items: center;
}

.kl-nav__group-toggle {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--kl-ink);
	cursor: pointer;
	list-style: none;
}

/* The native marker is replaced by `.kl-nav__caret` (same caret as the
   language selector). */
.kl-nav__group-toggle::-webkit-details-marker {
	display: none;
}

.kl-nav__group-toggle:hover,
.kl-nav__group:focus-within > .kl-nav__group-toggle {
	color: var(--kl-accent-hover);
}

.kl-nav__caret {
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	margin-left: var(--kl-space-2);
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--kl-dur-fast) var(--kl-ease);
}

.kl-nav__group:hover .kl-nav__caret,
.kl-nav__group:focus-within .kl-nav__caret {
	transform: rotate(225deg);
}

/* `.kl-nav__list a` (the touch-target rule) also matches these links and sets
   `display: inline-flex; align-items: center`, which turned every panel title
   and description into a centred, shrink-to-fit box. The two-part selector
   outranks it so the column stretches instead. */
.kl-nav__list .kl-nav__panel-link {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	justify-content: center;
	min-height: 44px;
	padding: var(--kl-space-2) var(--kl-space-3);
	border-radius: var(--kl-radius-input);
	color: var(--kl-ink);
	text-decoration: none;
}

.kl-nav__panel-link:hover,
.kl-nav__panel-link:focus {
	background: var(--kl-accent-soft);
	color: var(--kl-accent-hover);
}

.kl-nav__panel-title {
	font-weight: var(--kl-weight-semibold);
}

.kl-nav__panel-desc {
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	line-height: var(--kl-leading-snug);
}

/* The header action that replaces the old `Contact` menu entry. Its address
   comes from wellcarechina_lead_form_page_url(), the same helper the footer and
   the standing bar use. */
.kl-header__cta {
	min-height: 44px;
	padding: var(--kl-space-2) var(--kl-space-4);
}

/* Desktop: the row is a flex line - the menu takes what is left after the CTA -
   and a group panel is a flyout anchored to the row itself (not to the group),
   so it can never run past the viewport on a narrow desktop. */
@media (min-width: 901px) {
	.kl-nav {
		position: relative;
		display: flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-width: 0;
	}

	.kl-nav__list {
		flex: 1 1 auto;
		min-width: 0;
	}

	.kl-header__cta {
		flex: 0 0 auto;
	}

	/* Chrome 131+ wraps the non-summary content of a `<details>` in a
	   `::details-content` box and gives it `content-visibility: hidden`, which
	   also creates a containing block (`contain: layout`). A closed group must
	   not clip its flyout to the group's own 60-120px box, so the content stays
	   visible and `.kl-nav__panel`'s own `display` decides what shows. */
	.kl-nav__group::details-content {
		content-visibility: visible;
	}

	.kl-nav__group {
		position: static;
	}

	.kl-nav__panel {
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 25;
		display: none;
		grid-template-columns: minmax(0, 1fr);
		gap: var(--kl-space-1);
		padding: var(--kl-space-2);
		border: 1px solid var(--kl-border-strong);
		border-top: 0;
		border-radius: 0 0 var(--kl-radius-card) var(--kl-radius-card);
		background: var(--kl-paper);
		box-shadow: var(--kl-shadow-2);
	}

	.kl-nav__group:hover > .kl-nav__panel,
	.kl-nav__group:focus-within > .kl-nav__panel {
		display: grid;
	}
}

/* Two columns once the row is wide enough for readable entries. */
@media (min-width: 1024px) {
	.kl-nav__panel {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* 901-1279px used to be the band where the row could not hold the brand, five
   menu controls, the header action, the language switcher and the search box,
   so it swapped the search for the 44px toggle. dev-053 withdraws that control,
   and the band now only needs the smaller menu type (the e006 mark economy is
   gone with the mark - see the v9 wordmark rules at the end of this file). */
@media (min-width: 901px) and (max-width: 1279px) {
	.kl-header__inner {
		position: relative;
	}

	.kl-nav__list {
		font-size: var(--kl-text-base);
	}

	.kl-header__cta {
		padding-left: var(--kl-space-2);
		padding-right: var(--kl-space-2);
	}
}

/* ------------------------------------------------- Header row rhythm (dev-053) ---
 *
 * The header search control is withdrawn (user ruling 2026-10-02): the box was
 * the last thing that kept the row at its dev-034 width, and the two utility
 * pill and the menu label were all sharing a 4px gutter. Without it the row has
 * the whole 1200px axis, so the arrangement is re-cut from measured slack:
 *
 *   >=1024px    content 1152/976px - brand 172/124 - language 115 - gutters 48
 *               leaves the menu 817/689px. The five labels need 425/402px, so
 *               the row can afford a 32px label gutter and a 32px gutter before
 *               the Contact action, and still leave >130px of air.
 *   901-1023px  content 853px leaves the menu 582px; a 16px label gutter and a
 *               16px action gutter fit with 24px to spare.
 *
 * The spacing lives on the labels (not in the list's row gap), so each item is
 * also a real hover/focus pill. The group toggle is a `<summary>` inside
 * `<details class="kl-nav__group">`, not a direct child of the `<li>`, which is
 * why the group selectors below walk the full path.
 */
@media (min-width: 901px) {
	.kl-header__inner {
		gap: var(--kl-space-5);
	}

	.kl-nav {
		padding: 0;
		gap: var(--kl-space-6);
	}

	.kl-nav__list {
		gap: 0;
	}

	.kl-nav__list > .kl-nav__item > a,
	.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 var(--kl-space-4);
		border-radius: var(--kl-radius-input);
	}

	.kl-nav__list > .kl-nav__item > a:hover,
	.kl-nav__list > .kl-nav__item > a:focus-visible,
	.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle:hover,
	.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle:focus-visible {
		background: var(--kl-accent-soft);
		color: var(--kl-accent-hover);
	}
}

@media (min-width: 901px) and (max-width: 1023px) {
	.kl-header__inner {
		gap: var(--kl-space-4);
	}

	.kl-nav {
		gap: var(--kl-space-4);
	}

	.kl-nav__list > .kl-nav__item > a,
	.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 var(--kl-space-2);
	}
}

/* The brand tagline is 343px wide. On the fixed 1200px content axis there is no
   width at which it fits beside the brand, five menu controls, the header
   action, the language switcher and the search box - and a tagline that wrapped
   would push the row past the 88px budget this batch holds. It is already
   dropped at <= 900px, so it leaves the header everywhere (measured: with it,
   /hospitals/ still wrapped to two rows at 1440px). */
.kl-branding__tagline {
	display: none;
}

/* <= 900px: the row is the mobile accordion, so the panel goes back to being a
   plain block and the native `<details>` decides what shows - no hover, no
   position:absolute, no shadow. */
@media (max-width: 900px) {
	.kl-nav__item {
		display: block;
	}

	.kl-nav__group-toggle {
		width: 100%;
	}

	.kl-nav__panel {
		position: static;
		padding: 0 0 0 var(--kl-space-4);
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
	}

	.kl-header__cta {
		margin-top: var(--kl-space-3);
	}
}

/* ------------------------------------------ Contact page layout (dev-047) ---
   ui-028: `/contact/` was a single ~640px column on the far left with ~700px
   empty to its right, because `.kl-prose { max-width: none }` cancelled
   `.kl-container`'s 1200px cap while every field stayed at `--kl-measure`. The
   page now sits on the shared main axis and, from 1024px up, is a two-column
   grid: the form on the left, the notice-at-collection and the privacy entry on
   the right. Only new rules are added here - the `.kl-lead*` block elsewhere is
   untouched, and the field measure is lifted inside this page alone. */

.kl-contact-page {
	padding-bottom: var(--kl-space-8);
}

.kl-contact-layout {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	align-items: start;
	gap: var(--kl-space-7);
}

.kl-contact-layout__main {
	min-width: 0;
}

.kl-lead-section__title {
	margin: 0 0 var(--kl-space-5);
	font-size: var(--kl-text-2xl);
}

/* The fields fill their column instead of the 72ch reading measure they carry
   elsewhere: on a two-column desktop the measure would leave the column half
   empty again. Scoped to this page so no other form is affected. */
.kl-contact-layout__main .kl-lead__field,
.kl-contact-layout__main .kl-lead__actions,
.kl-contact-layout__main .kl-lead__status,
.kl-contact-layout__main .kl-lead__records,
.kl-contact-layout__main .kl-lead__consent {
	max-width: none;
}

/* dev-047 T1.3: the three field groups. The heading is a real h3 (the form's
   own h2 sits above it), so the outline reads page -> form -> group. */
.kl-lead__group {
	margin: 0 0 var(--kl-space-6);
}

.kl-lead__group-title {
	margin: 0 0 var(--kl-space-4);
	padding-bottom: var(--kl-space-2);
	border-bottom: 1px solid var(--kl-border);
	color: var(--kl-ink);
	font-size: var(--kl-text-lg);
}

/* The notice-at-collection card: the page's own compliance copy, on the site's
   card language (border, radius, alt paper - no shadow, no new colour). */
.kl-contact-side {
	padding: var(--kl-space-5);
	border: 1px solid var(--kl-border);
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
}

.kl-contact-side__title {
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-xl);
}

.kl-contact-side__list {
	margin: 0;
	padding-left: var(--kl-space-5);
}

.kl-contact-side__list li + li {
	margin-top: var(--kl-space-2);
}

.kl-contact-side__privacy {
	margin: var(--kl-space-5) 0 0;
	padding-top: var(--kl-space-4);
	border-top: 1px solid var(--kl-border);
}

.kl-contact-side__privacy a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

/* Under the two-column breakpoint the page is one column, like the rest of the
   site (skeleton v1 §6). */
@media (max-width: 1023px) {
	.kl-contact-layout {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--kl-space-6);
	}
}

/* ---------------------------------------------- dev-048 card walls (T3) ---
   The condition / guide / news card walls give every card in a row the same
   description start. The block above the description carries a fixed floor, so
   a one-line and a two-line title (or a one-row and a two-row chip cloud) end on
   the same line; the description then grows to fill the rest of the card, which
   keeps the foot at the bottom exactly as `margin-top:auto` did (skeleton v1
   §4) while its own first line lands on the shared axis. The chip cloud is
   capped at two rows (the `+N` counter already sits outside the clipped row,
   per known-issues #9) - the cap is inert while the records stay under it. */

.kl-card-list > .kl-card .kl-card__title a {
	min-height: 72px;
}

.kl-archive--news .kl-card__meta {
	min-height: 70px;
}

.kl-card-list > .kl-card .kl-chip-row {
	min-height: 96px;
}

.kl-card-list > .kl-card .kl-chip-row > .kl-chips {
	max-height: 96px;
	overflow: hidden;
}

.kl-card-list > .kl-card .kl-card__excerpt {
	flex: 1 1 auto;
	margin-top: 0;
}


/* -------------------------------- hospital chips, script-only (dev-078) ---
   Everything below exists only while assets/js/hospital-chips.js is running:
   `kl-has-js` is set on <html> by that file, and the clamp and the reveal
   control are both created by it. With the script absent or broken the rules
   never match, so the card keeps its complete, readable list - which is the
   state the markup alone is meant to render. The clamp is deliberately
   instant (no `transition`): it is applied and removed in one frame, and an
   animated clip would show a half-faded row on the way in or out. */
.kl-has-js .kl-chip-cloud[data-kl-specialty-clamped] [data-kl-specialty-list] {
	max-height: var(--kl-cloud-h, 0px);
	overflow: hidden;
	-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 34px), rgba(0, 0, 0, 0.16) 100%);
	mask-image: linear-gradient(to bottom, #000 calc(100% - 34px), rgba(0, 0, 0, 0.16) 100%);
}

.kl-has-js .kl-chip-more {
	margin: var(--kl-space-3) 0 var(--kl-space-3);
	padding: 0;
	font-size: var(--kl-text-sm);
}

.kl-has-js .kl-chip-more[hidden] {
	display: none;
}

.kl-has-js .kl-chip-more__btn {
	display: inline-flex;
	align-items: center;
	gap: var(--kl-space-1);
	/* The card's one new control takes the site's touch floor (44px, the same
	   one check-ui holds every header control to): the directory is a browsing
	   surface a reader uses on a phone as much as on a desktop. */
	min-height: 44px;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	color: var(--kl-accent-hover);
	font: inherit;
	font-weight: var(--kl-weight-semibold);
	cursor: pointer;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

.kl-has-js .kl-chip-more__btn:hover,
.kl-has-js .kl-chip-more__btn:focus {
	color: var(--kl-ink);
}

.kl-has-js .kl-chip-more__btn:focus-visible {
	border-radius: 3px;
	outline: 2px solid var(--kl-accent-ring);
	outline-offset: 2px;
}

.kl-has-js .kl-chip-more__icon {
	width: 14px;
	height: 14px;
	flex: 0 0 auto;
	transition: transform var(--kl-dur-fast) var(--kl-ease);
}

.kl-has-js .kl-chip-more__btn[aria-expanded="true"] .kl-chip-more__icon {
	transform: rotate(180deg);
}


/*
 * Brand v9 (2026-10-08, user ruling): the 入 mark is retired; the header logo
 * is the one-line English wordmark alone - navy letters, teal dot on the "i"
 * of China. The artwork is an <img> inside the brand link, so its alt text is
 * the link's accessible name (check-legal E6) and the 44px hit area from the
 * rule above still applies. 919x100 = the SVG's aspect ratio.
 */
.kl-branding__logo {
	display: block;
	width: auto;
	height: 20px;
}

/* The wide band keeps the brand group 1.8-3x the nav spacing away from the
   menu (the e006 rhythm, user note 2026-10-07); the narrower bands drop the
   logo a size so the row still holds brand + menu + language. */
@media (min-width: 1280px) {
	.kl-branding {
		margin-right: 80px;
	}
}

/* 1024-1279: the one-line wordmark needs ~64px more than the e006 caption did,
   so this band buys it back from the nav rhythm - item padding 16 -> 12 (24px
   label gutters, inside the dev-053 floor of 16px), list-to-CTA gap 32 -> 24,
   header gaps 24 -> 16. Nothing else in the row changes. */
@media (min-width: 1024px) and (max-width: 1279px) {
	.kl-header__inner {
		gap: var(--kl-space-4);
	}

	.kl-nav {
		gap: var(--kl-space-5);
	}

	.kl-nav__list > .kl-nav__item > a,
	.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 var(--kl-space-3);
	}
}

/* B mock: the nav shares the mark's navy, and hover / current draw the teal
   rule instead of the old soft pill. */
.kl-nav__list a {
	color: var(--kl-navy);
}

.kl-nav__list > .kl-nav__item > a:hover,
.kl-nav__list > .kl-nav__item > a:focus-visible,
.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle:hover,
.kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle:focus-visible {
	background: transparent;
	color: var(--kl-navy);
	text-decoration: underline;
	text-decoration-color: var(--kl-accent);
	text-decoration-thickness: 2px;
	text-underline-offset: 6px;
}

.kl-nav__list .current-menu-item > a,
.kl-nav__list .current_page_item > a,
.kl-nav__list .current-menu-ancestor > a {
	text-decoration: underline;
	text-decoration-color: var(--kl-accent);
	text-decoration-thickness: 2px;
	text-underline-offset: 6px;
}

/* Until the wide desktop row, the brand has to keep the same footprint as the
   text it replaces (124px wide at the smaller type sizes), or the header wraps
   to a second row (check-ui dev-045/dev-053, check-pages P7). */
/* 901-1023 is the tightest desktop band (15px menu, 8px item padding): the
   wordmark returns to the footprint of the text brand it replaces (124px). */
@media (max-width: 1023px) {
	.kl-branding__logo {
		height: 14px;
	}
}

/* <= 900 is the mobile row: the brand shares it with the menu toggle only. */
@media (max-width: 900px) {
	.kl-branding__logo {
		height: 19px;
	}
}

/* ---------------------------------------- Hospital tier badge (dev-102) ---
   The 2026-10-08 user ruling: the administrative grade read too weakly on the
   hospital listings and the condition-page hospital block, because a reader
   outside China takes "Tier 1" for the strongest band while China's 1-3 scale
   reads the other way round and tier 3 is its top. The badge states the fact in
   a shape as well as in words. It sits on the hospital card, the condition-page
   hospital rows, the hospital hero, its administrative-grade row, the key-facts
   panel and the hospital-details list; its band and its wording are computed by
   wellcarechina_hospital_tier_badge(), never typed here. It is text and shape,
   not a control: no link, no focus, no title.

   The 2026-10-10 user ruling ("looks like a wifi mark, make it designed") went
   through four shapes before landing: three ascending bars, three adjacent
   steps, a numeral plate, a teal medal - the first three rejected, the fourth
   rejected as too quiet - and settled on the gold medal the user picked from a
   six-option review sheet (assets/icons/tier-up.svg): a ribbon bail over a solid
   gold disc with a coin rim, no numeral, nothing drawn about scale. The label
   carries two registers - the band in the text's own ink, the qualifier one step
   quieter - so the eye reads the band first and the "highest tier" note second.
   Colours come from tokens only, and the medal is the one place that spends
   --kl-gold: a medal is metal, and this is the only mark on the site that names
   a designation. */

.kl-tier {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	max-width: 100%;
	padding: 3px var(--kl-space-3) 3px var(--kl-space-2);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper-alt);
	color: var(--kl-ink);
	font-size: var(--kl-text-sm);
	line-height: 1.25;
	letter-spacing: .005em;
}

.kl-tier__icon {
	flex: 0 0 auto;
	color: var(--kl-gold);
}

/* The two registers of the one fixed label: the band leads in the text's own
   ink, the qualifier follows as a note (slate, normal weight) so the band is
   what the eye lands on first. The band is 600 - the weight the surrounding
   card titles already use for emphasis - never a colour of its own. */
.kl-tier__band {
	font-weight: 600;
}

.kl-tier__qual {
	color: var(--kl-slate);
	/* One all-caps word reads as a tag rather than a sentence; the extra tracking
	   is what keeps caps from looking cramped at 13px (2026-10-10 ruling). */
	letter-spacing: .04em;
}

/* The label may wrap inside its own pill rather than push its container wider
   (the flex-wrap + min-width:0 the ruling asks for, so a 390px card cannot be
   broken by a long band name). */
.kl-tier__text {
	min-width: 0;
	overflow-wrap: anywhere;
}

/* The badge keeps a line of its own under whatever it annotates. */
.kl-badge-row {
	margin: var(--kl-space-2) 0 0;
}

.kl-card > .kl-badge-row {
	margin-bottom: var(--kl-space-3);
}

/* In the administrative-grade row the badge sits inside a `.kl-num` cell (mono
   face, nowrap); the badge is neither, so both are reset for its subtree. */
.kl-tier-cell {
	display: block;
	margin-top: var(--kl-space-2);
	font-family: var(--kl-font-sans);
	font-variant-numeric: normal;
	white-space: normal;
}

/* The tag is short on purpose (2026-10-10: "控制在一行，短小精悍一点"), so the
   narrow `Rank / tier` column is asked to make room for it instead of breaking
   it: the table's auto layout takes the width from the wide `Caliber` column,
   and the tag stays one line. It may still wrap if a future wording is longer -
   the pill's own wrap rules stay in force. */
.kl-tier-cell .kl-tier {
	white-space: nowrap;
}

/* dev-108: the same badge now sits under the value in the key-facts panel and
   in the hospital-details list, kept on its own line by the `<br />` the two
   blocks already use between value and source wording. The badge is an atomic
   inline-level box, so the small top margin applies and the pill does not hug
   the line above it. */
.kl-facts__value .kl-tier,
.kl-fields__list .kl-tier {
	margin-top: var(--kl-space-1);
}

/* --------------------------------------- Video stories index (dev-101) ---
   The third-party video index at `/video-stories/` (user ruling 2026-10-08).
   Every row is one card in the shared `.kl-card-list`, so the page adds no new
   layout language - only the row's own parts and the policy box. It is a
   link-out page: the one control per card is the outbound button, nothing is
   embedded, and no word here comments on an outcome. The band classes are
   `.kl-videos__*`; nothing already in this file is changed. */

.kl-videos-page {
	padding-top: var(--kl-space-7);
	padding-bottom: var(--kl-space-8);
}

/* The three rules sit in the shared panel shell; the box is a note, not a
   section, so it carries no heading of its own. */
.kl-videos__policy {
	margin: 0 0 var(--kl-space-6);
}

.kl-videos__rules {
	margin: 0;
	padding-left: var(--kl-space-5);
}

.kl-videos__rules li + li {
	margin-top: var(--kl-space-2);
}

/* dev-101d (user 2026-10-08): the library is categorised, so the top of the
   page carries a plain anchor index (no script, no state) and each category
   is one section with its own heading and its own card grid. */
.kl-videos__index {
	margin: 0 0 var(--kl-space-6);
}

.kl-videos__index-list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--kl-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.kl-videos__index-link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 var(--kl-space-4);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper);
	color: var(--kl-navy);
	font-size: var(--kl-text-sm);
	text-decoration: none;
}

.kl-videos__index-link:hover,
.kl-videos__index-link:focus-visible {
	border-color: var(--kl-accent);
	color: var(--kl-accent-hover);
}

.kl-videos__group + .kl-videos__group {
	margin-top: var(--kl-space-7);
}

.kl-videos__group-title {
	/* The header is not sticky today; the margin still keeps an anchor jump
	   clear of it if that ever changes. */
	scroll-margin-top: var(--kl-space-6);
	margin: 0 0 var(--kl-space-4);
	font-size: var(--kl-text-xl);
	text-wrap: balance;
}

.kl-videos__group-count {
	margin-left: var(--kl-space-2);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-regular);
	vertical-align: middle;
}

.kl-videos__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kl-space-2) var(--kl-space-3);
	margin: 0 0 var(--kl-space-3);
}

/* The platform badge is a label, not a control: it carries no 44px floor and
   no hover state, unlike `.kl-chip`. */
.kl-videos__platform {
	display: inline-flex;
	align-items: center;
	padding: 2px var(--kl-space-2);
	border: 1px solid var(--kl-border-strong);
	border-radius: var(--kl-radius-pill);
	background: var(--kl-paper-alt);
	color: var(--kl-slate);
	font-size: var(--kl-text-xs);
	letter-spacing: var(--kl-tracking-caps);
	text-transform: uppercase;
}

.kl-videos__channel {
	min-width: 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-semibold);
	overflow-wrap: anywhere;
}

/* The original title is the video's own wording, kept as published. */
.kl-videos__title {
	margin: 0 0 var(--kl-space-3);
	font-size: var(--kl-text-lg);
	overflow-wrap: anywhere;
}

.kl-videos__facts {
	margin: 0;
}

/* dev-105 (排版评审 v1 方案①; 用户 2026-10-08「检查页面、排版、字号」):
   the two facts were 13px all-caps slate - the same weight as the page's
   furniture, so a reader had to read the whole card before its structure was
   visible. They keep 13px but read as labels now: sentence case as written in
   the copy, 600 weight, navy. */
.kl-videos__facts dt {
	color: var(--kl-navy);
	font-size: var(--kl-text-sm);
	font-weight: var(--kl-weight-semibold);
	letter-spacing: normal;
	text-transform: none;
}

.kl-videos__facts dd {
	margin: var(--kl-space-1) 0 var(--kl-space-3);
}

.kl-videos__facts dd:last-of-type {
	margin-bottom: 0;
}

/* From 640px up the pair reads as two columns (label | value), so the card's
   shape is legible before the text is. Below 640px it stays stacked: a label
   column on a 292px phone card would squeeze the value it introduces. */
@media (min-width: 640px) {
	.kl-videos__facts {
		display: grid;
		grid-template-columns: minmax(0, auto) minmax(0, 1fr);
		column-gap: var(--kl-space-4);
		align-items: baseline;
	}

	.kl-videos__facts dt {
		grid-column: 1;
	}

	.kl-videos__facts dd {
		grid-column: 2;
		margin: 0 0 var(--kl-space-3);
	}
}

.kl-videos__place {
	margin: var(--kl-space-3) 0 0;
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

.kl-videos__watch {
	margin: var(--kl-space-4) 0 0;
}

/* dev-105 (排版评审 v1 方案①): fifteen solid pills were the loudest thing on
   the page - it said "button" before it said "story". The card's one control
   is a text link now, and it keeps the site's 44px touch floor (padding grows
   the hit box, not the type), the accent colour and an underline on
   hover/focus. */
.kl-videos__watch-link {
	display: inline-flex;
	align-items: center;
	gap: var(--kl-space-2);
	min-height: 44px;
	color: var(--kl-accent-hover);
	font-weight: var(--kl-weight-semibold);
	text-decoration: none;
}

.kl-videos__watch-link:hover,
.kl-videos__watch-link:focus-visible {
	text-decoration: underline;
}

.kl-videos__checked {
	margin: var(--kl-space-6) 0 0;
	padding-top: var(--kl-space-3);
	border-top: 1px solid var(--kl-border);
	color: var(--kl-slate);
	font-size: var(--kl-text-sm);
}

/* ---- dev-101 T2: the two entries into the index (design §4) ----------------
   One line on the hospital hub (after the filter / browse area) and one at the
   foot of the visa long page. Both are quiet notes, not calls to action, so
   they wear the secondary type and the reading measure rather than the accent
   button. */

.kl-hub__videos {
	margin: var(--kl-space-4) 0 0;
	max-width: var(--kl-measure);
	color: var(--kl-slate);
}

/* The long page's own container closes before the template can append to it,
   so this note gets its own axis-aligned container below the page. */
.kl-videos-entry {
	padding-bottom: var(--kl-space-8);
}

.kl-videos-entry__note {
	max-width: var(--kl-measure);
	color: var(--kl-slate);
}

/* ------------------------------- video card art, append-only (dev-104) ---
   The user asked (2026-10-08) for one picture per video card, so the section
   stops reading as a wall of text. The figure is shaped exactly like every
   other illustrated card on the site - 16:9, 14px radius, cover crop - but the
   shared media rules above are NOT edited: this block is appended, so the
   dev-018 / dev-073 call sites keep their markup and their CSS untouched.
   The picture sits above the platform label: the label and the title stay the
   first thing a reader scans for, which is what dev-101d ordered. */

.kl-videos__media {
	margin: 0 0 var(--kl-space-4);
	overflow: hidden;
	border-radius: var(--kl-radius-card);
	background: var(--kl-paper-alt);
	aspect-ratio: 16 / 9;
}

.kl-videos__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ------------------------------------------- fix-025 R2: es / ru header ---
 * The published es menu wrapped to two rows on desktop and ru was about to
 * ship the same way (user report 2026-10-16). R1 measured why: `.kl-nav__list`
 * keeps `flex-wrap: wrap` on desktop, and the es / ru label run is wider than
 * the list's real width. en / zh stay on one row at every desktop step, so the
 * fault is the label length, not the template.
 *
 * Everything below is scoped to `html[lang^="es"]` (es-419) and
 * `html[lang="ru-RU"]` - the two `lang` values the pages actually carry. en and
 * zh are untouched at every width, and the <= 900px mobile row is untouched for
 * all four editions.
 *
 * Measured (R2 probe, `docs/testing/fix-025/r2-nav-tune.mjs`, height 900):
 *
 *   band            menu list width   label run          slack
 *   >= 1280  es     676px (was 588)   596px (was 707)    80px
 *   >= 1280  ru     664px (was 576)   638px (was 752)    26px
 *   1200-1279 es    716px             596px             120px
 *   1200-1279 ru    704px             638px              66px
 *
 * The >= 1280 band is the hard one: it is the only band that carries the wide
 * brand gap (`margin-right: 80px`, the e006 rhythm), and at the capped 1200px
 * container that leaves the list just 588 / 576px - NOT the ~817px the 1024-1279
 * band has. The three compact parameters alone (label padding, nav gap, menu
 * type) fit es there with 8px to spare but leave ru 46px short, so the es / ru
 * row also withdraws that one gap: 80px -> 8px (user ruling 2026-10-16, option
 * "收窄品牌↔菜单间距"). The 1024-1279 band never had the gap, so this only
 * brings >= 1280 down to the narrower band's own rhythm. */

@media (min-width: 901px) {
	html[lang^="es"] .kl-nav,
	html[lang="ru-RU"] .kl-nav {
		gap: var(--kl-space-4);
	}

	html[lang^="es"] .kl-nav__list > .kl-nav__item > a,
	html[lang="ru-RU"] .kl-nav__list > .kl-nav__item > a,
	html[lang^="es"] .kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle,
	html[lang="ru-RU"] .kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 var(--kl-space-2);
	}
}

@media (min-width: 1280px) {
	html[lang^="es"] .kl-nav__list,
	html[lang="ru-RU"] .kl-nav__list {
		font-size: var(--kl-text-base);
	}

	html[lang^="es"] .kl-branding,
	html[lang="ru-RU"] .kl-branding {
		margin-right: var(--kl-space-2);
	}
}

/* 901-1131 (es) and 901-1183 (ru): below the first width where the compact run
 * fits inside the contract's 24px margin, the two editions take the burger the
 * mobile row already has - the desktop row swaps for the same `<details>` toggle
 * earlier than en / zh, which keep it down to 901. The switch points are the
 * measured minimum single-row width + a 32px safety pad:
 *
 *   edition   min single-row   + 32   band starts   slack at the switch
 *   es        1100px           1132   >= 1132px     52px
 *   ru        1152px           1184   >= 1184px     50px
 *
 * (Both bounds verified with `--strip-burger` on the R2 probe, which removes the
 * band below and measures the row at the boundary itself.)
 *
 * The body is written once per edition on purpose: a media condition cannot take
 * a custom property, and the two switch at different widths. It mirrors the
 * <= 900px block above verbatim, only scoped - including the group panels, which
 * go back to the native accordion (static, details-driven), which is why the
 * flyout-only `content-visibility: visible` is undone for a closed group. */

@media (min-width: 901px) and (max-width: 1131px) {
	html[lang^="es"] .kl-branding {
		flex: 1 1 200px;
		min-width: 0;
	}

	html[lang^="es"] .kl-nav__details {
		display: block;
		flex: 0 0 auto;
	}

	html[lang^="es"] .kl-nav__toggle {
		display: inline-flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		cursor: pointer;
		list-style: none;
	}

	html[lang^="es"] .kl-nav__toggle::-webkit-details-marker {
		display: none;
	}

	html[lang^="es"] .kl-nav {
		display: none;
	}

	html[lang^="es"] .kl-nav__details[open] ~ .kl-nav {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 30;
		padding: var(--kl-space-3) var(--kl-space-5) var(--kl-space-4);
		background: var(--kl-paper);
		border-top: 1px solid var(--kl-border);
		box-shadow: var(--kl-shadow-2);
	}

	html[lang^="es"] .kl-nav__list {
		flex-direction: column;
		gap: 0;
	}

	html[lang^="es"] .kl-nav__list a {
		width: 100%;
	}

	html[lang^="es"] .kl-nav__item {
		display: block;
	}

	html[lang^="es"] .kl-nav__group-toggle {
		width: 100%;
	}

	html[lang^="es"] .kl-nav__group:not([open])::details-content {
		content-visibility: hidden;
	}

	html[lang^="es"] .kl-nav__panel {
		display: block;
		position: static;
		padding: 0 0 0 var(--kl-space-4);
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
	}

	html[lang^="es"] .kl-header__cta {
		margin-top: var(--kl-space-3);
	}
}

@media (min-width: 901px) and (max-width: 1183px) {
	html[lang="ru-RU"] .kl-branding {
		flex: 1 1 200px;
		min-width: 0;
	}

	html[lang="ru-RU"] .kl-nav__details {
		display: block;
		flex: 0 0 auto;
	}

	html[lang="ru-RU"] .kl-nav__toggle {
		display: inline-flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		cursor: pointer;
		list-style: none;
	}

	html[lang="ru-RU"] .kl-nav__toggle::-webkit-details-marker {
		display: none;
	}

	html[lang="ru-RU"] .kl-nav {
		display: none;
	}

	html[lang="ru-RU"] .kl-nav__details[open] ~ .kl-nav {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 30;
		padding: var(--kl-space-3) var(--kl-space-5) var(--kl-space-4);
		background: var(--kl-paper);
		border-top: 1px solid var(--kl-border);
		box-shadow: var(--kl-shadow-2);
	}

	html[lang="ru-RU"] .kl-nav__list {
		flex-direction: column;
		gap: 0;
	}

	html[lang="ru-RU"] .kl-nav__list a {
		width: 100%;
	}

	html[lang="ru-RU"] .kl-nav__item {
		display: block;
	}

	html[lang="ru-RU"] .kl-nav__group-toggle {
		width: 100%;
	}

	html[lang="ru-RU"] .kl-nav__group:not([open])::details-content {
		content-visibility: hidden;
	}

	html[lang="ru-RU"] .kl-nav__panel {
		display: block;
		position: static;
		padding: 0 0 0 var(--kl-space-4);
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
	}

	html[lang="ru-RU"] .kl-header__cta {
		margin-top: var(--kl-space-3);
	}
}

/* ------------------------------------------- dev-132 R1c: id header ---
 * The `id` edition shipped inside the dev-132 launch gate carrying the same
 * desktop fault fix-025 also fixed for es / ru: `.kl-nav__list` keeps
 * `flex-wrap: wrap` on desktop, and the id label run is wider than the list's
 * real width, so the top-level items fell to a second row at every desktop
 * step (`docs/testing/dev-132/gates/R1-nav-break-after.txt`).
 *
 * The fix-025 es / ru recipe alone is NOT enough here: injected read-only it
 * still left the >= 1280 band 51px short (`R1-id-nav-fit.txt`, level A),
 * because the id labels are longer (runW 801px vs ru 638 / es 597) and the
 * switcher's new fifth option narrows the wrapped list by a further ~62px.
 * The measured viable compaction (level D) keeps the on-scale
 * `--kl-text-base` type but tightens the label padding to 2px and the nav gap
 * to `--kl-space-2`: single row down to 1152px (slack +9), so the switch
 * point is 1152 + 32 = 1184 - the same band boundary ru uses.
 *
 * Everything below is scoped to `html[lang^="id"]` (id-ID). en / zh / es / ru
 * are untouched at every width, and the <= 900px mobile row is untouched for
 * all editions. The 901-1183 burger band mirrors the <= 900px block verbatim,
 * only scoped - exactly as the es / ru blocks above do - including the group
 * panels, which go back to the native accordion (static, details-driven),
 * which is why the flyout-only `content-visibility: visible` is undone for a
 * closed group. */

@media (min-width: 901px) {
	html[lang^="id"] .kl-nav {
		gap: var(--kl-space-2);
	}

	html[lang^="id"] .kl-nav__list > .kl-nav__item > a,
	html[lang^="id"] .kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 2px;
	}
}

@media (min-width: 1280px) {
	html[lang^="id"] .kl-nav__list {
		font-size: var(--kl-text-base);
	}

	html[lang^="id"] .kl-branding {
		margin-right: var(--kl-space-2);
	}
}

/* 901-1183 (id): below the first width where the compact run fits inside the
 * contract's 24px margin (level D measured min single-row 1152px + 32px pad =
 * 1184), the id edition takes the burger the mobile row already has - the
 * desktop row swaps for the same `<details>` toggle earlier, as es / ru do. */

@media (min-width: 901px) and (max-width: 1183px) {
	html[lang^="id"] .kl-branding {
		flex: 1 1 200px;
		min-width: 0;
	}

	html[lang^="id"] .kl-nav__details {
		display: block;
		flex: 0 0 auto;
	}

	html[lang^="id"] .kl-nav__toggle {
		display: inline-flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		cursor: pointer;
		list-style: none;
	}

	html[lang^="id"] .kl-nav__toggle::-webkit-details-marker {
		display: none;
	}

	html[lang^="id"] .kl-nav {
		display: none;
	}

	html[lang^="id"] .kl-nav__details[open] ~ .kl-nav {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 30;
		padding: var(--kl-space-3) var(--kl-space-5) var(--kl-space-4);
		background: var(--kl-paper);
		border-top: 1px solid var(--kl-border);
		box-shadow: var(--kl-shadow-2);
	}

	html[lang^="id"] .kl-nav__list {
		flex-direction: column;
		gap: 0;
	}

	html[lang^="id"] .kl-nav__list a {
		width: 100%;
	}

	html[lang^="id"] .kl-nav__item {
		display: block;
	}

	html[lang^="id"] .kl-nav__group-toggle {
		width: 100%;
	}

	html[lang^="id"] .kl-nav__group:not([open])::details-content {
		content-visibility: hidden;
	}

	html[lang^="id"] .kl-nav__panel {
		display: block;
		position: static;
		padding: 0 0 0 var(--kl-space-4);
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
	}

	html[lang^="id"] .kl-header__cta {
		margin-top: var(--kl-space-3);
	}
}

/* ------------------------------------------- fix-026: th typography ---
 * Thai has no letter-spacing: the display tracking above (`-0.01em` / `-0.02em`
 * on h1-h4 and the title classes) pinches the combining marks onto the base
 * consonant, and the cap-height uppercase tracking is Latin-only anyway. The
 * th edition therefore resets the tracking to 0 and lifts the body leading
 * from the snug/base scale to 1.7 (`docs/i18n/th_文风与术语指南_v1.md` §4.4).
 *
 * Everything below is scoped to `:lang(th)`, which only matches the th edition
 * (`<html lang="th">`); en / zh / es / ru / id / ar keep every value they had.
 * `body` already carries `--kl-leading-body` (1.7); the rule restates it for
 * `p` / `li` and for the one snug note that overrides the scale on the home
 * page. No existing rule is edited. */
:lang(th) h1,
:lang(th) h2,
:lang(th) h3,
:lang(th) h4,
:lang(th) .kl-hero__title,
:lang(th) .kl-section__title,
:lang(th) .kl-columns__title,
:lang(th) .kl-panel__title {
	letter-spacing: 0;
}

:lang(th) p,
:lang(th) li,
:lang(th) .kl-home-example__note {
	line-height: 1.7;
}

/* ------------------------------------------- dev-146 R1: th header ---
 * The th edition ships its seventh switcher option in the same batch, and the
 * Thai label run is the widest of the seven editions: with the stock label
 * padding the five top-level items need 637px at the fixed 1200px axis and
 * only 618px are left (measured `docs/testing/dev-146/R1/nav.txt`), so the row
 * fell to two lines and the header grew to 105px at every desktop step >=1280.
 *
 * The measured compaction is one step down on the label gutter, nothing else:
 * `padding: 0 var(--kl-space-2)` (8px, the value the 901-1023 band already
 * uses) brings the run to 557px at >=1280 (slack +61) and 531px below
 * (slack +31 at 1024). The font size, the gap, the brand and the switcher are
 * untouched - the Thai script keeps the fix-026 typography it already has.
 *
 * Single row is measured down to 930px; with the fix-025 R2 32px pad the th
 * switch point would be 962. It is set to 1024 instead - the site's next real
 * breakpoint - so the desktop band keeps >=31px of slack at every step and the
 * 901-1023 band takes the burger the mobile row already has (below). This is
 * the same recipe es / ru / id use, scoped so en / zh / es / ru / id / ar keep
 * every value they had. */

@media (min-width: 901px) {
	html[lang^="th"] .kl-nav__list > .kl-nav__item > a,
	html[lang^="th"] .kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 var(--kl-space-2);
	}
}

@media (min-width: 901px) and (max-width: 1023px) {
	html[lang^="th"] .kl-branding {
		flex: 1 1 200px;
		min-width: 0;
	}

	html[lang^="th"] .kl-nav__details {
		display: block;
		flex: 0 0 auto;
	}

	html[lang^="th"] .kl-nav__toggle {
		display: inline-flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		cursor: pointer;
		list-style: none;
	}

	html[lang^="th"] .kl-nav__toggle::-webkit-details-marker {
		display: none;
	}

	html[lang^="th"] .kl-nav {
		display: none;
	}

	html[lang^="th"] .kl-nav__details[open] ~ .kl-nav {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 30;
		padding: var(--kl-space-3) var(--kl-space-5) var(--kl-space-4);
		background: var(--kl-paper);
		border-top: 1px solid var(--kl-border);
		box-shadow: var(--kl-shadow-2);
	}

	html[lang^="th"] .kl-nav__list {
		flex-direction: column;
		gap: 0;
	}

	html[lang^="th"] .kl-nav__list a {
		width: 100%;
	}

	html[lang^="th"] .kl-nav__item {
		display: block;
	}

	html[lang^="th"] .kl-nav__group-toggle {
		width: 100%;
	}

	html[lang^="th"] .kl-nav__group:not([open])::details-content {
		content-visibility: hidden;
	}

	html[lang^="th"] .kl-nav__panel {
		display: block;
		position: static;
		padding: 0 0 0 var(--kl-space-4);
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
	}

	html[lang^="th"] .kl-header__cta {
		margin-top: var(--kl-space-3);
	}
}

/* ------------------------------------------- fix-029: fr typography ---
 * French typesetting forbids letter-spacing and wants body leading >= 1.6
 * (`docs/i18n/fr_文风与术语指南_v1.md` §4 items 4-5). The display tracking
 * above (`-0.01em` / `-0.02em` on h1-h4 and the title classes) pinches the
 * French accents, and `p.kl-home-example__note` is the one snug note that
 * overrides the scale on the home page (1.45; measured
 * `docs/testing/dev-147/viewing/fr-typesetting-checklist.txt`).
 *
 * Everything below is scoped to `:lang(fr)`, which only matches the fr edition
 * (`<html lang="fr-FR">`); en / zh / es / ru / id / ar / th keep every value
 * they had. `body` already carries `--kl-leading-body` (1.7); only the one
 * note is restated. No existing rule is edited. */
:lang(fr) h1,
:lang(fr) h2,
:lang(fr) h3,
:lang(fr) h4,
:lang(fr) .kl-hero__title,
:lang(fr) .kl-section__title,
:lang(fr) .kl-columns__title,
:lang(fr) .kl-panel__title {
	letter-spacing: 0;
}

:lang(fr) .kl-home-example__note {
	line-height: 1.7;
}

/* ------------------------------------------- dev-153 R1: fr header ---
 * The fr edition ships its eighth switcher option in the same batch. With the
 * stock label gutter the French label run wrapped to two rows at every desktop
 * step except 1200, and the header grew to 105px
 * (`docs/testing/dev-153/R1/nav-fr-probe-brk901.txt`).
 *
 * The measured compaction is the id recipe - label padding 2px and the nav gap
 * at `--kl-space-2`, plus the branding margin at >=1280 - nothing else: the
 * font size, the brand and the switcher stay as they are. Scoped to
 * `html[lang^="fr"]` (fr-FR); every other edition keeps its values. */

@media (min-width: 901px) {
	html[lang^="fr"] .kl-nav {
		gap: var(--kl-space-2);
	}

	html[lang^="fr"] .kl-nav__list > .kl-nav__item > a,
	html[lang^="fr"] .kl-nav__list > .kl-nav__item--group > .kl-nav__group > .kl-nav__group-toggle {
		padding: 0 2px;
	}
}

@media (min-width: 1280px) {
	html[lang^="fr"] .kl-nav__list {
		font-size: var(--kl-text-base);
	}

	html[lang^="fr"] .kl-branding {
		margin-right: var(--kl-space-2);
	}
}

/* The measured single row holds down to 1100px
 * (`docs/testing/dev-153/R1/nav-fr-after.txt`); with the fix-025 R2 32px pad
 * the switch point is 1132 - the same band boundary es uses. The 901-1131 band
 * takes the burger the mobile row already has, mirroring the <= 900px block
 * verbatim, only scoped. */

@media (min-width: 901px) and (max-width: 1131px) {
	html[lang^="fr"] .kl-branding {
		flex: 1 1 200px;
		min-width: 0;
	}

	html[lang^="fr"] .kl-nav__details {
		display: block;
		flex: 0 0 auto;
	}

	html[lang^="fr"] .kl-nav__toggle {
		display: inline-flex;
		align-items: center;
		gap: var(--kl-space-2);
		min-height: 44px;
		padding: 0 var(--kl-space-4);
		border: 1px solid var(--kl-border-strong);
		border-radius: var(--kl-radius-pill);
		background: var(--kl-paper);
		color: var(--kl-ink);
		cursor: pointer;
		list-style: none;
	}

	html[lang^="fr"] .kl-nav__toggle::-webkit-details-marker {
		display: none;
	}

	html[lang^="fr"] .kl-nav {
		display: none;
	}

	html[lang^="fr"] .kl-nav__details[open] ~ .kl-nav {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		z-index: 30;
		padding: var(--kl-space-3) var(--kl-space-5) var(--kl-space-4);
		background: var(--kl-paper);
		border-top: 1px solid var(--kl-border);
		box-shadow: var(--kl-shadow-2);
	}

	html[lang^="fr"] .kl-nav__list {
		flex-direction: column;
		gap: 0;
	}

	html[lang^="fr"] .kl-nav__list a {
		width: 100%;
	}

	html[lang^="fr"] .kl-nav__item {
		display: block;
	}

	html[lang^="fr"] .kl-nav__group-toggle {
		width: 100%;
	}

	html[lang^="fr"] .kl-nav__group:not([open])::details-content {
		content-visibility: hidden;
	}

	html[lang^="fr"] .kl-nav__panel {
		display: block;
		position: static;
		padding: 0 0 0 var(--kl-space-4);
		border: 0;
		border-radius: 0;
		background: transparent;
		box-shadow: none;
	}

	html[lang^="fr"] .kl-header__cta {
		margin-top: var(--kl-space-3);
	}
}

/* ------------------------------------------ fix-030: ar typography ---
 * The Arabic style guide forbids letter-spacing (it breaks the joined script)
 * and sets body leading at >=1.7. The shared display styles still carried
 * -0.01/-0.02em headings, .005/.04em/caps tracking on labels, and a 1.45
 * home-example note. Scope the correction to the Arabic html lang so every
 * other edition keeps its existing values. `body *` also catches the existing
 * single-class tracking rules; the stacked-table label is a pseudo-element
 * and gets its own selector. */
html[lang="ar"] body * {
	letter-spacing: normal;
}

html[lang="ar"] body .kl-table--stack td::before {
	letter-spacing: normal;
}

html[lang="ar"] body p,
html[lang="ar"] body li,
html[lang="ar"] body .kl-home-example__note {
	line-height: 1.7;
}
