/* Airport pages (flying.app/airports). Loaded after /landing.css, which
   provides the colors, nav, buttons, and footer. */

.ap {
  /* Status colors, matching the app. */
  --status-major: #ff6961;
  --status-minor: #fd9131;
  --status-normal: #4cd27a;
  --status-yellow: #ffd60a;
  /* Card surfaces. */
  --card: #000;
  /* Hover on clickable cards: a hairline edge and a soft glow. */
  --card-glow: 0 0 0 1px rgba(255, 255, 255, 0.14), 0 0 28px rgba(255, 255, 255, 0.1);
  max-width: 880px;
  margin: 0 auto;
  padding: 140px 24px 40px;
}

.ap h2 {
  margin: 0 0 16px;
  font-size: clamp(24px, 3vw, 32px);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.ap h3 {
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text-dim);
}

.ap-dim {
  color: var(--text-dim);
}

.ap-note {
  margin: 12px 0 0;
  font-size: 13px;
}

.ap-lead {
  margin: 0 0 8px;
  font-size: 17px;
  line-height: 1.5;
  text-wrap: pretty;
}

/* Screen-reader-only text */
.ap-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- Header ---------- */
.ap-header {
  margin-bottom: 32px;
}

/* The homepage's blue accent. */
.ap-eyebrow {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 600;
  color: rgb(64, 132, 255);
}

.ap-eyebrow a:hover {
  text-decoration: underline;
}

.ap-header h1 {
  margin: 0 0 8px;
  font-size: clamp(36px, 6vw, 60px);
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.ap-subtitle {
  margin: 0;
  font-size: clamp(16px, 1.6vw, 19px);
  line-height: 1.5;
  color: var(--text-dim);
}

.ap-header .hero-cta {
  margin-top: 24px;
}

/* ---------- Sections and cards ---------- */
.ap-section {
  margin-top: 56px;
}

.ap-section:first-of-type {
  margin-top: 0;
}

.ap-card {
  padding: 20px;
  border-radius: 20px;
  background: var(--card);
}

.ap-section > .ap-card + .ap-card,
.ap-grid-2 + .ap-card {
  margin-top: 12px;
}

.ap-card p {
  margin: 0;
  line-height: 1.5;
}

.ap-card p + p {
  margin-top: 8px;
}

.ap-card--compact {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Pinned to the bottom of a compact card when it's stretched to match a
   taller neighbor, with the card's title staying at the top. */
.ap-card-foot {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: auto;
}

.ap-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.ap-grid-2--top {
  align-items: start;
}

.ap-section > .ap-card,
.ap-section > .ap-grid-2 {
  margin-top: 16px;
}

/* ---------- Section menu ----------
   Sticks just under the floating site nav. On narrow screens the links
   scroll sideways. */
/* Same width as the site nav (--nav-width from landing.css, inside 24px of
   side padding), centered on the page like it. */
.ap-tabs {
  --tabs-width: min(var(--nav-width, 832px), 100vw - 48px);
  position: sticky;
  top: 88px;
  z-index: 50;
  width: var(--tabs-width);
  margin: -8px calc((100% - var(--tabs-width)) / 2) 32px;
  display: flex;
  align-items: center;
  padding: 5px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: rgba(17, 18, 21, 0.72);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

.ap-tabs-track {
  display: flex;
  flex: 1;
  min-width: 0;
  gap: 2px;
  overflow-x: auto;
  scrollbar-width: none;
}

/* The airport code and live dot only show once the menu is stuck. They
   take no room until then, and fade in. */
.ap-tabs-code,
.ap-tabs-live {
  flex: none;
  width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 250ms ease;
}

.ap-tabs-code {
  font-size: 15px;
  font-weight: bold;
  letter-spacing: 0.02em;
}

.ap-tabs-live {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--text-dim);
}

/* Both sides get the same width, so the links center on the whole menu. */
.ap-tabs.is-stuck .ap-tabs-code,
.ap-tabs.is-stuck .ap-tabs-live {
  width: 92px;
  opacity: 1;
}

.ap-tabs.is-stuck .ap-tabs-code {
  padding-left: 14px;
}

.ap-tabs.is-stuck .ap-tabs-live {
  justify-content: flex-end;
  overflow: visible;
  padding-right: 14px;
}

/* Centered between them, without cutting off the first link when they
   overflow (which justify-content: center would). */
.ap-tabs.is-stuck .ap-tabs-track > a:first-child {
  margin-left: auto;
}

.ap-tabs.is-stuck .ap-tabs-track > a:last-child {
  margin-right: auto;
}

.ap-tabs-track::-webkit-scrollbar {
  display: none;
}

/* Opening a link like /airports/jfk#security lands below the menu. */
.ap-section[id] {
  scroll-margin-top: 160px;
}

/* Fade the edges when the links overflow, to show they scroll sideways. */
.ap-tabs-track.is-overflowing {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 20px, #000 calc(100% - 20px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 20px, #000 calc(100% - 20px), transparent);
}

.ap-tabs a {
  flex: none;
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
  transition: background 150ms ease, color 150ms ease;
}

.ap-tabs a:hover {
  color: var(--text);
}

.ap-tabs a.is-active {
  background: var(--text);
  color: #000;
}

.ap-tabs a:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 1px;
}

/* ---------- Live traffic map ---------- */
.ap-map {
  position: relative;
  height: 440px;
  border-radius: 20px;
  overflow: hidden;
  background:
    radial-gradient(60% 60% at 50% 50%, rgba(64, 132, 255, 0.12), transparent 70%),
    var(--card);
}

/* Scrolling over the map scrolls the page, and the map zooms with a pinch
   or Ctrl/Cmd and scroll. Mapbox shows a hint saying so each time someone
   scrolls past it; hide it. */
.ap-map .mapboxgl-scroll-zoom-blocker,
.ap-map .mapboxgl-touch-pan-blocker {
  display: none !important;
}

/* Runways in use, as a row under the map, with the flying conditions on
   the right. Wraps on narrow screens. */
.ap-runways {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 28px;
  margin-top: 12px;
  padding: 16px 20px;
}

.ap .ap-runways h3 {
  margin: 0;
  color: var(--text);
}

.ap-runways-group,
.ap-runways-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

/* When the row doesn't fit on one line (a script checks), the title stays
   on the left, and landing and taking off stack on the right: a block
   pushed to the right edge, with its labels and chips lined up in columns.
   Column 2 is an empty spacer. */
.ap-runways.is-stacked {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px 12px;
}

.ap-runways.is-stacked h3 {
  grid-row: span 2;
  grid-column: 1;
}

.ap-runways.is-stacked:has(.ap-conditions) h3 {
  grid-row: span 3;
}

.ap-runways.is-stacked .ap-runways-group {
  display: contents;
}

.ap-runways.is-stacked .ap-runways-label {
  grid-column: 3;
}

.ap-runways.is-stacked .ap-runways-chips {
  grid-column: 4;
}

.ap-runways.is-stacked .ap-conditions {
  grid-column: 3 / span 2;
  justify-self: start;
  margin-left: 0;
}

.ap-runways-label {
  margin-right: 4px;
  font-size: 14px;
  color: var(--text-dim);
}

.ap-runways .ap-conditions {
  margin-left: auto;
}

.ap-conditions {
  cursor: help;
}

/* Two classes, so this wins over mapbox-gl.css (loaded later), which sets the
   map container to position: relative. */
.ap-map .ap-map-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.ap-map-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(17, 18, 21, 0.72);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  font-size: 13px;
  pointer-events: none;
}

/* The airport's elevation, centered at the bottom of the map (between the
   Mapbox logo and the attribution button). */
.ap-map-elevation {
  position: absolute;
  bottom: 12px;
  left: 50%;
  z-index: 2;
  margin: 0;
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(17, 18, 21, 0.72);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  font-size: 13px;
  white-space: nowrap;
  transform: translateX(-50%);
  pointer-events: none;
}

/* Airports on the overview map: a dot in the status color, bigger for
   worse status. Each links to the airport's dashboard. */
.ap-map-dot {
  display: block;
  width: 9px;
  height: 9px;
  border: 1.5px solid rgba(0, 0, 0, 0.55);
  border-radius: 50%;
  background: var(--status-normal);
  cursor: pointer;
  transition: transform 150ms ease;
}

.ap-map-dot:hover {
  transform: scale(1.5);
}

.ap-map-dot--minor {
  width: 12px;
  height: 12px;
  background: var(--status-minor);
  box-shadow: 0 0 10px rgba(253, 145, 49, 0.6);
}

.ap-map-dot--major {
  width: 14px;
  height: 14px;
  background: var(--status-major);
  box-shadow: 0 0 12px rgba(255, 105, 97, 0.7);
}

.ap-map-dot--unknown {
  background: var(--text-faint);
}

/* On narrow maps the flights on their way in go on a second line. */
@media (max-width: 760px) {
  .ap-map-badge {
    border-radius: 14px;
  }

  .ap-map-inbound {
    display: block;
  }

  .ap-map-sep {
    display: none;
  }
}

.ap-map.is-error .ap-pulse {
  display: none;
}

/* Planes, as on the live.flying.app map: an overlay of rotated icons. */
.ap-plane-overlay {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.ap-plane {
  position: absolute;
  top: 0;
  left: 0;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  pointer-events: auto;
  will-change: transform;
}

.ap-plane img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

.ap-plane-label {
  position: absolute;
  top: -1px;
  left: 28px;
  display: flex;
  flex-direction: column;
  font-size: 9px;
  font-weight: 600;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
  color: #fff;
  text-shadow: 0 0 3px rgba(0, 0, 0, 0.95), 0 1px 2px rgba(0, 0, 0, 0.9);
  white-space: nowrap;
  pointer-events: none;
}

.ap-plane-label span + span {
  color: rgba(255, 255, 255, 0.75);
  font-weight: 500;
}

/* ---------- Live status ---------- */
.ap-updated {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font-size: 13px;
  color: var(--text-dim);
}

.ap-pulse {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--status-normal);
  box-shadow: 0 0 0 0 rgba(76, 210, 122, 0.6);
  animation: ap-pulse 2s ease-out infinite;
}

/* "live now" next to a live number, with a smaller dot. */
.ap-live-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.ap-live-label .ap-pulse {
  width: 6px;
  height: 6px;
  animation-name: ap-pulse-small;
}

@keyframes ap-pulse-small {
  70% { box-shadow: 0 0 0 4px rgba(76, 210, 122, 0); }
  100% { box-shadow: 0 0 0 0 rgba(76, 210, 122, 0); }
}

@keyframes ap-pulse {
  70% { box-shadow: 0 0 0 8px rgba(76, 210, 122, 0); }
  100% { box-shadow: 0 0 0 0 rgba(76, 210, 122, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .ap-pulse {
    animation: none;
  }
}

/* Tinted like the app's status cards: the whole card takes the status
   color, and the status itself is colored text rather than a pill. */
.ap-status {
  --tone: var(--text-dim);
}

.ap-status--major {
  --tone: var(--status-major);
  background: rgba(190, 92, 88, 0.3);
}

.ap-status--minor {
  --tone: var(--status-minor);
  background: rgba(184, 129, 88, 0.29);
}

.ap-status--normal {
  --tone: var(--status-normal);
  background: rgba(84, 160, 112, 0.26);
}

.ap-status-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--tone);
  white-space: nowrap;
}

.ap-status-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.ap-status-head h3 {
  margin: 0;
  font-size: 18px;
  color: var(--text);
}

.ap-status p {
  font-size: 16px;
}

/* Same colors the app uses for each status. */
.ap-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text-dim);
  background: var(--glass-strong);
}

.ap-badge--major { color: var(--status-major); background: rgba(255, 105, 97, 0.14); }
.ap-badge--minor { color: var(--status-minor); background: rgba(253, 145, 49, 0.14); }
.ap-badge--normal { color: var(--status-normal); background: rgba(76, 210, 122, 0.14); }

/* FAA advisories: a plain card with a hairline border, and the live icon
   in the site's blue. */
.ap-card--advisories {
  padding: 22px 24px;
  border: 1px solid var(--border-strong);
}

.ap-advisories-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 16px;
  margin-bottom: 12px;
}

.ap-card--advisories h3 {
  display: flex;
  align-self: center;
  align-items: center;
  gap: 8px;
  margin: 0;
  color: var(--text);
}

.ap-icon {
  flex: none;
}

.ap-icon--live {
  color: rgb(64, 132, 255);
}

.ap-icon--live .ap-wave {
  animation: ap-wave 2.4s ease-in-out infinite;
}

.ap-icon--live .ap-wave--outer {
  animation-delay: 0.3s;
}

@keyframes ap-wave {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
  .ap-icon--live .ap-wave {
    animation: none;
  }
}

.ap-advisories {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ap-advisory + .ap-advisory {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

/* The advisory on the left, and when it's expected to end on the right. */
.ap-advisory-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 16px;
}

.ap-advisory-message {
  flex: 1 1 260px;
  min-width: 0;
  font-weight: 600;
}

.ap-advisory-until {
  flex: none;
  margin-left: auto;
  color: var(--text-dim);
  white-space: nowrap;
}

.ap-chip {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 8px;
  background: var(--glass-strong);
  font-size: 13px;
}

.ap-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px !important;
}

/* ---------- Stats ---------- */
.ap-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.ap-stat,
.ap-card--compact {
  padding: 18px;
  border-radius: 20px;
  background: var(--card);
}

/* When a card is taller than its content (its row has a taller card), the
   content sits at the bottom. */
.ap-stat {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 4px;
}

.ap-stat-value {
  font-size: 26px;
  font-weight: bold;
  letter-spacing: -0.02em;
}

/* Number colors: green is good, red is bad. */
.ap-tone--green { color: var(--status-normal); }
.ap-tone--yellow { color: var(--status-yellow); }
.ap-tone--orange { color: var(--status-minor); }
.ap-tone--red { color: var(--status-major); }

.ap-stat-label {
  font-size: 13px;
  line-height: 1.35;
  color: var(--text-dim);
}

/* ---------- Hourly delay charts ---------- */
.ap-legend {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  font-size: 12px;
  color: var(--text-dim);
}

.ap-legend i {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: -6px;
  border-radius: 3px;
}

.ap-chart-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  margin-top: 8px;
}

.ap-chart-panel {
  margin: 0;
  min-width: 0;
}

.ap-chart-panel figcaption {
  margin-bottom: 12px;
  font-size: 14px;
  font-weight: 600;
}

.ap-chart-body {
  display: grid;
  grid-template-columns: 44px 1fr;
  height: 140px;
}

.ap-axis {
  position: relative;
}

.ap-axis span {
  position: absolute;
  right: 8px;
  transform: translateY(50%);
  font-size: 11px;
  color: var(--text-faint);
  white-space: nowrap;
}

.ap-plot {
  position: relative;
}

.ap-gridlines i {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.08);
}

.ap-chart,
.ap-xlabels {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ap-chart {
  position: relative;
  height: 100%;
}

.ap-col {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-width: 0;
  cursor: default;
}

.ap-bar {
  width: min(14px, 70%);
  border-radius: 3px 3px 1px 1px;
  transition: filter 150ms ease;
}

.ap-col:hover .ap-bar {
  filter: brightness(1.25);
}

.ap-bar--green { background: var(--status-normal); }
.ap-bar--yellow { background: var(--status-yellow); }
.ap-bar--orange { background: var(--status-minor); }
.ap-bar--red { background: var(--status-major); }
.ap-bar--none { background: transparent; }

.ap-xlabels {
  margin: 6px 0 0 44px;
  font-size: 11px;
  text-align: center;
  color: var(--text-faint);
}

.ap-xlabels li {
  display: flex;
  justify-content: center;
  white-space: nowrap;
}

.ap-chart-legend {
  margin-top: 16px;
}

/* ---------- Tooltip ---------- */
.ap-tip {
  position: fixed;
  z-index: 200;
  padding: 6px 10px;
  border-radius: 8px;
  border: 1px solid var(--border-strong);
  background: rgba(30, 31, 36, 0.96);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  font-size: 12px;
  line-height: 1.4;
  /* Short tips stay on one line; longer ones (like the conditions pill's)
     wrap instead of running off the screen. */
  width: max-content;
  max-width: min(260px, calc(100vw - 16px));
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -100%);
  transition: opacity 100ms ease;
}

.ap-tip.is-below {
  transform: translate(-50%, 0);
}

.ap-tip.is-visible {
  opacity: 1;
}

/* ---------- Definition lists ---------- */
.ap-dl,
.ap-facts {
  display: grid;
  gap: 10px;
  margin: 0;
}

.ap-dl div,
.ap-facts div {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 12px;
  align-items: baseline;
}

.ap-dl dt,
.ap-facts dt {
  font-size: 14px;
  color: var(--text-dim);
}

.ap-dl dd,
.ap-facts dd {
  margin: 0;
}

.ap-facts {
  grid-template-columns: 1fr 1fr;
  gap: 14px 24px;
  padding: 20px;
  border-radius: 20px;
  background: var(--card);
}

/* ---------- Weather ---------- */
.ap-weather-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 12px;
}

.ap-weather-icon svg {
  display: block;
  width: 44px;
  height: 44px;
}

.ap-weather-temp {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 34px;
  font-weight: bold;
  letter-spacing: -0.02em;
}

.ap-weather-temp .ap-dim {
  font-size: 17px;
  font-weight: 600;
}

/* ---------- Security heatmap ---------- */
/* Positioned so the hidden cell labels stay inside the scroll area. */
.ap-heatmap-wrap {
  position: relative;
  overflow-x: auto;
}

.ap-heatmap {
  width: 100%;
  min-width: 520px;
  border-collapse: separate;
  border-spacing: 3px;
  table-layout: fixed;
}

.ap-heatmap th {
  font-size: 11px;
  font-weight: normal;
  color: var(--text-faint);
}

.ap-heatmap thead th {
  height: 18px;
  text-align: left;
}

/* The table uses fixed layout, so the day column's width is set on the
   first row's header cell. */
.ap-heatmap th:first-child {
  width: 36px;
}

.ap-heatmap tbody th {
  text-align: left;
}

.ap-heatmap td {
  height: 22px;
  border-radius: 4px;
  cursor: default;
  transition: filter 150ms ease;
}

.ap-heatmap td:hover {
  filter: brightness(1.3);
}

.ap-heat--none { background: rgba(255, 255, 255, 0.04); }
/* Close to solid, so they match the delay bars. */
.ap-heat--green { background: rgba(76, 210, 122, 0.9); }
.ap-heat--yellow { background: rgba(255, 214, 10, 0.9); }
.ap-heat--orange { background: rgba(253, 145, 49, 0.9); }
.ap-heat--red { background: rgba(255, 105, 97, 0.9); }

/* The "no data" key needs an outline to show up against the card. */
.ap-legend .ap-heat--key {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2);
}

.ap-heat-legend {
  margin-top: 12px;
}

/* Card heading with a control on the right (the customs line toggle). */
.ap-card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
}

.ap-card-head h3 {
  margin: 0;
}

.ap-customs {
  position: relative;
}

/* Segmented control made of hidden radio buttons and their labels. */
.ap-seg-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.ap-seg {
  display: inline-flex;
  padding: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
}

.ap-seg label {
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}

#customs-visitors:checked ~ .ap-card-head label[for="customs-visitors"],
#customs-citizens:checked ~ .ap-card-head label[for="customs-citizens"] {
  background: rgba(255, 255, 255, 0.16);
  color: var(--text);
}

#customs-visitors:focus-visible ~ .ap-card-head label[for="customs-visitors"],
#customs-citizens:focus-visible ~ .ap-card-head label[for="customs-citizens"] {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 1px;
}

#customs-visitors:checked ~ .ap-seg-panel:not(.ap-seg-panel--visitors),
#customs-citizens:checked ~ .ap-seg-panel:not(.ap-seg-panel--citizens) {
  display: none;
}

/* Stats: a takeoffs row and a landings row, each with its plane icon in a
   narrow card on the left. */
.ap-stat-rows {
  display: grid;
  gap: 12px;
}

.ap-stat-row {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  gap: 12px;
}

.ap-stat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 20px;
  background: var(--card);
  color: var(--text-dim);
}

.ap-stat-icon svg {
  width: 22px;
  height: 22px;
}

.ap-stats--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* Two stats sharing one card (cancellations and diversions), split by a
   hairline. The inner stats drop their own card. When the card is too
   narrow for both side by side, they stack, each value next to its label. */
.ap-stat.ap-stat--pair {
  display: block;
  container-type: inline-size;
}

.ap-stat-pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  height: 100%;
}

.ap-stat-pair > .ap-stat.ap-stat {
  padding: 0;
  border-radius: 0;
  background: none;
}

.ap-stat-pair > .ap-stat.ap-stat + .ap-stat {
  padding-left: 16px;
  border-left: 1px solid var(--border);
}

@container (max-width: 230px) {
  .ap-stat-pair {
    grid-template-columns: minmax(0, 1fr);
    align-content: end;
    gap: 6px;
  }

  .ap-stat-pair > .ap-stat.ap-stat {
    flex-direction: row;
    justify-content: flex-start;
    align-items: baseline;
    gap: 8px;
  }

  .ap-stat-pair > .ap-stat.ap-stat + .ap-stat {
    padding: 6px 0 0;
    border-left: 0;
    border-top: 1px solid var(--border);
  }

  .ap-stat-pair .ap-stat-value {
    min-width: 1.4em;
  }
}

/* Read out by screen readers; shown next to the icon on phones. */
.ap-stat-icon-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* A second number in a stat's label ("63% on time", "2 diversions") stays
   in one piece; on phones it gets its own line (see the media query below). */
.ap-stat-extra {
  white-space: nowrap;
}

/* Stats: a heading with the Today / Past hour toggle on the right. */
.ap-section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}

.ap-section-head h2 {
  margin: 0;
}

#stats-today:checked ~ .ap-section-head label[for="stats-today"],
#stats-hour:checked ~ .ap-section-head label[for="stats-hour"] {
  background: rgba(255, 255, 255, 0.16);
  color: var(--text);
}

#stats-today:focus-visible ~ .ap-section-head label[for="stats-today"],
#stats-hour:focus-visible ~ .ap-section-head label[for="stats-hour"] {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 1px;
}

#stats-today:checked ~ [data-live] .ap-seg-panel:not(.ap-seg-panel--today),
#stats-hour:checked ~ [data-live] .ap-seg-panel:not(.ap-seg-panel--hour) {
  display: none;
}

.ap-stats-section .ap-stats + .ap-card,
.ap-stats-section .ap-seg-panel + .ap-card {
  margin-top: 12px;
}

.ap-checkpoints {
  display: grid;
  gap: 8px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
}

.ap-checkpoints li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.ap-checkpoints li > :first-child {
  flex: none;
}

/* ---------- Shortest and longest wait by day ---------- */
.ap-days {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

.ap-days th,
.ap-days td {
  padding: 10px 8px;
  border-top: 1px solid var(--border);
  text-align: left;
}

.ap-days thead th {
  padding-top: 0;
  border-top: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
}

.ap-days tbody th {
  font-weight: 600;
}

.ap-days th:first-child,
.ap-days td:first-child {
  padding-left: 0;
}

.ap-day-short {
  display: none;
}

/* Live wait times: the same table style, with the minutes right-aligned
   in their columns. */
.ap-live .ap-live-table {
  margin-top: 8px;
}

.ap-live-table th:not(:first-child),
.ap-live-table td {
  text-align: right;
}

.ap-live-table th:last-child,
.ap-live-table td:last-child {
  padding-right: 0;
}

/* The lanes a checkpoint has, under its name in the live table. */
.ap-lane-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

.ap-days .ap-lane-chips .ap-chip {
  margin: 0;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
  vertical-align: 0;
}

.ap-days .ap-chip {
  margin-left: 6px;
  padding: 1px 7px;
  font-size: 12px;
  font-weight: 600;
  vertical-align: 1px;
}

/* ---------- Links to other pages ---------- */
.ap-link-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 12px;
  padding: 18px 20px;
  transition: box-shadow 200ms ease;
}

.ap-link-card:hover {
  box-shadow: var(--card-glow);
}

.ap-link-card strong {
  display: block;
  font-weight: 600;
}

.ap-link-card .ap-dim {
  display: block;
  margin-top: 2px;
  font-size: 14px;
}

.ap-chevron {
  flex: none;
  color: var(--text-faint);
}

.ap-header + .ap-link-card,
.ap-header + .ap-links {
  margin: -8px 0 40px;
}

/* A secondary link under an airport's title. */
.ap-header-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  padding: 9px 16px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  font-size: 14px;
  font-weight: 600;
  transition: box-shadow 200ms ease;
}

.ap-header-link:hover {
  box-shadow: var(--card-glow);
}

.ap-header-link svg {
  color: rgb(64, 132, 255);
}

/* Not found and error pages: the message centered in whatever space the
   window has above the footer. */
body.ap-message-page {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

.ap.ap-message {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding-top: 100px;
  text-align: center;
}

.ap-message .ap-header {
  max-width: 560px;
  margin: 0;
}

.ap-message .hero-cta {
  margin-top: 28px;
}

.ap-links {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.ap-links > .ap-card.ap-link-card {
  margin-top: 0;
}

/* ---------- FAQ ----------
   The question and answer styles come from landing.css; these undo the
   airport pages' smaller h3. */
.ap .faq-item h3 {
  margin: 0 0 8px;
  font-size: 18px;
  color: var(--text);
}

.ap .faq-item a {
  color: rgb(64, 132, 255);
}

/* ---------- Airport lists ---------- */
.ap-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ap-row {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  border-radius: 18px;
  background: var(--card);
  transition: box-shadow 200ms ease;
}

.ap-row:hover {
  box-shadow: var(--card-glow);
}

.ap-row-code {
  font-size: 20px;
  font-weight: bold;
  letter-spacing: 0.02em;
}

.ap-row-name {
  font-weight: 600;
}

.ap-row-wait {
  font-size: 20px;
  font-weight: bold;
  letter-spacing: -0.02em;
}

.ap-row-name .ap-dim {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  font-weight: normal;
}

.ap-row-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  font-size: 13px;
  text-align: right;
}

/* ---------- Download prompt ----------
   Two classes, so the margin wins over .ap-section:first-of-type on pages
   where the prompt is the first section at its level (the airport list). */
.ap-section.ap-cta {
  margin-top: 96px;
  padding: 48px 24px;
  border-radius: var(--radius-lg);
  background: var(--card);
  text-align: center;
}

.ap-cta .ap-dim {
  max-width: 520px;
  margin: 0 auto 24px;
  line-height: 1.5;
}

/* ---------- Dashboard (/airports/dashboard/{code}) ----------
   The logo and search on top, then the title, then two columns: the map,
   runways, weather, and nearby airports on the left; status, stats, and
   wait times on the right. Overrides use .ap.apd or .apd so they win over
   the airport page styles. */
.ap.apd {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  /* Header, the two columns, and a bottom row with the nearby airports and
     the footer. The columns end on the same line, so the last cards in
     each (weather, and wait times) line up. */
  grid-template-rows: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: 16px;
  max-width: 1680px;
  padding: 20px 24px 40px;
}

.apd-col {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

/* Spacing comes from the columns' gap. */
.apd .ap-section,
.apd .ap-runways,
.apd .ap-grid-2 + .ap-card {
  margin-top: 0;
}

/* The header row: logo, title and details, live indicator, search. Above
   the rest of the page, so the search suggestions cover the map. */
.apd-top {
  position: relative;
  z-index: 20;
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-areas: "logo title live search";
  align-items: center;
  gap: 8px 20px;
}

.apd-logo {
  grid-area: logo;
  padding-right: 20px;
  border-right: 1px solid var(--border-strong);
}

.apd-logo img {
  display: block;
  width: auto;
  height: 26px;
}

/* The details follow the title on the same line, on its baseline, and drop
   under it when there isn't room. */
.apd-title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 14px;
  grid-area: title;
  min-width: 0;
}

.apd-title h1 {
  margin: 0;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.apd-title .ap-subtitle {
  font-size: 14px;
}

.apd-live {
  grid-area: live;
}

.apd-live .ap-updated {
  margin: 0;
  white-space: nowrap;
}

.apd-search {
  position: relative;
  grid-area: search;
  width: 300px;
}

.apd-search input {
  width: 100%;
  padding: 10px 40px 10px 40px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  outline: none;
  transition: box-shadow 200ms ease, border-color 200ms ease;
}

.apd-search input::placeholder {
  color: var(--text-faint);
}

.apd-search input:focus {
  border-color: rgba(255, 255, 255, 0.28);
  box-shadow: var(--card-glow);
}

/* Hides the browser's own clear button; Escape closes the suggestions. */
.apd-search input::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

.apd-search-icon {
  position: absolute;
  top: 50%;
  left: 15px;
  color: var(--text-faint);
  transform: translateY(-50%);
  pointer-events: none;
}

.apd-search-key {
  position: absolute;
  top: 50%;
  right: 12px;
  padding: 1px 7px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  color: var(--text-faint);
  font: inherit;
  font-size: 12px;
  transform: translateY(-50%);
  pointer-events: none;
}

.apd-search input:focus ~ .apd-search-key {
  display: none;
}

.apd-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 300;
  margin: 0;
  padding: 6px;
  border: 1px solid var(--border-strong);
  border-radius: 18px;
  background: #17181c;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  list-style: none;
}

.apd-results li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 12px;
  cursor: pointer;
}

.apd-results li.is-active,
.apd-results li:hover {
  background: rgba(255, 255, 255, 0.08);
}

.apd-results b {
  flex: none;
  width: 40px;
  font-size: 15px;
  letter-spacing: 0.02em;
}

.apd-results span {
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
}

.apd-results small {
  display: block;
  font-size: 12px;
  font-weight: normal;
  color: var(--text-dim);
}


/* Left column */
.apd .ap-map {
  height: 440px;
}

.apd .ap-runways {
  container-type: inline-size;
  gap: 10px 18px;
  padding: 14px 18px;
}

/* Keeps the row to one line on narrower windows. */
@container (max-width: 600px) {
  .apd .ap-runways-extra {
    display: none;
  }
}

/* Half-width charts: every other hour label, with room for "Now". */
.apd .ap-xlabels li:nth-child(odd):not(:last-child),
.apd .ap-xlabels li:nth-last-child(2) {
  visibility: hidden;
}

.apd .ap-xlabels li:last-child {
  justify-content: flex-end;
}

.apd-weather {
  display: flex;
  align-items: center;
  gap: 8px 16px;
  padding: 12px 18px;
  container-type: inline-size;
}

.apd-weather-now {
  display: flex;
  flex: none;
  align-items: center;
  gap: 10px;
  cursor: default;
}

.apd-weather .ap-weather-icon svg {
  width: 26px;
  height: 26px;
}

.apd-weather-temp {
  font-size: 17px;
  font-weight: bold;
  white-space: nowrap;
}

.apd-weather-temp .ap-dim {
  font-size: 14px;
  font-weight: 600;
}

.apd-weather-summary {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  font-size: 14px;
  color: var(--text-dim);
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: default;
}

.apd-weather-chips {
  display: flex;
  flex: none;
  gap: 6px;
  margin-left: auto;
}

/* Too little room for the summary to be useful: it's in the tooltip. */
@container (max-width: 600px) {
  .apd-weather-summary {
    display: none;
  }
}

.apd-nearby {
  display: flex;
  flex: none;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 0 4px;
}

.apd-nearby-label {
  margin-right: 4px;
  font-size: 13px;
  color: var(--text-faint);
}

.apd-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--card);
  font-size: 13px;
  font-weight: 600;
  transition: box-shadow 200ms ease;
}

.apd-chip:hover {
  box-shadow: var(--card-glow);
}

.apd-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-faint);
}

.apd-dot--major { background: var(--status-major); }
.apd-dot--minor { background: var(--status-minor); }
.apd-dot--normal { background: var(--status-normal); }

/* Status cards, then any FAA advisories, spaced like the rest of the
   column. */
.apd-status {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Right column: tighter cards than the airport page. */
.apd .ap-status,
.apd .ap-card--advisories {
  padding: 16px 20px;
}

.apd .ap-card--advisories {
  padding: 14px 20px;
}

.apd .ap-advisories-head {
  margin-bottom: 6px;
}

.apd .ap-advisory p {
  font-size: 15px;
}

.apd .ap-section-head {
  margin-bottom: 12px;
}

.apd .ap-section-head h2 {
  font-size: 20px;
}

.apd .ap-stat-rows {
  gap: 10px;
}

.apd .ap-stat-row {
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 10px;
}

.apd .ap-stats {
  gap: 10px;
}

.apd .ap-stat {
  padding: 13px 16px;
}

.apd .ap-stat-value {
  font-size: 22px;
}

.apd .ap-stats-section .ap-card {
  padding: 16px 20px;
}

.apd .ap-stats-section .ap-card h3 {
  margin-bottom: 4px;
}

.apd .ap-chart-legend {
  margin-top: 10px;
}

/* Security and customs, one line each */
.apd-waits {
  display: grid;
  grid-auto-columns: minmax(0, 1fr);
  grid-auto-flow: column;
  gap: 12px;
}

.apd-wait {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  transition: box-shadow 200ms ease;
}

.apd-wait:hover {
  box-shadow: var(--card-glow);
}

.apd-wait-label {
  font-weight: 600;
}

.apd-wait-values {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: 2px 14px;
  font-size: 15px;
}

.apd-footer {
  display: none;
}

/* The dashboard has its own download card, so the footer's is left out. */
.apd-page .footer-cta {
  display: none;
}

/* On narrower screens the dashboard scrolls and shows the site footer,
   lined up with the dashboard's own edges. */
.apd-page .footer {
  width: calc(100% - 48px);
  max-width: 1632px;
}

/* Overview: status counts, then the most disrupted airports. */
.apd-disrupted h2 {
  margin: 4px 4px 12px;
  font-size: 20px;
}

.apd-disrupted .ap-list {
  gap: 8px;
}

.apd-disrupted .ap-row {
  padding: 12px 18px;
}

.apd-disrupted .ap-list.has-more-above {
  --fade-top: 40px;
}

.apd-disrupted .ap-list.has-more-below {
  --fade-bottom: 40px;
}

.apd .apd-counts {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.apd-regions {
  padding: 14px 20px 6px;
}

.apd-regions .ap-days th,
.apd-regions .ap-days td {
  padding-top: 8px;
  padding-bottom: 8px;
}

/* The bottom row: nearby airports, the app download bar, and the footer. */
.apd-bottom {
  position: relative;
  z-index: 30;
  display: flex;
  grid-column: 1 / -1;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-width: 0;
}

/* Share, a pill the height of the download bar next to it. */
.apd-share {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 18px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: box-shadow 200ms ease;
}

.apd-share[hidden] {
  display: none;
}

.apd-share:hover {
  box-shadow: var(--card-glow);
}

.apd-share:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.6);
  outline-offset: 2px;
}

/* App download, as a thin bar in the site's blue, so it stands out from
   the dark cards around it. */
.apd-app {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 5px 5px 5px 12px;
  border-radius: 999px;
  background: linear-gradient(135deg, #2a6cf6, #4a8dff);
  box-shadow: 0 8px 28px rgba(42, 108, 246, 0.3);
}

/* The app icon (also the favicon). It has its own rounded corners and a
   light rim, so it needs no styling of its own. */
.apd-app-icon {
  flex: none;
  width: 30px;
  height: 30px;
}

/* The text takes the bar's spare width, and the subtitle shows only when
   it fits in full (about 495px with the title), rather than cut off. */
.apd-app-text {
  display: flex;
  flex: 1 1 auto;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
  container-type: inline-size;
}

@container (max-width: 500px) {
  .apd-app-text > span {
    display: none;
  }
}

.apd-app-text strong {
  font-size: 14px;
  white-space: nowrap;
}

/* The bar keeps the subtitle short; the card has room for the platforms. */
.apd-app-platforms {
  display: none;
}

.apd-app-text > span {
  min-width: 0;
  overflow: hidden;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.82);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Hovering or focusing Download shows a QR code above it, white so it
   scans, for getting the app on a phone. */
.apd-app-get {
  position: relative;
  flex: none;
}

.apd-qr-pop {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  width: 180px;
  padding: 16px 16px 12px;
  border-radius: 18px;
  background: #fff;
  color: #000;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
  text-align: center;
  opacity: 0;
  transform: translate(-50%, 6px);
  transition: opacity 150ms ease, transform 150ms ease;
  pointer-events: none;
}

.apd-qr-pop svg {
  display: block;
  width: 148px;
  height: 148px;
  margin: 0 auto 10px;
}

.apd-qr-pop span {
  font-size: 12px;
  font-weight: 600;
  color: #1d1d1f;
}

.apd-app-get:hover .apd-qr-pop,
.apd-app-get:focus-within .apd-qr-pop {
  opacity: 1;
  transform: translate(-50%, 0);
}

.apd .apd-app-download {
  margin: 0;
  padding: 8px 14px;
}

/* App layout, on screens big enough for it: the page fills the window. The
   map takes whatever height the left column has left, and the hourly chart
   whatever the right column has left. Only if the window is too short for
   the rest does the right column scroll. */
@media (min-width: 1200px) and (min-height: 720px) {
  body.apd-page {
    height: 100dvh;
    overflow: hidden;
  }

  .apd-page .footer {
    display: none;
  }

  .ap.apd {
    height: 100dvh;
    padding: 16px 24px;
    align-items: stretch;
  }

  .apd-col {
    min-height: 0;
  }

  /* Scrolls only if the window is too short. The padding (taken back by the
     negative margins) leaves room for the cards' hover glow, which the
     scroll area would otherwise cut off; it reaches into the column gap,
     the page's side padding, and the gap above the bottom row. */
  .apd-col--right {
    margin: 0 -24px -16px -16px;
    padding: 0 24px 16px 16px;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
  }

  .apd-map {
    flex: 1;
    min-height: 200px;
  }

  .apd .apd-map .ap-map {
    height: 100%;
  }

  /* The disrupted list scrolls on its own if it's longer than the space,
     keeping the counts in view. */
  .apd-disrupted {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
  }

  /* Each edge fades out while there's more list beyond it: the top once
     scrolled down, the bottom until the end (a script sets the classes). */
  .apd-disrupted .ap-list {
    --fade-top: 0px;
    --fade-bottom: 0px;
    min-height: 0;
    margin: -10px -10px 0;
    padding: 10px 10px 28px;
    overflow-y: auto;
    -webkit-mask-image: linear-gradient(transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent);
    mask-image: linear-gradient(transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
  }

  /* No min-height: 0 here, so on short windows the column scrolls rather
     than the chart overlapping the cards below it. */
  .apd .ap-stats-section,
  .apd .ap-stats-section > [data-live] {
    display: flex;
    flex: 1;
    flex-direction: column;
  }

  .apd .ap-stats-section > [data-live] > .ap-card {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 150px;
    margin-top: 10px;
  }

  .apd .ap-stats-section .ap-chart-pair {
    flex: 1;
    min-height: 0;
  }

  .apd .ap-chart-panel {
    display: flex;
    flex-direction: column;
  }

  .apd .ap-chart-body {
    flex: 1;
    height: auto;
    min-height: 70px;
  }

  .apd-footer {
    display: flex;
    flex: none;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 6px 14px;
    margin: 0 4px;
    font-size: 12px;
    color: var(--text-faint);
  }

  .apd-footer a:hover {
    color: var(--text-dim);
  }
}

/* Shorter windows: the chart can get smaller, and its color legend goes
   (each bar still shows its delay on hover). */
@media (min-width: 1200px) and (min-height: 720px) and (max-height: 860px) {
  .ap.apd {
    row-gap: 12px;
  }

  .apd-col {
    gap: 10px;
  }

  .apd .ap-status {
    padding: 13px 18px;
  }

  .apd .ap-chart-body {
    min-height: 44px;
  }

  .apd .ap-stats-section > [data-live] > .ap-card {
    min-height: 0;
  }

  .apd .ap-stat {
    padding-top: 10px;
    padding-bottom: 10px;
  }

  .apd-status {
    gap: 10px;
  }
}

/* Shorter windows also drop the chart's heading (still read out by screen
   readers); its Takeoffs and Landings captions stay. */
@media (min-width: 1200px) and (min-height: 720px) and (max-height: 860px) {
  .apd .ap-stats-section .ap-card > h3 {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .apd .ap-stats-section .ap-chart-legend {
    display: none;
  }
}

/* Narrower screens: one column, with the map first, and the page scrolls
   normally. The header puts the logo and search on top, and the
   title and live indicator under them. */
@media (max-width: 1199px) {
  /* The live indicator joins the logo and search on the top row. */
  .apd-top {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "logo live search"
      "title title title";
  }

  .apd-live {
    justify-self: end;
  }

  .apd-search {
    justify-self: end;
    width: min(300px, 100%);
  }

  .apd-logo {
    padding-right: 0;
    border-right: 0;
  }

  .ap.apd {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The columns step aside so their cards can be ordered one by one: the
     map, then status, stats, and wait times, then runways, weather, and
     nearby airports. */
  .apd-col {
    display: contents;
  }

  .apd-map { order: 1; }
  .apd-counts { order: 2; }
  .apd-disrupted { order: 3; }
  .apd-regions-wrap { order: 4; }
  .apd-status { order: 2; }
  .apd .ap-stats-section { order: 3; }
  .apd-waits { order: 4; }
  .apd .ap-runways { order: 6; }
  .apd-weather { order: 7; }

  .apd-nearby {
    order: 8;
  }

  /* The bottom row steps aside too, and the app download becomes a card
     after the wait times, with Download going straight to the App Store. */
  .apd-bottom {
    display: contents;
  }

  /* Share goes just above the download card, full width. */
  .apd-share {
    justify-content: center;
    order: 5;
    height: 46px;
  }

  .apd-app {
    flex-direction: column;
    order: 5;
    gap: 14px;
    padding: 28px 24px;
    border-radius: 20px;
    text-align: center;
  }

  .apd-app-icon {
    width: 60px;
    height: 60px;
  }

  .apd-app-text {
    flex: none;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: 100%;
    container-type: normal;
  }

  .apd-app-text strong {
    font-size: 20px;
    letter-spacing: -0.01em;
  }

  .apd-app-text .apd-app-platforms {
    display: inline;
  }

  .apd-app-text > span {
    max-width: 380px;
    font-size: 15px;
    line-height: 1.45;
    white-space: normal;
    text-wrap: balance;
  }

  .apd-qr-pop {
    display: none;
  }

  .apd .apd-app-download {
    padding: 10px 20px;
    font-size: 14px;
  }
}

/* ---------- Small screens ---------- */
@media (max-width: 760px) {
  .ap {
    padding-top: 120px;
  }

  .ap-grid-2,
  .ap-facts,
  .ap-links {
    grid-template-columns: 1fr;
  }

  .ap-stats {
    grid-template-columns: 1fr 1fr;
  }

  /* On phones the icon sits above its row, and a row of three ends with a
     full-width card. */
  .ap-stat-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
  }

  .ap-stat-icon {
    justify-content: flex-start;
    padding: 0 4px;
    background: none;
  }

  .ap-stat-icon svg {
    width: 20px;
    height: 20px;
  }

  .ap-stat-icon {
    gap: 8px;
  }

  .ap-stat-icon-label {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    font-size: 15px;
    font-weight: 600;
  }

  .ap-stats--3 > :last-child {
    grid-column: span 2;
  }

  /* A row with a pair card: the pair takes a full line, and the other two
     cards share one. */
  .ap-stats--with-pair {
    grid-auto-flow: dense;
  }

  .ap-stats--with-pair > .ap-stat--pair {
    grid-column: span 2;
  }

  .ap-stats--with-pair > :last-child {
    grid-column: auto;
  }

  .ap-chart-pair {
    grid-template-columns: 1fr;
  }

  .ap-tabs {
    top: 80px;
    margin-bottom: 24px;
  }

  .ap-section[id] {
    scroll-margin-top: 148px;
  }

  .ap-runways .ap-conditions {
    margin-left: 0;
  }


  .ap-stat-extra {
    display: block;
  }

  .ap-stat-sep {
    display: none;
  }

  .ap-days {
    font-size: 14px;
  }

  .ap-days th,
  .ap-days td {
    padding: 10px 4px;
    white-space: nowrap;
  }

  .ap-day-long {
    display: none;
  }

  /* The hour and its wait on two lines, so the table fits. */
  .ap-days:not(.ap-live-table) td .ap-day-sep {
    display: block;
    height: 0;
    overflow: hidden;
  }

  /* The live table can have up to five columns: fixed widths, and text that
     wraps, so it fits the card. */
  .ap-live-table {
    table-layout: fixed;
  }

  .ap-live-table thead th:first-child {
    width: 36%;
  }

  .ap-days.ap-live-table th,
  .ap-days.ap-live-table td {
    white-space: normal;
  }

  .ap-wide-only {
    display: none;
  }

  .ap-live-table thead th {
    font-size: 12px;
    line-height: 1.3;
    vertical-align: bottom;
  }

  .ap-day-short {
    display: inline;
  }

  .ap-tabs a {
    padding: 6px 12px;
    font-size: 13px;
  }

  /* Just the dot on phones, to leave the links room. */
  .ap-tabs-live-text {
    display: none;
  }

  .ap-tabs.is-stuck .ap-tabs-code,
  .ap-tabs.is-stuck .ap-tabs-live {
    width: 48px;
  }

  .ap-tabs.is-stuck .ap-tabs-code {
    padding-left: 10px;
    font-size: 14px;
  }

  .ap-tabs.is-stuck .ap-tabs-live {
    padding-right: 12px;
  }

  .ap-map {
    height: 340px;
  }

  .ap.apd {
    padding: 16px 16px 32px;
  }

  .apd-page .footer {
    width: calc(100% - 32px);
  }




  .apd .ap-stat-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
  }

  .apd-waits {
    grid-auto-flow: row;
  }

  .apd .ap-map {
    height: 340px;
  }

  .apd-search-key {
    display: none;
  }

  /* Phones: just "Live" next to the logo, and the search takes the rest of
     the row. The title line below shows the time. */
  .apd-top {
    grid-template-columns: auto auto minmax(0, 1fr);
    column-gap: 14px;
  }

  .apd-live {
    justify-self: start;
  }

  .apd-live-time {
    display: none;
  }

  .apd .apd-search {
    width: 100%;
  }

  /* Phones have the height to spare: the weather row wraps, with the
     summary on its own line. */
  .apd-weather {
    flex-wrap: wrap;
  }

  .apd .apd-weather-summary {
    display: block;
    flex-basis: 100%;
    order: 1;
    white-space: normal;
  }

  .apd-weather-chips {
    flex: 1 1 100%;
    flex-wrap: wrap;
    order: 2;
    margin-left: 0;
  }



  .ap-xlabels li:nth-child(odd):not(:last-child),
  .ap-xlabels li:nth-last-child(2) {
    visibility: hidden;
  }

  .ap-xlabels li:last-child {
    justify-content: flex-end;
  }

  .ap-heatmap {
    min-width: 0;
    border-spacing: 2px;
  }

  .ap-heatmap td {
    height: 18px;
    border-radius: 3px;
  }

  .ap-heatmap th:first-child {
    width: 32px;
  }

  .ap-row {
    grid-template-columns: 48px 1fr;
    gap: 6px 12px;
    padding: 14px 16px;
  }

  .ap-row-code {
    font-size: 17px;
  }

  .ap-row-meta {
    grid-column: 2;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    text-align: left;
  }
}
