/*
THE PALETTE, and every value here is the one release item 10b measured on
2026-08-17. The four that carry text were darkened because white on the old red
was 3.14:1 and the old blue 2.86:1, against a 4.5 standard. If you change one,
measure it against the background it will actually sit on and not against white:
the search panel is #F6F8F9 and the "at a glance" box is #D8E8F1 (item 11m), and
a grey that passes on white can fail on either. It failed on the blue: #6B6B6B
measured 4.25:1 there and had to go to #555.
⚠️ This line used to read "the facts panels are #F6F8F9". They were never
repainted to that - option C took their background away entirely - and item 11m
then gave the glance box the blue. Two changes late.

Blue:				2A72A8   5.16:1 with white. ⚠️ CHANGED THREE TIMES IN A WEEK AND
					THIS IS THE SETTLED ONE - read P3-72 before touching it again.
					Item 10b darkened 4FA0D7 -> 2A72A8 on 17 Aug for white text
					(2.86 -> 5.16) and nobody checked the LOGO, whose dark grey went
					4.22 -> 2.34. The owner spotted that by eye on 21 Aug and had it
					put back. Then they replaced the logo with an ALL-WHITE one
					(img/logo-head2.png, 22 Aug), which removed the reason for the
					light blue - so it is dark again and now the whole wordmark is
					5.16:1 instead of half the logo failing whichever value was set.
Red, everything:	CE3A36   was FF5556, FF7071 and D55654 - three reds, now one.
					4.90:1 with white, in both directions
Red, darker:		A82F2B   the ribbon fold and the hover state. Carries no text
					of its own; it exists to be darker than CE3A36
Grey, labels:		666E76   was 8A9096 and 7A8288. 4.86:1 on the panels.
					⚠️ 8A9096 CAME BACK in item 11n and was removed again in
					11k2 - to 6B6B6B, not to this, because those labels are on
					a white card and this figure is against a panel. P3-69.
					THE FIVE .search-panel RULES, as of release item 11k. The one
					rule that carried this grey into an article column's own
					furniture (.route-facts__bags thead th) was folded to 6B6B6B,
					because there it sat directly under a caption already in
					6B6B6B doing the same job.
					⚠️ NOT "an article column's labels are all 6B6B6B", which is
					what this said first and is FALSE: the search panel is
					included INSIDE .columns.eight.content, so .search-panel__title
					is 666E76 in an article column whenever that panel renders -
					which is after a search, never on a landing
Grey, figures:		6B6B6B   was 777. 5.00:1 on the panels
Grey, quiet text:	5C6773   was 747F8B (4.08:1). 5.76:1 with white
Grey light back:	D7D7D7
Grey dark back:		363636
Blue light back:	D9E7F0
*/

/*
*
* Reuseable styles
*
*/
h3.ribbon {
	position: relative;
	display: inline-block;
	margin: 10px 0 0 -17px;
	padding: 0 15px 0 20px;
	font-size: 2rem;
	letter-spacing: 0.03em;
	height: 2.0em;
	line-height: 2.0em;
	color: #fff;
	background-color: #CE3A36;
	font-weight: 400;
	text-transform: uppercase;
	
}
h3.ribbon:after {
	content: ' ';
	position: absolute;
	width: 0;
	height: 0;
	left: 0px;
	top: 100%;
	border-width: 5px 5px;
	border-style: solid;
	/* The fold under the ribbon, and it has to stay DARKER than the ribbon or
	 * there is no fold. It used to be #D55654 under a #FF5556 ribbon; both of
	 * those became one red in release item 10b, which would have made this
	 * invisible against the thing it is folding away from. It carries no text,
	 * so it is chosen by eye rather than by contrast ratio. */
	border-color: #A82F2B transparent transparent transparent;
}


/*
* icon shapes
*/
i.diamond {
	position: relative; 
	width: 0; 
	height: 0; 
	top: -37px;
	border: 37px solid transparent; 
	border-bottom-color: #2A72A8;
} 

i.diamond:after {
	position: absolute; 
	content: ''; 
	width: 0; 
	height: 0; 
	top: 37px; 
	left: -37px; 
	border: 37px solid transparent; 
	border-top-color: #2A72A8;
}
i.circle {
	width: 100px;
	height: 100px;
	background: red;
	-moz-border-radius: 50px;
	-webkit-border-radius: 50px;
	border-radius: 50px;
	/* Cleaner, but slightly less support: use "50%" as value */
}
.animated {
  -webkit-animation-duration: 500ms;
  animation-duration: 500ms;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

@-webkit-keyframes fadeInDown {
	from {
		opacity: 0;
		-webkit-transform: translate3d(0, -10%, 0);
		transform: translate3d(0, -10%, 0);
	}
	to {
		opacity: 1;
		-webkit-transform: none;
		transform: none;
	}
}
@keyframes fadeInDown {
	from {
		opacity: 0;
		-webkit-transform: translate3d(0, -10%, 0);
		transform: translate3d(0, -10%, 0);
	}
	to {
		opacity: 1;
		-webkit-transform: none;
		transform: none;
	}
}
.fadeInDown {
	-webkit-animation-name: fadeInDown;
	animation-name: fadeInDown;
}
@-webkit-keyframes fadeOutUp {
 	from {
		opacity: 1;
	}
	to {
		opacity: 0;
		-webkit-transform: translate3d(0, -10%, 0);
		transform: translate3d(0, -10%, 0);
	}
}
@keyframes fadeOutUp {
	from {
		opacity: 1;
	}
	to {
		opacity: 0;
		-webkit-transform: translate3d(0, -10%, 0);
		transform: translate3d(0, -10%, 0);
	}
}
.fadeOutUp {
	-webkit-animation-name: fadeOutUp;
	animation-name: fadeOutUp;
}

/*
* Zebra Datepicker updates
*/
.Zebra_DatePicker {
	box-sizing: border-box;
    padding: 20px;
	font: 16px 'Roboto', sans-serif;
	width: 100% !important;
}
@media (min-width: 750px) {
	.Zebra_DatePicker {
		width: 350px !important;
	}
}
.Zebra_DatePicker h6 {
	font-family: 'Roboto', sans-serif;
	font-size: 1.8rem;
	color: #CE3A36;
	font-weight: 700;
	text-align: center;
}
.Zebra_DatePicker table {
	margin-bottom: 0;
}
.Zebra_DatePicker .dp_body .dp_hover,
.Zebra_DatePicker .dp_body .dp_hover.dp_time_control,
.Zebra_DatePicker .dp_actions .dp_hover {
    background: #e9f0f3;
}
.Zebra_DatePicker .dp_body .dp_selected {
    background: #CE3A36;
}

/*
*
* Header 
*
*/
header {
	height: 50px;
	margin: 0px;
	padding: 2px 0 5px 0;
	color: #fff;
	background-color: #2A72A8;
}
@media (min-width: 700px) {
	header {
		padding: 1px 0 5px 0;
		height: 57px;
	}
}
@media (min-width: 950px) {
	header {
		height: 109px;
	}
}
header .container {
	margin: 10px auto 0px;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}
header .container.main { 
	padding: 0 100px 0 15px;
}
header a {
	color: #fff;
}
header .logo {
	position: absolute;
	display: block;
	width: 200px;
	height: auto;
	float: left;
	z-index: 2;
}
@media (min-width: 350px) {
	header .logo {
		width: 270px;
	}
}
@media (min-width: 470px) {
	header .logo {
		width: 350px;
	}
}
@media (min-width: 700px) {
	header .logo {
		width: 430px;
	}
}
@media (min-width: 950px) {
	header .logo {
		width: 490px;
	}
}
header .logo img {
	width: 100%;
	height: auto;
}

@media (min-width: 950px) {
	header .connect {
		display: inline-block;
		float: right;
	}
}


header #head--search-box {
	display: none;
	width: 250px;
	margin: 6px 0 0 40px;
	padding: 3px 20px;
	float: left;
	background-color: #fff;
	border-radius: 20px;
}
@media (min-width: 950px) {
	header #head--search-box {
		display: inline-block;
	}
}
header #head--search-box i {
	display: inline-block;
	float: left;
	margin-top: 10px;
	font-size: 2rem;
	color: #2A72A8;
}
header #head--search-box input[type=text] {
	width: 230px;
	margin: 0;
	padding: 0 0 0 0.5em;
	color: #666;
	border: none;
	font-size: 1.8rem;
	background-color: #fff;
	-webkit-transition: width 0.2s ease-in-out;
	transition: width 0.2s ease-in-out;
}


header .connect {
	position: relative;
	display: none;
	margin-top: 10px;
}
@media (min-width: 950px) {
	header .connect {
		display: inline-block;
		float: right;
	}
}
header .connect a {
	display: inline-block;
}
header .connect a i {
	display: inline-block;
	font-size: 3.5rem;
	margin-left: 0.5em;
	vertical-align: middle;
	
	transition: all 0.1s ease-in;
	-ms-transition: all 0.1s ease-in;
	-moz-transition: all 0.1s ease-in;
	-webkit-transition: all 0.1s ease-in;
}
header .connect a:hover i,
header .connect a i:hover {
	color: #D7D7D7;
}

header .icon-bell {
	position: relative;
	margin-left: 0.5em;
	font-size: 3.5rem;
	vertical-align: middle;
	cursor: pointer;
}
header .icon-bell .num {
	position: absolute;
	width: 14px;
	height: 14px;
	font-size: 1.0rem;
	top: -2px;
	right: -2px;
	color: #fff;
	background-color: #CE3A36;
	border-radius: 50%;
	padding: 2px;
	text-align: center;
}
header .icon-bell {
	position: relative;
	margin-left: 0.5em;
	font-size: 3.5rem;
	vertical-align: middle;
	cursor: pointer;
}

/*
* Notification dropdown
* From https://codepen.io/mohamedalzahaby/pen/oRBbRB
*/
#notifications-dropdown {
	position: absolute;
	display: none;
	right: 0px;
	top: 53px;
	width: 390px;
	min-width: 100px;
	min-height: 10px;
	
	box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
	z-index: 20;
}
#notifications-dropdown.show {
	display: block;
}
#notifications-dropdown .dropdown-header {
	background: #FFF;
	padding: 15px;
	position: relative;
	text-align: center;
	color: #5C6773;
	font-weight: bold;
	border-radius: 10px 10px 0 0;
	border: 0px;
	border-style: solid;
	border-bottom-width: 1px;
	-moz-border-image: -moz-linear-gradient(right, white, #cedae0, #cedae0, white) 1 20%;
	-o-border-image: -o-linear-gradient(right, white, #cedae0, #cedae0, white) 1 20%;
	border-image: linear-gradient(to right, white 0%, #cedae0 40%, #cedae0 60%, white 100%) 1 20%;
	box-shadow: 0px 2px 10px -2px #cedae0;
}
#notifications-dropdown .triangle {
	position: absolute;
	top: -8px;
	right: 11px;
	height: 15px;
	width: 15px;
	border-radius: 6px 0px 0px 0px;
	transform: rotate(45deg);
	background: #FFF;
}
#notifications-dropdown .dropdown-body {
	max-height: 292px;
	background: #e9f0f3;
	overflow-y: auto;
	overflow-x: hidden;	
}
#notifications-dropdown .notification {
	display: block;
	min-height: 45px;
	padding: 15px;
	border: 0px;
	border-style: solid;
	border-bottom-width: 1px;
	-moz-border-image: -moz-linear-gradient(right, white, #cedae0, #cedae0, white) 1 20%;
	-o-border-image: -o-linear-gradient(right, white, #cedae0, #cedae0, white) 1 20%;
	border-image: linear-gradient(to right, white 0%, #cedae0 40%, #cedae0 60%, white 100%) 1 20%;
	color: #5C6773;
	cursor: pointer;
	font-size: 1.4rem;
	word-spacing: 2px;
	line-height: 21px;
	text-decoration: none;
}
/* Three rules were deleted here on 2026-08-22 (owner) with the two fixed rows
   they styled - the "kiwi Guarantee" advert at the top of the panel and the
   "More travel guides" link at the bottom. No call to action replaces them:
   asked and answered.

     .notification.open-booking-form   the advert's white background
     .notification.single              both rows' tighter padding
     .notification.no-icon             both rows' icon-width indent

   Derived, not recalled: after the change, a grep for those three class names
   across the .php and .css files found no live user of any of them - only
   `css/-dft.css`, an unserved stale copy of this file that is deliberately
   left alone.

   ⛔ THE COMMAND IS DESCRIBED RATHER THAN QUOTED, AND THAT IS DELIBERATE. An
   earlier version pasted the grep in verbatim, and an audit ran it: it matched
   three times in THIS FILE, because a pattern written into a comment matches
   the comment. A quoted search pattern is true when it is run and false the
   moment it is saved next to itself.

   ⚠ `.open-booking-form` ITSELF IS STILL LIVE and its dft.js click handler
   still has work: two buttons in template-airline.php. An earlier version of
   this note also credited the schedules table's "Enter Dates" buttons - those
   were deleted by release item 11g and survive only as prose in
   constants-html-templates.php. */

#notifications-dropdown .notification:hover {
	background-color: #DDE6EB;
}
/* What the panel shows when nothing qualifies as recently updated. It is a
   <span>, not a link, so the `cursor: pointer` and the hover colour it inherits
   from `.notification` are both turned back off.

   ⛔ THE ORDER OF THESE TWO BLOCKS IS THE FIX, NOT AN ACCIDENT.
   `#notifications-dropdown .notification-empty:hover` and
   `#notifications-dropdown .notification:hover` have IDENTICAL specificity
   (one id, two classes), so whichever is written last wins. The first version
   put the empty-state rule above the generic one and it did nothing at all. */
#notifications-dropdown .notification-empty {
	cursor: default;
	color: #6B6B6B;
	text-align: center;
}
#notifications-dropdown .notification-empty:hover {
	background-color: transparent;
}
#notifications-dropdown .notification .highlight {
	font-weight: 700;
}
/* The update date under each row's title - owner, 2026-08-22. It carries the
   same colour and the same job as `.page-updated`, the "Updated <date>" line on
   the page itself: a quiet second line that a reader can check the heading
   against. It is a step smaller than the row title because it repeats on every
   row and the title is the thing being chosen between.
   The left margin clears the floated 32px icon, which stops at 50px from the
   top of the row - a two-line title already clears it, a one-line title does
   not, and without this the date would sit under the icon on the short rows. */
#notifications-dropdown .notification .notification-date {
	display: block;
	margin-left: 47px;
	font-size: 1.3rem;
	font-weight: 400;
	line-height: 1.5;
	color: #6B6B6B;
}
#notifications-dropdown .notification img,
#notifications-dropdown .notification i {
	display: inline-block;
	float: left;
	width: 32px;
	height: 45px;
	margin: 0 15px 0 0;
	color: #000;
}
#notifications-dropdown .notification i {
	height: 35px;
	margin: 15px 10px 0 5px;
	font-size: 2.4rem;
}
#notifications-dropdown .notification:hover i {
	color: #000;
}



/*
*
* Header Navigation
*
*/
header nav {
	position: absolute;
	top: 0;
	right: 0;
	left: 0;
	z-index: 1;
}
@media (min-width: 950px) {
	header nav {
		position: relative;
		float: none;
		clear: both;
		margin: 0;
		padding: 0;
		width: 100%;
		background-color: #363636;
	}
}
header nav .container {
	width: 100%;
	margin-bottom: 0;
}
@media (min-width: 950px) {
	header nav .container {
		width: 96%;
	}
}
header nav ul {
	position: absolute;
	top: 47px;
	right: 0;
	left: 0;
	min-height: 35px;
	margin: 0 auto;
	padding: 10px 0;
	background-color: #363636;
	text-align: center;
	list-style: none;
}
@media (min-width: 700px) {
	header nav ul {
		top: 53px;
	}
}
@media (min-width: 950px) {
	header nav ul {
		position: relative;
		top: 0;
		text-align: left;
		padding: 0;
	}
}
header nav ul li {
	display: block;
	margin: 0;
	padding: 0;
	border-bottom: 1px #444 solid;
}
@media (min-width: 950px) {
	header nav ul li {
		display: inline-block;
	}
}
header nav ul li:hover {
	background-color: #444;
}
header nav ul li a {
	display: block;
	height: 48px;
	margin: 0;
	padding: 0 0.5em;
	color: #fff;
	line-height: 45px;
	text-decoration: none;
	cursor: pointer;
}
@media (min-width: 950px) {
	header nav ul li a {
		padding: 0 1.25em 0 1.24em;
	}
	/*
	header nav ul li:first-child {
		margin-left: 0;
	}
	*/
}
header nav ul li a.active {
	background-color: #444;
}
header nav ul li a:hover {
	text-decoration: none;
}
header nav ul li a i {
	display: inline-block;
	margin-right: 5px;
	font-size: 2rem;
	transform: translateY(3px);
}


/* 
* menu toggle button
*/
.main-menu-btn {
	position: relative;
	display: inline-block;
	float: right;
	width: 31px;
	height: 28px;
	margin: 5px 15px;
	text-indent: 31px;
	white-space: nowrap;
	overflow: hidden;
	cursor: pointer;
	-webkit-tap-highlight-color: rgba(0,0,0,0);
}
@media (min-width: 950px) {
	/* hide the button in desktop view */
	.main-menu-btn {
		position: absolute;
		top: -99999px;
	}
}
/* hamburger icon */
.main-menu-btn-icon, 
.main-menu-btn-icon:before, 
.main-menu-btn-icon:after {
	position: absolute;
	top: 12px;
	left: 0;
	height: 3px;
	width: 31px;
	background: #fff;
	-webkit-transition: all 0.25s;
	transition: all 0.25s;
}
.main-menu-btn-icon:before {
	content: '';
	top: -11px;
	left: 0;
}
.main-menu-btn-icon:after {
	content: '';
	top: 11px;
	left: 0;
}
/* x icon */
#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon {
	height: 0;
	background: transparent;
}
#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon:before {
	top: 0;
	-webkit-transform: rotate(-45deg);
	transform: rotate(-45deg);
}
#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon:after {
	top: 0;
	-webkit-transform: rotate(45deg);
	transform: rotate(45deg);
}
/* hide menu state checkbox (keep it visible to screen readers) */
#main-menu-state {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	border: 0;
	padding: 0;
	overflow: hidden;
	clip: rect(1px,1px,1px,1px);
}
/* hide the menu in mobile view */
#main-menu-state:not(:checked) ~ #main-menu {
	display: none;
}
@media (min-width: 950px) {
	/* always show the menu in desktop view */
	#main-menu-state:not(:checked) ~ #main-menu {
		display: block;
	}
}
#main-menu-state:checked ~ #main-menu {
	display: block;
}


/*
*
* Schedules Slidebar
*
*/
.js-close-any {
	position: relative;
	cursor: pointer;
	overflow: hidden;
}
.js-close-any:before:hover {
	transform: scale(1.3, 1.3);
	color: red;
}
.js-close-any:after {
	position: absolute;
	content: ' ';
	top: 0; right: 0;
	bottom: 0; left: 0;
	width: 100%;
	height: 100%;
	padding: 10000px 0;
	background:rgba(0,0,0,0.7);
	z-index: 1;
	cursor: pointer;
	transition: all 0.5s;
	-webkit-transition: all 0.5s;
	-moz-transition: all 0.5s;
}
#schedules.slidebar {
	padding: 20px 0px 0px 0px;
	color: #333;
	background-color: #e9f0f3;
}
.slidebar__close {
	display: none;
	position: fixed;
	top: 0;
	right: 0;
	color: #fff;
	width: 30px;
	height: 30px;
	padding: 10px;
	font-size: 4.0rem;
	text-align: center;
	line-height: 30px;
	cursor: pointer;
	z-index: 2;
	transition: all 0.1s linear;
}
.slidebar__close.show {
	display: block;
}
#schedules.slidebar h2 {
	margin-left: 15px;
	font-size: 3rem;
}
#schedules.slidebar h2 {
	margin-bottom: 0;
	padding-left: 15px;
	font-size: 2.5rem;
	font-weight: 700;
}
#schedules.slidebar h6 {
	margin-bottom: 10px;
	padding-left: 15px;
	font-size: 1.5rem;
	font-weight: 700;
}
#schedules.slidebar ul {
	margin: 1em 0 0 0;
	list-style-type: none;
}
#schedules.slidebar ul li {
	margin: 0;
	padding: 0;
}
#schedules.slidebar ul li.head {
	padding: 0.5em 0em;
}
#schedules.slidebar ul li a {
	display: block;
	margin: 0;
	padding: 0.4em 1em;
	font-size: 1.5rem;
	border-bottom: 1px #cedae0 solid;
	color: #5C6773;
	text-decoration: none;
}
#schedules.slidebar ul li a:hover {
	background-color: #DDE6EB;
}
#schedules.slidebar ul li ul {
	margin: 0;
	padding: 0;
}
#schedules.slidebar ul li ul li a {
	padding-left: 30px;
}
.mob_cta {
	display: block;
	position: fixed;
	bottom: 0;
	width: 100%;
	margin-bottom: 0;
	z-index: 1;
	border: none !important;
}
@media (min-width: 750px) {
	.mob_cta {
		display: none;
	}
}


/*
* Home page header
*
*/
section#banner {
	position: relative;
	padding: 10px 20px 0 20px;
	background: url("../img/bg-header.jpg") transparent no-repeat center;
	-webkit-background-size: cover;
	-moz-background-size: cover;
	-o-background-size: cover;
	background-size: cover;
	box-shadow: inset 0px 0px 50px rgba(0,0,0,0.8);
	
    
	-webkit-transition: all 0.5s ease-in-out;
	-moz-transition: all 0.5s ease-in-out;
	-o-transition: all 0.5s ease-in-out;
	transition: all 0.5s ease-in-out;
}
section#banner:after {
    position: absolute;
    display: block;
    content: " ";
    bottom: 0;
    left: 0;
    right: 0;
    height: 10px;
    background-image: -webkit-gradient(
        linear,
        left top,
        left bottom,
        color-stop(0, rgba(255, 255, 255, 0)),
        color-stop(1, rgba(255, 255, 255, 100)));
}
#banner.show {
    padding: 20px;
	max-height: 600px;
}
@media (min-width: 750px) {
	section#banner.show {
		padding: 40px 40px 50px;
	}
}
#banner.show:after {
    content: none;
}
section#banner .toggle-booking-form {
	position: absolute;
	left: 0;
	bottom: -40px;
	display: inline-block;
	width: 130px;
	height: 40px;
	margin: auto;
	padding: 0 30px;
	right: 0;
	text-align: center;
	visibility: visible;
	line-height: 40px;
	background-color: #CE3A36;
	color: #fff;
	border-bottom-left-radius: 3px;
	border-bottom-right-radius: 3px;
	cursor: pointer;
}
section#banner.show .toggle-booking-form {
	color: #CE3A36;
	background-color: #fff;
	border: 1px #CE3A36 solid;
	border-top: none;
}
section#banner .toggle-booking-form:hover {
	color: #fff;
	background-color: #A82F2B;
}
.open-booking-form {
	cursor: pointer;
}

section#banner #search-form {
	max-height: 156px;
    overflow: hidden;
	-webkit-transition: all 0.3s ease-in-out;
	-moz-transition: all 0.3s ease-in-out;
	-o-transition: all 0.3s ease-in-out;
	transition: all 0.3s ease-in-out;
	
}
section#banner.show #search-form {
	max-height: none;
	-webkit-transition: all 1.1s ease-in-out;
	-moz-transition: all 1.1s ease-in-out;
	-o-transition: all 1.1s ease-in-out;
	transition: all 1.1s ease-in-out;
}




/*
*
* Flight search form
*
*/
#search-form {
	position: relative;
	width: 100%;
	max-width: 1200px;
	margin: 0px;
	padding: 20px;
	color: #fff;
	background-color: #363636;
	background-color: rgba(54,54,54,0.6);
	box-shadow: inset 0px 0px 20px rgba(0,0,0,0.4);
}
@media (min-width: 750px) {
	#search-form {
		margin: 0 auto;
	}
}
		
#search-form h3.ribbon {
    margin: 0 0 10px -27px;
    padding: 0 40px
}
#search-form .options {
	display: inline-block;
}
#search-form .options label {
	margin-left: 20px;
	font-size: 2rem;
	
}
#search-form .options input {
	display: inline-block;
	margin-right: 0.2em;
}
#search-form label {
	display: inline-block;
}

#search-form input[type=text],
#search-form select,
#search-form textarea {
	display: block;
	margin: 5px 0;
	color: #333;
}
#search-form .fuzzyResults {
	left: 0 !important;
	right: 0 !important;
	width: 100%;
	/*
	 * `bottom: 0 !important` was here and is removed (P2-53).
	 *
	 * The plugin sets `top` inline on an absolutely-positioned box. With BOTH
	 * top and bottom set and height:auto, the used height is computed as
	 * (containing block - top - bottom) - and the containing block is the
	 * <label>, which is barely taller than the input. So the box was being
	 * squeezed to near zero height before a single option was in it.
	 *
	 * The list also needs a ceiling of its own: 38 airports at ~36px is over
	 * 1300px, which is taller than most viewports. Scroll it instead.
	 */
	max-height: 320px;
	overflow-y: auto;
	/*
	 * Above .mob_cta, which is position:fixed with z-index:1 and comes LATER in
	 * the document - so at equal z-index it paints over the foot of this list on
	 * mobile. Caught by a codex audit.
	 */
	z-index: 3;
}
/*
 * ...and the OPEN booking form must not clip it.
 *
 * `section#banner #search-form` is `max-height: 156px; overflow: hidden` so the
 * collapsed banner shows a teaser of the form - that part is deliberate and is
 * left alone. But `overflow: hidden` stays in force once the form opens, and
 * the dropdown is a child of the form, so it was being cut off at the form's
 * bottom edge. Under the "Depart from" field that leaves roughly 120px, i.e.
 * about THREE options - which is exactly what the owner reported seeing.
 *
 * Only the open state is changed. In the open state max-height is already
 * `none`, so overflow has nothing legitimate left to clip.
 */
section#banner.show #search-form {
	overflow: visible;
}
#search-form .locations {
	width: 100%;
}
#search-form .locations label {
	position: relative;
	width: 100%;
}
@media (min-width: 500px) {
	#search-form .locations label {
		width: 50%;
		box-sizing: border-box;
		padding: 0 5px;
	}
}
/*
* The × that clears an airport field (P2-53 follow-up, owner-requested).
*
* Positioned against the <label>, which is the positioned ancestor here, and
* pinned to the BOTTOM of it because the label holds its caption text above the
* input - so `bottom` tracks the input's own bottom edge whether or not the
* caption wraps. The label carries `padding: 0 5px` at >=500px, and absolute
* offsets are measured from the padding box, so `right: 5px` sits on the
* input's right edge rather than 5px outside it.
*
* Hidden until there is something to clear: an × on an empty box is noise, and
* on mobile it is noise occupying a thumb-sized piece of a small screen.
*/
.airport-clear {
	position: absolute;
	/*
	 * ⚠️ THESE TWO OFFSETS TRACK THE INPUT, NOT THE LABEL, and the difference is
	 * 5px of the input's own margin. Measured rather than eyeballed:
	 *
	 *   #search-form .locations input   margin: 5px 0   (both breakpoints)
	 *   #search-form .locations label   padding: 0 5px  at >=500px, 0 below it
	 *
	 * `bottom: 0` therefore sat the button 5px BELOW the input's bottom edge -
	 * outside the box it is supposed to live in - and the right offset has to
	 * differ by breakpoint because absolute offsets are measured from the
	 * label's padding box, which only has padding at the wider one.
	 *
	 * 6px = the input's 5px margin + 1px to sit inside its border. Height 34 in
	 * a 36px input for the same reason.
	 *
	 * If those two rules change, this breaks - so the clear-control harness
	 * (scratchpad `test-clear.js`, see docs/HANDOVER.md §4; there is no test
	 * runner in this repo) asserts the button's rect is INSIDE the input's rect
	 * at 390px rather than checking any of these numbers. That is the check that
	 * survives someone editing the form's spacing.
	 */
	right: 1px;
	bottom: 6px;
	display: none;
	/*
	 * 34px tall is the input's 36px less a 1px inset top and bottom, so the
	 * control sits inside the border rather than over it. The WIDTH is free, and
	 * it is what buys a finger-sized target - see the mobile rule below.
	 */
	width: 40px;
	height: 34px;
	margin: 0;
	padding: 0;
	border: none;
	border-radius: 0 2px 2px 0;
	background: #fff;
	color: #222;
	font-size: 2.8rem;
	font-weight: 400;
	line-height: 32px;
	text-align: center;
	letter-spacing: 0;
	text-transform: none;
	cursor: pointer;
	/* A × is a control, not content. Stops a double-tap selecting the glyph. */
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	-webkit-tap-highlight-color: rgba(0, 0, 0, 0.08);
}
.airport-clear.is-visible {
	display: block;
}
/* Matches the breakpoint on `#search-form .locations label`'s padding below. */
@media (min-width: 500px) {
	.airport-clear {
		right: 6px;
	}
}
/*
* Below 500px this is being hit with a thumb, so it gets the width it needs.
* The input is 36px tall and widening the form to reach a 44x44 target would be
* a layout change; 48 x 34 is 1632px2 against 44x44's 1936, in the corner of a
* control the thumb is already aimed at. The visible glyph is unchanged - the
* extra is hit area.
*/
@media (max-width: 499px) {
	.airport-clear {
		width: 48px;
		font-size: 3.2rem;
	}
	#search-form .locations input.airportPicker {
		padding-right: 50px;
	}
}
.airport-clear:hover,
.airport-clear:focus {
	border: none;
	background: #fff;
	color: #CE3A36;
}
/* A span with role="button" gets no focus ring of its own from the base rules. */
.airport-clear:focus {
	outline: 2px solid #2A72A8;
	outline-offset: -2px;
}
/*
* Keep the typed text from running under the ×.
*
* Applied ALWAYS, not only while the × is showing - the input is border-box so
* the field's outer width is unchanged, but the usable text area is 38px
* narrower at all times, including with JavaScript off when there is no × at
* all. That is the trade for not reflowing the text every time the button
* appears and disappears.
*/
#search-form .locations input.airportPicker {
	padding-right: 42px;
}
#search-form .locations input,
#search-form .dates input,
#search-form .extras input,
#search-form .extras select,
#search-form .extras button {
	width: 100%;
	height: 36px;
	line-height: 36px;
	font-size: 1.8rem;
	border: 1px #222 solid;
}
#search-form .locations input:focus,
#search-form .dates input:focus,
#search-form .extras input:focus,
#search-form .extras select:focus {
	box-shadow: 0px 0px 0px 3px rgba(79,160,215,1);
}

/*
* Fuzzy Results
*/
.fuzzyResults {
	position: absolute;
	display: none;
	border: 1px solid #ccc;
	background: #FFF;
	z-index: 1;
}
.__autoitem {
	padding: 5px 10px;
	font-weight: 400;
	color: #000;
	background-color: #e9f0f3;
	cursor: pointer;
	box-sizing: border-box;
}
.__autoitem:hover {
	background-color: #DDE6EB;
}
.__autoitem.selected{
	background: #2A72A8;
	/* Release item 10b. The text here is #000 from .__autoitem, and black on
	 * the darker blue is 4.07:1 - the one place the darkening pushed a passing
	 * element UNDER the bar. White gives 5.16:1. Audit finding. */
	color: #fff;
}


#search-form .dates,
#search-form .extras {
	display: inline-block;
	width: 100%;
}
@media (min-width: 750px) {
	#search-form .dates,
	#search-form .extras {
		width: 50%;
	}
}
#search-form .dates label {
	width: 50%;
	box-sizing: border-box;
	padding: 0 5px;
}

#search-form.oneway #search--return-date-label {
	display: none;
}
#search-form.oneway #search--depart-date-label {
	width: 100%;
}

/*
* BUGS.md P2-57 - this row collapsed, and not only on a phone.
*
* The three labels were 25% each with no rule of their own at any width, so
* they were only ever right when 25% of `.extras` happened to be wider than
* the word "Passengers:" - about 115px including the label's own padding.
* Where it was not, the captions were painted on top of one another (an
* inline-block does not clip) and the currency <select> was narrowed until it
* read "TH", so a visitor could not tell THB from USD, GBP or EUR on the
* site's primary conversion control.
*
* `.extras` is the full form width below 750px and HALF of it above - so the
* row got NARROWER at 750px than it was at 749px, and the same defect appears
* twice, in two separate bands:
*
*     width      .extras    25% - 10px padding   "Passengers:" fits?
*     390px       350px           78px           no  <- the reported case
*     500px       460px          105px           no, touching
*     600px       560px          130px           yes
*     750px       355px           79px           no  <- NOT in the register
*     1024px      492px          113px           no, touching
*     1280px      600px          140px           yes
*
* So it is written mobile-first: half and half with the button on its own row
* is the DEFAULT, and the one-row desktop arrangement applies only across the
* two bands where the captions provably fit. The register described 390px
* because 390px was the only width anyone had rendered; the 750-1039 band was
* found by rendering the rest of them.
*
* Thresholds measured, not derived - tests/verify-form-widths.js asserts at
* every boundary that the caption boxes do not intersect and that neither
* select is narrower than its own longest option.
*/
#search-form .extras label {
	width: 50%;
	box-sizing: border-box;
	padding: 0 5px;
}
#search-form .extras label#search--label-submit {
	width: 100%;
	color: #fff;
}
@media (min-width: 540px) and (max-width: 749px), (min-width: 1040px) {
	#search-form .extras label {
		width: 25%;
	}
	#search-form .extras label#search--label-submit {
		width: 50%;
	}
}
/*
* The word SEARCH used to be hidden below 500px, because the button was a
* quarter of a row and only the magnifier fitted. Wherever the button has a
* row to itself it can say what it does. (This was `display: none` plus a
* min-width:500px override putting it back; one rule replaces both.)
*/
#search-form .extras label#search--label-submit .submit-text {
	display: inline;
}
#search-form #search--submit {
	padding: 2px 15px;
	overflow: hidden;
	transition: all 0.1s linear;
}
#search-form #search--submit:hover {
	padding-right: 50px;
}
#search-form #search--submit i {
	display: inline-block;
	width: 20px;
	font-size: 1.5rem;
	transition: all 0.1s linear;
}
#search-form #search--submit:hover i {
	width: 0;
	opacity: 0;
	transform: translateY(-20px);
}
#search-form .poweredBy {
	position: absolute;
	top: 3px;
	right: 3px;
	width: auto;
	height: 38px;
	opacity: 1;
}

.Zebra_DatePicker_Icon_Wrapper {
	width: 100% !important;
	padding: 0 !important;
}

/*
*
* Content
*
*/
.content,
aside.sidebar {
	margin-top: 0px;
}
.content {
	padding: 0 20px;
}
@media (min-width: 750px) {
	.content,
	aside#sidebar {
		margin-top: 20px;
		margin-bottom: 60px;
		padding: 0;
	}
}
/* RELEASE ITEM 11d, PROPOSAL 2. BUGS.md P3-59.
   ⛔ THIS is the rule that governs article headings, not the one in
   skeleton-dft.css. Setting the weight there alone changed nothing - measured
   on a rendered h1, which still computed to 400 - because this selector is
   more specific. Both were changed.

   ⚠️ 700 AND NOT 600, AND THE REASON IS THE FONT LOADER RATHER THAN TASTE.
   The proposal sheet mocked 600. Read back from the page, the only Roboto
   weights this site loads are 400 and 700 (js/dft.js builds the request).
   Asking for 600 gets a browser-synthesised bold - a smeared 400 - or a snap
   to 700 depending on the engine. 700 is a weight that actually exists here.

   `line-height: 1.2` is REMOVED from this block, deliberately. It flattened
   all five levels to one ratio; the per-level values now come from
   skeleton-dft.css, where a 34px heading gets 1.15 and a 15px one gets 1.4. A
   large heading needs proportionally less leading than a small one, which a
   single ratio cannot express. */
.content h1,
.content h2,
.content h3,
.content h4,
.content h5 {
	/* RELEASE ITEM 11d, PROPOSAL 5. These margins were in `em`, so the gap a
	   heading left depended on the heading's own font size - 1.5em above an
	   h2 is 37.5px and above an h4 is 25.5px. That is where most of the
	   eleven distinct vertical gaps came from. They are `rem` now, so a gap
	   is a gap whatever the text around it is doing. */
	margin: 0 0 1.6rem 0;
	padding: 0;
	/* OWNER, 2026-08-19: "heading look cheap in red. remove the red rule".
	   Was #CE3A36 on every heading in the article column.

	   ⚠️ #222 RATHER THAN SIMPLY DELETING THE LINE, and that is a judgement
	   the owner should overrule if they disagree. Deleting it lets a heading
	   inherit the body's #555, which is the same colour as the paragraph under
	   it - so the only thing left marking a heading is its size and weight.
	   #222 is a dark ink, 15.9:1 on white, and it is a THIRD grey against
	   proposal 8's two. That is deliberate: proposal 8 was about accidental
	   near-duplicates (#444 vs #555, #666E76 vs #6B6B6B), not about refusing a
	   colour that does a job. Body #555, quiet text #6B6B6B, headings #222.

	   ⚠️ THIS SENTENCE HAS BEEN READ AS "BOTH PAIRS WERE FOLDED EVERYWHERE" AND
	   IT NEVER SAID THAT. Proposal 8 folded them in the article column, which is
	   all its measuring script could see - and until 2026-08-20 that script could
	   not see a ROUTE page at all, so two survivors sat there for a day. BUGS.md
	   P3-63 called both of them residue; release item 11k found only ONE of them
	   was. #666E76 is not retired - the palette header at the top of this file
	   names it the label grey and five .search-panel rules still use it. The pair
	   is folded where the two greys MEET, which is the article column. A
	   different surface may keep its own.

	   ⛔ LINKS KEEP THE BRAND RED. Only the heading rule was named, and red is
	   what marks a link in this article column. */
	color: #222;
	font-family: 'Roboto', sans-serif;
	font-weight: 700;
	clear: both;
}
.content h2 {
	/* The scale is 0.8 / 1.6 / 3.2 / 4.8rem. A section heading gets the
	   largest gap above it and the smallest below, because the space belongs
	   to the break between sections, not to the heading's own line. */
	margin: 4.8rem 0 1.6rem 0;
}
.content h3,
.content h4,
.content h5 {
	margin: 3.2rem 0 1.6rem 0;
}

/* ⛔ THE MEASURE CAP IS GONE. Owner, 2026-08-20, having been shown the numbers
   and having first chosen the other way: "no we still have a content area width
   and a text width. I've never seen a word wrap like that on other website.
   just make the text full width. it's readable."

   WHAT WAS HERE: item 11d proposal 7 capped running text at 66rem, and item 11s
   added the headings to that cap so the prose column read as one width. The
   owner has now seen both and wants neither - the text runs the column.

   ⚠️ THE COST IS RECORDED RATHER THAN ARGUED, because it was measured and put
   to them before they decided: lines go from 69-72 characters to **87-103**
   depending on the page, against a typographic comfortable range of 45-75. The
   worst case is a route page below 1,200px, where item 11i takes the sidebar
   out of the row and the column reaches 1,151px. **The owner's judgement, made
   with the figures in front of them.** BUGS.md P3-66 carries the numbers if it
   is ever revisited. */
.content p {
	margin: 0 0 1.6rem 0;
}

/* RELEASE ITEM 11d, PROPOSAL 5, and this half is what made the gap under a
   heading depend on WHAT FOLLOWED IT. skeleton-dft.css gives every table,
   list, form and blockquote `margin-bottom: 2.5rem` while a paragraph here
   had 1em - so a heading followed by a paragraph left 15px and the same
   heading followed by a list left 30px. One value for all of them. */
.content ul,
.content ol,
.content table,
.content blockquote,
.content dl,
.content figure {
	margin-bottom: 1.6rem;
}

.content a {
	color: #CE3A36;
}
.content a:hover {
	color: #000;
}

/* RELEASE ITEM 11d, PROPOSAL 5: `1em` here rendered 17px, one off the scale,
   for the same reason every other em margin did. */
.content .button {
	display: block;
	margin: 1.6rem auto;
	text-align: center;
	color: #fff;
	background-color: #CE3A36;
	border-color: #CE3A36;
}
.content .button:hover {
	color: #CE3A36;
	background-color: #fff;
}
/*
* Tables
*/
.content .table-cont {
	margin: 40px 0 20px 0;
	overflow-x: auto;
}
.content .table-cont table {
	margin-bottom: 0;
}


/* OWNER, 2026-08-19, item 11f: "tables (no class) heading have too much
   vertical cell padding and normal rows don't seem to have enough."

   Measured before the change, on a real airport page: a header cell stood 55px
   tall on 15px of vertical padding, an ordinary cell 35px on 5px. The header
   was 57% taller than the rows under it, and it was the same two rules for
   every table on the site - the baggage tables, the airport tables and the
   schedules table all use them.

   Both are 12px now, so a header is marked out by being red and white rather
   than by being fatter, and a row has room to breathe. Row height lands at
   ~45px, which also clears the 44px touch guidance for the rows that carry
   links.

   ⛔ AND A SECOND FAULT FELL OUT OF MEASURING IT: the header's first cell was
   inset 15px from the left and the body's first cell only 8px, so the column
   heading and its own data did not line up - by 7px, on every table on the
   site. Both are 1.6rem now. Nobody reported this one; it was found by reading
   the two rules next to each other. */
.content table th {
	padding: 1.2rem 1rem;
	font-size: 1.5rem;
	color: #fff;
	background-color: #CE3A36;
}
.content table th:first-child,
.content table td:first-child {
	padding-left: 1.6rem;
}
.content table tr:hover {
	background-color: #FBFBFB;
}
.content table tr button {
	visibility: hidden;
	padding: 6px 15px;
	color: #CE3A36;
	border-color: #CE3A36;
}
.content table tr:hover button {
	visibility: visible;
	color: #CE3A36;
	border-color: #CE3A36;
}
@media (hover: none) {
	table tr button {
		visibility: visible !important;
	}
}
.content table tr:hover button:hover {
	color: #ffffff;
	background-color: #CE3A36;
}
/* RELEASE ITEM 11d, PROPOSAL 4: 1.4rem was off the scale, and 43 table
   cells on the pages surveyed carried it. 15 is the nearest step up; the
   rule for a tie or a near-tie is round UP, because the reason to have a
   scale is legibility and 14 -> 13 would have made small text smaller.
   ⚠️ PADDING IS NOT TOUCHED HERE - table padding is release item 11f, which
   the owner queued separately, and 5px is exactly what they will want to
   look at. */
/* item 11f: 5px of vertical padding, against the header's 15px. Both 12px now
   - see the note above the th rule. */
.content table td {
	padding: 1.2rem 1rem;
	font-size: 1.5rem;
}
@media (min-width: 750px) {
	table td.logo_holdr {
		padding: 0;
	}
}
@media (min-width: 950px) {
	table td.logo_holdr {
		padding: 5px 8px;
	}
}
.content table .airport {
	margin: 10px 0 0 0 ;
	line-height: 1.4;
}
.content table .airline {
	font-weight: 700;
	text-decoration: none;
	line-height: 1.4;
}
.content table .airline:hover {
	color: #CE3A36;
	border-bottom: 1px #CE3A36 solid;
}
.content table .times {
	color: #CE3A36;
}
.content table .price {
	line-height: 1.4;
}

/* ⛔ THE DAY COLUMNS ARE CENTRED, HEADER AND FARE ALIKE. Owner, 2026-08-20:
   "center the prices or the table headers for the days of the week (at least
   make them consistently aligned)".

   They were not aligned with each other at all: the `th` and `td` inherited
   `text-align: left` while `.content table .price` set `text-align: right` on
   the div INSIDE the cell. Measured on the rendered page - the "Mon" heading
   started at x=318 and the fare under it ended at x=379, in a cell spanning
   318-389. Every column had a heading down its left edge and a number down its
   right, which is what the owner saw.

   ⚠️ Scoped by `[data-day]`, not by `.price`. Those attributes are on exactly
   the seven fare columns of the schedules table and nowhere else, so this
   cannot reach the airline pages' tables or the home page's route list - and it
   moves the heading and the figure together, by construction, rather than by
   two rules that have to be kept in step. */
#table--schedules th[data-day],
#table--schedules td[data-day],
#table--schedules td[data-day] .price {
	text-align: center;
}
.content table .logo {
	display: block;
	width: 64px;
	height: 64px;
	border-radius: 6px;
}
@media (min-width: 750px) {
	table .logo {
		display: none;
	}
}
@media (min-width: 950px) {
	table .logo {
		display: block;
	}
}
.content table a:hover .logo {
	transform: scale(1.03);
}








/*
*
* Sidebar
*
*/
aside#sidebar {
	padding: 0;
}
@media (min-width: 750px) {
	aside#sidebar {
		padding-left: 50px;
	}
}
#sidebar h1,
#sidebar h2,
#sidebar h3,
#sidebar h4,
#sidebar h5,
.slidebar h1,
.slidebar h2,
.slidebar h3,
.slidebar h4,
.slidebar h5 {
	margin-top: 0em;
	padding: 0;
	color: #CE3A36;
	font-family: 'Roboto', sans-serif;
	font-weight: 400;
	line-height: 1.2;
}


aside h2,
aside h3,
#subfoot h2,
#subfoot h3 {
	position: relative;
	display: block;
	margin: 0px 0 5px;
	padding-bottom: 20px;
	padding-left: 20px;
	font-family: 'Roboto', sans-serif;
	text-align: left;
	font-weight: 400;
	text-transform: uppercase;
}
aside .airports {
	margin: 0 0 40px 0;
	background-color: #D8E8F1;
	border: 1px #CCCCCC solid;
}

aside #airports .title,
aside #destinations .title {
	background: url(../img/bg-news.jpg) #fff no-repeat center;
	-webkit-background-size: cover;
	-moz-background-size: cover;
	-o-background-size: cover;
	background-size: cover;
	padding-bottom: 30px; /* release item 10c - was 50px */
}
aside #destinations .title {
	margin-top: 30px;
	background-image: url(../img/bg-travel.jpg);
}
/*
* RELEASE ITEM 10c - the picture header, shortened.
*
* This h2's bottom margin and the .title's bottom padding are together the only
* thing holding the photograph open: the h2 sits on the red band at the top of
* the block and the image is the .title's background, so the visible strip of
* photograph is exactly those two numbers added up. It was 70 + 50 = 120px on
* each of three blocks. It is now 40 + 30 = 70px, which is 150px off the
* sidebar and still shows the picture rather than a texture.
*/
aside #airports h2,
aside #destinations h2 {
	margin: 0px auto 40px auto; /* bottom space for image - was 70px, release item 10c */
	padding: 0 0 0 15px;
	color: #fff;
	font-size: 1.8rem;
	line-height: 4.2rem;
	background-color: #CE3A36;
}
aside .articles ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
aside .articles ul li {
	margin: 0;
}
aside .articles ul li a {
	display: block;
	margin: 0;
	padding: 0.8em 15px;
	text-align: left;
	font-size: 1.5rem;
	color: #636363;
	line-height: 1.2;
	background-color: #D8E8F1;
	border-bottom: 1px #fff solid;
	text-decoration: none;
	
    transition: all 0.1s ease-in;
    -ms-transition: all 0.1s ease-in;
    -moz-transition: all 0.1s ease-in;
    -webkit-transition: all 0.1s ease-in;
}
aside .articles ul li a.more {
	padding: 0.5em 1em;
	text-align: right;
}
aside .articles ul li a:last {
	border: none;
}
aside .articles ul li a:hover {
	background-color: #E1EAEF;
	color: #CE3A36;
	border-bottom: 1px #eee solid;
}

aside #links i {
	display: block;
	position: relative;
	line-height: 50px;
	margin: 0 auto 20px auto;
	font-size: 3.0rem;
	color: #fff;
	text-align: center;
	
	/* diamond section */
	width: 50px;
	height: 50px;
	vertical-align: middle;	
}




/*
* Index only
*/
.stripes * {
	position: relative;
	z-index: 1;
}  
.stripes:before {
	position: absolute;
	right: 0px;
	left: 0px;
	top: 0px;
	bottom: 0;
	content: ' ';
	z-index: 0;
	
	/* https://leaverou.github.io/css3patterns/#diagonal-stripes */
	background-image:
		repeating-linear-gradient(45deg, transparent, transparent 12px, 
		rgba(255,255,255,.1) 12px, 
		rgba(255,255,255,.1) 13px);
	/* grid
	background-image: 
		linear-gradient(rgba(255,255,255,.1) 2px, transparent 2px),
		linear-gradient(90deg, rgba(255,255,255,.1) 2px, transparent 2px),
		linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
	background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
	background-position:-2px -2px, -2px -2px, -1px -1px, -1px -1px;
	*/
	box-shadow: inset 0px 0px 100px rgba(0,0,0,0.3);
}	  
.stripes.strong:before {
	background-image:
		repeating-linear-gradient(45deg, transparent, transparent 12px, 
		rgba(255,255,255,0.8) 12px, 
		rgba(255,255,255,0.8) 13px);
}


.pages {
	position: relative;
	margin: 0px 0px 0 0;
	padding: 70px 50px 30px;
	background-color: #E5F5FF;
	/*background: url("../img/bg-sky-wing.jpg") transparent no-repeat center;*/
	-webkit-background-size: cover;
	-moz-background-size: cover;
	-o-background-size: cover;
	background-size: cover;
}
.pages__cont {
	max-width: 1000px;
	margin: 0 auto;
	padding: 0;
}
@media (min-width: 750px) {
	.pages__cont {
		padding: 0 50px;
	}
}
.page__details {
	margin-bottom: 50px;
}
.pages__icon {
	width: 60px;
	margin: 0px 0 0 0;
	float: left;
}
.pages__icon i {
	display: block;
	width: 45px;
	height: 45px;
	line-height: 45px;
	margin: 5px 0;
	font-size: 2.0rem;
	color: #fff;
	text-align: center;
	border-radius: 50%;
	background-color: #CE3A36;
}
.pages__icon i.icon-airplane {
	transform: rotate(90deg);
}
.pages__text {
	padding: 0 0 0 80px;
}
.pages__text h2 {
	margin: 0 0 0.5em 0;
	font-size: 2.2rem;
	color: #000;
}
.pages__text p {
	margin: 0 0em 1em 0;
	color: #000;
	font-size: 1.5rem;
}
@media (min-width: 750px) {
	.pages__text p {
		margin: 0 5em 1em 0;
	}
}
.pages__text a {
	font-size: 1.5rem;
	color: #000;
	transition: all 0.1s linear;
	overflow: hidden;
}
.pages__text a:hover {
	padding-right: 30px;
	background-color: #D9E7F0;
}
@media (min-width: 750px) {
	.pages__text a:hover {
		padding-right: 50px;
	}
}
.pages__text a i {
	display: none;
	width: 20px;
	transition: all 0.1s linear;
}
@media (min-width: 750px) {
	.pages__text a i {
		display: inline-block;
	}
}
.pages__text a:hover i {
	width: 0;
	opacity: 0;
	transform: translateY(-20px);
}



#index__text {
	padding: 0px 0 20px;
}

.features {
	position: relative;
	margin: 0px 0 0px 0;
	padding: 30px 50px 10px;
	color: #fff;
	background-color: #CE3A36;
}
.features__title {
	margin: 30px auto;
	max-width: 900px;
}
.features__title h2 {
	padding: 0 50px;
	font-size: 3.8rem;
	text-align: center;
}
.features__title h2 span {
	display: block;
	font-size: 1.8rem;
	line-height: 1.8;
}
.features__title p {
	font-size: 2rem;
	text-align: center;
	line-height: 1.4;
}
.features__cont {
	max-width: 1020px;
	margin: 0 auto;
}
/* Release item 10b, and it is the ribbon fold again: these discs sit ON the
 * red band, and they used to be #FF7071 against a #FF5556 band. Folding the
 * reds into one made the disc the same colour as the thing it sits on, so it
 * vanished. #A82F2B is the same darker red the fold uses. Audit finding, and
 * the fold was hand-fixed while this one was missed - a search for "what else
 * did two different colours become one on top of" is the check that would
 * have found both. */
.features__cont i {
	display: block;
	font-size: 4.5rem;
	margin: 30px 0;
	border-radius: 50%;
	height: 45px;
	line-height: 45px;
	width: 45px;
	text-align: center;
	background-color: #A82F2B;
}
.features__cont h3 {
	line-height: 1;
	font-weight: 700;
}
.features__cont p {
	font-size: 2.0rem;
}
.features__cont .first i,
.features__cont .first h3,
.features__cont .first p,
.features__cont .third i,
.features__cont .third h3,
.features__cont .third p {
	transform: scale(0.85);
	transform-origin: top left;
}


.callout {
	width: 100%;
	margin: 0px 0 50px;
	background-color: #e9f0f3;
}
.callout p {
	max-width: 900;
	margin: 0 auto;
	padding: 40px 15%;
	font-size: 3.1rem;
	text-align: center;
	line-height: 1.4;
}




#index__routes.container {
	max-width: 1200px;
	margin: 0 auto;
	padding: 50px 30px;
}
#index__routes h2 {
	margin: 0 10px 20px 10px;
	text-align: center;
}
#index__routes ul {
	list-style-type: none;
}
#index__routes li {
	padding-left: 3em;
}
#index__routes a {
	display: block;
	text-decoration: none;
	transform-origin: center left;
}
#index__routes a:hover {
	transition: transform 0.1s;
	transform: scale(1.05);
}
#index__routes a h5 {
	color: #CE3A36;
	margin: 10px 0 0px 0;
	font-size: 1.8rem;
	transition: transform 0.05s;
}
#index__routes a h5 .route {
	display: block;
	padding-right: 50px;
}
#index__routes a h5 .route:after {
	display: inline-block;
	content: '\00bb';
	margin-right: -30px;
	padding-left: 0.2em;
	font-size: 2.8rem;
	transition: transform 0.2s;
	transform: scale(0);
}
#index__routes a:hover h5 .route:after {
	transform: scale(1);
}
#index__routes a .price {
	color: #2A72A8;
}
#index__routes .icon-plane {
	display: inline-block;
	padding-bottom: 1em;
	font-size: 1.5em;
	color: #555;
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
    transform: rotate(90deg);
}
#index__routes .icon-plane.return {
	padding-bottom: 0;
    -webkit-transform: rotate(-90deg);
    -moz-transform: rotate(-90deg);
    -o-transform: rotate(-90deg);
    -ms-transform: rotate(-90deg);
    transform: rotate(-90deg);
}

/*
* Airline logos sub footer
*/
#section__airline-logos {
	position: relative;
	padding: 60px 0 60px;
	background-color: #fff;
	text-align: center;
}
#section__airline-logos h3 {
	margin:  0 0.5em 60px;
	font-size: 3.2rem;
}
#section__airline-logos a {
	display: inline-block;
	margin: 0 30px 30px 30px;
	cursor: pointer;
}
#section__airline-logos img {
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
	background: #fff;
	border-radius: 6px;
}
#section__airline-logos:hover img:hover {
	box-shadow: 0 2px 20px rgba(0, 0, 0, 0.4);
	filter: none;
	-webkit-filter: grayscale(0);
}


/*
* Index pages load more button
*/
.show_more_main {
	margin: 15px 25px;
}
/* RELEASE ITEM 11d, PROPOSAL 4: 12px, in px where the rest of the sheet uses
   rem, and the only two 12px values left in the content column. 1.3rem is the
   scale's bottom step and renders 13px. */
.show_more {
	background-color: #f8f8f8;
	background-image: -webkit-linear-gradient(top,#fcfcfc 0,#f8f8f8 100%);
	background-image: linear-gradient(top,#fcfcfc 0,#f8f8f8 100%);
	border: 1px solid;
	border-color: #d3d3d3;
	/* RELEASE ITEM 11d, PROPOSAL 8: five greys down to two - #555 for text, #6B6B6B for quiet secondary text. */
	color: #555;
	font-size: 1.3rem;
	outline: 0;
}
.show_more {
	display: block;
	padding: 10px 0;
	text-align: center;
	font-weight: bold;
	cursor: pointer;
}
.show_more.hide {
	display: none;
}
.loading {
	display: none;
	padding: 10px 0;
	/* RELEASE ITEM 11d, PROPOSAL 8: five greys down to two - #555 for text, #6B6B6B for quiet secondary text. */
	color: #555;
	font-size: 1.3rem;
	text-align: center;
	outline: 0;
	font-weight: bold;
	background-color: #e9e9e9;
	border: 1px solid #c6c6c6;
}
.loading.show {
	display: block;
}
.loading_txt {
	border: 0;
	display: inline-block;
	height: 16px;
	padding-left: 20px;
}





#popular-destinations {
	padding: 70px 50px;
	background-color: #e9f0f3;
}
#popular-destinations .holdr {
	position: relative;
	width: 100%;
	height: 0;
	padding-bottom: 100%;
	overflow: hidden;
}
#popular-destinations .holdr img {
	width: 100%;
	height: auto;
}
#popular-destinations .holdr:hover {
	
}
#popular-destinations .text {
	position: absolute;
	left: 0;
	bottom: 0; right: 0;
	padding: 2em 1em 1em 1em;
	text-align: left;
	color: #fff;
	
	-moz-box-shadow: inset 0 -10px 10px -10px #000000;
	-webkit-box-shadow: inset 0 -10px 10px -10px #000000;
	box-shadow: inset 0 -90px 90px -90px #000000;
}
#popular-destinations .text h5 {
	margin: 0;
	border-bottom: 1px #fff solid;
}
#popular-destinations .text p {
	margin: 0;
}
#popular-destinations .text p:after {
	content: ' >';
}


/*
* Cards
*/
.card {
	position: relative;
	display: inline-block;
	float: left;
	
	width: 100%;
	margin-right: 0%;
	margin-bottom: 40px;
	
	text-decoration: none;
	background-color: #fff;
	box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
	transition: all 0.3s cubic-bezier(.25,.8,.25,1);
	box-sizing: border-box;
}
@media (min-width: 400px) {
	.card:not(.full-width) {
		width: 46%;
		margin-right: 4%;
	}
}
@media (min-width: 550px) {
	.card:not(.full-width) {
		width: 29%;
		margin-right: 1.5%;
		margin-right: 1.5%;
	}
}
@media (min-width: 750px) {
	.card:not(.full-width) {
		width: 46%;
		margin-left: 2%;
		margin-right: 2%;
	}
}
@media (min-width: 950px) {
	.card:not(.full-width) {
		width: 29%;
		margin-right: 2.3%;
	}
}
@media (min-width: 1200px) {
	.card:not(.full-width) {
		width: 23%;
		margin-left: 1%;
		margin-right: 1%;
	}
}
/* different responsive layout for full width template */

@media (min-width: 450px) {
	.card.full-width {
		width: 46%;
		margin-left: 2%;
		margin-right: 2%;
	}
}
@media (min-width: 900px) {
	.card.full-width {
		width: 23%;
		margin-left: 1%;
		margin-right: 1%;
	}
}





a.card:hover {
	/* hover effect on <a> only */
	opacity: 0.9;
	box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
}
.card.no-hover:hover {
	opacity: 1;
	box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
}
.card img {
	position: relative;
	display: block;
	width: 100%;
	height: auto;
}
.card:after {
	content: '';
	display: block;
	height: 100%;
	position: absolute;
	top: 0;
	width: 100%;
	-webkit-box-shadow: inset 0px 60px 55px -70px rgba(100,100,100,0.5);
	-moz-box-shadow: inset 0px 60px 55px -70px rgba(100,100,100,0.5);
	box-shadow: inset 0px 60px 55px -70px rgba(100,100,100,0.5);
	transition: all 0.3s;
}
.card:hover:after {
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
	box-shadow: none;
}
.card .text {
	padding: 15px 15px 0 15px;
	border-bottom: 15px #F4F4F4 solid;
	background-color: #F4F4F4;
	height: 58px;
	overflow: hidden;
}
.card h3,
/* RELEASE ITEM 11d, PROPOSAL 4. This selector was declared TWICE in a row -
   1.8rem, then 1.6rem overriding it three lines later - so the first size
   had never applied to anything. Both were off the six-step scale; one
   declaration now, at the nearest step. */
.card h4 {
	margin: 0 0 0.25em 0;
	padding: 0px;
	font-size: 1.7rem;
	/* RELEASE ITEM 11d, PROPOSAL 8: five greys down to two - #555 for text, #6B6B6B for quiet secondary text. */
	color: #555;
}
.card:hover h3,
.card:hover h4 {
	color: #CE3A36;
}
.card h3 a,
.card h4 a {
	text-decoration: none;
}



/* --------------------------------------------------------------------------
   ITEM 11p - THE PHOTOGRAPHS ARE 16:9 WINDOWS.

   Owner, 2026-08-20: "the airport images are too square and we have to scroll
   too much. Can you put them in a container so they are full width and crop the
   top and bottom so they are 16:9?" and then "Do the image cropping on all
   pages".

   ⚠️ "TOO SQUARE" IS 3:2, AND THE SCROLLING IS THE REAL COST. Measured before:
   the hero on an airport page was 700x467 - 1.50, capped at 700px inside an
   862px column - and the picture on a card was 304x361, which is TALLER THAN
   WIDE. That last one is not a design choice, it is a defect: the markup
   carries `width="190" height="226"` on a source image that is 300x200, so
   until the file arrives the browser reserves a portrait box for a landscape
   picture. Nine cards down a page, that is most of a screen of scrolling spent
   on a shape nobody chose.

   ⛔ THE CROP IS `object-fit: cover`, NOT A NEW SET OF FILES. Every picture is
   already served at 300x200, 700x467 or 1200x630; re-cutting them to 16:9 would
   mean regenerating the whole library, a deploy step, and a second copy of
   every file. The browser does the crop for nothing, and `object-position:
   center` keeps the middle of the frame. ⚠️ That it is the RIGHT part of the
   frame is an assumption, not a measurement - the derivatives are already
   centre-cropped once, and nobody has looked at all 91 of them for a subject
   that sits high or low. An audit round asked; it is on the register.

   ⚠️ IT IS THE PHOTOGRAPHS, NOT "EVERY PICTURE ON THE SITE", and an earlier
   draft of this header said the second thing. What these three selectors reach:
   the featured image on airport, airline, guide, article and news pages; the
   index cards; the guide and news list thumbnails; and the related-content and
   sub-footer cards. What they do NOT reach, all deliberately: a picture written
   into a page's BODY through the CMS (cropping a diagram or a portrait would be
   wrong), and the home banner and sidebar photographs, which are CSS
   backgrounds already using `background-size: cover`.

   ⚠️ THE FALLBACK IS NOT "WHAT IT DOES TODAY" EITHER, WHICH IS THE OTHER THING
   THAT DRAFT GOT WRONG. A browser with no `aspect-ratio` ignores it, so the
   cards and thumbnails keep their old loaded shape - but the featured image
   does not, because this rule also drops its `max-width: 700px`: it would show
   at about 862x575 instead of 700x467. The alternative - a wrapper div and the
   padding-top trick - works everywhere, and needs new markup in four page
   templates plus six image strings in constants-html-templates.php, for a case
   measured at nobody.

   ⛔ AND IT FIXES A LAYOUT SHIFT AS A SIDE EFFECT. A fixed ratio in CSS beats
   the wrong `width`/`height` attributes, so the space is reserved correctly
   before the file arrives. ⚠️ The old shift was about **159px** - a 304px card
   reserved 362px from the 190x226 attributes and settled at 203px once the
   300x200 file arrived. An earlier draft said 190px, which is the gap between
   the wrong box and the new one, not the collapse. **The attributes are still
   wrong**; this hides the symptom rather than curing it, and fixing them is on
   the register. ⚠️ There is no print override, so the crop applies on paper too.
   -------------------------------------------------------------------------- */
.content img.featured {
	display: block;
	/* The owner asked for full width. It was capped at 700px inside a column
	   that is 862px at 1440 and 753px at 1200, so the hero was the one thing on
	   the page that stopped short of the measure everything else uses. */
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	object-position: center;
	/* RELEASE ITEM 11d, PROPOSAL 5: 30px -> 32px, onto the 0.8/1.6/3.2/4.8rem scale */
	margin: 3.2rem auto;
}
/* The card pictures and the list thumbnails. `width` is deliberately NOT set
   here - the card's is already 100% and the list thumbnail is sized by its own
   layout; all these two need is the shape. */
.card img,
.all_items .item img {
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	object-position: center;
}

/*
* RELEASE ITEM 9 - the related-links block runs the full twelve columns, below
* the sidebar, instead of being squeezed into the eight the body uses. It was
* 753px wide at a 1,200px viewport; it is now the width of the container.
*
* THE DESKTOP HALF NEEDS NO RULE HERE AT ALL, and that is worth writing down
* because the obvious rule is wrong. The block carries `twelve columns`, which
* skeleton-dft.css makes `width:100%; margin-left:0`. A float that needs the
* whole row cannot be placed beside the 65.3% body and the 30.7% sidebar at any
* height, so it drops below both on its own. `clear: both` was written here
* first and then deleted: removing it changed no pixel, and a guard whose
* removal is invisible is not a guard.
*
* It does move down by ~80px on a page whose body already reached past the
* sidebar - the eight-column's own 60px bottom margin plus the 20px top margin
* this block gains by taking `.content`. Clearance is measured against margin
* edges. That is spacing, not a gap.
*
* THE MOBILE HALF DOES NEED A RULE, AND WITHOUT IT THE MOVE IS A REGRESSION.
* Below 750px Skeleton has no columns at all - every `.columns` is width:100%
* and the page is one stack in source order. This block has to come AFTER the
* sidebar in the source (a float's top may not be higher than the top of an
* earlier block-level box, so putting it first would push the sidebar under
* it), which on a phone would put three site-wide lists between the article and
* the links about the page being read. The three `order` values below restore
* exactly today's phone order: body, related links, sidebar.
*
* The flex is declared plainly and switched OFF at min-width:750px, rather than
* written as max-width:749px. That reuses Skeleton's own breakpoint, so there
* is no fractional viewport width at which neither rule applies.
*
* `.row:after`, Skeleton's clearfix, becomes a flex item here with the default
* order 0 and therefore sorts first. It is empty, zero-height and has no
* margin, so it is invisible - and the three elements named below are the only
* other children the five templates put in this row.
*/
.page-row {
	display: flex;
	flex-direction: column;
}
@media (min-width: 750px) {
	.page-row {
		display: block;
	}
}
.page-row > .columns.eight {
	order: 1;
}
.page-row > #related-content {
	order: 2;
}
.page-row > #sidebar {
	order: 3;
}

/* --------------------------------------------------------------------------
   ITEM 11i - THE SCHEDULES TABLE IS CUT OFF ON A TABLET.

   Owner, 2026-08-19: "the schedules table on tablet seems to be cut off before
   necessary - side bar isn't disappearing early enough." BUGS.md P3-50.

   ⚠️ RE-MEASURED AFTER ITEM 11g REMOVED TWO COLUMNS FROM THAT TABLE, because
   the report predates that change. It did not fix this. Measured in the layout
   as it then was - a 482px article column at 768 - the 82 tables' own minimum
   widths ran from 531px to 688px, every one of them wider than the column they
   were in. That column is 642px at 1024 and 690px at 1100.

   ⚠️ THE TABLE'S MINIMUM IS NOT ONE NUMBER, IT STEPS - and the step is ONE
   CELL. `td.logo_holdr`, the airline-logo column, has no right padding between
   750 and 949 and 8px from 950 up (the `min-width: 950px` block by the logo
   rules, further down this file). An ordinary day cell does not move: 10px each
   side at both widths, measured. So the same table is 686px at 768 and 694px at
   1024. Two earlier drafts of this paragraph got this wrong - one put the step
   "above 1,000px", the next blamed `.content table td` generally - and an audit
   round caught each. It matters because the figure the breakpoint has to clear
   is the LARGER one, which is why the harness sweeps two widths.

   ⚠️ SO THE BAND IS NOT UNIFORM, and an earlier draft of this comment said it
   was. At 768 the column is narrower than the narrowest of the 82 tables, so
   EVERY route page is cut off. Higher up the band the narrow tables start
   fitting one by one, and the widest - /bangkok-to-koh-samui, whose fares run
   to five digits - is the last, at a 1,120px viewport. "Some route page is cut
   off at every width from 750 to 1,119" is the true statement; "every route
   page is cut off across that band" is not.
   ⚠️ Do not read a single width for that table off this comment. It is 686px at
   768 and 694px at 1,024 for the reason above, and the harness prints the
   figure it actually used. ⚠️ Both of those are measured on a FINISHED page. The
   harness read 688 and 696 while it was still using `domcontentloaded`; it
   waits for `load` now. ⚠️ That the cause is the late Montserrat webfont is the
   obvious reading and is NOT measured - what was measured is that the figure
   moves by two pixels and then settles.

   ⛔ ROUTE PAGES ONLY, AND THAT IS MEASURED. An airport page, an airline page,
   /travel-guide, /news and the home page were each checked at 768, 900 and
   1024 for an element whose content is wider than its own clipping box. The
   only hit besides this table was `label.main-menu-btn`, whose clipped content
   is the words "Toggle main menu visibility" - an accessible name on an
   icon-only button, clipped on purpose. It appeared on every page and width in
   that sample, including the ones this item does not touch, which is what makes
   it noise rather than a finding.
   ⚠️ THAT IS FIVE TEMPLATES AT THREE WIDTHS, NOT A PROOF ABOUT THE WHOLE SITE.
   It is enough to decide the scope question and it is not more than that.
   Widening the breakpoint for the other page types would be changing layouts
   nobody reported, which is the mistake item 10d was stopped for.

   WHAT IT DOES: keeps the single-column stack that item 9 already built for
   phones (the flex block above) up to 1,199px on route pages, instead of
   handing 30% of the row to the sidebar while the main content is cut off.
   The order is item 9's: article, related links, sidebar.

   ✅ AND IT COSTS NO LINE LENGTH, which was the obvious objection. Body copy is
   capped at max-width 660px by item 11d, so widening the article does not
   lengthen a single line: measured at 768, 1024, 1100, 1200 and 1440, the
   paragraph width is 660px at all five.

   ⚠️ EVERY SELECTOR HERE OUT-SPECIFIES WHAT IT OVERRIDES rather than tying it
   and winning on source order - a stylesheet reorder would otherwise silently
   restore the two columns. `.page-row.page-row--schedules` (0,2,0) beats
   `.page-row` (0,1,0); adding `> .columns` (0,3,0) beats skeleton-dft.css's
   `.eight.columns` / `.four.columns` (0,2,0); and the sidebar's padding is
   reset through `aside#sidebar` (1,2,1) because `aside#sidebar` alone is
   (1,0,1) and no class selector can beat an id.

   ⚠️ 1,200px RATHER THAN THE 1,120px THE MEASUREMENT GIVES, AND THE MARGIN IS
   THE POINT. 1,120 is where the widest table today first fits beside the
   sidebar - with EIGHT PIXELS to spare, measured. Eight pixels is not a margin.
   The table's width is decided by content as well as by CSS: automatic table
   layout will not take a column below the widest unbreakable run of text in it,
   which for a fare column is the figure itself ("1,497", not "1,497 THB" - that
   wraps at the space) and for the first column is the longest word in an
   airport name. Both are collected weekly. A fare gaining a digit in the column
   that is already the widest would put the reported fault back on a page nobody
   is looking at. At 1,200 the same table has 59px to spare. The band it costs
   is 1,120-1,199, where a route page is one column that would have fitted two.

   ⚠️ AND THE MARGIN IS HELD BY A CHECK RATHER THAN TRUSTED.
   tests/verify-item11i-tablet-table.js sweeps all 82 pages at two widths for a
   cut-off table and for clipped cell text, then walks the band on whichever
   table is widest and prints the remaining slack at 1,200 - so the 59px above
   can be re-read rather than believed. ⚠️ It SAMPLES the band (750, 768, 900,
   1024, 1119, 1199) on that one page; it does not test all 82 at all widths.
   -------------------------------------------------------------------------- */
@media (max-width: 1199px) {
	.page-row.page-row--schedules {
		display: flex;
		flex-direction: column;
	}
	.page-row.page-row--schedules > .columns {
		width: 100%;
		margin-left: 0;
	}
	/* The 50px indent is there to separate the sidebar from the article beside
	   it. Stacked, there is nothing to its left to separate it from. */
	.page-row.page-row--schedules > aside#sidebar {
		padding-left: 0;
	}
}

/*
* Related content
*/
/* RELEASE ITEM 11d, PROPOSAL 5: 30px -> 32px. This is the last of the six
   near-32 values that made the gap under a heading look arbitrary. */
#related-content h2 {
	margin-bottom: 3.2rem;
}

/* --------------------------------------------------------------------------
   ITEM 11k-a - THE GAP UNDER THE SCHEDULES TABLE. Owner, 2026-08-21: "there's
   way too big a smal on desktip under the scedule table."

   ⚠️ MEASURED AT 1440 BEFORE ANYTHING WAS CHANGED, because the cause is three
   separate margins stacking and none of them looks wrong on its own:

     disclaimer ends 10284 -> "Airports on this route" heading at 10448 = 164px
       16px  the paragraph's own bottom margin
       60px  `.columns` bottom margin, on the article column
       20px  `.content` top margin, on #related-content
       20px  `.content` top margin AGAIN, on the .five/.seven columns inside it
       48px  the global `h2` top margin

     the chips end 10596 -> "Related travel guide articles" at 10720 = 124px
       60px  `.columns` bottom margin on the inner column
       48px  the global `h2` top margin

   ⛔ THE DOUBLE APPLICATION IS THE ACTUAL DEFECT. `#related-content` is a
   `.columns` block that CONTAINS a `.row` of more `.columns`, so the grid's
   outer margins are applied twice to the same nesting - once by the wrapper
   and once by each child. That is not a spacing preference, it is the same
   rule running on both levels.
   -------------------------------------------------------------------------- */
#related-content .row > .columns {
	margin-top: 0;
	margin-bottom: 1.6rem;
}
/* The container already carries the separation; a heading sitting at the top
   of one must not add a second. ⚠️ NOT `h2 { margin-top: 0 }` for every h2 in
   the block - the one that follows a finished row is a new section and needs
   the break, which is the rule below it. */
#related-content .row > .columns > h2:first-child {
	margin-top: 0;
}
/* ⚠️ 3.2rem, AND IT IS MEASURED AGAINST THE OTHER BREAK RATHER THAN CHOSEN.
   The gap above the FIRST heading is fixed at 76px by the article column's own
   60px bottom margin, which is the site's section rhythm and is not this
   item's to change. So the second break is set to land at 72px from the last
   chip - 16 from the list, 16 from the column, 8 from the item, 32 here - and
   the two reads as one decision instead of two. */
#related-content > h2 {
	margin-top: 3.2rem;
}
.page-row > #related-content {
	margin-top: 0;
}
#related-content ul {
	list-style-type: none;
}

/* OWNER, 2026-08-19, item 11e2 follow-up: "the wall of buttons. I think we can
   put the buttons a bit closer together and also lose a bit of vertical
   padding."

   ⛔ THE PADDING WAS NOT WHERE THE SPACE WAS, AND MEASURING SAID SO BEFORE ANY
   OF THIS WAS WRITTEN. Each chip stood 45px tall while the rows sat 76-77px
   apart - so 31px of every row was empty, more than the 22px of padding inside
   the chip. Cutting padding alone would have shaved 8px off a 77px pitch and
   the wall would have looked the same.

   The dead space came from the `li` being `display: inline`: the chips are
   inline-block boxes sitting in an inline run, so the line box carried a strut
   and the leading around it that nothing here wanted. `inline-block` on the
   `li` takes the row pitch back to "chip height plus the margin I asked for".

   ⚠️ AND THIS IS THE THIRD ATTEMPT AT THIS BLOCK. The 4b.2 restyle was built,
   shown to the owner and REJECTED on the live pages - "still reading as an
   inline run, LARGER than before rather than smaller, overlapping". So two
   things were measured rather than eyed, on the real page at four widths:
   whether the block got SMALLER, and whether any two chips OVERLAP. It is not a
   flex grid, which is what 4b.2 tried; inline-block is one step from what was
   there and cannot overlap in normal flow.

   Vertical padding 11px -> 7px. Horizontal 15px -> 14px, and the gap between
   chips 15px -> 8px, both on item 11d's spacing scale.

   ⚠️ On a phone the chips stay 44px tall regardless: item 11d proposal 9 sets a
   44px minimum on every control below 750px, and a smaller tap target is not
   the trade being made here. */
#related-content ul li {
	display: inline-block;
	/* ⛔ `line-height: 0` IS THE LINE THAT ACTUALLY CLOSES THE GAP, and without
	   it the rest of this change did nothing measurable. With inline-block alone
	   the chip was 37px and the ROW PITCH WAS STILL 77px - re-measured, not
	   assumed. The li inherited a 27.2px line-height from 17px body copy, and an
	   inline-block child sits on that strut, so the li stood 69px tall around a
	   37px chip. Zeroing the strut makes the li exactly as tall as the chip.

	   The anchor below therefore states its own line-height rather than
	   inheriting: unitless inheritance would hand it this 0 and collapse the
	   label onto a single point. */
	line-height: 0;
	margin: 0 0.8rem 0.8rem 0;
}
#related-content ul a.button {
	display: inline-block;
	width: 100%;
	height: auto;
	/* ⛔ AND THIS `margin: 0` IS WHAT FINALLY CLOSED IT. Zeroing the li's strut
	   changed the row pitch by NOTHING - re-measured at 77px, twice. The 32px
	   was `.content .button { margin: 1.6rem auto }`, which these chips inherit
	   because they sit inside .content: 37px of chip plus 16px above and 16px
	   below is the 69px the li actually stood at.

	   Worth keeping because it is the third wrong guess in a row on one block -
	   padding, then the strut, then the truth - and each time the fix was applied
	   and the measurement said 77. The spacing between these chips is the li's
	   margin and nothing else now. */
	margin: 0;
	padding: 0.7rem 1.4rem;
	font-size: 1.3rem;
	line-height: 1.6;
}
@media (min-width: 550px) {
	#related-content ul a.button {
		width: auto;
	}
}

/*
* PLAN.md 4b.2 — THE RESTYLE WAS REVERTED. The four rules above are the
* originals, restored byte for byte, and `related_links_items_html()` puts
* `class="button"` back on the anchor so they still match.
*
* What was tried: quiet grey chips in a flex grid, sentence case, red on hover.
* The owner's verdict on the live pages was that it was worse than what it
* replaced - still reading as an inline run, LARGER than before rather than
* smaller, overlapping, and the red hover far too heavy. I could not see the
* rendered pages (browser screenshots are blocked on this vhost) and had checked
* the design only in a standalone preview, which is not the same thing and did
* not reproduce any of it.
*
* So do not treat the reverted rules as a considered choice to be preserved -
* they are simply the status quo, restored because iterating on a design nobody
* can see is how the above happened. The restyle is folded into 4b.3 and wants
* a screenshot or a real browser to work against. See docs/PLAN.md 4b.2.
*
* The ONLY thing kept from the restyle is the overflow disclosure below, which
* the cap needs. <details> and not a script: the CSP runs a per-request nonce
* with 'strict-dynamic', and links that need JavaScript to become visible is a
* worse trade than a native disclosure. Styled as a plain link so it sits with
* the existing furniture rather than introducing a new visual language.
*/
#related-content .related-links-more {
	margin: 0 0 15px 0;
}
#related-content .related-links-more > summary {
	display: inline-block;
	margin: 0 0 10px 0;
	font-size: 1.3rem;
	cursor: pointer;
}

/*
* PLAN.md 5.9a. The label said "Show all 54 routes" while all 54 were showing.
* Both labels are in the markup and these two rules choose between them, so no
* JavaScript is involved - see the comment at related_links_html() for why that
* constraint is not negotiable here.
*
* The open-state label carries the `hidden` ATTRIBUTE, which is what makes this
* degrade properly with no stylesheet: `hidden` is a browser default rule, so
* without dft.css exactly one label shows. The rule below has to beat it.
*
* ⚠️ IT BEATS IT ON CASCADE ORIGIN, NOT SPECIFICITY, and this comment said
* specificity until the audit corrected it. ANY author rule outranks a browser
* default rule regardless of how specific either is, so the [hidden] in the
* selector below is there to say what is being overridden, not to win a fight.
* The effect was never in doubt; the stated reason was wrong.
*/
/*
 * ⛔ NOT PREFIXED WITH #related-content, AND THE OTHER RULES IN THIS BLOCK ARE.
 * That is deliberate, and it was a defect found by the code audit. Five
 * templates render the disclosure inside <div id="related-content">, but
 * template-no-route.php calls the same renderer OUTSIDE it — so a prefixed rule
 * left that page saying "Show all" with everything showing, which is the exact
 * defect being fixed, on the one page nobody would think to look at.
 *
 * The label rules belong to the component, not to where it happens to sit.
 */
.related-links-more[open] > summary .related-links-more__closed {
	display: none;
}
.related-links-more[open] > summary .related-links-more__open[hidden] {
	display: inline;
}



/* Contact form */
#contact_form #contact_message {
	height: 165px;
}
#contact_form  #contact_website {
	border: 0;
	clip: rect(0 0 0 0);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
}

/* THE CALLOUT BOXES - owner, 2026-08-19, item 11e.

   The owner named these precisely: `.alert`, `.alert-warning`, `.alert-info`
   and the rest of the family.

   WHAT THEY WERE: a flat block of saturated pastel with 12px of padding, in the
   2008 'alert' palette - bright blue, bright green, bright pink. Nothing about
   them shared a language with the rest of the site.

   ⛔ AND TWO OF THE FOUR FAILED CONTRAST, WHICH IS NOT A TASTE QUESTION.
   Measured before the change: success #4F8A10 on #DFF2BF was 3.54:1 and error
   #D8000C on #FFBABA was 3.31:1, against a 4.5 bar. This is BUGS.md P3-52, and
   it is fixed here rather than left because the owner asked for these exact
   boxes - it is the item, not a 'while I'm in there'. Info and warning already
   passed; warning was fixed in item 11d, proposal 3.

   WHAT THEY ARE NOW: the same shape as the facts panels, which is the only
   other boxed element in the article column - a pale tint, a 4px accent rule
   down the left, 3px corners. So a reader meets one visual idea for 'this is a
   box of its own', not two.

   Every pair below is computed from the WCAG formula, not picked by eye:

     info     #1B4A6E on #EAF2F9   8.25:1
     success  #215B24 on #EDF6EE   7.35:1
     warning  #7A4A00 on #FDF3E4   6.81:1
     error    #8E241A on #FBECEA   7.57:1

   ⚠️ THE MARKUP IS A BARE <p class="alert alert-info">, WRITTEN INTO STORED
   CONTENT BY AN EDITOR - 12 info and 11 warning boxes across the airport,
   airline and guide pages, measured. There is no icon element and no heading
   inside one, so nothing here may depend on either. `.alert` is also used as a
   <div> by the contact form and the nav, which is why the margin is on `.alert`
   itself and not only on the paragraph form.

   Padding and margin are on item 11d's four-step scale: 1.6 / 2.0 / 3.2 / 4.8rem.
   `.alert:last-of-type { margin-bottom: 2em }` is DELETED - it existed to add
   space after the last of a run, and a uniform 1.6rem bottom margin does that
   for every one of them without a special case. */
.alert {
	margin: 0 0 1.6rem;
	padding: 1.6rem 2rem;
	border-left: 4px solid;
	border-radius: 3px;
}
.alert-info {
	color: #1B4A6E;
	background-color: #EAF2F9;
	border-left-color: #2A72A8;
}
.alert-success {
	color: #215B24;
	background-color: #EDF6EE;
	border-left-color: #2E7D32;
}
.alert-warning {
	color: #7A4A00;
	background-color: #FDF3E4;
	border-left-color: #B36A00;
}
.alert-error {
	color: #8E241A;
	background-color: #FBECEA;
	border-left-color: #C0392B;
}

.alert .container {
	margin-top: 0;
}


/*
* The live-price panel (docs/PLAN.md 5.11)
*
* Shown under the <h1> of a route page when the visitor arrived from a dated
* search of ours. A PANEL, not a modal: it sits in the flow and covers nothing,
* because a modal on arrival is indistinguishable from an interstitial to
* someone who has never seen the page.
*
* Written against a real rendering, not a preview - the 4b.2 restyle was built
* against a standalone page, was wrong in four ways on the live one and had to
* be reverted in full. Every number below was read off the actual page:
* body copy is 1.7rem/#555, .content h1 is 3.4rem/#CE3A36, .content h2 is
* 2.0rem/#CE3A36, and 1rem is 10px here.
*/
.search-panel {
	margin: 0 0 3.2rem;
	padding: 2rem 2.5rem 2.2rem;
	background: #F6F8F9;
	border: 1px #E1E1E1 solid;
	/* The one strong brand cue. A full red panel would out-shout the h1 it
	   sits under and read as an ad rather than as a confirmation. */
	border-left: 4px #CE3A36 solid;
	border-radius: 3px;
}
/*
* The title repeats the route the <h1> has just given, so it is demoted to a
* label. As a .content h2 it inherited 2.0rem/#CE3A36 and fought the heading
* directly above it.
*/
.content .search-panel__title {
	margin: 0 0 0.6rem;
	font-size: 1.3rem;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #666E76;
}
/* The dates are the proof we understood the request, so they are the biggest
   thing in the panel - bigger than the body copy, smaller than the h1. */
.search-panel .search-panel__dates {
	margin: 0 0 1.4rem;
	font-size: 2.2rem;
	line-height: 1.3;
	color: #30363d;
}
.search-panel .search-panel__dates strong {
	font-size: 1.5rem;
	font-weight: 400;
	color: #666E76;
}
.search-panel p {
	margin-bottom: 1.4rem;
}
.search-panel__cta {
	margin: 1.8rem 0 1.4rem;
}
/*
* This site's .button is display:block, so the CTA was rendering as a
* full-column red slab. One button, sized to its own text.
*/
.search-panel .button.button-primary {
	display: inline-block;
	width: auto;
	margin: 0;
}
/* Body text, deliberately NOT a second button - it describes what is already
   further down the page rather than offering a competing destination. */
.search-panel__or {
	font-size: 1.5rem;
	line-height: 1.6;
	color: #666E76;
}
.search-panel__or em {
	color: #666E76;
}
/*
* Dismiss. Also not a button: it inherited the site's bordered button style and
* came out the same visual weight as the CTA next to it, which is exactly the
* competing-action problem the panel spec calls out.
*/
.search-panel__dismiss,
.search-panel__dismiss:hover,
.search-panel__dismiss:focus {
	display: inline-block;
	width: auto;
	height: auto;
	margin: 0;
	padding: 0;
	border: none;
	background: none;
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.6;
	letter-spacing: 0;
	text-transform: none;
	text-decoration: underline;
	color: #666E76;
	cursor: pointer;
}
.search-panel__dismiss:hover,
.search-panel__dismiss:focus {
	color: #30363d;
}
.search-panel p:last-child {
	margin-bottom: 0;
}
/* On a phone the CTA is the only thing that matters, so let it have the width. */
@media (max-width: 550px) {
	.search-panel {
		padding: 1.6rem 1.6rem 1.8rem;
	}
	.search-panel .button.button-primary {
		display: block;
		width: 100%;
		text-align: center;
	}
}



/*
*
* Footer
*
*/
#sub_footer {
	position: relative;
	padding: 60px 0 60px;
	background-color: #e9f0f3;
}
#sub_footer h2 {
	text-align: center;
}



/*
*
* Footer
*
*/
footer {
	padding: 60px 0 40px;
	background-color: #363636;
}
footer .container {
	padding: 0 20px;
}
@media (min-width: 1200px) {
	footer .container {
		padding: 0;
	}
}
footer a,
footer p,
footer h1,
footer h2,
footer h3,
footer h4,
footer h5,
footer h6 {
	color: #fff;
}
footer a {
	text-decoration: none;
}
footer a:hover {
	border-bottom: 1px #fff dotted;
}

footer .connect a i {
	display: inline-block;
	font-size: 3.5rem;
	margin-right: 0.5em;
	vertical-align: middle;
	line-height: 1.5;
	
	transition: all 0.1s ease-in;
	-ms-transition: all 0.1s ease-in;
	-moz-transition: all 0.1s ease-in;
	-webkit-transition: all 0.1s ease-in;
}
/* Release item 10b, and this one is the opposite of everywhere else: the
 * footer is #363636, so DARKENING the blue made it worse - 4.22:1 became
 * 2.34:1. On a dark ground the accent has to go lighter, not darker. 5.29:1.
 * Audit finding. */
footer .connect a:hover,
footer .connect a:hover i,
footer .connect a i:hover {
	color: #6FB3E0;
	bordeR: none;
}
footer #footer__small_p {
	margin-top: 45px;
}

/*
* ===========================================================================
* The route facts panel (docs/PLAN.md 5.9, release item 7)
* ===========================================================================
*
* Sits under the opening paragraph of a route page and summarises the flight
* data the page already holds: flights a day, airlines, first and last
* departure, typical flight time, typical fare, and checked baggage per
* airline.
*
* Written against the real rendered page, per the note on .search-panel above,
* and using the same measured values: body copy is 1.7rem/#555, .content h2 is
* 2.0rem/#CE3A36, and 1rem is 10px here.
*
* ⚠️ NO CHARTS, AND THAT IS A DECISION RATHER THAN AN OMISSION. Measured
* 2026-08-15: 41 of the 82 route pages that serve 200 carry one or two
* flights and 48 carry a single airline, so a histogram there has two bars and
* a share chart has one slice. See docs/RELEASE-PLAN.md item 7.
*
* It borrows .search-panel's shape deliberately - same grey, same border, same
* red left edge - because both are "here is the summary" blocks in the same
* position on the same template, and two different panel styles under one h1
* would read as two unrelated components.
*/
/* OWNER PICKED OPTION C, 2026-08-19, item 11e3: one divided row, no box.

   WHAT IT WAS: a tinted panel with a hairline border and a 4px red left edge.
   ⛔ AND THE REASON IT HAD TO CHANGE IS THIS WEEK'S OWN DOING. Item 11e gave
   the callout boxes a pale tint with a coloured left rule - deliberately
   borrowing this panel's language so the article column had one idea of "a
   box". It reads well for the callouts, and it left a panel of DATA looking
   like a NOTE. The options put to the owner all moved the panel away rather
   than moving the callouts back.

   Then: a 2px rule above, a hairline below, nothing behind. The figures are
   separated by vertical hairlines instead of by a gap, which is what makes
   them read as separate facts.

   ⛔ AND THE OWNER REVERSED THE "NOTHING BEHIND" HALF OF THAT ON 2026-08-20 -
   see "ITEM 11m" below, which puts the heading and the figures inside a blue
   box. ⚠️ THIS SENTENCE USED TO ADD "the rest of option C is untouched", AND AN
   AUDIT ROUND CAUGHT IT TWICE - the second time because the correction was
   written into the 11m block below while the false sentence stayed here. Six
   things moved: the top rule, the section's padding, the figures' alignment,
   their flex-basis, the quiet ink, and which element does the clipping. They
   are listed in the 11m block. What IS untouched is the hairlines-not-gaps idea
   and the reason behind it - which is why this paragraph is kept, because that
   reason is also why the box is the sidebar's blue rather than the callouts'
   pale tint. ⚠️ It used to read "Now:".

   ⚠️ THE FIGURE STAYS 2.5rem, THOUGH THE MOCK-UP THE OWNER PICKED SHOWED 28px.
   25 is a step on the six-size scale accepted as item 11d proposal 4 and 28 is
   not; adding a seventh size to match a mock-up by three pixels would undo the
   thing that scale is for. The dividers do the work the extra size was doing.

   ⚠️ The route panel also carries a baggage TABLE and two notes, which used to
   sit inside the box. They now sit inside the ruled region instead - between
   the figures and the bottom hairline - so nothing is homeless. */
.route-facts {
	margin: 3.2rem 0;
	padding: 0 0 1.6rem;
	border-bottom: 1px #E1E1E1 solid;
}

/* --------------------------------------------------------------------------
   ITEM 11m - THE "AT A GLANCE" BOX IS BLUE, AND IT HOLDS THE HEADING AND THE
   FIGURES - NOTHING AFTER THEM.

   Owner, 2026-08-20, on being shown the panel rendered both ways: "#3 At a
   glance only in blue", and on being asked which of two readings that was,
   "Only 'at a glance' turns blue". The booking form above the schedule table
   keeps its grey.

   ⛔ IT REVERSES HALF OF OPTION C, WHICH THE SAME OWNER CHOSE THE DAY BEFORE.
   That is theirs to do. What is not allowed is the comment above still saying
   "nothing behind" while there is - so it now says when it stopped being true.

   ⚠️ AND SIX OTHER THINGS MOVED WITH IT, WHICH AN EARLIER DRAFT OF THIS BLOCK
   CALLED "the only thing that changes". ⚠️ THE DRAFT AFTER THAT LISTED FOUR AND
   WAS ALSO WRONG; an audit round found the two it missed. Listed rather than
   glossed:
     1. the section's 2px top rule is GONE - the box's own edge does that job,
        and two horizontal edges 20px apart read as a mistake;
     2. the section's 2rem top padding became a 3.2rem top margin, because
        without the rule there is nothing for padding to sit inside;
     3. the figures are inset from the box instead of aligned with the body copy
        above - that is what a box does, and it is why the item 11e3 harness's
        alignment check had to be rewritten rather than satisfied;
     4. the figures' flex-basis went 13rem to 12rem - see the note further down,
        which is about undoing what the box cost rather than about the box;
     5. the heading and label ink went #6B6B6B to #555, because #6B6B6B fails
        contrast on the blue - the note below this one;
     6. the CLIP moved from the section to the box, which is not cosmetic: it is
        what hides the hairline at the start of each row, and moving it is why
        the item 11e3 harness had to be pointed at a different element.

   ⚠️ TWO THINGS THE OWNER WAS TOLD FIRST, because the request rested on both:
   the panel had NO background at all, not the "very light grey" the request
   described - the grey being seen is the hairlines and the quiet caption ink;
   and on a route page the section is the whole block, so a plain tint on it
   left the baggage table sitting WHITE on blue. That is why this is a wrapper
   element and not a background on `.route-facts`.

   THE COLOUR IS THE SIDEBAR'S OWN #D8E8F1, not a new one - it is already the
   background of every sidebar link on the site, and the sidebar is on these
   pages, so this adds no colour to the page's palette. ⚠️ AND THERE IS NO
   BORDER, WHICH IS A DECISION RATHER THAN AN OMISSION: rendered both ways, the
   fill alone already reads as a box against white, and the outline was adding a
   second edge to say what the first one said.
   ⛔ An earlier draft justified it as "a border would cost a new colour". An
   audit round showed that is not true - the sidebar's own block is bordered
   #CCC and this panel already uses #E1E1E1 - so the reason above is the real
   one, and the palette argument is withdrawn.
   ⛔ AND THE QUIET GREY HAD TO CHANGE, WHICH THE FIRST VERSION OF THIS DID NOT
   NOTICE. `.route-facts__heading` and `.route-facts__label` are #6B6B6B - item
   11d's "quiet secondary" ink, chosen against WHITE and against the old
   #F6F8F9. On #D8E8F1 it measures **4.25:1** and fails. The rule below moves
   both to #555, the OTHER ink on item 11d's two-grey scale, which measures
   5.94:1 - so this costs no new colour either. The figure's #222 is 12.68:1 and
   was never in question. ⚠️ The first draft of this comment claimed 5.9:1 for
   the label without computing it; the harness computed it and it was 4.25.
   That is this project's own rule about a number in prose, again.

   ⚠️ THE PADDING USED TO BE LOAD-BEARING AND NO LONGER IS. Option C's hairlines
   were hidden by shifting the list a gutter left and letting this box clip it,
   so the padding had to stay under 1.9rem or the stray rules came back inside
   the box. Item 11n replaced the row with a grid of cards, which have gaps
   instead of rules - so there is nothing to clip, the `overflow: hidden` is
   gone with it, and this number is now only spacing. **Two audit rounds were
   spent on that mechanism and the answer in the end was to delete it.**
   -------------------------------------------------------------------------- */
.route-facts__glance {
	margin: 0 0 1.6rem;
	padding: 1.7rem;
	background: #D8E8F1;
	border-radius: 6px;
}
/* ⚠️ THE HEADING ONLY, AND ITEM 11n IS WHY THE LABEL CAME OFF THIS LIST. The
   quiet ink #6B6B6B measures 4.25:1 on the blue and fails, which is why this
   override exists - but item 11n moved the labels onto WHITE cards, where the
   same ink is 5.33:1 and passes (an earlier draft said 5.24, uncomputed). Darkening them there would be correcting a
   fault that is no longer under them. The heading is still directly on the
   blue and still needs it.
   `.content` is repeated for the same reason it is elsewhere in this file:
   `.content .route-facts__heading` is (0,2,0), so this has to OUT-specify it
   rather than tie it and win on source order. */
.content .route-facts__glance .route-facts__heading {
	color: #555;
}
/*
* Demoted like .search-panel__title, and for the same reason: as a .content h2
* it would inherit 2.0rem/#CE3A36 and compete with the real question headings
* immediately below the panel.
*/
.content .route-facts__heading {
	margin: 0 0 1.4rem;
	font-size: 1.3rem;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	/* RELEASE ITEM 11d, PROPOSAL 8: five greys down to two - #555 for text, #6B6B6B for quiet secondary text. ⚠️ This one IMPROVES contrast rather than merely tidying: on the panel's #F6F8F9 it goes 4.83:1 -> 4.97:1, computed both ways */
	color: #6B6B6B;
}
/* --------------------------------------------------------------------------
   ITEM 11n - THE PANEL IS A DASHBOARD. Owner, 2026-08-20, twice: "Can they be
   like dashboard cards. we lost the icons even though claude design came up
   with some. these mustn't slow down page load time. impress me!!!!" and then
   "I want it to be even better than that. more like a dashboard."

   ⭐ THE ICONS WERE NOT LOST - THEY WERE NEVER BUILT. The Claude Design sheet
   for item 11e3 offered three options; **option B, "cards with an icon each",
   was its recommendation** and carried these drawings. The owner picked option
   C, which has neither, so B was never built. This is B, re-used rather than
   redrawn, plus the thing that answers "more like a dashboard": two of the
   five figures are RANGES, and they are now DRAWN as well as said.

   WHAT MAKES IT READ AS A DASHBOARD RATHER THAN AS FIVE BOXES:
     1. each fact is its own white card on the tinted panel, not a share of one
        band - the eye can land on one without reading the others;
     2. an icon in a tinted chip, so a fact can be found by shape before it is
        found by reading;
     3. **the two figures that are ranges carry a strip that draws the range** -
        the flying window across the 24 hours, and where the typical fare sits
        between the cheapest and the dearest. That is a dashboard's actual job:
        showing a shape, not printing a sentence with numbers in it.

   ⛔ AND IT COSTS NOTHING TO LOAD, WHICH WAS THE OWNER'S CONDITION. The icons
   are inline SVG - a few hundred bytes inside a page already being downloaded,
   no request, no icon font, no sprite. The strips are two `<span>`s with an
   inline width. There is no JavaScript, no canvas and no chart library, and
   nothing new is fetched: **zero additional network requests.**

   ⚠️ THE HAIRLINE MECHANISM IS GONE, AND THAT IS THE OTHER HALF OF THE ITEM.
   Option C's row needed the whole list shifted a gutter left so the container
   could clip the rule that starts each row, and that trick is why this panel
   has been got wrong twice - once by the code and once by the check watching
   the code. Cards have gaps instead of rules, so there is no rule to hide, no
   negative margin, no clip and no flex-basis to tune against a stray pixel.
   **The item made the mechanism smaller, which is the direction this project's
   own rules ask for.** ⚠️ An earlier draft of this paragraph said "CSS GRID,
   NOT FLEX" and was left in place after the grid was swapped back out for a
   flex line - see the note on the rule below for why. Two contradictory
   sentences about the same rule; an audit round found them.
   -------------------------------------------------------------------------- */
.route-facts__figures {
	display: flex;
	/* ⛔ FLEX, NOT `repeat(auto-fit, minmax())`, AND THE GRID WAS TRIED FIRST.
	   A grid's tracks are the same width whether or not the last row is full,
	   so a route page's FIVE cards became four and then one stranded card with
	   two thirds of a row of blue beside it. Flex stretches the last row to
	   fill, so five cards are 5-across where they fit and 4+1 where they do
	   not, with the one spanning the width - which reads as a summary row
	   rather than as a card that fell off the end.
	   ⚠️ 15.5rem IS MEASURED. A card at that basis has 15.5rem less its 1.5rem
	   padding each side and its border - 125px - and the widest value on any of
	   the three page types is a departure range, which wants 124px at the size
	   the rule below gives it. Before the two were measured against each other
	   the range spilled out of its own card at every width from 360 to 768. */
	flex-wrap: wrap;
	gap: 0.8rem;
	margin: 0;
	padding: 0;
	list-style: none;
}
.route-facts__card {
	display: block;
	flex: 1 1 15.5rem;
	margin: 0;
	padding: 1.5rem;
	background: #fff;
	border-radius: 6px;
	/* A hairline AND a shadow a millimetre deep. The border alone reads as a
	   table cell; the shadow is what says "card". ⚠️ It is NOT the site's
	   existing `.card` shadow at half strength, which is what an earlier draft
	   of this said - that one is two layers. This is one layer, lighter,
	   because these sit on a tint rather than on white. */
	border: 1px #E4EBF0 solid;
	box-shadow: 0 1px 2px rgba(17, 41, 59, 0.06);
	list-style: none;
}
/* The icon chip. The wash is the brand red at 10%, so the chip belongs to the
   palette without adding a colour to it.

   ⚠️ 4rem OF CHIP AROUND 2.2rem OF ICON. Owner, 2026-08-20: "The icons aren't
   very clear. they are small because they need padding around the light red
   background." It was a 3.2rem chip around an 1.8rem drawing - 7px of wash on
   each side, which is not enough to read as a chip, and a drawing too small to
   tell a stopwatch from a clock. The chip grew and the drawing grew with it, so
   the ratio stays about 55%: a chip that grows alone just gets emptier. */
.route-facts__ico {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 4rem;
	height: 4rem;
	margin: 0 0 1.2rem;
	color: #CE3A36;
	background: rgba(206, 58, 54, 0.1);
	border-radius: 10px;
}
.route-facts__ico svg {
	display: block;
	width: 2.2rem;
	height: 2.2rem;
}
/* ⛔ A `margin-left: -1.9rem` LIVED HERE AND ITEM 11n LEFT IT BEHIND. It was
   the other half of option C's hairline trick - the whole list shifted a gutter
   left so the container could clip the rule that started each row. The rule and
   the clip were both deleted with the cards; this was not, so for one build the
   card row hung 19px out of the left of the blue panel, mis-aligned with its
   own heading. An audit round found it. ⚠️ I FIRST BLAMED IT FOR SOMETHING
   ELSE: three item 11g booking-bar checks were red at the same time, and the
   two were not connected - see the note beside the jump-scroll in
   tests/verify-item11g-booking-bar.js for what that actually was.
   Kept as a note because "delete the mechanism" is not done until the last
   line of it is gone. */
/* ⛔ WHAT WAS HERE, AND WHY IT IS GONE. Option C separated the figures with a
   `border-left` on every `li`, and hid the one at the start of each row by
   shifting the whole list 1.9rem LEFT and letting the container clip it. Item
   11m spent a paragraph on the flex-basis that made the row wrap correctly, and
   an audit round spent two more on a check that could not see the clip being
   removed. **Item 11n deletes all of it**: cards have gaps, not rules, so there
   is no rule to hide, nothing to clip, and no basis to tune. Kept as a note
   because the deletion is the most useful thing that happened to this panel. */
/* The figure is the thing being scanned for, so it is the biggest text in the
   panel - bigger than body copy, smaller than the h1 it sits under. */
/* RELEASE ITEM 11d, PROPOSAL 4: 2.4rem -> 2.5rem, 1.4rem -> 1.5rem below.
   ⛔ WEIGHT 500 AND NOT 700 - owner, 2026-08-20: "the bold values are too
   bold". ⚠️ AND 500 RENDERS AS 400 HERE, WHICH IS DELIBERATE RATHER THAN A
   MISTAKE: js/dft.js fetches Montserrat at 400 and 700 only, so under the CSS
   font-matching rules anything from 501 to 700 resolves to 700 - a "600" would
   have changed nothing at all and looked like it had. 500 resolves DOWN to 400.
   The figure keeps its emphasis from being 25px against a 15px label and from
   #222 against #6B6B6B, which is how it was already doing most of the work.
   ⚠️ Loading a real 600 is the other answer and it was not taken: it is another
   webfont file on a page whose owner's condition for this item was "these
   mustn't slow down page load time". */
.route-facts__value {
	display: block;
	font-size: 2.5rem;
	font-weight: 500;
	/* RELEASE ITEM 11d, PROPOSAL 4: one leading per size. 25px existed at 1.2 here and 1.25 as an h2 - a 1.25px difference nobody chose */
	line-height: 1.25;
	/* RELEASE ITEM 11d, PROPOSAL 8: five greys down to two - #555 for text, #6B6B6B for quiet secondary text. The figure keeps its emphasis from being 25px and bold, not from being darker than the words around it */
	color: #222;   /* option C: the figure is the thing being scanned for, and #555 is body copy. #222 is the heading ink introduced when the owner took the red off headings. */
	/* At 375px the departure range broke after the dash and rendered as
	   "06:00-" over "22:00", which reads as two figures rather than one.
	   Measured on the real page, not guessed: the widest value is that range
	   and it fits a half-width column at this size. */
	white-space: nowrap;
}
/* Any value over nine characters - which today is the departure ranges on all
   three page types, and tomorrow is a five-figure average fare. See the note
   beside facts_card_html() for why the cut is nine and why counting characters
   is a proxy rather than a measurement. 2.0rem is the next step down on item
   11d's six-size scale; it is not a nudge. */
.route-facts__value--long {
	font-size: 2rem;
}
.route-facts__label {
	display: block;
	margin-top: 0.2rem;
	font-size: 1.5rem;
	/* RELEASE ITEM 11d, PROPOSAL 4: one leading per size. 15px existed at 1.4, 1.5 and 1.6. 1.5 is the label ratio; body text keeps 1.6 */
	line-height: 1.5;
	color: #6B6B6B;
}

/* --------------------------------------------------------------------------
   THE STRIP - item 11n. Two spans and an inline width; see facts_meter_html()
   in includes/functions-flights.php for what the numbers mean and why they are
   inline. The track is the whole range being drawn against (the 24 hours, or
   the fare spread) and the fill is the part of it that is this page's.

   ⚠️ IT IS DECORATION IN THE ACCESSIBILITY TREE, ON PURPOSE. Every strip sits
   directly under a label that already states the same range in words, so it
   carries `aria-hidden` - a screen reader reading "06:00-22:00, first and last
   departure" then meeting a nameless graphic would be worse off, not better.
   -------------------------------------------------------------------------- */
.route-facts__meter {
	display: block;
	position: relative;
	height: 6px;
	margin-top: 1.2rem;
	background: #EDF2F6;
	border-radius: 3px;
	overflow: hidden;
}
/* ⛔ THE MINIMUM WIDTH IS HERE AND NOT IN THE ARITHMETIC, AND AN AUDIT ROUND
   IS WHY. facts_meter_html() used to floor the fill at 2% of the track so a
   narrow range still had something to see - but 2% of a day is 29 minutes, so
   a route whose only two departures are ten minutes apart was DRAWN as half an
   hour. A strip that rounds the data up to stay visible is exactly the lie the
   strips exist not to tell. The floor is 3 rendered pixels now: the geometry
   stays true, and the browser stops it vanishing. */
.route-facts__meter-fill {
	position: absolute;
	top: 0;
	bottom: 0;
	min-width: 3px;
	background: #2A72A8;
	border-radius: 3px;
}
/* --------------------------------------------------------------------------
   THE TWELVE-COLUMN DAY - item 11t. Owner: "the highlighted bold line doesn't
   represent the first and last flight time." It did, to the minute, and that
   was the problem - see facts_bars_html() in includes/functions-flights.php.
   Twelve two-hour columns, tallest scaled to full height, with 00/06/12/18
   under them so the shape has a scale to be read against.
   -------------------------------------------------------------------------- */
.route-facts__bars {
	display: block;
	margin-top: 1rem;
}
.route-facts__bars-plot {
	display: flex;
	align-items: flex-end;
	gap: 2px;
	height: 3.2rem;
}
.route-facts__bar {
	flex: 1 1 0;
	min-height: 2px;
	background: #2A72A8;
	border-radius: 2px 2px 0 0;
}
/* An empty two hours is a flat stub, not a gap: the day keeps its twelve
   columns, so a quiet afternoon reads as quiet rather than as a rendering
   fault. */
.route-facts__bar.is-empty {
	height: 2px !important;
	background: #DCE5EC;
}
.route-facts__bars-hours {
	display: flex;
	margin-top: 0.4rem;
	font-size: 1.3rem;
	line-height: 1.2;
	/* RELEASE ITEM 11k2 / BUGS.md P3-69. WAS #8A9096, WHICH FAILS WCAG AA AT
	   3.23:1 ON THE WHITE CARD - and which the owner had already decided out
	   on 2026-08-17 (P3-51, same colour, same figure). Item 11n brought it
	   back on four rules. #6B6B6B measures 5.33:1 on white, measured on the
	   rendered page, and is what .route-facts__label on the same card already
	   uses - so the card ends up with one quiet grey, not two.
	   ⚠️ NOT #666E76, which P3-51 chose: that was measured against the PANEL
	   background, and these labels sit on a white card. Item 11k had just
	   folded #666E76 out of the article column; putting it back here would
	   undo that on the same day. */
	color: #6B6B6B;
}
.route-facts__bars-hours span {
	flex: 1 1 0;
	text-align: left;
}

/* --------------------------------------------------------------------------
   A RANGE WITH ITS OWN SCALE - item 11v. The shape that was deleted twice, put
   back with the thing that was missing: the two ends are LABELLED, so the
   marker means something without a legend. See facts_range_html().
   -------------------------------------------------------------------------- */
.route-facts__range {
	display: block;
	margin-top: 1rem;
}
.route-facts__range-track {
	display: block;
	position: relative;
	height: 6px;
	margin-top: 1.6rem;
	background: #DCE5EC;
	border-radius: 3px;
}
.route-facts__range-mark {
	position: absolute;
	top: -3px;
	bottom: -3px;
	width: 3px;
	margin-left: -1.5px;
	background: #2A72A8;
	border-radius: 2px;
}
.route-facts__range-ends {
	display: flex;
	justify-content: space-between;
	margin-top: 0.4rem;
	font-size: 1.3rem;
	line-height: 1.2;
	/* RELEASE ITEM 11k2 / BUGS.md P3-69. WAS #8A9096, WHICH FAILS WCAG AA AT
	   3.23:1 ON THE WHITE CARD - and which the owner had already decided out
	   on 2026-08-17 (P3-51, same colour, same figure). Item 11n brought it
	   back on four rules. #6B6B6B measures 5.33:1 on white, measured on the
	   rendered page, and is what .route-facts__label on the same card already
	   uses - so the card ends up with one quiet grey, not two.
	   ⚠️ NOT #666E76, which P3-51 chose: that was measured against the PANEL
	   background, and these labels sit on a white card. Item 11k had just
	   folded #666E76 out of the article column; putting it back here would
	   undo that on the same day. */
	color: #6B6B6B;
}

/* --------------------------------------------------------------------------
   ITEM 11k-b - THE TWO CARDS THAT HAD A NUMBER AND NO PICTURE.

   Owner, 2026-08-21: "every at a glance card airport, route airline needs to
   have a visual representation." They were shown the measurements and chose
   these two shapes; see facts_rank_html() and facts_fill_html() for what the
   other options were and why they were worse.

   THE RANK. A marker on a track, busiest at the LEFT, with the position said
   in words underneath.
   ⛔ THE WORDS ARE PART OF THE DRAWING. This panel has now taught the same
   lesson twice - the owner rejected a bare fare bar and a bare departure strip
   in the same afternoon - and both times the fault was a track with nothing to
   measure it against. "2nd busiest of 30 airports" is what makes the marker
   mean something.
   -------------------------------------------------------------------------- */
/* ⚠️ CAPPED, BECAUSE A CARD ON ITS OWN ROW STRETCHES TO THE WHOLE PANEL.
   Five cards wrap 4 + 1 on a route page, and the fifth then flexes to about
   830px. A seven-point week or twelve columns fill that happily; a TRACK with
   two end labels does not - it becomes a 6px hairline with "1,423" and "2,864"
   marooned at opposite ends of the panel, and the marker between them stops
   being readable as a position. Measured on /bangkok-to-nan, which is the page
   that made it visible.
   ⛔ IT CAPS THE DRAWING, NOT THE CARD. Capping the card leaves a hole in the
   row; the card should still fill its space, and only the thing inside it that
   cannot use the space is held back. */
.route-facts__rank,
.route-facts__range,
.route-facts__fill {
	max-width: 32rem;
}

.route-facts__rank {
	display: block;
	margin-top: 1rem;
}
.route-facts__rank-track {
	display: block;
	position: relative;
	height: 6px;
	margin-top: 1.6rem;
	background: #DCE5EC;
	border-radius: 3px;
}
.route-facts__rank-mark {
	position: absolute;
	top: -3px;
	bottom: -3px;
	width: 3px;
	margin-left: -1.5px;
	background: #2A72A8;
	border-radius: 2px;
}
.route-facts__rank-words {
	display: block;
	margin-top: 0.6rem;
	font-size: 1.3rem;
	line-height: 1.2;
	/* RELEASE ITEM 11k2 / BUGS.md P3-69. WAS #8A9096, WHICH FAILS WCAG AA AT
	   3.23:1 ON THE WHITE CARD - and which the owner had already decided out
	   on 2026-08-17 (P3-51, same colour, same figure). Item 11n brought it
	   back on four rules. #6B6B6B measures 5.33:1 on white, measured on the
	   rendered page, and is what .route-facts__label on the same card already
	   uses - so the card ends up with one quiet grey, not two.
	   ⚠️ NOT #666E76, which P3-51 chose: that was measured against the PANEL
	   background, and these labels sit on a white card. Item 11k had just
	   folded #666E76 out of the article column; putting it back here would
	   undo that on the same day. */
	color: #6B6B6B;
}

/* HOW MUCH OF THE COUNTRY A CARRIER REACHES. One block per airport that has
   flights, filled for the ones it serves.
   ⚠️ BLOCKS RATHER THAN A PERCENTAGE BAR, and at this size that is the whole
   point: they are countable, so "24 airports served" can be CHECKED against
   the picture. A bar could only be believed.
   ⚠️ `flex: 1 1 0` with a 2px floor - 30 blocks in a card this wide is about
   3px each, which is thin but still resolves as separate marks. If the network
   ever grows past what a card can show as individual blocks, this becomes a
   bar and the sentence above stops being true. */
.route-facts__fill {
	display: flex;
	gap: 2px;
	height: 3.2rem;
	margin-top: 1.6rem;
	align-items: stretch;
}
.route-facts__fill-block {
	flex: 1 1 0;
	min-width: 2px;
	background: #DCE5EC;
	border-radius: 1px;
}
.route-facts__fill-block.is-on {
	background: #2A72A8;
}

/* --------------------------------------------------------------------------
   WHO FLIES IT - item 11t. Owner: "linked airlines. we know how many there are
   in total, so we have light blocks and dark block to represents the number?"
   One block per airline, width by its share of the flights; see
   facts_blocks_html() for why it is not "N of a total".
   -------------------------------------------------------------------------- */
/* ⚠️ 3.2rem, THE SAME AS THE BARS' PLOT, AND THAT IS THE POINT. Owner,
   2026-08-20: "Make them th same hieght as each other." The blocks were an 8px
   rule and the twelve-column day was 32px, so two cards side by side drew their
   data at two different weights and the panel read as one dashboard element and
   one afterthought. */
.route-facts__blocks {
	display: flex;
	gap: 2px;
	margin-top: 1rem;
	height: 3.2rem;
}
.route-facts__block {
	flex-grow: 0;
	flex-shrink: 1;
	background: #2A72A8;
	border-radius: 2px;
}
/* Alternating, so six carriers read as six blocks rather than as one bar with
   hairlines in it. */
.route-facts__block.is-alt {
	background: #8FB7D4;
}

/* --------------------------------------------------------------------------
   THE SEVEN-DAY FARE LINE - item 11r. See facts_spark_html() in
   includes/functions-flights.php for what it draws and why it is not a chart
   library. Owner, on the bar it replaced: "What is the long bar on the price."

   ⚠️ `preserveAspectRatio="none"` ON THE SVG, so the 100x24 drawing stretches
   to whatever width the card gives it - and `vector-effect: non-scaling-stroke`
   on the line, so the stroke does NOT stretch with it. Without the second one a
   wide card gets a line thin at the top and fat at the sides.
   -------------------------------------------------------------------------- */
.route-facts__spark {
	display: block;
	margin-top: 1rem;
	color: #2A72A8;
}
.route-facts__spark svg {
	display: block;
	width: 100%;
	height: 3.4rem;
	overflow: visible;   /* the marker at the top or bottom point sits on the edge */
}
/* The seven initials, one under each point. `space-between` puts the first and
   last hard against the ends, which is where the line starts and finishes. */
.route-facts__spark-days {
	display: flex;
	justify-content: space-between;
	margin-top: 0.4rem;
	font-size: 1.3rem;
	line-height: 1.2;
	/* RELEASE ITEM 11k2 / BUGS.md P3-69. WAS #8A9096, WHICH FAILS WCAG AA AT
	   3.23:1 ON THE WHITE CARD - and which the owner had already decided out
	   on 2026-08-17 (P3-51, same colour, same figure). Item 11n brought it
	   back on four rules. #6B6B6B measures 5.33:1 on white, measured on the
	   rendered page, and is what .route-facts__label on the same card already
	   uses - so the card ends up with one quiet grey, not two.
	   ⚠️ NOT #666E76, which P3-51 chose: that was measured against the PANEL
	   background, and these labels sit on a white card. Item 11k had just
	   folded #666E76 out of the article column; putting it back here would
	   undo that on the same day. */
	color: #6B6B6B;
}
.route-facts__spark-days .is-low {
	font-weight: 700;
	color: #CE3A36;
}

/* The typical-fare mark. It rides ON the fill, so it needs to be the one thing
   in the strip that is not the fill's colour. */
.route-facts__meter-mark {
	position: absolute;
	top: -2px;
	bottom: -2px;
	width: 3px;
	margin-left: -1.5px;
	background: #CE3A36;
	border-radius: 2px;
}
/*
* The baggage table. .table-cont is the existing scroll wrapper the schedules
* table already uses (see "Tables" above), so a narrow phone scrolls this one
* the same way - which is why it is reused rather than replaced. Its 40px top
* margin is too much inside a panel.
*/
/* .content is repeated so this OUT-SPECIFIES `.content .table-cont` above
   rather than merely tying it and winning on source order. The rest of this
   block genuinely out-specifies what it overrides; this one line did not, and
   a stylesheet reorder would silently restore the 40px top margin inside the
   panel. Code audit finding. */
.content .route-facts .table-cont {
	margin: 0.6rem 0 1.2rem;
}
/* ⛔ THE OWNER, 2026-08-20, ON SEEING THE BLUE BOX SHIPPED: "this whole section
   does not look good... There's no reason for the 'Checked baggage included
   with' text to be in a tiny column."

   THEY WERE RIGHT AND THE CAUSE IS THIS TABLE'S WIDTH. The table had none, so
   it shrank to its content - two short columns - and a `<caption>` can never be
   wider than the table it belongs to. On a one-airline route page that made the
   table about 215px and wrapped the caption into four lines of a column
   narrower than a phone. The caption is 113 characters and two sentences;
   ⚠️ a first draft of this note called it "a 90-character sentence" without
   counting it, and an audit round did count it.
   ⚠️ AND "WORST ON THE PAGES WITH THE LEAST DATA" IS THE INTUITION, NOT A
   MEASUREMENT. What sets the width is the widest airline NAME plus the header
   cells, not the row count - a single-airline page whose airline is "Bangkok
   Airways" is wider than a three-airline page of short names. Two pages were
   rendered, not eighty-two: /bangkok-to-loei went 215px and four lines of
   caption to 460px and two, /bangkok-to-chiang-mai 256px and three lines to the
   same 460px and two. The fix does not depend on which is worst.

   ⚠️ 46rem RATHER THAN 100%. Two columns holding "Bangkok Airways" and "20 kg"
   stretched across the whole 803px article column leaves a hand's width of
   empty rule between them, which is the other way to make a small table look
   broken. 46rem is wide enough for the caption to read as a sentence and narrow
   enough that the two columns still relate to each other.
   The weight is right-aligned against the table's own right edge, so the
   figures form a column instead of floating after names of six different
   lengths. */
/* The caption, out of the table since item 11n - see the note beside it in
   includes/functions-flights.php. It runs the article's own width, so on a
   desktop it is one line where a <caption> stuck at the table's 460px was two.
   ⚠️ It carried a 66rem cap to match body copy until the owner removed that cap
   from body copy; a note that wrapped narrower than the paragraphs around it
   would be the raggedness they asked to be rid of, one element down. */
.content .route-facts__bags-note {
	margin: 0 0 1rem;
	font-size: 1.5rem;
	line-height: 1.6;
	color: #6B6B6B;
}
.content .route-facts__bags {
	width: 100%;
	max-width: 46rem;
	margin: 0;
	font-size: 1.5rem;
	background: #fff;
}
.content .route-facts__bags caption {
	padding: 0 0 0.8rem;
	font-size: 1.3rem;
	line-height: 1.5;
	color: #6B6B6B;
	text-align: left;
	caption-side: top;
}
/*
* ⚠️ THE BACKGROUND RESET IS THE LOAD-BEARING LINE HERE, NOT THE PADDING.
* `.content table th` above paints EVERY th white-on-red, because the only
* table on this template until now was the schedules table, whose th cells are
* its red header bar. Applied to this table it made the airline names white
* text on a red block - invisible - and left the head row red with the grey
* label colour on top of it.
*
* Found by SCREENSHOTTING the panel, not by reading the markup: the HTML was
* correct, the entities were correct, and curl showed nothing wrong. This is
* the "don't design what you cannot see" rule doing its job on its first
* outing.
*/
.content .route-facts__bags th,
.content .route-facts__bags td {
	padding: 0.9rem 1.6rem 0.9rem 0;
	color: #555;
	background: none;
	background-color: transparent;
	text-align: left;
}
.content .route-facts__bags th:first-child {
	padding-left: 0;
}
/* The weight column, right-aligned to the table's own edge - see the note on
   the table above. `td` is the weight and `th[scope=row]` is the airline name,
   so this cannot reach the names. */
.content .route-facts__bags td,
.content .route-facts__bags thead th:last-child {
	padding-right: 0;
	text-align: right;
}
.content .route-facts__bags thead th {
	font-size: 1.3rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	/* RELEASE ITEM 11k. WAS #666E76, WHICH IS A LIVE PALETTE COLOUR AND NOT A
	   STRAY - the header at the top of this file names it the label grey, and
	   five .search-panel rules still use it, which is why only THIS rule folded.
	   It is the one #666E76 the design inventory finds on a route page, and it
	   sat on the column headings of a table whose caption - the paragraph
	   directly above it, .route-facts__bags-note - is #6B6B6B doing the same
	   job. Those two are the near-duplicate pair proposal 8 named.

	   ⚠️ AND NOT BECAUSE "THIS IS THE ONLY PLACE THE GREY REACHES AN ARTICLE
	   COLUMN", WHICH IS WHAT THIS COMMENT SAID FIRST AND IS FALSE. The search
	   panel is included from template-schedules.php INSIDE
	   `.columns.eight.content`, and `.content .search-panel__title` is #666E76.
	   It renders only after a search, never on a landing, so the inventory never
	   sees it - which is a fact about the instrument, not about the page.

	   Contrast on white: 5.18:1 before, 5.33:1 after, both measured on the
	   rendered page. BUGS.md P3-63. */
	color: #6B6B6B;
	border-bottom: 1px #E1E1E1 solid;
}
.content .route-facts__bags tbody th {
	font-weight: 400;
}
/* The schedules table's row hover is a cue that its rows are interactive.
   These are not. */
.content .route-facts__bags tr:hover {
	background-color: transparent;
}
.route-facts__hand,
.route-facts__collected {
	margin: 0 0 0.6rem;
	/* RELEASE ITEM 11d, PROPOSAL 4: 1.4rem is off the six-step scale (13/15/17/20/25/34); 1.5rem is the nearest step. */
	font-size: 1.5rem;
	line-height: 1.5;
	color: #6B6B6B;
}
.route-facts__collected {
	margin-bottom: 0;
}
/* ⛔ 750px, NOT 550px, AND THE OLD 550 RULE IS DELETED RATHER THAN KEPT.
   Below 750 this is no longer one row, so the vertical hairlines have to go -
   see the note on the li above. The rule this replaces also set a horizontal
   padding on .route-facts. ⚠️ THAT SENTENCE USED TO END "which option C no
   longer has: with no box there is nothing to inset from, and the figures must
   line up with the body copy". Item 11m put a box back, so the figures are
   inset from it now - by `.route-facts__glance`, not by this element. */
@media (max-width: 750px) {
	/* Two figures a row rather than a ragged wrap. The dividers are NOT dropped
	   here any more - the clipping above makes them correct at every width, so
	   the phone gets the same idea as the desktop rather than a second design.
	   ⚠️ 30% AND NOT 40%: at 40 the basis plus the two 18px gutters came to
	   355px against a 354px list at 375 wide, so it fell to ONE figure a row and
	   the panel grew from 324px tall to 437. One pixel. Measured, then fixed. */
	/* ⚠️ ITEM 11n: this used to set a flex-basis. Below 750 the article is the
	   whole page, so the desktop minimum would force one card a row on a phone;
	   13.5rem is the value that gives TWO at 360px and three at 600.
	   ⚠️ A SMALLER ONE WAS TRIED AND WAS TOO SMALL: at 600px it packed four
	   cards into 96px each and the departure range spilled out of every one of
	   them. Measured at 320, 360, 390, 414, 600 and 768 on all three page
	   types, before and after. */
	.route-facts__card {
		flex-basis: 13.5rem;
	}
	/* One step further down for the departure range on a phone. A card at this
	   basis has about 120px inside it and the range wants 124px at 2.0rem; at
	   1.7rem it wants 105px. Both numbers are measured on the real pages, and 1.7rem is
	   the next step on item 11d's scale rather than a nudge. */
	.route-facts__value--long {
		font-size: 1.7rem;
	}
}


/*
* ===========================================================================
* THE AIRPORT FILTER - release item 8b.
* ===========================================================================
*
* ⛔ .airport-filter ITSELF GETS NO `display` RULE, AND THAT IS LOAD-BEARING
* RATHER THAN TIDY. The control is served with the `hidden` attribute and
* revealed by dft.js, so a reader with no JavaScript sees every flight and no
* dead control. But `[hidden] { display: none }` is an AUTHOR rule on this site,
* not a browser default - so ANY later author `display` rule on this element
* beats it on source order and the control would render visible and dead.
* Putting `display: flex` here, which is the obvious way to lay out a row of
* buttons, is exactly what would do it. The layout is on the inner wrapper for
* that one reason.
*
* ⚠️ THE RULE IS THE FIRST LINE OF css/skeleton-dft.css, a minified normalize
* v3.0.2. This comment cited css/normalize.css:77, which is in the tree and is
* NOT LINKED BY ANY PAGE - inc.header.php loads skeleton-dft.css and this file.
* The cascade argument is unchanged; the citation was wrong. Code audit finding.
*
* The same cascade is documented ~430 lines above, on the "Show all" label
* rules, where it is deliberately exploited. Design audit finding, 2026-08-16,
* before any of this was written.
*/
.airport-filter {
	margin: 0 0 1.6rem;
}
.airport-filter__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
}
.airport-filter__legend {
	margin: 0 1.2rem 0.8rem 0;
	/* RELEASE ITEM 11d, PROPOSAL 4: 1.4rem is off the six-step scale (13/15/17/20/25/34); 1.5rem is the nearest step. */
	font-size: 1.5rem;
	font-weight: 700;
	line-height: 1.4;
	color: #6B6B6B;
}
.airport-filter__buttons {
	display: flex;
	flex-wrap: wrap;
	margin-bottom: 0.8rem;
}
/*
* A <button> here inherits the site's big red form button, which is the wrong
* weight entirely for a control that sits above a table - it would read as the
* page's main action. They carry body copy's own ink and weight until pressed,
* which is quieter than the red button - NOT quieter than body copy, which is
* what this line claimed while the colour was #444, a DARKER grey than body
* copy's #555. Corrected with the fold in release item 11k.
*/
.content .airport-filter__button {
	height: auto;
	margin: 0 0.8rem 0 0;
	padding: 0.6rem 1.2rem;
	font-family: inherit;
	/* RELEASE ITEM 11d, PROPOSAL 4: 1.4rem is off the six-step scale (13/15/17/20/25/34); 1.5rem is the nearest step. */
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: 0;
	text-transform: none;
	/* RELEASE ITEM 11k: #444 vs #555 is the near-duplicate pair proposal 8 named,
	   and this was the LAST `color: #444` in any stylesheet the site loads. The
	   three left in this file are not text - two background-color and one border
	   - and css/-dft.css is not included by anything. `.airport-filter__count`
	   sets no colour of its own, so it folds with this one. Contrast on this
	   #F6F8F9: 9.14:1 before, 7.00:1 after, both measured on the rendered page,
	   against a 4.5 bar. P3-63. */
	color: #555;
	background: #F6F8F9;
	border: 1px #E1E1E1 solid;
	border-radius: 3px;
	cursor: pointer;
}
.content .airport-filter__button:hover {
	border-color: #B9BEC2;
}
/*
* The pressed state has to be legible without colour - aria-pressed says it to
* a screen reader, and the border and weight say it to everyone else, so it
* does not rest on the red alone.
*/
.content .airport-filter__button.is-on {
	font-weight: 700;
	color: #fff;
	background: #CE3A36;
	border-color: #CE3A36;
}
/* No matching rule for the pressed state: the span sets no colour of its own,
   so it inherits #fff from .is-on above. One was written and the code audit
   pointed out it did nothing. */
.airport-filter__count {
	font-weight: 700;
}
.content .airport-filter__status {
	width: 100%;
	margin: 0;
	/* RELEASE ITEM 11d, PROPOSAL 4: 1.4rem is off the six-step scale (13/15/17/20/25/34); 1.5rem is the nearest step. */
	font-size: 1.5rem;
	line-height: 1.5;
	color: #6B6B6B;
}
@media (max-width: 550px) {
	/* The legend on its own line, so two long airport names are not competing
	   with it for a 375px row. */
	.airport-filter__legend {
		width: 100%;
		margin-right: 0;
	}
	.content .airport-filter__button {
		margin-bottom: 0.8rem;
	}
}

/* Release item 11c - the "Updated <date>" line under a page heading, on the
   airport, airline and travel-guide templates.

   #6B6B6B and 1.4rem are not new values: they are what .airport-filter__status
   already uses for a muted secondary line on white, from release item 8b.
   5.32:1 against #fff, against a 4.5 bar. The greys that FAIL are the facts
   panels' (P3-51) and this is deliberately not one of them.

   It sits between the h1 and the featured image, and the negative top margin
   pulls it up against the heading. ⚠️ THE FIRST VALUE WAS -0.6em AND IT DID NOT
   DO THAT - measured in Chromium at 375, 768 and 1200, it left 26px above the
   line and 30px below it, so the line floated in the middle of the gap instead
   of belonging to the heading. The h1 carries margin-bottom: 34px = 3.4rem, so
   -2.6rem collapses that to the 0.8rem this wants. Re-measured after the
   change: 8px above, 28px below, identical at all three widths. The root font
   size is 10px, which is what makes rem and px interchangeable here. */
.content .page-updated {
	/* ⛔ RELEASE ITEM 11d, PROPOSAL 5 BROKE THIS AND THE MEASUREMENT CAUGHT IT. The -2.6rem was tuned in item 11c against the h1's THEN margin-bottom of 34px, leaving 8px. Proposal 5 made that margin 16px, so the same -26px pull put the line 10px INTO the heading - the inventory reported a -10px gap. -0.8rem restores the 8px against the new value, and the bottom margin goes onto the scale */
	margin: -0.8rem 0 3.2rem 0;
	/* RELEASE ITEM 11d, PROPOSAL 4: 1.4rem is off the six-step scale (13/15/17/20/25/34); 1.5rem is the nearest step. */
	font-size: 1.5rem;
	line-height: 1.5;
	color: #6B6B6B;
}

/* RELEASE ITEM 11d, PROPOSAL 9 - 44px tap targets on a touch screen.
   BUGS.md P3-60, which supersedes P3-49's "four places".

   Measured at 375px, and the classification is the point: of the small targets
   on an airport page, 18 are sidebar links at 34px, 9 are footer links at 20px,
   8 are links inside running prose at 20px, and the rest are the search panel's
   form controls - the smallest being the Return / One way radios at 13px.

   ⛔ THE PROSE LINKS ARE DELIBERATELY NOT TOUCHED, AND THIS IS A NARROWING OF
   WHAT THE PROPOSAL SHEET PROMISED. It said "links, buttons and form controls".
   A link inside a sentence cannot be 44px tall without breaking the sentence -
   the line would open up around every link and the paragraph would come apart.
   Applied literally the rule damages the thing it is meant to help. So the rule
   here is: every STANDALONE control gets 44px; a link inside prose does not.
   The footer's links look inline but sit one-per-paragraph, so they are
   navigation and they are in.

   750px is the site's own breakpoint - below it there are no columns - so this
   engages exactly where the layout is already in its single-column form. */
@media (max-width: 750px) {

	/* Sidebar, footer and main-menu links: navigation, one per line. */
	aside#sidebar li a,
	footer section p a,
	#main-menu a {
		display: block;
		min-height: 44px;
		padding-top: 11px;
		padding-bottom: 11px;
		box-sizing: border-box;
	}

	/* Every form control, wherever it is. min-height rather than height so a
	   control that is already taller is left alone. */
	input[type="text"],
	input[type="email"],
	input[type="search"],
	input[type="tel"],
	input[type="number"],
	input[type="password"],
	input[type="date"],
	select,
	textarea,
	button,
	.button,
	input[type="submit"],
	input[type="button"] {
		min-height: 44px;
	}

	/* The Return / One way radios are 13px and cannot be enlarged without
	   redrawing the control. They sit INSIDE a <label class="radio">, so the
	   label is the tap target and that is what gets the height. */
	.options label.radio {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}


	/* The hamburger. It measured 28px, and on a phone it is the ONLY way into
	   the navigation - the single most important target on the page. */
	.main-menu-btn {
		display: flex;
		align-items: center;
		min-height: 44px;
	}

	/* The footer's social icons, 20px and carrying no text label. */
	footer section.connect a {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		min-height: 44px;
		min-width: 44px;
	}

	/* The two calendar icon buttons beside the date fields measured 16px. */
	.search-panel__icon,
	button.icon-calendar,
	.datepicker-trigger {
		min-height: 44px;
		min-width: 44px;
	}
}


/* ==========================================================================
   RELEASE ITEM 11g - THE BOOKING BAR ON ROUTE PAGES
   docs/SPEC-11g-sticky-booking-bar.md

   ONE form. It renders in the flow directly above the schedule table, and when
   it scrolls out of view JavaScript fixes it to the bottom of the viewport.
   The fixed state is a presentation change of the SAME element - there is no
   second form on the page.

   ⛔ `position: fixed` DOES NOT WORK INSIDE THE CANVAS AT ALL, WHICH IS WHY THE
   SCRIPT MOVES THE FORM OUT TO STICK. Slidebars puts a transform on [canvas],
   making it the containing block for any fixed descendant - and because that
   element also scrolls its own overflow, the "fixed" bar scrolled away with the
   content: measured at top -1309 with the page at 2500. So on sticking the form
   is moved to the end of the document and moved back afterwards. Moved, not
   cloned: there is still exactly one <form>. See the comment beside `stick()`
   in js/dft.js.
   ⚠️ THIS PARAGRAPH SAID THE OPPOSITE UNTIL 2026-08-20 - that fixed positioning
   "works because the canvas fills the viewport", and that the bar would slide
   sideways with the page "which the old .mob_cta did NOT do". Both described
   the design before it was built. Being outside the canvas, the bar does not
   slide either. Independent audit of the built code.

   BREAKPOINT 700px, not the site's usual 750: below 700 three fields and a
   button cannot share a line, which is the objection the owner raised and the
   real hole in the first version of this design.
   ========================================================================== */

.booking-bar {
	/* The placeholder. It keeps its height when the form inside goes fixed, so
	   the page does not jump by the height of the bar at the moment it sticks.
	   JS writes the measured height here; this is the floor. */
	margin: 0 0 2.4rem;
}
.booking-bar__form {
	/* ⚠️ Not inherited: skeleton sets border-box on `.container` and the column
	   classes, not globally. Without it `max-width: 1320px` on the stuck bar
	   measured 1354px on the page - the cap plus its own padding and borders -
	   so the bar overhung the content it was supposed to line up with by 17px a
	   side. Measured, not assumed. */
	box-sizing: border-box;
	display: flex;
	flex-wrap: nowrap;
	align-items: flex-end;
	gap: 1.2rem;
	padding: 1.6rem;
	background: #F6F8F9;
	border: 1px #E1E1E1 solid;
	border-radius: 3px;
}

/* --------------------------------------------------------------------------
   ITEM 11q - THE IN-FLOW FORM IS BLUE TOO. Owner, 2026-08-20: "should the data
   form on the schedule page above the schedule table have the light blue
   instead of the grey as well (booking) on the page, not the footer."

   ⛔ THE IN-FLOW ONE ONLY. The `:not(--stuck)` is the whole point: the bar that
   sticks to the bottom of the viewport is RED, which the owner asked for on
   2026-08-20 as "the key cta so it needs to be really obvious", and painting
   that blue would undo it. The form and the bar are the SAME element - it is
   moved, not cloned - so the two states have to be told apart by class rather
   than by selector position.

   The colour is the sidebar's #D8E8F1 again, so the page now has one tint doing
   one job - "this is a panel of ours" - instead of a grey for the form and a
   blue for the dashboard. The border goes with it: on a tint, #E1E1E1 reads as
   a seam rather than an edge.
   -------------------------------------------------------------------------- */
.booking-bar__form:not(.booking-bar__form--stuck) {
	background: #D8E8F1;
	border-color: transparent;
}

/* The fixed state. Full-bleed, its own top rule, and a shadow so the table
   scrolling underneath is visibly behind it rather than merged with it. */
.booking-bar__form--stuck {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 4;   /* above .mob_cta's old 1 and the airport autocomplete's 3 */
	box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.12);
	background: #fff;

	/* ⛔ IT STOPS WHERE THE PAGE STOPS. Owner, 2026-08-20, on seeing it:
	   "apply a container to the form so it doesn't span the entire width of
	   the screen". Full-bleed, on a 1440px screen the bar ran 120px past the
	   content on each side and read as browser furniture rather than as part of
	   the page it belongs to.

	   1320px is not a number chosen here - it is `.container`'s own max-width
	   (skeleton-dft.css), set by item 11d proposal 10. `left: 0; right: 0` plus
	   `margin: 0 auto` is what centres a FIXED element; `width: 100%` would pin
	   it left. Below 1320 nothing changes: the bar is already narrower than the
	   cap and still reaches both edges. */
	max-width: 1320px;
	margin: 0 auto;
	border-width: 1px;
	border-radius: 3px 3px 0 0;
}

.booking-bar__from {
	margin: 0 0.8rem 0.6rem 0;
	font-size: 1.5rem;
	line-height: 1.4;
	color: #555;
	white-space: nowrap;
}
.booking-bar__from strong {
	color: #222;
}

.booking-bar__fields {
	display: flex;
	flex: 1 1 auto;
	gap: 1.2rem;
	min-width: 0;
}
.booking-bar__field {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	min-width: 0;
}
.booking-bar__field--pax {
	flex: 0 0 8rem;
}
/* ⚠️ THE DATE FIELDS NEED A REAL FLOOR, NOT `flex: 1 1 auto` ALONE. At 1280 the
   three fields shared what the label and the button left over and the dates came
   out ~106px wide, which clipped their own placeholder to "Add a da". A date is
   the only thing this bar is asking for; it should not be the narrowest control
   on it. Measured on the rendered page, not guessed.

   ⛔ AND IT IS SCOPED TO 700px UP, WHICH IS NOT TIDINESS. Below that the fields
   stack in a COLUMN, where `flex-basis` is a HEIGHT - so the same rule made each
   date row 160px tall and the phone panel 940px. Caught in a screenshot, not in
   review. A flex rule written for one axis has to say which axis it meant. */
@media (min-width: 700px) {
	.booking-bar__fields .booking-bar__field:not(.booking-bar__field--pax) {
		flex: 1 1 16rem;
		min-width: 12rem;
	}
}

/* ⛔ ZEBRA'S CALENDAR ICON IS POSITIONED ONCE, WITH AN INLINE `top`, AND THEN
   NEVER AGAIN. It measured `top: 14px` while the label sat above the input; on
   the phone the label moves BESIDE the input, so the icon dropped below its own
   field and rendered as a ghost under it. The bar also MOVES in the DOM when it
   sticks, which no re-measure would survive either.

   Overriding the inline value is the smallest fix that cannot go stale: centred
   on the field, whatever the layout and wherever the form currently lives. */
.booking-bar__field .Zebra_DatePicker_Icon_Wrapper {
	display: block;
	flex: 1 1 auto;
	min-width: 0;
}
.booking-bar__field .Zebra_DatePicker_Icon {
	top: 50% !important;
	right: 10px !important;
	margin: 0 !important;
	transform: translateY(-50%);
	/* ⛔ AND THE SPRITE HAS TO BE CLIPPED TO ONE FRAME.
	   `zebra-datepicker/bootstrap/icons.png` is a vertical sprite pinned at
	   `50% 0`. Item 11d gives every `button` below 750px `min-height: 44px` -
	   a good rule, and this is a button - so the box is 44px tall and the NEXT
	   frame of the sprite showed through underneath as a second, ghostly
	   calendar. ⚠️ Setting `height: 16px` does not fix it: `min-height` wins.

	   So the 44px TAP TARGET is kept and the PAINTED area is cut down to the
	   frame: 14px of padding top and bottom leaves a 16px content box, and
	   clipping the background to it means only one frame is ever drawn. Found
	   in a screenshot - no measurement was going to report "there are two
	   calendars". */
	background-position: 50% 0 !important;
}
/* ⛔ AND THE CLIPPING ONLY BELOW 750px, WHERE THE 44px RULE APPLIES.
   Item 11d gives every `button` under 750px `min-height: 44px` - correct, and
   this is a button - so the sprite's NEXT frame showed through underneath as a
   second, ghostly calendar. The fix cuts the PAINTED area down to one frame
   while keeping the 44px tap target: 14px of padding leaves a 16px content box,
   and the background is clipped to it.
   ⚠️ APPLIED AT EVERY WIDTH IT ERASED THE ICON COMPLETELY. Above 750px there is
   no min-height, the button is its natural 16px, and 28px of padding leaves a
   content box of zero. Caught in a screenshot one iteration after the first
   screenshot caught the ghost - the same rule, wrong at both ends. */
@media (max-width: 750px) {
	.booking-bar__field .Zebra_DatePicker_Icon {
		padding: 14px 0 !important;
		background-origin: content-box;
		background-clip: content-box;
	}
}
.booking-bar__field label {
	margin-bottom: 0.4rem;
	font-size: 1.3rem;
	font-weight: 700;
	line-height: 1.4;
	color: #555;
}
.booking-bar__field input,
.booking-bar__field select {
	width: 100%;
	height: 44px;          /* the phone tap-target floor, kept everywhere */
	margin: 0;
	font-size: 1.5rem;
	background: #fff;
}
.booking-bar__go {
	flex: 0 0 auto;
	height: 44px;
	margin: 0;
	padding: 0 2rem;
	font-size: 1.5rem;
	line-height: 42px;
	white-space: nowrap;
}

/* The phone disclosure button. `hidden` in the markup, unhidden by script - so
   with no JavaScript it never appears and the fields are simply always open. */
.booking-bar__summary {
	display: none;
}
.booking-bar__summary-pax {
	flex: 0 0 auto;
	color: #6B6B6B;
}

/* --------------------------------------------------------------------------
   PHONE - below 700px. Collapsed to one line; the fields open ABOVE the bar.
   -------------------------------------------------------------------------- */
@media (max-width: 699px) {
	.booking-bar__form {
		flex-wrap: wrap;
		gap: 0.8rem;
		padding: 1.2rem;
	}
	/* No room, and it is not part of the collapsed summary. */
	.booking-bar__from {
		display: none;
	}
	.booking-bar__fields {
		flex: 1 1 100%;
		flex-direction: column;
		gap: 0.8rem;
		order: -1;            /* the panel opens ABOVE the bar's own line */
	}
	.booking-bar__field {
		flex-direction: row;
		align-items: center;
		gap: 1.2rem;
	}
	.booking-bar__field label {
		flex: 0 0 10rem;
		margin: 0;
	}

	/* Only when script is running: the one-line collapsed bar. */
	.booking-bar__form--js .booking-bar__summary {
		display: flex;
		/* ⚠️ BASIS 0, NOT `auto`. With `auto` the summary asks for its content
		   width before anything shrinks, and at 360px - a common Android width -
		   that tipped the line over and the button wrapped onto a second row:
		   122px against the one-line agreement. It fitted at 390 and failed at
		   360, which is exactly why 360 is in the measured set. */
		flex: 1 1 0;
		overflow: hidden;
		align-items: baseline;
		gap: 0.8rem;
		height: 44px;
		min-width: 0;
		margin: 0;
		padding: 0 1.2rem;
		font-size: 1.5rem;
		font-weight: 400;
		line-height: 42px;
		text-align: left;
		text-transform: none;
		letter-spacing: 0;
		color: #555;
		background: #fff;
		border: 1px #E1E1E1 solid;
		border-radius: 3px;
	}
	.booking-bar__form--js .booking-bar__summary-text {
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}
	.booking-bar__form--js:not(.booking-bar__form--open) .booking-bar__fields {
		display: none;
	}
	.booking-bar__form--js .booking-bar__go {
		padding: 0 1.2rem;
	}
	/* The expanded panel, when the bar is fixed, sits on the same white ground
	   as the bar rather than floating over the table. */
	.booking-bar__form--stuck {
		padding: 1.2rem;
	}
}

/* --------------------------------------------------------------------------
   THE WEEKDAY HIGHLIGHT IS GONE - removed in item 11y, 2026-08-21.

   Owner: "remove the column highlighting of the schedules table when that day
   is selected." It painted the chosen weekday's column #EDF6EE on selection.
   Both rules and the script that added the class have been DELETED rather than
   commented out or switched off - a rule nothing can reach is a rule someone
   re-enables by accident.

   ⚠️ `data-day` STAYS ON THE CELLS. It is not orphaned by this: the centring
   rule further up scopes itself by `[data-day]` rather than by `.price`, so
   the attributes have a second reader that predates the highlight going.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   THE FIXED BAR IS HELD TO ONE ROW OF CONTROLS - spec section 5, "one line in
   the collapsed state. The owner's acceptance of the interstitial risk was
   given for one line and does not extend further."

   ⚠️ MEASURED, THEN FIXED. In the flow the field labels sit above their inputs
   and the bar is 117px at 700 and 768. Fixed to the bottom of the viewport that
   is 15% of an 800px screen, permanently, on a page whose whole job is reading
   a table. Stuck, the labels go visually-hidden and the bar is one control row.

   ⛔ HIDDEN, NOT DELETED. `clip` rather than `display: none`, so the <label>
   stays in the accessibility tree and keeps its `for` relationship - a screen
   reader still announces "Leaving" on the field. The inputs carry placeholders
   ("Add a date", "One way") for everyone else.
   -------------------------------------------------------------------------- */
@media (min-width: 700px) {
	/* With the labels gone every child of the stuck bar is a 44px control, so
	   they centre against each other instead of hanging off a baseline that no
	   longer exists. In the flow the labels ARE there and flex-end is right. */
	.booking-bar__form--stuck {
		align-items: center;
	}
	.booking-bar__form--stuck .booking-bar__from {
		margin-bottom: 0;
	}
	.booking-bar__form--stuck .booking-bar__field label {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
	}
}

/* The narrow widths drop the words that do not fit. See the comment in
   template-schedules.php beside the button for the measurement that forced it.

   ⚠️ 999px, NOT 699. The phone was the obvious case, but at 700 the STUCK bar
   is the full viewport and the full label still left the date field 57px of
   usable room - clipped, on the money path, at a width nobody would have
   thought to look at. Above 1000px the affiliate is named, which is what §3.3
   of the spec asks for and what the panel CTA does. */
@media (max-width: 999px) {
	.booking-bar__go-long {
		display: none;
	}
}

/* The icon needs room; skeleton's default padding does not know that. Measured
   rather than nudged: with the default the usable text width at 700px was 57px
   against the 82px the placeholder needs.

   ⛔ AND THE `padding-right` HERE NEVER APPLIED TO A DATE FIELD - IT LOST TO AN
   INLINE STYLE. Item 11x. Owner, 2026-08-21: "the dates once selected are
   partley masked". Zebra writes `padding-right: 76px` onto the input itself when it
   attaches its icon, and an inline declaration beats any selector without
   `!important`. So the date inputs ran at 76px, not 30px, and this rule's own
   comment described a measurement of Zebra's number. (`padding-left` was never
   affected: Zebra does not set one.)

   ⚠️ 76px IS ZEBRA'S ARITHMETIC FOR AN ICON WE THEN MOVED. It reserves room
   for the icon at ITS chosen offset - the inline `right: 30px` it also writes -
   and the rule above pulls the icon to `right: 10px !important`. So 76px was
   reserving roughly 20px of nothing, on top of the room the icon does need.

   Item 11u then capped these fields at 17rem, which is where it started to
   show. ⚠️ THE BORDERS ARE PART OF THE SUM AND AN EARLIER DRAFT DROPPED THEM
   FROM ONE HALF OF IT: a 170px field is 168px inside its two 1px borders, so
   168 - 10 - 76 leaves 82px of text - and 82px is EXACTLY the placeholder "Add
   a date". A selected "Aug 30, 2026" is 98px, so the browser scrolled the text
   and ate the "Au".

   3.4rem is the icon where we actually put it - 10px of offset, 16px of icon,
   8px of gap - and leaves 168 - 10 - 34 = 124px. Measured in the browser at
   1440: 82px before, 124px after.

   ⚠️ AND ZEBRA NOW ASKS FOR 84px, NOT 76. Its inline value is computed from
   whatever padding it finds, so raising ours raised its answer too; the
   `!important` is what holds. 76px is the number it wrote BEFORE this rule
   existed, which is the one the defect came from. */
.booking-bar__field input {
	padding-left: 1rem;
	padding-right: 3.4rem !important;
}

/* --------------------------------------------------------------------------
   THE IN-FLOW FORM TAKES THE STUCK BAR'S LAYOUT - ITEM 11z, 2026-08-21.

   Owner: "Why don't we copy the exact same behaviour of the sticky footer
   booking bar here? That works really well. do that."

   ⚠️ "THE EXACT SAME BEHAVIOUR" MEANS THE LAYOUT, NOT EVERY RULE, and an
   earlier draft of this comment claimed otherwise - that the price label was
   "the one thing still different". Two audits later, the honest list of what
   is still in-flow-only is three rules and they are all deliberate:

     - the blue ground, `.booking-bar__form:not(.booking-bar__form--stuck)`
       further up - item 11q, the owner's, and the stuck bar is RED on purpose;
       it also turns the shared border transparent rather than adding one;
     - the price label hidden, the declaration below;
     - the button's margin zeroed, further down - which RESTORES the stuck
       bar's own value rather than choosing a different one.

   And the stuck bar has a set of its own besides: full-bleed, red, field
   labels hidden, the button recoloured. What was copied is the thing the owner
   was looking at - fields that fill the row, the long button words, one line.

   Everything below is why the three overrides that used to live here are gone,
   kept because each was measured and each was still wrong.

   ⛔ 1. IT USED TO WRAP ONTO TWO ROWS, and the measurement behind that aged
   out from underneath it. The form lives in the article column, which was
   482px at 768 - the sidebar had the rest - so the label plus three fields did
   not fit on a line. ⚠️ ITEM 11i TOOK THE SIDEBAR OUT OF THE ROW BELOW 1,200px.
   That column is 737px at 768 and 1,151px at 1,199 now, and item 11u put the
   form back on one row.

   ⛔ 2. THE FIELDS USED TO BE CAPPED AT 17rem. They really were oversized -
   294 to 354px each, measured, for a placeholder needing 82px - but a cap
   fixes that by parking the slack BETWEEN the last field and the button rather
   than inside the fields. Owner, seeing it: "now there'es too much empty
   space. can't we make the form elements fill up the horizontal space." Flex
   fills the row on its own; the cap was the thing stopping it.

   ⛔ 3. THE BUTTON USED TO DROP ITS LONG WORDS. Owner: "previously he had
   'check prices on kiwi.com' on the button". ⚠️ THE ARITHMETIC THAT JUSTIFIED
   HIDING THEM COUNTED THE "From ... THB" LABEL, AND THE LABEL IS HIDDEN HERE.
   Without it the row needs 651px at its minimum - 120 + 120 + 80 for the three
   fields, 295 for the long button, 36 of gaps.
   ⚠️ AGAINST 719px, WHICH IS THE ROW, NOT THE COLUMN. The narrowest article
   column is 753px, at 1,200px where the sidebar comes back; the form's own
   32px of padding and 2px of border leave 719px inside it. An earlier draft
   called 719 "the column", which is a different measurement that happens to
   support the same conclusion. It fits either way, with 68px spare.

   And the price label stays hidden here, which is the declaration below. The
   owner took it off this bar in item 11u - "can we just lose the price and
   have the button on the same row" - and their fixed bar still carries the
   figure. It is not a layout judgement being made twice; it is a thing they
   removed once.
   -------------------------------------------------------------------------- */
/* ⛔ AND A FOURTH OVERRIDE WENT WITH THEM: `flex-wrap: nowrap`, which could
   never do anything. `.booking-bar__form` is ALREADY `nowrap` at the top of
   this section; the only rule that sets `wrap` is the phone block, scoped to
   `max-width: 699px`. Restating `nowrap` inside `min-width: 700px` was a
   declaration that could not change a single pixel at any width.
   ⚠️ FOUND BY AN AUDIT ASKING WHETHER THE SENTENCE "this block holds ONE
   declaration" WAS TRUE. It was not, and the right fix was to delete the rule
   rather than to soften the sentence. */
@media (min-width: 700px) {
	.booking-bar__form:not(.booking-bar__form--stuck) .booking-bar__from {
		display: none;
	}
}

/* ⛔ THE BUTTON'S MARGIN IS ZEROED AT EVERY WIDTH, NOT ONLY ABOVE 700px - 11x.
   Owner, 2026-08-21: "bookar bar submit button doesn't align with the form
   fields", and then "the button is still misaligned on responsive" after a
   first fix that sat inside the 700px block above. The phone layout is exactly
   the half that fix could not reach - which is the same mistake as scoping a
   rule to a band and assuming the band is everywhere it matters.

   The button sat 16px HIGH of the fields, and `align-self` was doing its job:
   the MARGIN box was flush and a bottom margin held the border box up.
   ⚠️ THE MARGIN COMES FROM `.content .button { margin: 1.6rem auto }`, which
   out-specifies `.booking-bar__go { margin: 0 }` two classes to one. That is
   also why the STUCK bar was never crooked - sticking moves the form to
   <body>, out of `.content`, so its own `margin: 0` wins - and it is why this
   rule is scoped to the in-flow form: it RESTORES the stuck bar's value rather
   than choosing a new one. Measured: the button's bottom was 1867 against the
   inputs' 1883. */
.booking-bar__form:not(.booking-bar__form--stuck) .booking-bar__go {
	margin: 0;
}

/* ⛔ AND IN THE STUCK BAR BELOW 1000px THE LABEL IS WHAT GIVES.
   At 700 the whole viewport is the bar, and the "From ... THB" label (116px)
   plus the button (295px) left the date field 57px of usable room - clipped
   again. At these widths the fields need the space more than a visitor needs a
   figure they have already read further up the page.
   ⚠️ SCOPED, because an earlier version of this rule sat inside the wrap block
   above and quietly removed the label from the stuck bar at EVERY width,
   including the ones with plenty of room. Widening a media query moves every
   rule inside it. */
@media (min-width: 700px) and (max-width: 999px) {
	.booking-bar__form--stuck .booking-bar__from {
		display: none;
	}
}

/* --------------------------------------------------------------------------
   THE STUCK BAR IS RED. Owner, 2026-08-20, on seeing the built page:

     "I think the bottom sticky bar needs to stand out more. a thicker border
      around it. it's the key cta so it needs to be really obvious. consider
      making the background red with white text?"

   ⛔ THIS IS THE ONE ELEMENT ON THE SITE THAT IS ALLOWED TO SHOUT. The owner's
   words for this item from the start: the CTA "is the monetisation of the
   entire site". A white bar with a red button reads as another row of the
   table it is sitting on top of; a red bar does not.

   ⚠️ THE BUTTON INVERTS RATHER THAN COMPETING. A red button on a red bar has
   nothing to say, so on the stuck bar it becomes white with red text - the same
   two colours, swapped, so the action is still the most contrasted thing there.

   CONTRAST, computed rather than eyeballed - both directions of the same pair:
     white  on #CE3A36 ....... 4.90:1   labels, the "From" line
     #CE3A36 on white ........ 4.90:1   the button
   Both clear the 4.5 bar for normal text. ⚠️ The IN-FLOW form is untouched and
   stays quiet: it sits in the page's own reading column, where shouting would
   be wrong. Only the fixed state, which is competing with a table, is loud.
   -------------------------------------------------------------------------- */
.booking-bar__form--stuck {
	background: #CE3A36;
	/* The thicker border the owner asked for. #222 is the heading ink from item
	   11d - already in the palette, and the only thing dark enough to hold a
	   line against this red. */
	border: 3px #222 solid;
	border-bottom: 0;
	box-shadow: 0 -4px 14px rgba(0, 0, 0, 0.28);
}
.booking-bar__form--stuck .booking-bar__from,
.booking-bar__form--stuck .booking-bar__from strong,
.booking-bar__form--stuck .booking-bar__field label {
	color: #fff;
}
.booking-bar__form--stuck .booking-bar__go,
.booking-bar__form--stuck .booking-bar__go:hover,
.booking-bar__form--stuck .booking-bar__go:focus {
	color: #CE3A36;
	background-color: #fff;
	border-color: #fff;
}

/* --------------------------------------------------------------------------
   THE VALIDATION STATE. Owner, 2026-08-20, on using the built bar: pressing
   "Check live prices" with no date threw them to the top of the page to be told
   what was missing, and the bar they had just used was gone with it.

   ⚠️ THE MESSAGE SHARES THE "From ... THB" SLOT rather than adding a row, so the
   bar does not change height when it complains. One line was the agreement.

   ⛔ THE MARKED FIELD HAS TO READ AGAINST BOTH GROUNDS. In the flow the bar is
   pale grey; stuck, it is brand red. A red error border - the obvious choice,
   and the one `.alert-error` uses - is invisible on the red bar. #222 is the
   heading ink from item 11d, is already the stuck bar's own border colour, and
   holds a line against both.
   -------------------------------------------------------------------------- */
.booking-bar__field--error input {
	border: 2px #222 solid;
	background: #FBECEA;   /* .alert-error's ground, from item 11e */
}
.booking-bar__error {
	margin: 0 0.8rem 0.6rem 0;
	font-size: 1.5rem;
	font-weight: 700;
	line-height: 1.4;
	color: #8E241A;        /* .alert-error's ink, 6.81:1 on white */
	white-space: nowrap;
}
.booking-bar__form--stuck .booking-bar__error {
	/* On the red bar the alert ink has nothing to say; white is the only thing
	   that reads, and it is the same 4.90:1 the rest of the bar's text has. */
	color: #fff;
	margin-bottom: 0;
}
@media (max-width: 699px) {
	/* The phone bar has no room for it beside the summary, so it goes with the
	   fields it is talking about - which are open by then, because the submit
	   handler opens the panel before it complains. */
	.booking-bar__error {
		flex: 1 1 100%;
		order: -2;
		margin: 0 0 0.4rem;
		white-space: normal;
	}
}
